Wikipedia mówi
„jednostki oprogramowania (klasy, moduły, funkcje itp.) powinny być otwarte na rozszerzenie, ale zamknięte na modyfikację”
Słowo funkcje złapany oczy, a ja teraz zastanawiam się, czy możemy założyć, że tworzenie przeciążenie dla metody można uznać za przykład otwarty / zamknięty zasady czy nie?
Pozwól mi wyjaśnić przykład. Weź pod uwagę, że masz metodę w warstwie usług, która jest używana w prawie 1000 miejscach. Metoda pobiera userId i określa, czy użytkownik jest administratorem, czy nie:
bool IsAdmin(userId)
Teraz rozważ, że gdzieś trzeba ustalić, czy użytkownik jest administratorem, czy nie, na podstawie nazwy użytkownika, a nie identyfikatora użytkownika. Jeśli zmienimy podpis wyżej wspomnianej metody, złamaliśmy kod w 1000 miejscach (funkcje powinny być zamknięte na modyfikacje). W ten sposób możemy utworzyć przeciążenie, aby uzyskać nazwę użytkownika, znaleźć identyfikator użytkownika na podstawie nazwy użytkownika i oryginalną metodę:
public bool IsAdmin(string username)
{
int userId = UserManager.GetUser(username).Id;
return IsAdmin(userId);
}
W ten sposób rozszerzyliśmy naszą funkcję, tworząc dla niej przeciążenie (funkcje powinny być otwarte na rozszerzenie).
Czy to przykład zasady otwartej / zamkniętej?
źródło
Przeciążając metodę rozszerzasz funkcjonalność istniejącego modułu, spełniając tym samym nowe potrzeby Twojej aplikacji
Nie wprowadzasz żadnych zmian w istniejącej metodzie, więc nie naruszasz drugiej reguły.
Chciałbym usłyszeć, co inni mają do powiedzenia na temat niedopuszczania do zmiany oryginalnej metody. Tak, możesz wprowadzić odpowiednie modyfikatory dostępu i wymusić enkapsulację, ale co jeszcze można zrobić?
Patrz: http://www.objectmentor.com/resources/articles/ocp.pdf
źródło
Zasada Otwartego Zamknięcia to cel, idealny przypadek, nie zawsze rzeczywistość. Szczególnie w przypadku refaktoryzacji starego kodu pierwszym krokiem jest często ciężka modyfikacja, aby umożliwić OCP. Podstawą tej zasady jest to, że działający kod już działa, a zmiana prawdopodobnie wprowadza błędy. Dlatego najlepszym scenariuszem nie jest zmiana istniejącego kodu, a jedynie dodanie nowego kodu.
Powiedzmy, że masz funkcję o nazwie
BigContrivedMethod(int1, int2, string1)
.BigContrivedMethod
robi trzy rzeczy: rzecz1, rzecz2 i rzecz3. W tym momencie ponowne użycie BCM jest prawdopodobnie trudne, ponieważ robi za dużo. Przeredagowanie go (jeśli to możliwe) naContrivedFunction1(int)
,ContrivedFunction2(int)
iContrivedFunction3(string)
daje trzy mniejsze, bardziej skoncentrowane metody, które można łatwiej łączyć.I to jest klucz do OCP w odniesieniu do metod / funkcji: kompozycji. „Rozszerzasz” funkcje, wywołując je z innych funkcji.
Pamiętaj, że OCP jest częścią 5 innych zasad, wytycznych SOLID. Ten pierwszy jest kluczem, Single Responsibility. Jeśli wszystko w bazie kodu wykonało tylko jedną konkretną czynność, nigdy nie musiałbyś modyfikować kodu. Wystarczy tylko dodać nowy kod lub połączyć stary kod w nowy sposób. Ponieważ prawdziwy kod rzadko spełnia tę wytyczną, często trzeba go zmodyfikować, aby uzyskać SRP, zanim będzie można uzyskać OCP.
źródło
Jeśli zmieniasz zachowanie programu, pisząc nowy kod, a nie stary, postępujesz zgodnie z zasadą otwartego zamknięcia.
Ponieważ jest całkiem niemożliwe, aby napisać kod, który jest otwarty na każdą możliwą zmianę (a nie chcesz, ponieważ wprowadzasz paraliż analizy), piszesz kod, który reaguje na wszystkie różne zachowania, nad którymi obecnie pracujesz, poprzez rozszerzenie, a nie modyfikację.
Kiedy natrafisz na coś, co musisz zmienić, zamiast po prostu coś zmienić, aby umożliwić nowe zachowanie, zastanawiasz się, jaki jest sens zmiany, zrestrukturyzujesz program bez zmiany jego zachowania, abyś mógł zmienić to zachowanie, pisząc NOWY kod .
Jak to dotyczy twojej sprawy:
Jeśli dodajesz nowe funkcje do swojej klasy, twoja klasa nie jest otwarta / zamknięta, ale klientami funkcji, którą przeciążasz, są.
Jeśli dodajesz po prostu nowe funkcje, które działają w twojej klasie, zarówno ona, jak i klienci twojej funkcji są otwarci / zamknięci.
źródło