Programuj w języku dziedziny
Oryginalny tytuł: Code in the Language of the Domain
Autor: Dan North
Wyobraź sobie dwa fragmenty kodu. Pierwszy:
if (portfolioIdsByTraderId.get(trader.getId())
.containsKey(portfolio.getId())) {...}
Zachodzisz w głowę, co takiego ten kod robi. Wygląda to na pobranie ID z obiektu trader, w celu pobrania mapy z... hmm... mapy map i później sprawdzenie, czy inne ID obiektu portfolio istnieje w zagnieżdżonej mapie. Zachodzisz w głowę jeszcze bardziej. Szukasz deklaracji portfolioIdsByTraderId i znajdujesz to:
Map<int, Map<int, int>> portfolioIdsByTraderId;
Ostatecznie dochodzisz do wniosku, że pewnie jest to coś, co sprawdza, czy handlowiec ma dostęp do poszczególnego portfolio. I oczywiście znajdziesz właśnie taki - albo może podobny-ale-subtelnie-inny - fragment kodu kiedy chodzi o sprawdzenie, czy trader ma dostęp do konkretnego portfolio.
Weźmy inny kod na który mógłbyś się natknąć:
if (trader.canView(portfolio)) {...}
Tutaj nie potrzeba się długo zastanawiać. Nie musisz wiedzieć w jaki sposób działa trader. Być może jest tam wepchnięta jedna z tych map na mapach. Ale to jest interes tradera, nie Twój.
Teraz, z którym kodem wolałbyś pracować?
Kiedyś mieliśmy tylko podstawowe struktury danych: bity, bajty i znaki (w zasadzie same bajty, ale udajmy, że część z nich to litery i znaki interpunkcyjne). Liczby dziesiętne były dość trudne do osiągnięcia, ponieważ 10 jako podstawa naszego systemu liczbowego nie za bardzo chce działać w systemie binarnym. Mieliśmy więc typy zmiennoprzecinkowe o różnych rozmiarach. Później pojawiły się tablice i stringi (po prostu tablice). Następnie stosy i kolejki, tablice hashujące, listy i listy z przeskokami oraz cała masa innych ciekawych struktur danych, które nie istnieją w świecie rzeczywistym. „Informatyka” przyłożyła wiele starań, aby odwzorowywać realny świat w nasze ograniczone struktury danych. Prawdziwi guru pamiętają nawet jak to zrobili.
Później mieliśmy typy definiowane przez użytkownika! No dobra, może nie jest to rewelacja, ale zmieniło to trochę reguły gry. Jeśli Twoja dziedzina zawiera koncepcje takie jak handlowiec i portfolio, możesz modelować je przy pomocy typów nazwanych, powiedzmy: Trader i Portfolio. Ale, co ważniejsze, możesz również modelować relacje między nimi używając terminów z tej dziedziny.
Jeśli nie programujesz używając terminów dziedziny i tworzysz ukryte (czytaj: sekretne) założenia, że ten int identyfikuje handlowca, tymczasem tamten int, o ten, tutaj, identyfikuje portfolio. (Lepiej ich nie pomylić!); jeśli więc masz odwzorować założenie biznesowe („Niektórzy handlarze nie mogą przeglądać niektórych portfolio – jest to nielegalne”) we fragmencie algorytmu - powiedzmy sprawdzasz istnienie relacji w mapie kluczy – to nie pomagasz ludziom z audytu.
Następny programista może nie zdawać sobie sprawy z sekretu, więc czemu nie przedstawić go wyraźnie? Używanie klucza, żeby szukać innego klucza, który przeprowadza sprawdzenie istnienia czegoś tam nie jest specjalnie oczywiste. W jaki sposób ktoś miałby intuicyjnie domyślić się, że kod który odpowiada za regułę biznesową uniknięcia konfliktu jest zaimplementowany?
Tworzenie koncepcji dziedziny explicite w kodzie pozwoli pozostałym programistom zrozumieć intencję kodu dużo łatwiej niż gdyby na siłę rozszerzać algorytm o to, co rozumieją oni w dziedzinie. Oznacza to również, że kiedy model dziedziny będzie ewoluował – a będzie, tak jak Twoje zrozumienie dziedziny – jesteś w dogodnej pozycji, żeby rozbudować kod. Dodając do tego dobrą enkapsulację, są duże szanse, że reguła będzie istniała tylko w jednym miejscu i że będziesz mógł ją tam zmienić, bez konieczności modyfikacji w kodzie, który jest od niej zależny.
Programista, który przyjdzie kilka miesięcy później, aby pracować nad kodem podziękuje Ci. Programistą, który przyjdzie za kilka miesięcy możesz być Ty.
Artykuł został opublikowany na licencji Creative Commons Uznanie Autorstwa 3.0.