Czy pogwałcenie zasady otwartego i zamkniętego aktualizowania stałej reprezentującej rzeczywistą wartość?

10

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?

Analiza Paradisys
źródło
10
Oprogramowanie zmienia się, ponieważ zmienia się świat rzeczywisty. Z drugiej strony ustalenie stałej stawki procentowej nie jest tak samo naruszeniem zasady otwartej, jak i ignoranckiej. Procent podatku to oczywisty element, który należy zmienić w czasie wykonywania.
Richard Chambers,
4
Całkowicie zgadzam się z Richardem. Jeśli musisz zmienić kod, aby naprawić tę „stałą”, OCP to najmniejszy problem.
Robert Harvey,
3
To, co stanowi naruszenie OCP, jest wysoce subiektywne, a i tak całość jest nieco przestarzała (ponieważ dziedziczenie implementacji nie jest już najlepszą praktyką). Jest to typowe pytanie, w którym musisz odgadnąć, co myśli osoba zadająca pytanie.
Robert Bräutigam,
2
@DocBrown: co stanowi „nowy wymóg”? Pokazujesz mi kod, mogę wskazać nowe wymagania, które na pewno będą wymagać zmiany kodu, niezależnie od tego, jak dostosujesz go do OCP. Wróćmy zatem do pytania: jeśli programista zapytał o to eksperta biznesowego i nie było żadnych oczekiwań, że stawka podatkowa zmieni się więcej niż raz na kilka lat, nie ma sensu konfigurować jej ani wstrzykiwać. Po prostu zachowaj prostotę i przygotuj się na to, co wiesz . I dla tych rzeczy, oczywiście, uczyń to zewnętrznym dla klasy. Więc to zależy .
Robert Bräutigam,
1
@ RobertBräutigam: chodzi mi o to, że IMHO nie ma czegoś takiego jak „zgodność OCP”, jest tylko „zgodność OCP w kontekście niektórych kategorii wymagań”. Z pewnością może być pewna subiektywność, do których kategorii składnik powinien być „zgodny z OCP”. Ale w przypadku opisanym w tym pytaniu, w moim rozumieniu, zmieniony wymóg został już zidentyfikowany, tak więc ta „klasa obliczania dochodu” wyraźnie nie spełnia OCP w kontekście tego konkretnego wymogu.
Doc Brown,

Odpowiedzi:

14

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ń.

Doktor Brown
źródło
OK, więc OCP polega na zapewnieniu rozszerzalnego zachowania dla różnych przypadków użycia za pomocą jednego z trzech wymienionych przez ciebie środków, prawda? Ale co, jeśli przykład PO sugeruje, że coś fundamentalnego wkrótce się zmieni? Nie wiem z jakiego kraju pochodzi OP, ale w moim kraju stawka podatkowa nie zmienia się zbyt często. To był kiepski przykład, ale może został celowo wyodrębniony w sposób ciągły, aby podkreślić ten punkt. Jestem prawie pewien, że nie miał być konfigurowalny ani rozszerzalny. Być może więc pytanie dotyczyło „nie ma to nic wspólnego z zakazaniem jakiejkolwiek zmiany kodu źródłowego przez część A”.
Vadim Samokhin
Przynajmniej tak to zrozumiałem. Biedny facet, który usunął zaakceptowaną odpowiedź, zrobił to chyba tak. Widziałeś to z nieco innej perspektywy - rozumiem twój punkt widzenia i zgadzam się z tym. Wygląda jednak na to, że najmądrzejszy komentarz przekazał @Robert Bräutigam. Do tej pory nie zdawałem sobie sprawy, że OCP jest TO subiektywne.
Vadim Samokhin,
1
Wydaje mi się, że jeśli kiedykolwiek zostanie mi zadane to samo pytanie, należy odpowiedzieć na jedno pytanie: „czy to zachowanie powinno zostać w jakiś sposób rozszerzone lub skonfigurowane?”. Jeśli tak, to bezpośrednia modyfikacja samej klasy stanowi naruszenie OCP. Jeśli nie - OCP po prostu nie ma zastosowania w tej sytuacji.
Vadim Samokhin
1
@Zapadlo: Myślę, że jeśli komponent spełnia wymagania OCP dla klasy wymagań, nie jest to zbyt subiektywne - w większości przypadków jest całkiem jasne, czy nowe wymaganie wymaga modyfikacji kodu źródłowego komponentu, czy też komponent obsługuje to wymaganie ". Możliwe podejścia do wdrożenia nie są ograniczone do pierwszych 3 środków, które wymieniłem, zobacz moją edycję. Twoje pojęcie podmiotowości może być spowodowane, ponieważ OCP ma po prostu mylącą nazwę i jest dość źle wyjaśniony w wielu podręcznikach.
Doc Brown
Moje pojęcie subiektywności spowodowane było tym, że nie do końca zrozumiałem, co powiedziałeś - ale chyba teraz rozumiem. Bardzo dziękuję za wnikliwe komentarze i odpowiedź.
Vadim Samokhin,
4

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.

Erik Eidt
źródło
1
Pytanie nie brzmiało, czy to zły pomysł zakopać w kodeksie procent podatku, jestem pewien, że jest to oczywiste dla większości z nas (w tym PO). Pytanie brzmiało: „czy to narusza OCP?” Więc nie rozumiem, jak twoja odpowiedź odnosi się do tego pytania.
Doc Brown,
1

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.

Christopher Francisco
źródło
0

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.

Vadim Samokhin
źródło
-2

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.

Zalomon
źródło
„Wada projektowa” polega na tym, że narusza zasadę otwartego zamknięcia, ponieważ trzeba ponownie skompilować kod, aby zmienić stałą?
Erdrik Ironrose,