2009-03-27 13 views
7

Utrzymywanie luźno powiązanych klas jest ważnym aspektem pisania kodu, który jest łatwy do zrozumienia, modyfikacji i debugowania - rozumiem. Jako początkujący, prawie w każdej chwili wychodzę poza najprostsze przykłady, z którymi walczę.Luźne praktyki sprzęgania i OO dla początkujących

Rozumiem, mniej więcej, jak mogę hermetyzować ciągi, liczby całkowite i proste typy danych w klasach własnych. Kiedy jednak zaczynam zajmować się takimi informacjami jak formatowanie tekstu sformatowanego, rzeczy stają się naprawdę skomplikowane - chyba że po prostu użyję różnych metod już obecnych w komponencie. Aby kontynuować ten przykład, załóżmy, że pisałem coś, co zawierało komponent noty RTF w interfejsie użytkownika. W Delphi komponent ma wbudowane metody do robienia rzeczy, takich jak zapisywanie sformatowanego tekstu. Ponadto czasami wydaje się, że jedynymi (lub przynajmniej najlepszymi) sposobami pracy z tekstem RTF są same metody wbudowane w komponent.

W jaki sposób (lub dlaczego) wykonałbym całą pracę związaną z zapisywaniem, ładowaniem i formatowaniem tekstu w innej klasie, gdy już posiadam komponent, który robi to wszystko dla mnie?

Na własną rękę zwykle kończę: (a) robienie czegoś, co wydaje się bardziej skomplikowane niż potrzeba, wymyślanie już istniejących metod lub (b) tworzenie słabo wykonanych klas, które są nadal ściśle ze sobą powiązane. Jak mówią w informa- cjach: "Musi istnieć lepszy sposób!"

Po prostu zagubiłem się koncepcyjnie, jak działa ten "lepszy sposób". jakieś pomysły?

Odpowiedz

5

Wydaje mi się, że brakowało Ci podstawowych pojęć.

Pomysł na OOP rozpoczyna się od dyskretnych, wielokrotnego użytku jednostek logiki. Z naciskiem na tworzenie samowystarczalnych modułów.

W przypadku komponentu Memo RTF spełnia on powyższe kryteria, przetwarzając dany zestaw danych (notę) w taki sposób, że program i inne obiekty w programie nie obchodzą go, jak to działa praca. Jego celem jest pokazanie interfejsu, zaakceptowanie danych, manipulowanie konkretnymi danymi i przekazanie tych danych do innej części programu.

Ideą bycia loosely coupled jest po prostu zastąpienie tej kontrolki memo innym sterowaniem, które spełnia te same specyfikacje interfejsu. Mianowicie, aby można było utworzyć instancję, pozwolić użytkownikowi na interakcję z nią i wyciągnąć dane w razie potrzeby.

Być luźno związanym idzie w parze z ideą Separation of Concerns (SoC); jest to proces łamania programu na różne funkcje w celu ograniczenia nakładania się funkcji i ułatwienia zarządzania. Ale to nie to samo. Incydentalnie, był to także jeden z głównych czynników, które spowodowały odejście od proceduralnego stylu programowania w OOP. Ponieważ OOP wymusza na programowaniu myślenie w kategoriach powiązanych i dyskretnych funkcji.

Wygląda na to, że naprawdę pytasz o SoC.

Istnieje wiele sposobów na osiągnięcie SoC. Czasem wymaga to oddzielenia interfejsu użytkownika, logiki przetwarzania i warstw persistant (weź pod uwagę na przykład wzorzec projektowania MVC). Czasami po prostu utrzymywanie powiązanych ze sobą funkcji w celu zmniejszenia złożoności; którą kontrolka RTF już robi, zawierając wszystkie funkcje niezbędne do manipulowania danymi, abyś nie miał kolejnych zależności.

0

Cóż, nie jestem do końca jasny na ten temat, ale wygląda na to, że wzór strategii będzie tutaj działał.

Utwórz obiekt na podstawie macierzystego obiektu RTF, ale ustaw metody obsługi do przechowywania itp. Jako obiekty zdefiniowane przy użyciu własnych metod.

Umożliwia to moc kompozycji bez ścisłego dziedziczenia wszystkich metod macierzystych i nie trzeba budować dużego niestandardowego obiektu, wystarczy zastąpić potrzebne metody.

5

Proponuję dwie koncepcje, interfejsy i wtrysk zależności, jako sposób na rozdzielenie zajęć. Interfejsy umożliwiają zdefiniowanie umowy lub zestawu oczekiwanych zachowań niezależnych od implementacji. Kiedy masz klasę zależną od interfejsu, a nie od klasy, masz swobodę podstawiania innych klas, które implementują interfejs, bez konieczności przepisywania klasy, która jest od niego zależna.

Gdy używasz interfejsów z wtryskiem zależności, tj. Nadasz klasie rzeczywistą implementację, nad którą ma pracować, zamiast tworzyć samodzielną implementację, uzyskasz jeszcze większe oddzielenie w swojej aplikacji. Teraz klasa wie tylko o interfejsie i nawet nie wie, jak go utworzyć, po prostu go używaj. Wstrzyknięcie zależności często stosuje się w przypadku kreacyjnych wzorców, takich jak Builder lub Factory, gdzie lokalizujesz konstrukcję obiektów w jednej klasie, tak że tylko ta klasa wymaga zmiany, gdy rozszerzasz aplikację o dodatkowe klasy.

Pamiętaj również, że sprzężenie (i jego bliźniak, spójność) jest miarą względną. Nie można wyeliminować wszystkich sprzężeń, a obiekty nie będą mogły wchodzić w interakcje. Konieczny jest pewien poziom zależności. Musisz to zrównoważyć z łatwością użycia i implementacją.

Co do konkretnego przykładu, trudno powiedzieć, bez rzeczywistego kodu. Podejrzewam, że nadużywasz rozwiązania i naruszasz zasadę DRY (nie powtarzaj się). Być może trzeba będzie spojrzeć na sposoby korzystania z interfejsów i być może lekkie opakowanie, aby oddzielić klasy od komponentu, a nie na pełną reimplementację.

+0

Nie, w Delphi bardziej prawdopodobne jest niewystarczające –

0

Wybrany przez Ciebie przykład jest dość złożony.

Masz rację mówiąc, że komponent pamięci rtf jest bardzo luźno sprzężony. Tak luźno, że praktycznie nie można go rozszerzyć i można go używać tylko tak, jak jest, ponieważ zawiera on widok/widok, kontroler i model.

Jeśli chcesz zobaczyć przykład dobrze zaprojektowanego, rozszerzalnego systemu tekstu sformatowanego, zajrzyj do dokumentacji OS X text system (lub Gnustep, jeśli chcesz przeczytać kod). Jest złożony, ponieważ istnieje wiele decyzji projektowych, które muszą zostać podjęte i muszą być ukryte w jednym module. Tam możesz bezpośrednio pracować w dobrej strukturze.

Komponent rtf notatka ma ograniczony zakres zastosowania, co może trzeba obejść stosując dobrze zaprojektowanych klas:

  • załadunku i zapisywanie danych komponentów tylko sens, jeśli nie trzeba zapisać inne dane w twoim programie w tym samym pliku/db.
  • Nie obsługuje również dużych ilości danych.
  • I tylko rozumie mały podzbiór rtf.