Bağlaşıklık (Coupling) ve Yapışıklık (Cohesion) Nedir?

Yazılım tasarımının bana göre en temel ve projelerin büyüklüğü ile doğru orantılı olarak en fazla baş ağrıtan meselesi… Yine de genellikle problemlerin ana kaynağı olduğu pek az yazılım geliştiricisi tarafından farkedilir.

Bağlaşıklık (Coupling) Nedir?

Bağlaşıklık – kısaca – modüller arası alaka yoğunluğudur. Burada `modül` deyince aklınıza gelmesi gereken şey rutin, fonksiyon gövdesi veya metot gövdesidir.

Prosedürel Programlamada Bağlaşıklık

Her programlama paradigmasında prosedür barınır. Bundan dolayı prosedürel programlamadaki bağlaşıklık çeşitleri aslında genel bağlaşıklık çeşitleridir.

İçerik Bağlaşıklığı (Content Coupling) – Çok Sıkı –

Prosedürel programlamada bir rutin bir alt rutinin kod satırlarını aynen kullanıyorsa içerik bağlaşıklığı var demektir ve bu en sıkı bağlaşıklıktır. Mesela goto label kullanımı böyle bir bağlaşıklık oluşturur.

Genellerle Bağlaşıklık (Commons Coupling)

Modüllerin global scope’taki (veya dil destekliyorsa ortak scope’taki) veriye bağımlı olmasıyla meydana gelmiş bağlaşıklıktır. Herhangi geneller (globals) verisi değişikliğinde, görülemeyen yan etkiler meydana gelebilir.

Kontrol Bağlaşıklığı (Control Coupling)

Bir modülün, diğer bir modülün akışını, pasladığı veri ile kontrol etmesi sonucu meydana gelmiş bağlaşıklıktır.

Veri Yapılarıyla Bağlaşıklık (Stamp Coupling or Data-Structured Coupling)

Bir modülün, diğeri ile, kompozit veri yapısı (ki bu genelde nesnedir) paylaşması ve paylaşımı alan tarafın bu veri yapısının tamamıyla değil bir kısmı ile ilgili olması sonucu meydana gelmiş bağlaşıklıktır. Paylaşılan şeyin veri yapısının kopyası değil referansı olduğu unutulmamalı. Bu tür bağlaşıklıkta sakınca, alınan veri yapısının tamamının okunmaya açık olması ile değil, tamamında değişiklik yapılmasına açık olması ile ortaya çıkar. Mesela referansı paslanmış mutable bir nesne… Veriyle bağlaşıklığa nisbeten, ortaya çıkan sıkılaşma bununla alakalıdır. Mesela immutable bir nesne referansı paslansa, veriyle bağlaşıklıktan çok farkı kalmaz.

Veriyle Bağlaşıklık (Data Coupling) – Çok Gevşek –

Bir modülün, diğeri ile veri kopyası (parametre/argüman vs.) paylaşması sonucu meydana gelmiş bağlaşıklıktır. Tabii ki burada bahsi geçen veri kopyası, parçalanamayan veri parçası (parçalansa anlamını yitiren) olma özelliğine sahiptir.

Nesne Yönelimli Programlamada Bağlaşıklık

Nesne yönelimli programlamada, prosedürel programlamadaki bağlaşıklık çeşitlerine ek olarak şunlar var:

Alt Sınıf Bağlaşıklığı (Subclass Coupling)

Bir sınıfın (sub-class) varsa üst sınıfına (parent class) olan -ve olabildiğince gevşek olması gereken- bağımlılığı veya bir üst sınıfın alt sınıfına olan -ama olmaması gereken- bağımlılığıdır. Liskov Substitution Prensibi de bu bağlaşıklık ile alakalıdır.

Zamansal Bağlaşıklık (Temporal Coupling)

Nesne yönelimli programlamada bir sınıfın iki veya daha fazla metodu arasında, bu metotlardan birinin diğerinden önce çağırılmasını gerektiren örtülü bir ilişkisi bulunması durumunda ortaya çıkar. Bu şart, öğeleri zamansal boyutta sıkıca bağlaştırır. Mesela ardışıl metot çağırmalarında hangisinin önce çağırılacağı önemliyse, söz konusu metotlar arasında zamansal bağlaşıklık vardır.

Programlama Paradigmalarından Bağımsız Olan Bağlaşıklık Çeşitleri

Dinamik Bağlaşıklık (Dynamic Coupling)

Herhangi bir modülde kullanılan arayüzün aynı olduğu durumlarda run-time esnasında bağımlılığın dinamik olarak değişebildiği noktadaki bağlaşıklıktır.

Anlamsal Bağlaşıklık (Semantic Coupling)

Yazılım varlıkları (software entities) arasındaki yakınlık veya benzerlikleri konu eden kavramsal bağlaşıklık çeşididir.

Mantıksal Bağlaşıklık (Logical Coupling, Evolutionary Coupling or Change Coupling)

Yazılımın sürüm geçmişi ile alakalıdır. Yazılım varlıklarından (software entities) biri değiştiğinde buna bağlı olarak başka hangi yazılım varlıkları hangi sırayla değişmesi gerektiğini tesbit ile ortaya çıkarılabilir. Mesela bir A sınıfında değişiklik yaptığımda bir B sınıfında da değişiklik yapmam gerekiyorsa A ve B arasında mantıksal bağlaşıklık var denilir.

Sıkı Bağlaşık (Tightly Coupled) Sistemin Dezavantajları

  1. Bir modüldeki değişiklik genellikle diğer modüllerde değişiklik yapmaya zorlar (ripple effect). Özellikle mantıksal bağlaşıklığın sıkı olması.
  2. Artan modüller arası bağımlılıktan dolayı modüllerin ictiması daha fazla efor ve zaman gerektirir.
  3. Alakalı modüllerin hepsinin import edilmesi gerektiğinden dolayı bir modülün yeniden kullanılması veya test edilmesi zorlaşır.

İdeal Olan Gevşek Bağlaşıklığı Tesis Etmek İçin

  1. Geliştirme yapılırken birbiriyle ilgisi olmayan her şey ayrı geliştirilmelidir (separation of concern). Aynı çağrışım kümesine ilişkin her şey bir arada geliştirilmelidir. Yani bir arada geliştirilen bu öğeler bir yapışıklık (cohesion) hatta kuvvetli bir yapışıklık (high cohesion) içinde olmalıdır.
  2. Derlenen yazılım parçaları bir araya getirildiğinde hep birlikte otomatik olarak çalışacak şekilde tasarlanmalıdır (automated deployment). Derleme sonrası yapılandırmalardan kaçınılmalıdır.
  3. Her bir sınıfa ilişkin bütünleştirici soyut sınıflar tanımlanmalıdır (abstraction of subclasses). Alt sınıflar detaylı olarak tanımlanmalı; ancak soyut sınıflar olarak kullanılmalıdır.
  4. İşlevlerin geri dönüş değerleri, parametreler ve nesneler, bağımlılık yapmayacak şekilde tanımlanmalıdır.
  5. Yazılım çalıştığı ortama bağımlı olarak geliştirilmemelidir (environment independent).

Yapışıklık (Cohesion) Nedir?

Bir modül tek sorumluluğa sahip olmalı. Bu, tekil sorumluluk prensibi (single responsibility principle) olarak adlandırılır. Peki bir modülün tekil sorumluluğa sahip olup olmadığını nasıl anlarız? Diğer yönden bir modülün sorumluluklarını teke indirgemek için ne yapmalıyız?

Her modülün bir tek odağı olmalıdır. Tek odaklılık genelde tam yapışıklılık demektir. Çok odaklılık söz konusu ise modülün hala parçalanmaya ihtiyacı vardır. Bir değişiklik yapılması gerekiyorsa yalnız bir noktada yapılması gerekmeli. Ve bir öğeyi değiştirmek gerekiyorsa bunun yalnızca bir adet sebebi olmalı.

Şimdi kısa kısa yapışıklık çeşitlerine bakalım:

Tesadüfi Yapışıklık (Coincidental Cohesion) – En kötüsü

Modüldeki öğelerin rasgele seçilmesi durumu. Çoğunlukla utils, helpers tarzı modüllerde görülür.

Mantıksal Yapışıklık (Logical Cohesion)

Aynı kategoride olduğu düşünülen öğelerin aynı modüle yerleştirilmesi durumu. Tek açıdan bakıldığında düşülen durum olur.

Zamansal Yapışıklık (Temporal Cohesion)

Zaman içinde peyderpey eklenen birbiri ile alakalı veya alakasız öğelerin modül oluşturması durumu.

Prosedürel Yapışıklık (Procedural Cohesion)

Bir akışın içindeki öğelerin bir veya daha fazla odağa sahip olarak beraberce bir modül oluşturması durumu. İşte bu genelde yeterince düşünülmeden, tasarlanmadan yazıldığında ortaya çıkan modülün yapışıklığıdır.

İletişimsel Yapışıklık (Communicational Cohesion)

Aynı genel veri, aynı girdi veya aynı çıktı üzerinde çalışan öğelerin aynı modülde bulunması durumu.

Ardışıl Yapışıklık (Sequential Cohesion)

Önceki öğenin çıktısının, sonraki öğenin girdisi olduğu bir zincirin modül oluşturması durumu.

İşlevsel Yapışıklık (Functional Cohesion) – En iyisi

Yalnızca bir tek iş yapmaya odaklı öğelerin bir araya getirilip modülleştirilmesi durumu.

Düşük yapışıklığın 3 büyük sebebi vardır

  1. Bir an önce çalışsın da…
  2. Üşengeçlik
  3. Karmaşık kodlama (complex coding) paranoyası

Bağlaşıklık (Coupling) ve Yapışıklık (Cohesion) İlişkisi

coupling-and-cohesion
Coupling & Cohesion

Bu iki kavram genelde birbirine karıştırılır. Aslında nicel saysak birbirine ters orantılı şeylerdir. Gevşek bağlaşıklık (loose coupling) genellikle yüksek yapışıklık (high cohesion) ve tabii ki sıkı bağlaşıklık (tight coupling) da genellikle düşük yapışıklık (low cohesion) demektir.

Özetle modüller arası (veya sınıflar arası) düzen bağlaşıklık (coupling), modül içi (veya sınıf içi) düzen yapışıklık (cohesion) olarak tanımlanabilir. Bağlaşıklık gevşetilirken (decoupling) yapışıklık da gevşetilmemeli, yapışıklık güçlendirilirken bağlaşıklık da sıkılaştırılmamalıdır.