2011-08-02 14 views
5

Ostatnio czytałem i spotkałem się z prawem Demeter. Teraz niektóre z tego, co przeczytałem, mają doskonały sens, np. gazeciarz nigdy nie powinien być w stanie przebić się przez kieszeń klientów, chwycić portfel i wyjąć pieniądze. Portfel to coś, nad czym klient powinien mieć kontrolę, a nie paperboy.Prawo Demeter and OOP confusion

Co rzuca mi się na prawo, może po prostu nie rozumiem tego wszystkiego, jest tak, że właściwości ciągnienia wraz z dziedzicznością funkcjonalności/informacji mogą być tak użyteczne. na przykład Klasa HTTPContext .NETs.

Would not kod, na przykład:

If DataTable.Columns.Count >= 0 Then 
    DataTable.Columns(0).Caption = "Something" 
End If 

Albo

Dim strUserPlatform as string = HttpContext.Current.Request.Browser.Platform.ToString() 

Albo

If NewTerm.StartDate >= NewTerm.AcademicYear.StartDate And 
    NewTerm.EndDate <= NewTerm.AcademicYear.EndDate Then 
    ' Valid, subject to further tests. 
Else 
    ' Not valid. 
End If 

być złamanie tego prawa? Pomyślałem (być może błędnie), że punktem OOP było po części zapewnienie dostępu do powiązanych klas w ładnej strukturze heirarchicznej.

lubię, na przykład, pomysł o przedstawieniu zestawu narzędzi narzędzie, które może być wykorzystywane przez klas stronie, aby uniknąć powtarzających się zadań, takich jak wysyłanie e-maili i enkapsulacji użytecznych metod wyrażenie:

Dim strUserInput As String = "London, Paris, New York" 
For Each strSearchTerm In Tools.StringManipulation.GetListOfString(strUserInput, ",") 
    Dim ThisItem As New SearchTerm 
    ThisItem.Text = strSearchTerm 
Next 

Wszelkie klarowność byłoby wspaniale ... w tej chwili nie mogę pogodzić się z tym, jak prawo wydaje się wyganiać własności i metody strunowe ... wydaje mi się dziwne, że należy zlekceważyć tak wielką moc? Jestem całkiem nowy w OOP, jak niektórzy z was mogli się domyślić, więc proszę jechać łatwo :)

+5

Te "prawa" nie są prawdziwymi prawami. W przeciwieństwie do zasad termodynamiki można je zginać i łamać, kiedy tylko chcesz. Aby powstrzymać się od obłędu, spróbuj pomyśleć o tym, jako o "wskazówce" Demeter, jeśli będziesz postępował zgodnie z tym, co religijne, skończysz pracować dla niego, nie robiąc tego dla ciebie. Wszystkie rzeczy z umiarem ... W tym umiar. –

+0

^--------- To! – Dan

+0

Dziękuję Binary :) –

Odpowiedz

6

Co prawo Demeter (również "Prawo Demeter dla funkcji/metod") chce zmniejszyć mówiąc "używaj tylko jednej kropki" to to, że w metodzie nie powinieneś zakładać tak dużego kontekstu od dostarczone argumenty. Zwiększa to zależność klasy i czyni ją mniej sprawdzalną.

To nie znaczy, że nie można używać wszystkich powyższych przykładów, ale sugeruje, że zamiast dawać metoda klientowi, który następnie uzyskuje dostęp do portfela i pobiera pieniądze od niego:

function getPayment(Customer customer) 
{ 
    Money payment = customer.leftpocket.getWallet().getPayment(100); 
    ... 
    // do stuff with the payment 
} 

że zamiast tylko przekazać co gazeciarz musi metody i jako takie zmniejszyć zależność dla metody, jeśli jest to możliwe:

function getPayment(Money money) 
{ 
    // do stuff with the payment 
} 

Twoje korzyści z niego będzie, że Ci nie zależy od klienta, aby mieć portfel w lewa kieszeń, ale zamiast tego tylko proces s pieniądze, które klient ci daje. To decyzja, którą musisz oprzeć na indywidualnym przypadku. Mniej zależności pozwala na łatwiejsze testowanie.

+0

Dziękuję za to, to ma dla mnie sens, że obiekt nie powinien wiedzieć zbyt wiele o innym obiekcie, gdy nie jest to konieczne. Na podstawie pierwszego przykładu inne klasy, takie jak narzędzie do czyszczenia okien, które może zostać dodane do tego systemu w przyszłości, będą musiały mieć tę samą instrukcję Money payment = customer.leftpocket.getWallet(). GetPayment (100), chyba że zrobisz to, co sugerujesz i daj klientowi metodę getPayment na początek. –

+0

+1:^--------- That! w rzeczy samej :) –

3

Myślę, że zastosowanie prawa Demeter do poszczególnych klas jest nieco za daleko. Myślę, że lepszą aplikacją jest zastosowanie jej do warstw w kodzie. Na przykład warstwa logiki biznesowej nie powinna potrzebować dostępu do niczego na temat kontekstu HTTP, a warstwa dostępu do danych nie musi uzyskiwać dostępu do niczego w warstwie prezentacji.

Zazwyczaj jest to dobra praktyka polegająca na zaprojektowaniu interfejsu obiektu, dzięki czemu nie trzeba wykonywać wielu połączeń łańcuchowych, ale wyobraź sobie ohydnie złożony interfejs, który można uzyskać, gdybyś próbował to zrobić. DataTable i HttpContext klas, które podałeś jako przykłady.

+0

Zgadzam się z tym, że przy projektowaniu klas, takich jak przykładowy papiernik, należy zachować ostrożność, aby nie mieć sytuacji, w której to, co powinno być funkcją klienta staje się częścią gazeciarza, zgadzam się również, że warstwy powinny być przechowywane rozdzielone w sposób, który sugerujesz. –

1

Prawo nie mówi, że nie powinno się mieć dostępu do jakichkolwiek informacji w klasie, ale że powinien on mieć dostęp do informacji tylko w taki sposób, aby nie można go było łatwo nadużywać.

Można na przykład nie dodawać kolumny w tabeli danych poprzez przypisanie nic do nieruchomości Count:

DataTable.Columns.Count = 42; 

Zamiast użyć metody obiektu Columns który pozwala dodać kolumnę w sposób Add że są tam wszystkie potrzebne informacje o kolumnie, a także, aby tabela danych została skonfigurowana z danymi dla tej kolumny.