tło
Czytam książkę „Czysty kod” i równolegle pracuję nad obiektami kalistenicznymi Kata, takimi jak konto bankowe, i utknąłem na tej zasadzie:
Dziewiąta zasada dotycząca obiektów kalistenicznych polega na tym, że nie używamy getterów ani seterów.
Wydaje się to całkiem zabawne i zgadzam się z tą zasadą. Ponadto na stronie 98-99 Czystego kodu autor wyjaśnia, że pobierający / ustawiający łamią abstrakcję i że nie musimy pytać o nasz obiekt, ale musimy powiedzieć o tym naszemu obiektowi.
Ma to dla mnie doskonały sens i całkowicie zgadzam się z tą zasadą. Problem pojawia się w praktyce.
Kontekst
Na przykład mam aplikację, w której muszę wymienić niektórych użytkowników i wyświetlić szczegółowe informacje o użytkownikach.
Mój użytkownik składa się z:
-> Name
--> Firstname --> String
--> Lastname --> String
-> PostalAddress
--> Street --> String
--> PostalCode --> String
Problem
Jak mogę to zrobić lub co mogę zrobić, aby uniknąć osób pobierających, gdy muszę tylko wyświetlić prostą informację ( i muszę potwierdzić, że nie potrzebuję dodatkowej operacji na tym konkretnym polu ), aby wyświetlić wartość imienia w prostym ( wsparcie losowe)?
Co przychodzi mi na myśl
Jednym z rozwiązań jest wykonanie:
user.getName().getFirstName().getStringValue()
Co jest totalnie okropne, łamanie wielu zasad obiektów kalistenicznych i łamanie Prawa Demeter.
Innym może być coś takiego:
String firstName = user.provideFirstnameForOutput();
// That would have called in the user object =>
String firstName = name.provideFirstnameForOutput();
// That would have called in the name object =>
String firstName = firstname.provideFirstnameForOutput();
Ale nie czuję się komfortowo z tym rozwiązaniem, które wydaje się być jedynie „akcesorium wyższego rzędu”, takim jak ominięcie standardowego gettera / setera za pomocą metody, która ma jedynie na celu dopasowanie prawa Demeter ...
Dowolny pomysł ?
źródło
Jednym z kierunków myślenia byłoby zapewnienie ogólnej funkcji składowej łańcucha znaków zamiast zapewniania dostępu do surowych danych. Coś takiego:
Widzisz, dzięki takiemu podejściu nie jesteś ograniczony jedynie do dostarczania pełnych danych takimi, jakie są, możesz zapewnić środki do transformacji danych w wygodny i znaczący sposób. Na przykład może być konieczne rozegranie lew z przypadkiem postaci:
Możesz także zdefiniować niektóre powszechnie używane, być może złożone formaty, więc możesz na przykład powiedzieć
Piękno tego podejścia polega na tym, że utrzymuje on poszczególne ciągi wewnątrz
User
klasy, a jednocześnie zapewnia znacznie większą funkcjonalność kodowi wywołującemu. Minusem jest jednak to, że musisz wdrożyć mechanizm szablonów, wformatDescription()
którym będzie kilka linii kodu.W związku z tym może to być całkowita przesada: nigdy nie zapominaj, że zasady programowania są jedynie wytycznymi. I ilekroć przestrzeganie innej zasady narusza zasadę KISS, najlepiej zrobić to w prosty sposób. Tak więc, chyba że potrzebujesz przynajmniej takiego elementu formatującego, nie zawracałbym sobie głowy jego implementacją ze względu na prostotę, stosując podejście oparte na akcesoriach.
źródło
User
obiektu jest parsowanie i kompilowanie / interpretacja języka szablonów?User
klasa sama musi wdrożyć tę funkcjonalność. Gdybym miał tylko dwie klasy, które potrzebowałyby takiej funkcjonalności, mógłbyś postawić się na mnie, biorąc pod uwagę mechanizm zamiany szablonów na własną klasę. Ma to być przykład tego, jak można podnieść abstrakcję, któraUser
zapewnia więcej niż tylko kontener danych. I wierzę, że o to właśnie chodzi w tym, żeby unikać akcesorów: robić OOP zamiast obsługiwać kilkastruct
s.