Wzorzec Table Data Gateway – dostęp do bazy

Dziś przyjrzymy się wzorcowi  Table Data Gateway. To najprostszy i bardzo często używany wzorzec projektowy przy dostępie do bazy. Dziś już nieco archaiczny ale nadal spotykany w legacy code.

Table Data Gateway

Sens tego wzorca jest podobny do wzorca „Fasada” (Facade). Dostarcza nam jednego interfejsu do operacji na tabeli (lub całej bazie). Nie musimy już pisać kodu SQL (lub CQL czy innego). Wszystkim zajmuje się jedna klasa.

Tworzymy jeden obiekt (klasę, lub singleton), który służy jako biblioteka metod. Każda z funkcji przyjmuje parametry i powoduje odczytanie lub modyfikację tabeli w bazie. Przykładowo dla bazy samochodów możemy stworzyć model (przykłady jak zwykle w PHP):

class CarsStorage {
   public function getCar($id) { ... }
   public function addCar($name, $model, $engine) { ... }
   public function setCar($id, $name, $model, $engine) { ... }
   public function deleteCar($id) { ... }
   public function setName($id,$name) { ... }
   public function getByName($name) { ... }
   public function getCarOwnerDrivingLicenceNo($carId) { ... }
   ...
}

Tylko od nas zależy jakie stworzymy metody. Mogą być proste operacje CRUD jak i bardziej skomplikowane. Walidacja, obliczanie danych, wyjątki – mamy wolną rękę w zarządzaniu tabelą. Możemy nawet pobierać dane z kilku tabel lub modyfikować kilka naraz.

Chodzi o to, aby zamknąć cały SQL wewnątrz klasy. Nikt poza naszą klasą nie powinien wykonywać żadnych operacji SQL. Klient wywołuje jedynie nasze metody. Jeden model powinien zajmować się jednym zagadnieniem (czymkolwiek ono jest – zobacz artykuł o zasadzie jednej odpowiedzialności).

Nasze metody mogą być bardzo ogólne, np. mogą to być settery i gettery dla poszczególnych pól. Mogą też być specyficzne dla danego zagadnienia jak ostatnia metoda w przykładzie.

Jeśli dane zagadnienie (albo domena w DDD) obejmuje kilka ściśle ze sobą związanych tabel to również możemy zamknąć je w tej jednej klasie. Powyżej metoda pobiera numer prawa jazdy właściciela auta. Prawdopodobnie musi sięgnąć do innej tabeli aby znaleźć tą osobę i jej dokument.

Ten wzorzec często widzimy w aplikacjach. Pozwala on zamknąć działanie bazy wewnątrz obiektu. Na zewnątrz wystawiaamy gotowe metody. Dzięki temu, gdy baza się zmieni, wystarczy zmienić metodę, sam interfejs pozostaje bez zmian.

Wady Table Data Gateway

Duża ilość kodu to pierwsza wada tego wzorca. Jeśli robimy metody specyficzne dla domeny, musimy napisać je dla każdej reguły biznesowej. Takie modele rosną z czasem. Dopisujemy coraz to nowe metody. W końcu okazuje się, że klasa ma dziesiątki lub setki metod a zarządzanie nimi jest koszmarem. Niektórzy określają to jako „śmietnik metod„.

Brak struktury danych to kolejna wada. Metody często są implementowane jak się podoba programiście. Getter zwróci nam tabelę lub obiekt. Setter przyjmie w parametrach listę pól. Rzadko spotykamy spójny sposób komunikacji z taką klasą.

Wymieszanie odpowiedzialności to też problem. Czasem klasa zajmuje się np. konwersją kodowania, excapowaniem kodu. Czasem nie. Nie jesteśmy pewni dopóki nie sprawdzimy w dokumentacji (jeśli jest) lub wprost w kodzie.

Testowanie takiej klasy może być małym koszmarem. Skąd mamy wiedzieć, czy wywołanie jednej metody nie robi „jeszcze czegoś”? Dla dobrych testów musimy sprawdzać pełną strukturę i zawartość bazy przed i po każdym teście.

Do czego używać?

Wzorca Table Data Gateway możemy używać jedynie do bardzo małych projektów. Jeśli wady nie przeszkadzają, aplikacja nie będzie rosnąć z czasem to używanie lepszych, większych wzorców może być wytaczaniem armaty na wróble. Gdy mamy tylko kilka – dwie, trzy, pięć metod i wiemy, że nie będzie ich więcej, ten wzorzec może być dobry. Zaleta to mały kod bez nadmiaru klas, interfejsów, dziedziczenia itp.

 

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *