Nie mogę zrozumieć pojęcia „luźnego sprzężenia”. Przypuszczam, że nie pomaga to, że słowo „luźne” ma zwykle negatywne konotacje, więc zawsze zapominam, że luźne sprzężenie to dobra rzecz.
Czy ktoś może pokazać jakiś kod (lub pseudokod) „przed” i „po”, który ilustruje tę koncepcję?
oop
language-agnostic
loose-coupling
trebormf
źródło
źródło
Odpowiedzi:
Rozważmy prostą aplikację koszyka na zakupy, która używa klasy CartContents do śledzenia pozycji w koszyku oraz klasy Order do przetwarzania zakupu. Zamówienie musi określić całkowitą wartość zawartości koszyka, może to zrobić w następujący sposób:
Przykład ściśle powiązany:
Zwróć uwagę, jak metoda OrderTotal (a tym samym klasa Order) zależy od szczegółów implementacji klas CartContents i CartEntry. Gdybyśmy spróbowali zmienić tę logikę, aby umożliwić zniżki, prawdopodobnie musielibyśmy zmienić wszystkie 3 klasy. Ponadto, gdybyśmy zaczęli używać kolekcji List do śledzenia przedmiotów, musielibyśmy również zmienić klasę Order.
Oto nieco lepszy sposób na zrobienie tego samego:
Mniej powiązany przykład:
Logika specyficzna dla implementacji pozycji koszyka lub kolekcji koszyka lub zamówienia jest ograniczona tylko do tej klasy. Mogliśmy więc zmienić implementację którejkolwiek z tych klas bez konieczności zmiany innych klas. Moglibyśmy posunąć się jeszcze dalej, ulepszając projekt, wprowadzając interfejsy itp., Ale myślę, że rozumiesz o co chodzi.
źródło
Order
aby mieć jakąkolwiek wiedzę oCart
. Zakupy na żywo i fakturowanie to dwa różne konteksty. Gdy klient jest gotowy do zapłaty, możesz mieć proces odpowiedzialny za przetłumaczenie wpisów koszyka na coś znaczącego dlaOrder
. W ten sposóbOrder
klasa byłaby również instancjonowana i używana bezCart
.CartEntry
iCartContents
. Ponieważ mają one doskonale jasne znaczenie, powinny być po prostu modelowane jako martwe dane. w kategoriach bazy danych wszystko, czego potrzeba, to tabelaCREATE TABLE entry (price INTEGER, quantity INTEGER)
Wiele zintegrowanych produktów (zwłaszcza Apple), takich jak iPody , iPady, jest dobrym przykładem ścisłego połączenia: gdy bateria wyczerpie się, równie dobrze możesz kupić nowe urządzenie, ponieważ bateria jest przylutowana na stałe i nie poluzuje się, co sprawia, że wymiana jest bardzo kosztowny. Luźno spięty odtwarzacz pozwoliłby na bezproblemową wymianę baterii.
To samo dotyczy tworzenia oprogramowania: generalnie (znacznie) lepiej jest mieć luźno powiązany kod, aby ułatwić rozszerzenie i wymianę (oraz ułatwić zrozumienie poszczególnych części). Jednak bardzo rzadko w szczególnych okolicznościach ścisłe połączenie może być korzystne, ponieważ ścisła integracja kilku modułów pozwala na lepszą optymalizację.
źródło
Jako przykładu użyję Javy. Powiedzmy, że mamy klasę, która wygląda następująco:
Kiedy zadzwonię do klasy, będę musiał zrobić coś takiego:
Na razie w porządku. Powiedzmy teraz, że mam inną klasę, która wygląda tak:
Wygląda dokładnie tak samo jak ABC, ale powiedzmy, że działa w sieci zamiast na dysku. A teraz napiszmy taki program:
To działa, ale jest trochę nieporęczne. Mógłbym to uprościć za pomocą takiego interfejsu:
Teraz mój kod może wyglądać tak:
Zobacz, o ile jest to czystsze i łatwiejsze do zrozumienia? Właśnie zrozumieliśmy pierwszą podstawową zasadę luźnego powiązania: abstrakcja. Kluczem jest tutaj zapewnienie, że ABC i XYZ nie zależą od żadnych metod ani zmiennych klas, które je wywołują. Dzięki temu ABC i XYZ mogą być całkowicie niezależnymi API. Innymi słowy, są one „oddzielone” lub „luźno powiązane” z klasami nadrzędnymi.
Ale co, jeśli potrzebujemy komunikacji między nimi? Cóż, wtedy możemy użyć dalszych abstrakcji, takich jak model zdarzeń, aby upewnić się, że kod nadrzędny nigdy nie musi łączyć się z utworzonymi interfejsami API.
źródło
DiskAccessor
iNetworkAccessor
? I dunno no java ...Przepraszamy, ale „luźne połączenie” to nie problem z kodowaniem, ale z projektem. Termin „luźne sprzężenie” jest ściśle powiązany z pożądanym stanem „wysokiej spójności”, będącej przeciwieństwem, ale komplementarnością.
Luźne powiązanie oznacza po prostu, że poszczególne elementy projektu powinny być konstruowane tak, aby zmniejszyć ilość niepotrzebnych informacji, które muszą wiedzieć o innych elementach projektu.
Wysoka spójność jest czymś w rodzaju „ścisłego sprzężenia”, ale wysoka spójność to stan, w którym elementy projektu, które naprawdę muszą o sobie znać, są projektowane tak, aby współpracowały ze sobą czysto i elegancko.
Chodzi o to, że niektóre elementy projektu powinny znać szczegóły dotyczące innych elementów projektu, więc powinny być zaprojektowane w ten sposób, a nie przypadkowo. Inne elementy projektu nie powinny znać szczegółów na temat innych elementów projektu, więc powinny być projektowane w ten sposób, celowo, a nie losowo.
Realizacja tego pozostawiamy jako ćwiczenie dla czytelnika :).
źródło
Ściśle powiązany kod opiera się na konkretnej implementacji. Jeśli potrzebuję listy ciągów w moim kodzie i deklaruję to w ten sposób (w Javie)
to jestem zależny od implementacji ArrayList.
Jeśli chcę to zmienić na luźno powiązany kod, ustawiam odwołanie jako typ interfejsu (lub inny abstrakcyjny).
Uniemożliwia mi to wywołanie jakiejkolwiek metody,
myList
która jest specyficzna dla implementacji ArrayList. Jestem ograniczony tylko do metod zdefiniowanych w interfejsie List. Jeśli później zdecyduję, że naprawdę potrzebuję LinkedList, wystarczy mi zmienić kod w jednym miejscu, w którym utworzyłem nową Listę, a nie w 100 miejscach, w których wykonałem wywołania metod ArrayList.Oczywiście możesz utworzyć wystąpienie ArrayList przy użyciu pierwszej deklaracji i powstrzymać się od używania metod, które nie są częścią interfejsu List, ale użycie drugiej deklaracji sprawia, że kompilator zachowuje uczciwość.
źródło
Stopień różnicy między odpowiedziami tutaj pokazuje, dlaczego byłoby to trudne do zrozumienia, ale mówiąc najprościej, jak mogę to opisać:
Żeby wiedzieć, że jeśli rzucę ci piłkę, to ty możesz ją złapać, naprawdę nie muszę wiedzieć, ile masz lat. Nie muszę wiedzieć, co jadłeś na śniadanie i naprawdę nie obchodzi mnie, kto był twoim pierwszym zakochanym. Muszę tylko wiedzieć, że możesz złapać. Jeśli to wiem, to nie obchodzi mnie, czy to ty, rzucam piłkę do ciebie lub twojego brata.
W przypadku języków niedynamicznych, takich jak C #, Java itp., Osiągamy to za pośrednictwem interfejsów. Powiedzmy, że mamy następujący interfejs:
A teraz powiedzmy, że mamy następujące klasy:
Teraz zarówno CatcherA, jak i CatcherB implementują metodę Catch, więc usługa, która wymaga Catcher, może używać jednego z nich i tak naprawdę nie obchodzi, która to jest. Tak więc ściśle powiązana usługa może bezpośrednio zainicjować przechwyconą tzw
Tak więc CatchService może robić dokładnie to, co zaplanował, ale używa CatcherA i zawsze będzie używać CatcherA. Jest mocno zakodowany, więc pozostaje tam, dopóki ktoś nie przyjdzie i go nie przerobi.
Teraz weźmy inną opcję, zwaną iniekcją zależności:
Tak więc calss, które inicjują CatchService, mogą wykonać następujące czynności:
lub
Oznacza to, że usługa Catch nie jest ściśle powiązana z CatcherA ani CatcherB.
Istnieje kilka innych strategii dla luźnego łączenia usług, takich jak użycie frameworka IoC itp.
źródło
Możesz myśleć o (ścisłym lub luźnym) sprzężeniu jako o ilości wysiłku, jakiej wymagałoby od ciebie oddzielenie określonej klasy od jej zależności od innej. Na przykład, jeśli każda metoda w Twojej klasie miała mały ostatecznie blok na dole, w którym wywołałeś Log4Net w celu zarejestrowania czegoś, powiedziałbyś, że twoja klasa jest ściśle powiązana z Log4Net. Gdyby zamiast tego twoja klasa zawierała prywatną metodę o nazwie LogSomething, która była jedynym miejscem, które wywoływało komponent Log4Net (a inne metody nazywały się zamiast tego LogSomething), to powiedziałbyś, że twoja klasa była luźno powiązana z Log4Net (ponieważ nie zajmie dużo próba wyciągnięcia Log4Net i zastąpienia go czymś innym).
źródło
64BitBob
odpowiedź.Definicja
Zasadniczo sprzężenie to stopień, w jakim dany obiekt lub zestaw obiektów polega na innym obiekcie lub innym zestawie obiektów, aby wykonać swoje zadanie.
Wysokie sprzęgło
Pomyśl o samochodzie. Aby silnik mógł się uruchomić, należy włożyć kluczyk do stacyjki, przekręcić, musi być benzyna, musi pojawić się iskra, tłoki muszą zapalić, a silnik musi ożyć. Można powiedzieć, że silnik samochodu jest silnie sprzężony z kilkoma innymi obiektami. To jest wysokie sprzężenie, ale nie jest to złe.
Luźne powiązanie
Pomyśl o kontrolce użytkownika dla strony internetowej, która jest odpowiedzialna za umożliwienie użytkownikom publikowania, edytowania i przeglądania pewnego rodzaju informacji. Pojedyncza kontrolka może być wykorzystana do umożliwienia użytkownikowi opublikowania nowej informacji lub edycji nowej informacji. Kontrolka powinna mieć możliwość współdzielenia między dwiema różnymi ścieżkami - nową i edytuj. Jeśli formant jest napisany w taki sposób, że potrzebuje jakiegoś rodzaju danych ze stron, które będą go zawierać, można powiedzieć, że jest zbyt silnie powiązany. Formant nie powinien potrzebować niczego ze swojej strony kontenera.
źródło
To dość ogólna koncepcja, więc przykłady kodu nie dadzą pełnego obrazu.
Pewien facet tutaj, w pracy, powiedział mi: „wzory są jak fraktale, można je zobaczyć, gdy się bardzo blisko przybliża, a kiedy przybliża się do poziomu architektury”.
Przeczytanie krótkiej strony Wikipedii może dać ci poczucie tej ogólności:
http://en.wikipedia.org/wiki/Loose_coupling
Jeśli chodzi o konkretny przykład kodu ...
Oto jedno luźne połączenie, z którym ostatnio pracowałem, z rzeczy Microsoft.Practices.CompositeUI.
Ten kod deklaruje, że ta klasa ma zależność od CustomizableGridService. Zamiast bezpośrednio odwoływać się do dokładnej implementacji usługi, po prostu stwierdza, że wymaga ona NIEKTÓREJ implementacji tej usługi. Następnie w czasie wykonywania system rozwiązuje tę zależność.
Jeśli nie jest to jasne, możesz przeczytać bardziej szczegółowe wyjaśnienie tutaj:
http://en.wikipedia.org/wiki/Dependency_injection
Wyobraź sobie, że ABCCustomizableGridService to implementacja, którą zamierzam tutaj podłączyć.
Jeśli zdecyduję się, mogę to wyciągnąć i zastąpić XYZCustomizableGridService lub StubCustomizableGridService bez żadnych zmian w klasie z tą zależnością.
Gdybym bezpośrednio odwołał się do ABCCustomizableGridService, musiałbym wprowadzić zmiany w tym / tych odwołaniach, aby zamienić inną implementację usługi.
źródło
Sprzężenie ma związek z zależnościami między systemami, które mogą być modułami kodu (funkcjami, plikami lub klasami), narzędziami w potoku, procesami serwer-klient i tak dalej. Im mniej ogólne są zależności, tym bardziej stają się „ściśle powiązane”, ponieważ zmiana jednego systemu wymagała zmiany innych systemów, które na nim polegają. Idealną sytuacją jest „luźne sprzężenie”, w którym można zmienić jeden system, a systemy od niego zależne będą dalej działać bez modyfikacji.
Ogólnym sposobem uzyskania luźnego połączenia są dobrze zdefiniowane interfejsy. Jeśli interakcja między dwoma systemami jest dobrze zdefiniowana i przestrzegana po obu stronach, łatwiej będzie zmodyfikować jeden system, zapewniając jednocześnie, że konwencje nie zostaną złamane. W praktyce często zdarza się, że nie tworzy się dobrze zdefiniowanego interfejsu, co powoduje niechlujną konstrukcję i ścisłe połączenie.
Kilka przykładów:
Aplikacja zależy od biblioteki. Przy ścisłym sprzężeniu aplikacja psuje się w nowszych wersjach lib. Google dla nazwy „DLL Hell”.
Aplikacja kliencka odczytuje dane z serwera. Przy ścisłym sprzężeniu zmiany na serwerze wymagają poprawek po stronie klienta.
Dwie klasy współdziałają w hierarchii zorientowanej obiektowo. Przy ścisłym sprzężeniu zmiany w jednej klasie wymagają aktualizacji drugiej w celu dopasowania.
W rurze komunikuje się wiele narzędzi wiersza polecenia. Jeśli są one ściśle powiązane, zmiany w wersji jednego narzędzia wiersza polecenia spowodują błędy w narzędziach odczytujących jego dane wyjściowe.
źródło
Sprzężenie odnosi się do tego, jak ściśle różne klasy są ze sobą połączone. Ściśle powiązane klasy zawierają dużą liczbę interakcji i zależności.
Klasy luźno powiązane są przeciwieństwem, ponieważ ich wzajemne zależności są ograniczone do minimum i zamiast tego polegają na dobrze zdefiniowanych wzajemnych interfejsach publicznych.
Legos, zabawki, które SNAP razem są uważane za luźno połączone, ponieważ można po prostu połączyć razem elementy i zbudować dowolny system. Jednak układanka ma elementy, które są MOCNIE połączone. Nie można wyjąć elementu z jednej układanki (systemu) i włożyć go do innej układanki, ponieważ system (układanka) jest bardzo zależny od bardzo konkretnych elementów, które zostały zbudowane specjalnie dla tego konkretnego „projektu”. Klocki Lego są zbudowane w bardziej ogólny sposób, dzięki czemu można ich używać w Twoim domu Lego lub w moim Lego Alien Man.
Źródła: https://megocode3.wordpress.com/2008/02/14/coupling-and-cohesion/
źródło
Dwa komponenty są silnie sprzężone, gdy zależą od konkretnej implementacji.
Załóżmy, że mam ten kod gdzieś w metodzie w mojej klasie:
Teraz moja klasa zależy od SomeObject i są one silnie powiązane. Z drugiej strony, powiedzmy, że mam metodę InjectSomeObject:
Wtedy pierwszy przykład może po prostu użyć wstrzykniętego SomeObject. Jest to przydatne podczas testowania. Podczas normalnej pracy możesz używać ciężkich, wykorzystujących bazy danych, korzystających z sieci klas itp., Podczas gdy testy przechodzą lekką, próbną implementację. Z ściśle powiązanym kodem nie możesz tego zrobić.
Możesz ułatwić niektóre części tej pracy, używając kontenerów iniekcji zależności. Więcej o DI można przeczytać w Wikipedii: http://en.wikipedia.org/wiki/Dependency_injection .
Czasami łatwo jest posunąć się za daleko. W pewnym momencie musisz uczynić rzeczy konkretnymi, inaczej twój program będzie mniej czytelny i zrozumiały. Więc używaj tej techniki głównie na granicy komponentów i wiedz, co robisz. Upewnij się, że korzystasz z luźnego połączenia. Jeśli nie, prawdopodobnie nie potrzebujesz go w tym miejscu. DI może uczynić twój program bardziej złożonym. Upewnij się, że dokonałeś dobrego kompromisu. Innymi słowy, utrzymuj dobrą równowagę. Jak zawsze przy projektowaniu systemów. Powodzenia!
źródło
Rozważ aplikację systemu Windows z FormA i FormB. FormA jest formą podstawową i wyświetla FormB. Wyobraź sobie, że FormB musi przekazać dane z powrotem do swojego rodzica.
Jeśli zrobiłeś to:
FormB jest ściśle powiązany z FormA. FormB nie może mieć innego elementu nadrzędnego niż typ FormA.
Jeśli, z drugiej strony, miałeś FormB opublikować zdarzenie i zasubskrybowałeś FormA to zdarzenie, to FormB może przekazać dane z powrotem przez to zdarzenie do dowolnego subskrybenta, który ma to zdarzenie. W takim przypadku FormB nawet nie wie, że odzywa się do swojego rodzica; dzięki luźnemu powiązaniu wydarzenie zapewnia po prostu rozmowę z abonentami. Każdy typ może teraz być rodzicem FormA.
rp
źródło
W informatyce jest jeszcze jedno znaczenie „luźnego sprzężenia”, o którym nikt inny tu nie pisał, więc ... Proszę bardzo - mam nadzieję, że oddasz mi kilka głosów, aby nie stracić tego na dnie stosu! Z pewnością temat mojej odpowiedzi należy do jakiejkolwiek wyczerpującej odpowiedzi na pytanie ... To znaczy:
Termin „Loose Coupling” po raz pierwszy pojawił się w informatyce jako termin używany jako przymiotnik dotyczący architektury procesora w konfiguracji wieloprocesorowej. Jego odpowiednikiem jest „ścisłe sprzężenie”. Loose Coupling występuje, gdy procesory nie współdzielą wielu wspólnych zasobów, a Tight Coupling - wtedy, gdy to robią.
Termin „system” może być tutaj mylący, dlatego prosimy o uważne przeanalizowanie sytuacji.
Zwykle, ale nie zawsze, wiele procesorów w konfiguracji sprzętowej, w której istnieją one w jednym systemie (jak w pojedynczych komputerach PC), byłoby ściśle powiązanych. Z wyjątkiem niektórych systemów o bardzo wysokiej wydajności, które mają podsystemy, które faktycznie współdzielą pamięć główną między „systemami”, wszystkie podzielne systemy są luźno powiązane.
Pojęcia ściśle powiązane i luźno powiązane zostały wprowadzone wcześniej wynalezieniem wielowątkowych i wielordzeniowych procesorów, więc terminy te mogą wymagać pewnych towarzyszących im elementów, aby w pełni przedstawić dzisiejszą sytuację. I rzeczywiście, dzisiaj można bardzo dobrze mieć system, który obejmuje oba typy w jeden ogólny system. Jeśli chodzi o obecne systemy oprogramowania, istnieją dwie wspólne architektury, po jednej z każdej odmiany, które są wystarczająco powszechne i powinny być znane.
Po pierwsze, ponieważ o to właśnie chodziło, kilka przykładów systemów luźno powiązanych:
Z drugiej strony, niektóre ściśle powiązane przykłady:
We współczesnych komputerach przykłady działania obu systemów w jednym systemie nie są rzadkością. Weźmy na przykład nowoczesne dwu- lub czterordzeniowe procesory Pentium z Fedorą 9 - są to ściśle powiązane systemy obliczeniowe. Następnie połącz kilka z nich w luźno powiązany klaster Linuksa, a teraz masz zarówno luźne, jak i ściśle powiązane obliczenia! Och, czy nowoczesny sprzęt nie jest wspaniały!
źródło
Mówiąc prostym językiem, luźno powiązane oznacza, że nie zależy to od innego zdarzenia. Wykonuje się niezależnie.
źródło
Kilka długich odpowiedzi. Zasada jest jednak bardzo prosta. Przesyłam oświadczenie otwierające z wikipedii :
„Luźne powiązanie” opisuje odporną relację między dwoma lub więcej systemami lub organizacjami z pewnego rodzaju relacjami wymiany.
Każdy koniec transakcji jasno określa swoje wymagania i przyjmuje niewiele założeń co do drugiego końca ”.
źródło
Proponuję bardzo prosty Test sprzęgania kodu :
Fragment A kodu jest ściśle powiązany z Fragmentem B kodu, jeśli istnieje jakakolwiek możliwa modyfikacja Części B, która wymusiłaby zmiany w Części A w celu zachowania poprawności.
Fragment A kodu nie jest ściśle powiązany z Częścią B kodu, jeśli nie ma możliwości modyfikacji Części B, która spowodowałaby konieczność zmiany Części A.
Pomoże ci to sprawdzić, ile sprzężeń występuje między fragmentami twojego kodu. aby znaleźć uzasadnienie, zobacz ten post na blogu: http://marekdec.wordpress.com/2012/11/14/loose-coupling-tight-coupling-decoupling-what-is-that-all-about/
źródło
Podczas tworzenia obiektu klasy przy użyciu
new
słowa kluczowego w innej klasie, faktycznie robisz ścisłe połączenie (zła praktyka) zamiast tego powinieneś używać luźnego sprzężenia, co jest dobrą praktyką--- A.java ---
--- B.java ---
--- InterfaceClass ---
--- MainClass ---
Wyjaśnienie:
W powyższym przykładzie mamy dwie klasy A i B.
Klasa B implementuje Interface, czyli InterfaceClass.
InterfaceClass definiuje Contract for B, ponieważ InterfaceClass ma abstrakcyjne metody klasy B, do których może uzyskać dostęp każda inna klasa, na przykład A.
W klasie A mamy metodę display, która może poza obiektem klasy implementującej InterfaceClass (w naszym przypadku jest to klasa B). A na tym obiekcie metoda klasy A wywołuje metody display () i getVar () klasy B
W MainClass stworzyliśmy obiekt klasy A i B. Wywołanie metody wyświetlania A poprzez przekazanie obiektu klasy B tj. Objb. Metoda wyświetlania A zostanie wywołana z obiektem klasy B.
Teraz mówię o luźnym sprzężeniu. Załóżmy, że w przyszłości będziesz musiał zmienić nazwę klasy B na ABC, wtedy nie będziesz musiał zmieniać jej nazwy w metodzie wyświetlania klasy B, po prostu utwórz obiekt nowy (klasa ABC) i przekaż go do metody wyświetlania w MailClass. Nie musisz niczego zmieniać w klasie A.
ref: http://p3lang.com/2013/06/loose-coupling-example-using-interface/
źródło
Możesz przeczytać więcej o ogólnej koncepcji „luźnego sprzężenia” .
Krótko mówiąc, jest to opis relacji między dwiema klasami, gdzie każda klasa wie najmniej o sobie i każda klasa może potencjalnie nadal dobrze działać bez względu na to, czy druga jest obecna, czy nie i bez zależności od konkretnej implementacji drugiej klasa.
źródło
Ogólnie rzecz biorąc, luźne powiązanie to 2 podmioty pracujące niezależnie od siebie przy tym samym obciążeniu pracą. Więc gdybyś miał 2 serwery internetowe korzystające z tej samej bazy danych zaplecza, powiedziałbyś, że te serwery internetowe są luźno powiązane. Przykładem ścisłego połączenia może być posiadanie 2 procesorów na jednym serwerze WWW ... te procesory są ściśle powiązane.
Mam nadzieję, że to trochę pomocne.
źródło