Czy wzorzec ActiveRecord jest zgodny z zasadami projektowania SOLID?

43

Interesuje mnie, czy wzór ActiveRecord, rozsławiony przez Ruby on Rails, zachęca lub zniechęca do korzystania z zasad projektowania SOLID .

Na przykład wydaje mi się, że obiekty ActiveRecord zawierają zarówno logikę domeny, jak i logikę trwałości, co stanowi naruszenie zasady pojedynczej odpowiedzialności.

nicholaides
źródło
6
Jim Weirich, pod koniec swojej SOLID Ruby Talk na konferencji Ruby 2009, pyta publiczność: „Obiekty ActiveRecord implementują koncepcję domeny i koncepcję trwałości. Czy to narusza SRP (Single Responsibility Principle)?” Publiczność zgadza się, że narusza SRP. Jim pyta, czy to im przeszkadza. Wielu członków publiczności mówi tak. Dlaczego? Utrudnia to testowanie. To sprawia, że ​​obiekt uporczywości jest znacznie cięższy.
David J.

Odpowiedzi:

56

Istnieje pewna ważna krytyka na ActiveRecord. Jak zawsze wujek Bob podsumowuje to idealnie :

Problem, który mam z Active Record, polega na tym, że wprowadza zamieszanie na temat tych dwóch bardzo różnych stylów programowania. Tabela bazy danych to struktura danych. Wystawił dane i nie zachował się. Ale rekord aktywny wydaje się być obiektem. Ma „ukryte” dane i ujawnione zachowanie. Umieszczam słowo „ukryty” w cudzysłowie, ponieważ dane w rzeczywistości nie są ukryte. Prawie wszystkie pochodne ActiveRecord eksportują kolumny bazy danych za pośrednictwem akcesoriów i mutatorów. Rzeczywiście, rekord aktywny ma być używany jak struktura danych.

Z drugiej strony wiele osób umieszcza metody reguł biznesowych w swoich klasach Active Record; co sprawia, że ​​wydają się obiektami. To prowadzi do dylematu. Po której stronie linii przypada Active Record? Czy to obiekt? Czy jest to struktura danych?

Wikipedia podsumowuje krytykę w kwestii testowalności :

W OOP koncepcja enkapsulacji jest często sprzeczna z koncepcją oddzielenia problemów. Ogólnie rzecz biorąc, wzorce sprzyjające rozdzieleniu problemów są bardziej odpowiednie do izolowanych testów jednostkowych, podczas gdy wzorce sprzyjające enkapsulacji mają łatwiejsze w użyciu interfejsy API. Active Record zdecydowanie sprzyja enkapsulacji do tego stopnia, że ​​testowanie bez bazy danych jest dość trudne.

Specjalnie dla implementacji Ruby on Rails Gavin King pisze (moje wyróżnienie):

W tym momencie większość programistów myśli, ok, więc skąd mam wiedzieć, jakie atrybuty ma firma, patrząc na mój kod? I w jaki sposób moje IDE może je automatycznie uzupełniać? Oczywiście, ludzie Railsów mają szybką odpowiedź na to pytanie. Och, po prostu uruchom klienta bazy danych i zajrzyj do bazy danych! Następnie, zakładając , że znasz zasady automagicznej kapitalizacji i pluralizacji ActiveRecord / doskonale /, będziesz w stanie odgadnąć nazwy atrybutów własnej klasy firmowej i wpisać je ręcznie.

Również o implementacji Ruby on Rails John Januszczak pisze (moje wyróżnienie ):

PROBLEM # 1: METODY STATYCZNE

...

Niektórzy twierdzą, że stosowanie metod statycznych jest po prostu programowaniem proceduralnym, a zatem jest złym projektem obiektowym. Inni twierdzą, że metody statyczne to śmierć dla testowalności.

PROBLEM # 2: GLOBALNE USTAWIENIA KONFIGURACJI

...

Dlatego w moim przykładzie nie ma zastrzyku zależności od klasy konta, a przez to od instancji konta. Jak wszyscy powinniśmy już wiedzieć, szukanie rzeczy jest bardzo, bardzo złe!

Kilka dodatkowych informacji na temat tego, dlaczego ActiveRecord i ORM są ogólnie uważane za anty-wzorzec:

ActiveRecord zawsze wydawał się niezwykle użytecznym anty-wzorcem , ale zgadzam się, że jest to sprzeczne z SRP, a ponadto, że jest sprzeczne z zasadą inwersji zależności.

Yannis
źródło
WAŻNA aktualizacja dla Rails 5+: „A jak moje IDE może je automatycznie uzupełnić? Oczywiście, ludzie Railsów mają szybką odpowiedź na to pytanie. Och, po prostu uruchom klienta bazy danych i zajrzyj do bazy danych!”. już. Dzięki atrybutom API możesz zdefiniować wszystkie dostępne kolumny w modelu
Filip Bartuzi
6

(Zakładam, że klasa ActiveRecord jest implementowana bez żadnej możliwości wstrzyknięcia zależności).

Z własnego doświadczenia mogę powiedzieć, że wzorzec ActiveRecord staje się główną przeszkodą w pisaniu testów jednostkowych. Sprzężenie warstwy trwałości i logiki biznesowej w pojedynczej „klasie ActiveRecord” uniemożliwia napisanie testów jednostkowych (chyba że najpierw dokonamy refaktoryzacji). Dlatego jedyną opcją jest pisanie testów integracyjnych; i to nie jest tak skuteczne jak testy jednostkowe. Staje się to poważnym problemem, szczególnie jeśli przejmiesz projekt z dużą ilością klas ActiveRecord; poddaje się bardzo skomplikowanym testom integracji, które są trudne do utrzymania.

Tak więc ActiveRecord jest bardzo podobny do SRP i powoduje pewne bóle głowy związane z konserwacją; zdaje się odbierać moc pisaniu testów jednostkowych.

Guven
źródło