Programlama dünyasında, nesne yönelimli programlamanın ortaya çıkışından sonra, sınıflar ve nesneler kavramları ortaya çıktı. Ve programlama dünyası nesneleri olabildiğince böl parçala ve yönet şeklinde el almaya başladı. Burada ki amacı genel olarak tanımlama yapacak olursak ki bu tanım çok yetersiz kalır, olabildiğince spesifik kod yazmak diyebiliriz. Bu bağlamda olabildiğince ayırdığımız nesneleri ilişkilendirmeler üzerinde bir bütün haline getirip bir program çıkartırız. İşte bu eşleştirmede karşımıza Coupling dediğimiz kavram ortaya çıkmaktadır.
COUPLING (Bağlaşım/Bağlantı) Nedir?
Coupling’in klasik tanımı şudur: Yazılım bileşenlerinin birbirine ne derece bağımlı olduğudur.
C#’ta Coupling, C#’taki modüller arasındaki ilişkiyi, sınıfların ve nesnelerin nasıl bağlandığını ve ayrıca bunların birbirlerine ne kadar bağımlı olduklarını açıklar. Bu aynı zamanda kodun esneklik ve yeniden kullanılabilirlik kısmını da açıklar.
Modüller arasında başarılı iletişim için bir coupling (bağlantı) gereklidir. Ancak, modüllerin nasıl bağlandığı kodun standardını belirler. Şimdi iki coupling (bağlantı) türünü ayrıntılı olarak görelim.
Tightly Coupling (Sıkı Bağlantı)
Şöyle düşünelim – parmaklarımız elimize sıkı sıkıya bağlıdır, bu da parmakların konumunu ve konumlarını değiştirmeyi zorlaştırır. Yani, parmakların konumunu değiştirmenin imkansıza yakın olduğu ve elin yeniden tasarlanmasını gerektirdiğini düşünebiliriz. İşte bu, tightly coupling (sıkı bağlantı) bir şekilde bağlı olmanın bir örneğidir.
Sınıflar ve nesneler birbirine çok bağlıdır, bu nedenle kodu yeniden kullanmak zorlaşır. Birçok bağımlı bileşen olduğunda, geliştirmeler için kodu korumak zorlaşır. Bağımlı bileşen tanımı oldukça geniş bir konudur ama temel olarak şunu söyleyebilirim A ve B sınıflarımız olsun, B sınıfını bağımsız olarak kullanmadığımızı yalnızca A sınıfın içerisinde kullanabildiğimiz bir senaryo düşünelim. Bu durumda B sınıfı A sınıfına sıkı bağlı olacaktır.
Konuyu daha iyi anlamak için bir örnek yapalım.
internal class Program
{
private static void Main(string[] args)
{
var fileReader = new FileReader(@"C:\Users\fatih.alkan\Desktop\deneme.txt");
fileReader.StartReading();
fileReader.SaveData();
}
}
public class FileReader
{
private readonly string _filename;
private string _contents;
public FileReader(string filename)
{
_filename = filename;
}
public void StartReading()
{
_contents = File.ReadAllText(_filename);
}
public void SaveData()
{
var saver = new FileSaver(_filename.Replace(".txt", ".doc"), _contents);
saver.SaveData();
}
}
public class FileSaver
{
private readonly string _filename;
private string _contents;
public FileSaver(string filename, string contents)
{
_filename = filename;
_contents = contents;
}
public void SaveData()
{
File.WriteAllText(_filename, _contents);
}
}
Yukarıdaki kodda, kodun yürütülmeye başladığı bir Program sınıfımızın main metodunda bir dosya adı bekleyen filereader için bir nesne yaratma kodu var. Ve filereader sınıfının içinde, biri dosyadaki verileri okumak, diğeri verileri bir dosyaya kaydetmek için olmak üzere iki metot vardır. FileReader sınıfın içinde ki save metoduna baktığımız zaman, verileri farklı bir dosyaya kaydetmek için kullanılan başka bir sınıf için bir nesne oluşturduğunu göreceksiniz.
İşte bu tip bir Tightly Coupling (Sıkı Bağlı) yapıdır. Bu şekilde bağlantılı olduğundan ve sınıfın tüm uygulamasını bildiklerinden, ek değişiklikler yapmak zordur. Bunun nedeni, değişikliklerin birçok yerde yapılması gerekmesidir. Çok daha büyük bir uygulamada benzer türde bir bağlantı hayal edin. Kodu korumak ve desteklemek son derece zor olacaktır.
Loosely Coupling (Gevşek Bağlantı)
Loosely Coupling (gevşek bağlantı) modelini baş ve şapka örneği ile açıklayabiliriz. Örneğin, başımıza bir kovboy şapkası da sığabilir, bir şef şapkası da sığabilir. Burada, her ikisi de birbirine bağımlı olmadığı için baş ve başlık Loosely Coupling şekilde bağlanmış olur. Bu, onu çok daha az karmaşık hale getirir ve kodun yeniden kullanılabilirliğini sağlar.
Bu yapıya kod perspektifinden bakıldığı zaman, sınıf ve nesneler birbirine bağımlı değildir, bu nedenle kodu değiştirmek, yeniden kullanmak ve sürdürmek kolaylaşır. Yukarıda ki örneği loosely coupling modelini kullanarak tekrar ele alalım.
internal class Program
{
private static void Main(string[] args)
{
var fileReader = new FileReader(@"C:\Users\fatih.alkan\Desktop\deneme.txt");
fileReader.StartReading();
fileReader.SaveData();
}
}
public class FileReader
{
private readonly string _filename;
private string _contents;
public FileReader(string filename)
{
_filename = filename;
}
public void StartReading()
{
_contents = File.ReadAllText(_filename);
}
public void SaveData()
{
IFileSaver saver = new FileSaver();
saver.SaveFile(_filename, _contents);
}
}
public interface IFileSaver
{
public void SaveFile(string filename, string contents);
}
public class FileSaver : IFileSaver
{
public void SaveFile(string filename, string contents)
{
File.WriteAllText(filename, contents);
}
}
Yukarıdaki örneğe baktığımız zaman, main method ve FileReader sınıfı bir önceki örnek ile aynı görünmektedir. Ancak değişiklik, FileSaver sınıfının oluşturulmasında, uygulanmasında ve çağrılmasında mevcuttur. Loosely Coupled (Gevşek) bir şekilde bağlı hale getirmek için bir interface (IFileSaver) tanıtıldı. Peki Loosely Coupled nasıl gelişir?
Örneğin şu anda dosyayı txt formatında kaydediyoruz. Gelecekte, diğer biçimlere geçme seçeneği varsa, interface uygulayıcı sınıf tarafından miras alınacaktır ve Interface’e tanımlanan metotlar miras alan sınıf tarafından uygulanacağından minimum kod değişikliği ile kullanılabilir hale gelecektir.
Sonuç olarak, Kodun gerektiği gibi değiştirilmesini sağlayan modüler kod yapısı oluşturmak gerekir. Bu esnekliği sağlamak Loosely coupling modeli ile mümkündür. Küçük basit uygulamalarda, tightly coupling (sıkı) bir şekilde bağlanmış kodla devam etmek pek sorun değildir. Ancak yolunuza büyük değişiklikler geldiğinde büyük bir yenileme olacaktır.