Czas, w którym musisz rozważyć zajęcia, które mają zostać przedłużone, to czas, kiedy planujesz prawdziwe plany na przyszłość. Pozwól, że dam ci prawdziwy przykład z mojej pracy.
Sporo czasu spędzam na pisaniu narzędzi interfejsu między naszym głównym produktem a systemami zewnętrznymi. Gdy dokonujemy nowej sprzedaży, jednym dużym komponentem jest zestaw eksporterów, które są zaprojektowane do uruchamiania w regularnych odstępach czasu, które generują pliki danych szczegółowo opisujące zdarzenia, które miały miejsce tego dnia. Te pliki danych są następnie zużywane przez system klienta.
To doskonała okazja do przedłużenia zajęć.
Mam klasę eksportu, która jest klasą podstawową każdego eksportera. Wie, jak połączyć się z bazą danych, dowiedzieć się, gdzie musiała ostatnio działać, i utworzyć archiwa generowanych plików danych. Zapewnia również zarządzanie plikami właściwości, rejestrowanie i kilka prostych procedur obsługi wyjątków.
Ponadto mam innego eksportera do pracy z każdym rodzajem danych, być może istnieje aktywność użytkownika, dane transakcyjne, dane zarządzania gotówką itp.
Na szczycie tego stosu umieszczam warstwę specyficzną dla klienta, która implementuje strukturę pliku danych, której potrzebuje klient.
W ten sposób podstawowy eksporter bardzo rzadko się zmienia. Eksporterzy podstawowych typów danych czasami się zmieniają, ale rzadko, i zwykle tylko w celu obsługi zmian schematu bazy danych, które i tak powinny zostać rozpowszechnione wśród wszystkich klientów. Jedyną pracą, jaką muszę wykonać dla każdego klienta, jest ta część kodu, która jest specyficzna dla tego klienta. Idealny świat!
Struktura wygląda więc tak:
Base
Function1
Customer1
Customer2
Function2
...
Chodzi przede wszystkim o to, że dzięki takiej architekturze kodu mogę wykorzystać dziedziczenie przede wszystkim do ponownego użycia kodu.
Muszę powiedzieć, że nie mogę wymyślić żadnego powodu, by przejść trzy warstwy.
Wielokrotnie używałem dwóch warstw, na przykład, aby mieć wspólną Table
klasę, która implementuje zapytania do tabel bazy danych, podczas gdy podklasy Table
implementują określone szczegóły każdej tabeli, używając enum
do zdefiniowania pól. Pozwalając enum
implementować interfejs zdefiniowany w Table
klasie sprawia, że wszystkie rodzaje sensu.
Open/Closed principle
, a nieClosed Principle.