Yanıtlar:
Sıkı bağlantı, bir grup sınıfın birbirine oldukça bağımlı olduğu zamandır.
Bu senaryo, bir sınıf çok fazla sorumluluk üstlendiğinde veya bir endişe kendi sınıfına sahip olmak yerine birçok sınıfa yayıldığında ortaya çıkar.
Gevşek bağlantı, tek sorumluluğu ve endişelerin ayrılmasını teşvik eden bir tasarımla elde edilir.
Gevşek bağlanmış bir sınıf, diğer (beton) sınıflardan bağımsız olarak tüketilebilir ve test edilebilir.
Arabirimler ayırma için kullanılabilecek güçlü bir araçtır. Sınıflar, diğer somut sınıflardan ziyade arayüzler aracılığıyla iletişim kurabilir ve herhangi bir sınıf, sadece arayüzü uygulayarak bu iletişimin diğer ucunda olabilir.
Sıkı bağlantı örneği:
class CustomerRepository
{
private readonly Database database;
public CustomerRepository(Database database)
{
this.database = database;
}
public void Add(string CustomerName)
{
database.AddRow("Customer", CustomerName);
}
}
class Database
{
public void AddRow(string Table, string Value)
{
}
}
Gevşek bağlantı örneği:
class CustomerRepository
{
private readonly IDatabase database;
public CustomerRepository(IDatabase database)
{
this.database = database;
}
public void Add(string CustomerName)
{
database.AddRow("Customer", CustomerName);
}
}
interface IDatabase
{
void AddRow(string Table, string Value);
}
class Database implements IDatabase
{
public void AddRow(string Table, string Value)
{
}
}
Burada başka bir örnek .
Şapka vücuda "gevşek bir şekilde bağlıdır". Bu, kişide / bedende herhangi bir değişiklik yapmadan şapkayı kolayca çıkarabileceğiniz anlamına gelir. Bunu yapabildiğiniz zaman "gevşek bağlantınız" olur. Ayrıntılandırma için aşağıya bakın.
Cildinizi düşünün. Vücuduna yapışmış. Eldiven gibi uyar. Peki ya ten rengini beyazdan yeşile değiştirmek istersen? Cildinizi soymanın, boyamanın ve sonra tekrar yapıştırmanın ne kadar acı verici olacağını hayal edebiliyor musunuz? Vücudunuza sıkıca bağlı olduğu için cildinizi değiştirmek zordur. Kolayca değişiklik yapamazsınız. Bunu mümkün kılmak için bir insanı temelden yeniden tasarlamanız gerekir.
Tanrı iyi bir nesne yönelimli programcı değildi.
Şimdi sabah giyinmeyi düşün. Maviyi sevmiyor musun? Sorun değil: Bunun yerine kırmızı bir gömlek giyebilirsiniz. Bunu kolayca ve zahmetsizce yapabilirsiniz çünkü gömlek vücudunuza gerçekten cildinizle aynı şekilde bağlı değildir. Gömlek hangi vücuda gittiğini bilmiyor veya önemsemiyor . Başka bir deyişle, vücudunuzu gerçekten değiştirmeden kıyafetlerinizi değiştirebilirsiniz.
Özetle temel kavram budur.
Önemli, çünkü yazılım sürekli değişiyor. Genel olarak, kodunuzu değiştirmeden kodunuzu kolayca değiştirebilmek istersiniz. Bunun bir oksimoron gibi geldiğini biliyorum, ama lütfen bana katlan.
CSV / JSON / DB Örnekler: Birisi çıktılarını JSON vb. Yerine bir CSV dosyasında istiyorsa veya MySQL'den PostGreSQL'e geçmek istiyorsanız, bu değişiklikleri yeniden yazmanıza gerek kalmadan kodunuzda kolayca yapabilirsiniz. Başka bir deyişle, uygulamanızı belirli bir veritabanı uygulamasıyla (örneğin Mysql) veya belirli bir çıktıyla (örn. CSV dosyaları) sıkıca birleştirmek istemezsiniz. Çünkü yazılımda kaçınılmaz olduğu gibi değişiklikler de gelecek. Geldiklerinde, kodunuzun bazı bölümleri gevşek bir şekilde birleştirilirse çok daha kolaydır.
Araç Parçaları Örnek: Biri isterse kendi arabasını içinde siyah , bunu yapmak için tüm aracı yeniden tasarlamak zorunda olmamalıdır. Bir araba ve yedek parçaları gevşek bağlanmış bir mimarinin mükemmel bir örneği olacaktır. Motorunuzu daha iyi bir motorla değiştirmek isterseniz, çok fazla çaba harcamadan motorunuzu kolayca çıkartabilmeniz ve daha iyi bir motorla değiştirebilmeniz gerekir. Arabanız sadece Rolls Royce 1234 Motorları ile çalışıyorsa ve başka motor yoksa - o zaman arabanız bu motora sıkıca bağlanır (Rolls Royce 1234). Arabanızın tasarımını değiştirirseniz daha iyi olurdu, böylece herhangi biriyle çalışacakmotor, böylece bileşenleri ile biraz daha gevşek bir şekilde birleşti. Arabanız bir motora ihtiyaç duymadan çalışabilseydi daha da iyi olurdu! Bir miktar bağlantı gerçekleşecek, ancak mümkün olduğunca en aza indirmek için çalışmalısınız. Neden? Çünkü gereksinimler değiştiğinde hala çok iyi kalitede yazılım sunabilmeliyiz ve bu hedefe gevşek bağlantılarla yardımcı oluyoruz.
Kısacası, gevşek bağlantı kodun değiştirilmesini kolaylaştırır. Yukarıdaki cevaplar bu noktada okunmaya değer bazı kodlar sağlar.
Re: @TimoHuovinen yorum - gevşek bağlantı kavramı, polimorfizm kavramlarıyla el ele gider. Bir gömlek / araba parçalarının temel benzetmesini kavrarsanız, polimorfizmi anlamaya hazır olacaksınız. En iyi yol, bu noktada, bu iş parçacığındaki diğer cevaplarda tahmin edilebilir meslektaşlarım tarafından sağlanan kod örneklerini okumaktır. Artık söylersem çok fazla bilgi ile aşırı yüklenebilirsiniz.
Nesneye yönelik tasarımda kuplaj miktarı, bir sınıfın tasarımının başka bir sınıfın tasarımına ne kadar bağlı olduğunu ifade eder. Başka bir deyişle, A sınıfı değişimler B sınıfı değişimleri ne sıklıkta zorlar? Sıkı bağlantı, iki sınıfın sıklıkla birlikte değiştiği, gevşek bağlantı ise çoğunlukla bağımsız oldukları anlamına gelir. Genel olarak, gevşek kaplin önerilir, çünkü test edilmesi ve bakımı daha kolaydır.
Sen bulabilirsiniz Martin Fowler (PDF) tarafından bu kağıdı yararlı.
Genel olarak, Sıkı Kaplin kötüdür, ancak çoğu zaman, kodun esnekliğini ve yeniden kullanılabilirliğini azalttığı için, değişiklikleri çok daha zorlaştırır, test edilebilirliği vb.
Sıkı Birleştirilen Nesne, birbirleri hakkında biraz bilgi sahibi olması gereken bir nesnedir ve genellikle birbirine oldukça bağımlıdır. Sıkı birleştirilmiş bir uygulamada bir nesneyi değiştirmek genellikle diğer birkaç nesnede değişiklik gerektirir, Küçük uygulamada değişiklikleri kolayca belirleyebiliriz ve hiçbir şeyi kaçırmak için daha az şansımız vardır. Ancak büyük uygulamalarda bu bağımlılıklar her programcı tarafından her zaman bilinmemektedir veya değişiklikleri kaçırmak için şans vardır. Ancak her gevşek bağlanmış nesne kümesi diğerlerine bağımlı değildir.
Kısacası, gevşek bağlantı, bir bileşendeki değişikliklerin başka herhangi bir bileşende değişiklik gerektirme riskini azaltmak amacıyla bir sistemin bileşenleri arasındaki bağımlılıkları azaltmaya çalışan bir tasarım hedefidir. Gevşek bağlantı, bir sistemin esnekliğini arttırmayı, daha sürdürülebilir olmasını sağlamayı ve tüm çerçeveyi daha 'istikrarlı' hale getirmeyi amaçlayan çok daha genel bir kavramdır.
Birleştirme, bir elementin diğeriyle ilgili doğrudan bilgi derecesini ifade eder. bir örnek diyebiliriz: A ve B, sadece B davranışını sadece A davranışını değiştirdiğinde değiştirir. Gevşek bağlanmış bir sistem kolayca tanımlanabilir elemanlara ayrılabilir.
İki nesne gevşek bir şekilde birleştiğinde, etkileşime girebilirler, ancak birbirleriyle çok az bilgi sahibi olurlar.
Gevşek olarak birleştirilen tasarımlar, değişimi kaldırabilecek esnek OO sistemleri oluşturmamızı sağlar.
Gözlemci tasarım deseni, sınıfları gevşek bir şekilde birleştirmek için iyi bir örnektir, Wikipedia'da buna bir göz atabilirsiniz .
Bağlantı hakkındaki blog yayınımdan bir alıntı :
Sıkı Kaplin Nedir : -
Yukarıdaki tanımın bir parçası olarak, Sıkı Birleştirilmiş Nesne, diğer nesneler hakkında bilgi sahibi olması gereken ve genellikle birbirlerinin arayüzlerine oldukça bağımlı olan bir nesnedir.
Sıkı birleştirilmiş bir uygulamada bir nesneyi değiştirdiğimizde, sık sık diğer bazı nesnelerde değişiklik yapılmasını gerektirir. Küçük bir uygulamada değişikliği kolayca belirleyebileceğimiz bir sorun yok. Ancak büyük uygulamalar söz konusu olduğunda, bu karşılıklı bağımlılıklar her tüketici veya diğer geliştiriciler tarafından her zaman bilinmemektedir veya gelecekteki değişikliklerin olasılığı çok fazladır.
Sıkı bağlantıyı anlamak için bir alışveriş sepeti demo kodu alalım:
namespace DNSLooseCoupling
{
public class ShoppingCart
{
public float Price;
public int Quantity;
public float GetRowItemTotal()
{
return Price * Quantity;
}
}
public class ShoppingCartContents
{
public ShoppingCart[] items;
public float GetCartItemsTotal()
{
float cartTotal = 0;
foreach (ShoppingCart item in items)
{
cartTotal += item.GetRowItemTotal();
}
return cartTotal;
}
}
public class Order
{
private ShoppingCartContents cart;
private float salesTax;
public Order(ShoppingCartContents cart, float salesTax)
{
this.cart = cart;
this.salesTax = salesTax;
}
public float OrderTotal()
{
return cart.GetCartItemsTotal() * (2.0f + salesTax);
}
}
}
Yukarıdaki örnekle ilgili sorunlar
Sıkı Bağlantı bazı zorluklar yaratır.
Burada, OrderTotal()
yöntemler bize arabaların mevcut öğeleri için tam bir miktar verir. Bu alışveriş sistemine indirim özelliklerini eklemek istiyorsak. Yukarıdaki kodda yapmak çok zordur, çünkü her sınıfta çok sıkı bir şekilde bağlı olduğu için değişiklikler yapmak zorundayız.
Gevşek bağlantı, iki bileşen arasındaki bağımlılık derecesinin çok düşük olduğu anlamına gelir.
Örnek: GSM SIM
Sıkı bağlantı, iki bileşen arasındaki bağımlılık derecesinin çok yüksek olduğu anlamına gelir.
Örnek: CDMA Mobile
Anladığım kadarıyla, sıkı bir şekilde birleştirilmiş mimari, gevşek bir şekilde birleştirilmiş mimariye kıyasla değişim için çok fazla esneklik sağlamaz.
Ancak gevşek bağlanmış mimariler, mesaj formatları veya işletim platformları veya iş mantığının yenilenmesi durumunda diğer ucu etkilemez. Sistem bir yenileme için kaldırılırsa, elbette diğer uç hizmete bir süre erişemez, ancak bunun dışında, değişmeyen uç yenileme işleminden önceki gibi mesaj alışverişine devam edebilir.
Sıkı Bağlantı , bir sınıfın başka bir sınıfa bağlı olduğu anlamına gelir.
Gevşek Kavrama , bir sınıfın sınıf yerine arabirime bağlı olduğu anlamına gelir.
Olarak sıkı bağlama , yöntem bildirilen kodlanmış bağımlılık yoktur.
Olarak gevşek bağlanması , bunun yerine sabit kodlu bir zamanında harici bağımlılık geçmelidir. (Gevşek çift sistemleri, sınıfa olan bağımlılığın azalması için arayüz kullanır.)
Örneğin, çıkışı JSON çıkışı, CSV çıkışı vb. Gibi iki veya daha fazla yolla gönderebilen bir sistemimiz var.
public interface OutputGenerator {
public void generateOutput();
}
public class CSVOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("CSV Output Generator");
}
}
public class JSONOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("JSON Output Generator");
}
}
// In Other Code, we write Output Generator like...
public class Class1 {
public void generateOutput() {
// Here Output will be in CSV-Format, because of hard-coded code.
// This method tightly coupled with CSVOutputGenerator class, if we want another Output, we must change this method.
// Any method, that calls Class1's generateOutput will return CSVOutput, because Class1 is tight couple with CSVOutputGenerator.
OutputGenerator outputGenerator = new CSVOutputGenerator();
output.generateOutput();
}
}
Yukarıdaki örnekte, JSON'daki çıktıyı değiştirmek istiyorsak, Class1 CSVOutputGenerator sınıfıyla sıkıca bağlandığından kodun tamamını bulmamız ve değiştirmeniz gerekir.
public interface OutputGenerator {
public void generateOutput();
}
public class CSVOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("CSV Output Generator");
}
}
public class JSONOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("JSON Output Generator");
}
}
// In Other Code, we write Output Generator like...
public class Class1 {
public void generateOutput(OutputGenerator outputGenerator) {
// if you want to write JSON, pass object of JSONOutputGenerator (Dependency will be passed externally to this method)
// if you want to write CSV, pass object of CSVOutputGenerator (Dependency will be passed externally to this method)
// Due to loose couple with class, we don't need to change code of Class1, because Class1 is loose coupled with CSVOutputGenerator or JSONOutputGenerator class
// Any method, that calls Class1's generateOutput will desired output, because Class1 does not tight couple with CSVOutputGenerator or JSONOutputGenerator class
OutputGenerator outputGenerator = outputGenerator;
output.generateOutput();
}
}
Kütüphanelerinde bağımlılık sağlayan bazı araçlar vardır, örneğin .net'te Ninject Kütüphanesi var .
Java'da daha ileri gidiyorsanız, bahar bu yetenekleri sağlar.
Gevşek bağlı nesneler kodunuza Arayüzler tanıtılarak yapılabilir, bu kaynakların yaptığı budur.
Kodunda yazdığını söyle
Myclass m = new Myclass();
şimdi yönteminizdeki bu ifade, buna bağımlı myclass
olduğunuzun sıkı bir şekilde bağlandığını söylüyor . Şimdi bazı yapıcı enjeksiyonu veya özellik enjeksiyonu ve örnekleme nesnesi sağlıyorsanız, gevşek bir şekilde birleşecektir.
Burada analojileri kullanarak çok güzel cevaplar var ama işteki bir arkadaşım bana burada belirtilenlerden daha fazlasını sevdiğime bir örnek verdi ... Gözler ve Gözlükler!
Sıkı bağlama
Sıkı bağlantı gözler olacak. Eğer vizyonumu düzeltmek istersem, bir göz nakli yaptırmak çok pahalıdır ve oldukça fazla risk taşır. Ama ya tasarımcı (insan ırkı olmak) daha iyi bir yol bulursa. Kolayca değiştirilebilmesi için vücuda gevşek bir şekilde bağlanan bir özellik ekleyin! (evet .. gözlük)
Gevşek bağlantı
Alttaki vizyonumu bozmadan gözlüklerimi kolayca değiştirebilirim. Gözlükleri çıkarabilirim ve vizyonum daha önce olduğu gibi olacak (daha iyi veya daha kötü değil). Farklı gözlük çiftlerini kullanmak, dünyayı çok az risk ve kolay bakım ile gözlerimizden nasıl gördüğümüzü değiştirir.
özet
Bir dahaki sefere birisi size "kodumun sıkıca bağlı olup olmadığını kimin umurunda?" Cevap tamamen değiştirme çabası, sürdürme çabası ve değişim riski ile ilgilidir.
Peki bu C # nasıl yapılır? Arayüzler ve Bağımlılık Enjeksiyonu!
DÜZENLE
Gözlerin arayüz gereksinimlerini karşılayarak ancak farklı işlevler vererek (örn. Güneş gözlüğü, okuma gözlüğü, kuyumcular için büyüteçler vb.) Dekorasyon yaptığımız sınıf olduğu Dekoratör deseninin iyi bir örneği.
Gevşek bağlantı, eski stil sabit kodlu bağımlılıklara ve bir şey değiştiğinde ve yeniden kullanıldığında sık yeniden derleme gibi ilgili sorunlara yanıt verir. İşçi mantığının bileşenlere uygulanmasına ve orada çözüme özgü kablo kodundan kaçınmaya vurgu yapar.
Gevşek Bağlama, doğrudan kodlamanın iyi bir yolu olmayan bağımlılıkta verdiğiniz sıkı bağlantının olması durumunda, sınıfınızın ihtiyaç duyduğu bağımlılığı dolaylı olarak dolaysız olarak verme sürecidir (yani arayüzden itibaren).
Sınıfların bağımlılık oranı , gevşek bağlı olarak çok düşük ve sıkı bağlı olarak çok yüksek olan başkalarına bağımlılık oranı ile ilgilidir. Hizmet yönelimi mimarisinde açık olmak gerekirse , hizmetler birbirine bağımlı sınıfların amaçlandığı monolitik olana karşı gevşek bir şekilde birbirine bağlıdır.
Bir nesnenin yaratılması / varlığı, uyarlanamayan başka bir nesneye bağlıysa, sıkı bağlantısı. Ve eğer bağımlılık uyarlanabilirse, gevşek bağlantısı. Java'da bir örnek düşünün:
class Car {
private Engine engine = new Engine( "X_COMPANY" ); // this car is being created with "X_COMPANY" engine
// Other parts
public Car() {
// implemenation
}
}
Car
Sınıf istemcisi SADECE "X_COMPANY" motoruyla bir tane oluşturabilir.
Bu kuplajı aşağıdakileri değiştirme yeteneğiyle kırmayı düşünün:
class Car {
private Engine engine;
// Other members
public Car( Engine engine ) { // this car can be created with any Engine type
this.engine = engine;
}
}
Şimdi, a Car
"X_COMPANY" motoruna bağımlı değildir, çünkü bu türlerle oluşturulabilir.
Java'ya özel bir not: Java arayüzlerini sadece bağlantısız uğruna kullanmak uygun bir tasarım yaklaşımı değildir. Java'da bir arayüzün bir amacı vardır - intrisik olarak kuplajsız davranış / avantaj sağlayan bir sözleşme gibi davranmak.
Bill Rosmus'un kabul edilen cevaptaki yorumu iyi bir açıklamaya sahip.
Sıkı bağlantı, sınıfların ve nesnelerin birbirine bağımlı olduğu anlamına gelir. Genel olarak sıkı bağlantı genellikle iyi değildir, çünkü kodun esnekliğini ve yeniden kullanılabilirliğini azaltırken Gevşek bağlantı, farklı sınıfı doğrudan kullanan bir sınıfın bağımlılıklarını azaltmak anlamına gelir.
Sıkı Bağlama Sıkı bağlanmış nesne, diğer nesneler hakkında bilinmesi gereken ve genellikle birbirlerinin arabirimlerine oldukça bağımlı bir nesnedir. Sıkı birleştirilmiş bir uygulamada bir nesnenin değiştirilmesi genellikle diğer birkaç nesnede değişiklik yapılmasını gerektirir. Küçük uygulamalarda, değişiklikleri kolayca belirleyebiliriz ve hiçbir şeyi kaçırma şansı daha azdır. Ancak büyük uygulamalarda, bu bağımlılıklar her programcı tarafından her zaman bilinmemektedir ve değişiklikleri gözden kaçırma şansı vardır. Misal:
class A {
public int a = 0;
public int getA() {
System.out.println("getA() method");
return a;
}
public void setA(int aa) {
if(!(aa > 10))
a = aa;
}
}
public class B {
public static void main(String[] args) {
A aObject = new A();
aObject.a = 100; // Not suppose to happen as defined by class A, this causes tight coupling.
System.out.println("aObject.a value is: " + aObject.a);
}
}
In the above example, the code that is defined by this kind of implementation uses tight coupling and is very bad since class B knows about the detail of class A, if class A changes the variable 'a' to private then class B breaks, also class A's implementation states that variable 'a' should not be more than 10 but as we can see there is no way to enforce such a rule as we can go directly to the variable and change its state to whatever value we decide.
Output
aObject.a value is: 100
Loose Coupling
Loose coupling is a design goal to reduce the inter-dependencies between components of a system with the goal of reducing the risk that changes in one component will require changes in any other component.
Loose coupling is a much more generic concept intended to increase the flexibility of the system, make it more maintainable and makes the entire framework more stable.
Example:
class A {
private int a = 0;
public int getA() {
System.out.println("getA() method");
return a;
}
public void setA(int aa) {
if(!(aa > 10))
a = aa;
}
}
public class B {
public static void main(String[] args) {
A aObject = new A();
aObject.setA(100); // No way to set 'a' to such value as this method call will
// fail due to its enforced rule.
System.out.println("aObject value is: " + aObject.getA());
}
}
Yukarıdaki örnekte, bu tür bir uygulama tarafından tanımlanan kod gevşek bağlantı kullanır ve B sınıfının kuralların uygulandığı durumunu almak için A sınıfından geçmesi gerektiğinden önerilir. A sınıfı dahili olarak değiştirilirse, B sınıfı iletişim yolu olarak yalnızca A sınıfı kullandığından B sınıfı kesilmez.
Output
getA() method
aObject value is: 0