Jaka jest różnica między spójnością a sprzężeniem?
W jaki sposób sprzężenie i spójność mogą prowadzić do dobrego lub złego projektu oprogramowania?
Jakie są przykłady ilustrujące różnicę między nimi i ich wpływ na ogólną jakość kodu?
Jaka jest różnica między spójnością a sprzężeniem?
W jaki sposób sprzężenie i spójność mogą prowadzić do dobrego lub złego projektu oprogramowania?
Jakie są przykłady ilustrujące różnicę między nimi i ich wpływ na ogólną jakość kodu?
Odpowiedzi:
Spójność odnosi się do tego, co może zrobić klasa (lub moduł). Niska spójność oznaczałaby, że klasa wykonuje różnorodne działania - jest szeroka, nie koncentruje się na tym, co powinna zrobić. Wysoka spójność oznacza, że klasa koncentruje się na tym, co powinna robić, tj. Tylko na metodach związanych z intencją klasy.
Przykład niskiej spójności:
-------------------
| Staff |
-------------------
| checkEmail() |
| sendEmail() |
| emailValidate() |
| PrintLetter() |
-------------------
Przykład wysokiej spójności:
----------------------------
| Staff |
----------------------------
| -salary |
| -emailAddr |
----------------------------
| setSalary(newSalary) |
| getSalary() |
| setEmailAddr(newEmail) |
| getEmailAddr() |
----------------------------
Jeśli chodzi o sprzężenie , odnosi się do tego, jak powiązane lub zależne są dwie klasy / moduły względem siebie. W przypadku klas o niskim sprzężeniu zmiana czegoś ważnego w jednej klasie nie powinna wpływać na drugą. Wysokie sprzężenie utrudniłoby zmianę i utrzymanie kodu; ponieważ klasy są ze sobą ściśle powiązane, dokonanie zmiany może wymagać przebudowy całego systemu.
Dobry projekt oprogramowania ma wysoką spójność i niskie sprzężenie .
set
& get
ilustrują funkcjonalność, która jest bardziej specyficzna dla kontekstu „Staff” - im wyższa specyficzność, tym przykład daje większą spójność.
Spójność jest wskaźnikiem zależności w module.
Sprzężenie jest wskaźnikiem zależności między modułami.
Spójność
Sprzęganie
sprawdź ten link
Wysoka spójność w modułach i niskie połączenie między modułami są często uważane za związane z wysoką jakością w językach programowania OO.
Na przykład kod w każdej klasie Java musi mieć wysoką spójność wewnętrzną, ale być możliwie luźno powiązany z kodem w innych klasach Java.
Świetny opis tych problemów zawiera rozdział 3 Meyer Object-Oriented Software Construction (2. edycja) .
Spójność wskazuje, w jaki sposób powiązane i skoncentrowane są obowiązki elementu oprogramowania.
Sprzęganie odnosi się do tego, jak silnie element oprogramowania jest połączony z innymi elementami.
Elementem oprogramowania może być klasa, pakiet, komponent, podsystem lub system. Podczas projektowania systemów zalecane jest posiadanie elementów oprogramowania, które mają wysoką kohezję i obsługują niskie sprzężenie .
Niska kohezja powoduje, że klasy monolityczne są trudne do utrzymania, zrozumienia i zmniejszają możliwość ponownego użycia. Podobnie wysokie sprzężenie powoduje, że klasy są ściśle powiązane, a zmiany nie są nielokalne, trudne do zmiany i zmniejszają ponowne użycie.
Możemy przyjąć hipotetyczny scenariusz, w którym projektujemy typowy monitor ConnectionPool
z następującymi wymaganiami. Zauważ, że może to zbytnio wyglądać jak na prostą klasę, ConnectionPool
ale podstawowym celem jest tylko wykazanie niskiego sprzężenia i wysokiej kohezji za pomocą prostego przykładu i myślę, że powinien pomóc.
Przy niskiej spójności moglibyśmy zaprojektować ConnectionPool
klasę, silnie upychając wszystkie te funkcje / obowiązki w jedną klasę, jak poniżej. Widzimy, że ta pojedyncza klasa jest odpowiedzialna za zarządzanie połączeniami, interakcję z bazą danych oraz utrzymywanie statystyk połączeń.
Dzięki wysokiej spójności możemy przypisać tę odpowiedzialność między klasami i uczynić ją łatwiejszą do utrzymania i wielokrotnego użytku.
Aby zademonstrować niskie sprzężenie , będziemy kontynuować ConnectionPool
powyższy schemat wysokiej kohezji . Jeśli spojrzymy na powyższy schemat, chociaż obsługuje on wysoką spójność, ConnectionPool
jest ściśle powiązany z ConnectionStatistics
klasą i PersistentStore
oddziałuje z nimi bezpośrednio. Zamiast tego, aby zmniejszyć sprzężenie, moglibyśmy wprowadzić ConnectionListener
interfejs i pozwolić tym dwóm klasom zaimplementować interfejs i pozwolić im zarejestrować się w ConnectionPool
klasie. I ConnectionPool
będą iterować przez tych słuchaczy i powiadamiać ich o zdarzeniach związanych z uzyskiwaniem i zwalnianiem połączenia, co pozwoli na mniej sprzężenia.
Uwaga / słowo lub przestroga: w tym prostym scenariuszu może to wyglądać na przesadę, ale jeśli wyobrażamy sobie scenariusz w czasie rzeczywistym, w którym nasza aplikacja musi wchodzić w interakcje z wieloma usługami stron trzecich, aby sfinalizować transakcję: Bezpośrednie połączenie naszego kodu z usługami strony trzeciej oznaczałoby to, że wszelkie zmiany w usłudze strony trzeciej mogą spowodować zmiany w naszym kodzie w wielu miejscach, zamiast tego możemy mieć wewnętrzną Facade
interakcję z tymi wieloma usługami, a wszelkie zmiany w usługach stają się lokalne Facade
i wymuszają niskie powiązania z osobą trzecią usługi.
Zwiększona spójność i zmniejszone sprzężenie prowadzą do dobrego projektowania oprogramowania.
Spójność dzieli twoją funkcjonalność tak, aby była zwięzła i zbliżona do istotnych dla niej danych, a oddzielenie zapewnia, że funkcjonalna implementacja jest odizolowana od reszty systemu.
Oddzielenie pozwala zmienić implementację bez wpływu na inne części oprogramowania.
Spójność zapewnia, że wdrożenie bardziej specyficzne dla funkcjonalności, a jednocześnie łatwiejsze w utrzymaniu.
Najbardziej skuteczną metodą zmniejszania sprzężenia i zwiększania spójności jest projektowanie według interfejsu .
To główne obiekty funkcjonalne powinny się „znać” tylko za pośrednictwem interfejsu (interfejsów), które implementują. Wdrożenie interfejsu wprowadza spójność jako naturalną konsekwencję.
Choć w niektórych senariach nie jest to realistyczne, powinno być celem projektu.
Przykład (bardzo szkicowy):
public interface IStackoverFlowQuestion
void SetAnswered(IUserProfile user);
void VoteUp(IUserProfile user);
void VoteDown(IUserProfile user);
}
public class NormalQuestion implements IStackoverflowQuestion {
protected Integer vote_ = new Integer(0);
protected IUserProfile user_ = null;
protected IUserProfile answered_ = null;
public void VoteUp(IUserProfile user) {
vote_++;
// code to ... add to user profile
}
public void VoteDown(IUserProfile user) {
decrement and update profile
}
public SetAnswered(IUserProfile answer) {
answered_ = answer
// update u
}
}
public class CommunityWikiQuestion implements IStackoverflowQuestion {
public void VoteUp(IUserProfile user) { // do not update profile }
public void VoteDown(IUserProfile user) { // do not update profile }
public void SetAnswered(IUserProfile user) { // do not update profile }
}
W niektórych innych miejscach w bazie kodu możesz mieć moduł przetwarzający pytania niezależnie od tego, czym one są:
public class OtherModuleProcessor {
public void Process(List<IStackoverflowQuestion> questions) {
... process each question.
}
}
najlepsze wyjaśnienie kohezji pochodzi z czystego kodu wuja Boba:
Klasy powinny mieć niewielką liczbę zmiennych instancji. Każda z metod klasy powinna manipulować jedną lub większą liczbą tych zmiennych. Zasadniczo im więcej zmiennych manipuluje metoda, tym bardziej spójna jest jej metoda . Klasa, w której każda zmienna jest używana przez każdą metodę, jest maksymalnie spójna.
Zasadniczo nie jest ani wskazane, ani możliwe tworzenie takich maksymalnie spójnych klas; z drugiej strony chcielibyśmy, aby spójność była wysoka . Gdy spójność jest wysoka, oznacza to, że metody i zmienne klasy są współzależne i łączą się razem jako logiczna całość.
Strategia utrzymywania małych funkcji i krótkich list parametrów może czasami prowadzić do mnożenia zmiennych instancji, które są używane przez podzbiór metod. Kiedy tak się dzieje, prawie zawsze oznacza to, że przynajmniej jedna inna klasa próbuje wydostać się z większej klasy. Powinieneś spróbować podzielić zmienne i metody na dwie lub więcej klas, tak aby nowe klasy były bardziej spójne.
po prostu spójność reprezentuje stopień, w jakim część podstawy kodu tworzy logicznie pojedynczą jednostkę atomową. Z drugiej strony sprzężenie reprezentuje stopień, w jakim pojedyncza jednostka jest niezależna od innych. Innymi słowy, jest to liczba połączeń między dwiema lub więcej jednostkami. Im mniejsza liczba, tym niższe sprzęgło.
Zasadniczo wysoka spójność oznacza utrzymywanie części bazy kodu, które są ze sobą powiązane w jednym miejscu. Jednocześnie niskie sprzężenie polega na jak największym oddzieleniu niepowiązanych części podstawy kodu.
Rodzaje kodu z perspektywy spójności i sprzężenia:
Idealny jest kod zgodny z wytycznymi. Jest luźno sprzężony i bardzo spójny. Możemy zilustrować taki kod za pomocą tego obrazu:
Boski Obiekt jest wynikiem wprowadzenia wysokiej kohezji i wysokiego sprzężenia. Jest to anty-wzorzec i zasadniczo oznacza pojedynczy fragment kodu, który wykonuje całą pracę na raz: źle wybrany ma miejsce, gdy granice między różnymi klasami lub modułami są źle wybrane
Niszczycielskie odsprzęganie jest najbardziej interesujące. Czasami zdarza się, gdy programista próbuje rozdzielić bazę kodu tak bardzo, że kod całkowicie traci koncentrację:
czytaj więcej tutaj
Spójność w inżynierii oprogramowania to stopień, w jakim elementy danego modułu należą do siebie. Jest to zatem miara tego, jak silnie powiązany jest każdy element funkcjonalności wyrażony przez kod źródłowy modułu oprogramowania.
Łącząc w prostych słowach, jest to, ile jeden składnik (ponownie, wyobraź sobie klasę, choć niekoniecznie) wie o wewnętrznych działaniach lub wewnętrznych elementach innego, tj. Ile ma wiedzy na temat drugiego elementu.
Napisałem o tym post na blogu , jeśli chcesz przeczytać trochę więcej szczegółów z przykładami i rysunkami. Myślę, że to odpowiada na większość twoich pytań.
spójność odnosi się do tego, jak zaprojektowano jedną klasę. Spójność jest zasadą obiektową, ściśle związaną z zapewnieniem, że klasa została zaprojektowana w jednym, dobrze ukierunkowanym celu. Im bardziej skoncentrowana jest klasa, tym bardziej jej spójność jest większa. Zaletą wysokiej spójności jest to, że takie klasy są znacznie łatwiejsze do utrzymania (i rzadziej zmieniane) niż klasy o niskiej spójności. Inną zaletą wysokiej spójności jest to, że klasy o dobrze ukierunkowanym celu są zwykle bardziej użyteczne niż inne klasy.
Na powyższym zdjęciu widać, że przy niskiej spójności tylko jedna klasa jest odpowiedzialna za wykonanie wielu zadań, które nie są wspólne, co zmniejsza szansę na ponowne użycie i utrzymanie. Ale w wysokiej spójności istnieje osobna klasa dla wszystkich zadań do wykonania określonego zadania, co skutkuje lepszą użytecznością i konserwacją.
Kohezja (kohezja): Co, co oznacza razem , hesion, która oznacza trzymać się . System sklejania się cząstek różnych substancji.
Na przykład z życia: img Dzięki uprzejmości
Całość jest większa niż suma części - Arystoteles.
Kohezja jest porządkowym typem pomiaru i jest zwykle opisywana jako „wysoka kohezja” lub „niska kohezja”. Moduły o wysokiej kohezji są zwykle preferowane, ponieważ wysoka kohezja jest związana z kilkoma pożądanymi cechami oprogramowania, w tym odpornością, niezawodnością, możliwością ponownego użycia i zrozumiałością. Natomiast niska kohezja wiąże się z niepożądanymi cechami, takimi jak trudności w utrzymaniu, testowaniu, ponownym użyciu, a nawet zrozumieniu. wiki
Sprzężenie zwykle kontrastuje ze spójnością . Niskie sprzężenie często koreluje z wysoką kohezją i odwrotnie. Niskie sprzężenie jest często oznaką dobrze skonstruowanego systemu komputerowego i dobrego projektu, a w połączeniu z wysoką spójnością wspiera ogólne cele wysokiej czytelności i łatwości konserwacji. wiki
Myślę, że różnice można przedstawić następująco:
W tym poście na blogu piszę o tym bardziej szczegółowo.
Spójność wskazuje na względną wytrzymałość funkcjonalną modułu.
View Konwencjonalny widok:
„jednomyślność” modułu
Widok OO:
Hesion spójność oznacza, że komponent lub klasa obejmuje tylko atrybuty i operacje, które są ściśle ze sobą powiązane oraz z klasą lub samym komponentem
Evel Poziomy spójności
Funkcjonalny
Ay Warstwa
Komunikacyjny
EquSequential
Roc Procedura
Em Czasowy
Ilityutility
Sprzężenie jest wskaźnikiem względnej współzależności między modułami.
Sprzężenie zależy od złożoności interfejsu między modułami, momentu wprowadzenia lub odwołania do modułu i tego, jakie dane przechodzą przez interfejs.
Widok konwencjonalny: stopień, w jakim komponent jest połączony z innymi komponentami i światem zewnętrznym
Widok OO: jakościowa miara stopnia, w jakim klasy są ze sobą połączone
Poziom sprzężenia
Treść
Omm Często
Kontrola
AmpStamp
Dane
CallPonowne połączenie
Use Wpisz typ
CWłączenie lub import
Zewnętrzny #
Sprzężenie = interakcja / relacja między dwoma modułami ... Spójność = interakcja między dwoma elementami w module.
Oprogramowanie składa się z wielu modułów. Moduł składa się z elementów. Weź pod uwagę, że moduł to program. Funkcja w programie jest elementem.
W czasie wykonywania dane wyjściowe programu są wykorzystywane jako dane wejściowe dla innego programu. Nazywa się to interakcją między modułami lub komunikacją między procesami. Jest to również nazywane sprzężeniem.
W ramach jednego programu dane wyjściowe funkcji są przekazywane do innej funkcji. Nazywa się to interakcją elementów w module. Nazywa się to również Spójnością.
Przykład:
Łączenie = komunikacja między 2 różnymi rodzinami ... Spójność = komunikacja między ojcem-matką-dzieckiem w rodzinie.
Mówiąc najprościej, spójność oznacza, że klasa powinna reprezentować jedną koncepcję.
Publiczny interfejs klasy jest spójny, jeśli wszystkie funkcje klasy są powiązane z koncepcją reprezentowaną przez klasę. Na przykład, zamiast posiadania klasy CashRegister, posiadanie funkcji CashRegister i Monety powoduje, że spójność dzieli ją na 2 klasy - klasę CashRegister i Monet.
W sprzężeniu jedna klasa zależy od drugiej, ponieważ wykorzystuje obiekty klasy.
Problem z wysokim sprzężeniem polega na tym, że może powodować działania niepożądane. Jedna zmiana w jednej klasie może spowodować nieoczekiwany błąd w drugiej klasie i może uszkodzić cały kod.
Ogólnie wysoką kohezję i niskie sprzężenie uważa się za OOP wysokiej jakości.
Termin „ spójność” jest rzeczywiście nieco sprzeczny z intuicją w odniesieniu do tego, co oznacza w projektowaniu oprogramowania.
Wspólnym znaczeniem kohezji jest to, że coś, co dobrze do siebie pasuje, jest zjednoczone, które charakteryzuje się silnym wiązaniem, takim jak przyciąganie molekularne. Jednak w projektowaniu oprogramowania oznacza to dążenie do klasy, która idealnie robi tylko jedną rzecz, więc wiele podmodułów nawet nie jest zaangażowanych.
Być może możemy myśleć o tym w ten sposób. Część ma największą spójność, gdy jest jedyną częścią (robi tylko jedną rzecz i nie można jej dalej rozbić). Jest to pożądane w projektowaniu oprogramowania. Spójność to po prostu inna nazwa „pojedynczej odpowiedzialności” lub „rozdzielenia obaw”.
Pojęcie sprzężenia na ręce jest dość intuicyjne, co oznacza, że moduł nie zależy od zbyt wielu innych modułów, a te, z którymi się łączy, można łatwo zastąpić, na przykład przestrzegając zasady podstawienia Liskova .
1. Przypadkowy 2. Logiczny 3. Czasowy 4. Procedura 5. Komunikacja 6. Odpowiedni 7. Funkcjonalny