Mam klasę obliczającą roczny dochód netto pracowników. Ma stałą reprezentującą procent podatku. Ale pewnego dnia stawka podatku się zmieniła, więc muszę naprawić kod.
Czy czynność ustalenia tej stałej wskazuje na naruszenie zasady otwartego-zamkniętego , ponieważ postuluje, że klasa powinna być zamknięta na modyfikacje?
object-oriented
object-oriented-design
solid
Analiza Paradisys
źródło
źródło
Odpowiedzi:
OCP można lepiej zrozumieć, myśląc o klasach lub komponentach dostarczonych przez dostawcę A w jakiejś bibliotece czarnej skrzynki, do użytku przez użytkowników B, C i D (zauważ, że to tylko model mentalny, którego używam dla jasności, nie ma znaczenia, czy w rzeczywistości jedynym użytkownikiem klasy jest sam A).
Jeśli B, C i D mogą używać lub ponownie wykorzystywać dostarczone klasy dla różnych przypadków użycia, bez potrzeby modyfikacji kodu źródłowego biblioteki, wówczas komponent spełnia OCP ( w odniesieniu do kategorii przypadków użycia ). Istnieją różne sposoby osiągnięcia tego celu
sprawiając, że klasa będzie dziedziczona (zazwyczaj w połączeniu z wzorcem metody szablonu lub wzorcem strategii)
poprzez zapewnienie „punktów wstrzykiwania” dla wstrzykiwania zależności
przez podanie parametrów konfiguracyjnych dla klasy lub komponentu (na przykład poprzez zastosowanie parametru konstruktora „procent podatku”, jak w twoim przypadku, lub poprzez użycie innego mechanizmu konfiguracji)
może inne środki, w zależności od języka programowania lub ekosystemu
Typowe przykłady, które można znaleźć w podręcznikach, są często pierwszego lub drugiego typu (wydaje mi się, że w oczach autorów tych książek trzeci typ jest zbyt trywialny, aby o nim wspomnieć).
Jak widać, nie ma to nic wspólnego z zabronieniem jakiejkolwiek zmiany kodu źródłowego przez dostawcę A (na przykład w celu naprawy błędów, optymalizacji lub dodawania nowych funkcji w sposób zgodny z poprzednimi wersjami), co jest dość niezwiązane z OCP. OCP polega na tym, jak A projektuje interfejs i ziarnistość komponentów w lib, więc różne scenariusze ponownego użycia (takie jak ponowne użycie z różnymi stawkami podatkowymi) nie wywołują automatycznie wymagań dotyczących zmian.
Tak więc pomimo tego, co powiedziano wam tutaj innym, odpowiedź brzmi wyraźnie „tak” , byłoby to pogwałceniem OCP.
EDYCJA: wydaje się, że ktoś napisał szczegółowy post na blogu na ten temat. Chociaż niektóre jego fragmenty mogłyby być lepiej sformułowane (jak zauważył Derek Elkins), wydaje się, że autor ogólnie podziela mój punkt widzenia, że „spełnienie OCP” nie jest absolutną właściwością, ale czymś, co można ocenić tylko w kontekście pewnych kategorie zmian wymagań.
źródło
Jak mówią inni, idealnie klasa dochodu pracownika pozwoliłaby na parametryzację stałej, uniezależniając tę klasę od tej wartości.
Ostatecznie aplikacja wywołująca może również umożliwiać parametryzację pod kątem konfiguracji zewnętrznej (np. Pliku). Po skonfigurowaniu zewnętrznym możemy zmienić stawkę podatku - choć weź pod uwagę, że jeśli plik konfiguracyjny zostanie odczytany tylko raz przy uruchomieniu, aplikacja będzie musiała zostać ponownie uruchomiona, aby zaktualizowane wartości procentowe podatku zaczęły obowiązywać, więc warto o tym pamiętać umysł. Możemy udostępnić funkcję aplikacji, aby ponownie odczytać konfigurację, gdy jest to zalecane, lub możemy zapewnić bardziej skomplikowany mechanizm, który zauważa, gdy plik konfiguracyjny się zmienia ...
W dłuższej perspektywie może się okazać, że problemy podatkowe wymagają więcej niż tylko procent - na przykład, że pewnego dnia przepisy podatkowe są bardziej złożone i wymagają kilku wartości procentowych i niektórych stałych (np. Kwoty poniżej 10 000 USD opodatkowanej według X%, podczas gdy pozostała część opodatkowana według Y%).
Zasadniczo sugeruje to użycie wzorca strategii, w którym główna klasa, o której mowa, akceptuje obiekt strategii do obliczania podatku.
Różne strategie (oraz stałe% i $) powinny być dostępne z pliku konfiguracyjnego, a teraz dodanie nowej strategii wymaga dodania nowego kodu, ale niekoniecznie aktualizacji istniejącego kodu.
Każda strategia może wiedzieć, jak analizować / interpretować własne argumenty konfiguracji zewnętrznej, a także jak obliczać faktyczny podatek.
Dynamicznie podatek może dodatkowo zależeć od lokalnych ustawień, więc możesz mieć ustawienia regionalne związane z zarobkami lub pracownikami (lub oboma). W konfiguracji zewnętrznej możemy powiązać ustawienia regionalne ze strategią podatkową.
Zobacz także wstrzykiwanie zależności , w którym zarządzamy tymi rzeczami w sposób wyraźny.
źródło
Jeśli musisz zmodyfikować klasę, aby zmienić wartość podatku, wówczas jej konstrukcja rzeczywiście narusza OCP. Odpowiednim projektem, zgodnie z tym, co opisałeś do tej pory, jest przyjęcie przez klasę kalkulatora wartości podatku jako parametru.
Jeśli twoja klasa została utworzona (co oznacza, że nie jest klasą statyczną), czyniąc właściwość klasy zmiennej podatkowej, której wartość jest wprowadzana przez konstruktor, poprawiłbyś również spójność klasy.
Krótko mówiąc, twój obecny projekt uzależnia twoją klasę od stałej wartości, która tak naprawdę nie jest stała (definiowanie stałej jako wartości, która nigdy się nie zmieni bez względu na wszystko, na przykład wartości PI). Narusza OCP. Zmień projekt, aby otrzymać wartość podatku jako argument konstruktora.
źródło
Całkowicie zgadzam się z @Becuzz i chcę po prostu podsumować: OCP polega na znajdowaniu ponownie wykorzystywanych (stąd przydatnych) abstrakcji, które są wstrzykiwane w klasie. Zatem zachowanie klasy jest modyfikowane nie przez zmianę kodu, ale przez zapewnienie jej różnych implementacji. Zostało to wyraźnie wyjaśnione w książce Roberta Martina „ Agile Software Development, Principles, Patterns and Practices ”, sprawdź odpowiedni rozdział „Otwarta zasada”, podrozdział „Abstrakcja jest kluczem”. Wyjaśnia inne błędne przekonanie, że zachowanie można modyfikować tylko przez dziedziczenie. To Bertrand Meyer zaproponował, że w 1988 roku w swojej książce „ Object Objected Software Construction ”, a nie Robert Martin.
źródło
Moim zdaniem nie jest to naruszenie zasady otwartego zamkniętego. Jednak fakt, że coś, co musi się zmienić w czasie (takie jak procent podatku) jest stałą, jest wadą projektową: nie należy zmieniać wartości stałej, ale sposób obsługi procentu podatku. Powinno to być jakieś ustawienie, które można zmodyfikować bez ponownej kompilacji.
źródło