Dlaczego wszyscy nienawidzą Active Record? [Zamknięte]


103

W miarę jak coraz więcej uczę się o OOP i zaczynam wdrażać różne wzorce projektowe, wracam do przypadków, w których ludzie nienawidzą Active Record .

Często ludzie mówią, że nie skaluje się dobrze (podając Twittera jako najlepszy przykład) - ale nikt tak naprawdę nie wyjaśnia, dlaczego nie skaluje się dobrze; i / lub jak osiągnąć zalety AR bez wad (w podobny, ale inny sposób?)

Mam nadzieję, że nie przerodzi się to w świętą wojnę dotyczącą wzorców projektowych - wszystko, co chcę wiedzieć, to **** **** konkretnie ****, co jest nie tak z Active Record.

Jeśli nie skaluje się dobrze, dlaczego nie?

Jakie ma inne problemy?


9
Myślę, że generalnie dużo nienawiści i niechęci do wzorców projektowych wiąże się z niewłaściwym użyciem. Ludzie mają tendencję do nadużywania i używania ich w złym kontekście i kończą z bardziej złożonym rozwiązaniem niż oryginał
terjetyl

1
Implementacja modułu Active Record w Ruby bardziej przypomina ORM.
Jimmy T.

1
Istnieje zjawisko społeczne, które polega na tym, że po to, by zyskać uznanie, większe uznanie, wydawać się mądrzejsze i krwawiące, ludzie mają tendencję do mechanicznego powtarzania wszelkich szumów zaprzeczających jakimkolwiek obecnym standardom, modelom, szeroko przyjętym technologiom, myląc je z rewolucyjny postęp do następnej fali.
Andre Figueiredo

Odpowiedzi:


90

Istnieje ActiveRecord the Design Pattern i ActiveRecord the Rails ORM Library , a także mnóstwo podróbek dla .NET i innych języków.

To są różne rzeczy. Przeważnie stosują się do tego wzorca projektowego, ale rozszerzają i modyfikują go na wiele różnych sposobów, więc zanim ktokolwiek powie „ActiveRecord Sucks”, należy go zakwalifikować, mówiąc „który ActiveRecord, jest mnóstwo?”

Jestem zaznajomiony tylko z ActiveRecord Railsów, spróbuję odpowiedzieć na wszystkie skargi, które zostały podniesione w kontekście jego używania.

@BlaM

Problem, który widzę z Active Records polega na tym, że zawsze jest to tylko jedna tabela

Kod:

class Person
    belongs_to :company
end
people = Person.find(:all, :include => :company )

To generuje SQL z LEFT JOIN companies on companies.id = person.company_idi automatycznie generuje powiązane obiekty firmy, więc możesz to zrobić people.first.companyi nie musi trafiać do bazy danych, ponieważ dane są już obecne.

@ pix0r

Nieodłącznym problemem związanym z Active Record jest to, że zapytania do bazy danych są automatycznie generowane i wykonywane w celu zapełnienia obiektów i modyfikacji rekordów bazy danych

Kod:

person = Person.find_by_sql("giant complicated sql query")

Jest to odradzane, ponieważ jest brzydkie, ale w przypadkach, w których po prostu musisz napisać surowy kod SQL, jest to łatwe do zrobienia.

@Tim Sullivan

... i wybierzesz kilka wystąpień modelu, po prostu wykonujesz operację „wybierz * z ...”

Kod:

people = Person.find(:all, :select=>'name, id')

Spowoduje to wybranie tylko kolumn nazwy i identyfikatora z bazy danych, wszystkie inne „atrybuty” w mapowanych obiektach będą po prostu zerowe, chyba że ręcznie przeładujesz ten obiekt i tak dalej.


Potężny! Nie wiedziałem o tej konkretnej funkcji. Kolejny argument za AR, który powinienem umieścić w moim arsenale.
Tim Sullivan

Dołączanie wykracza poza wzorzec Active Record.
Jimmy T.

„Person.find_by_sql” w ogóle nie jest wzorcem Active Record. Jego „rekord aktywny” zawiódł mnie, więc muszę go ręcznie załatać.
magallanes

52

Zawsze uważałem, że ActiveRecord jest dobry do szybkich aplikacji opartych na CRUD, w których Model jest stosunkowo płaski (jak w przypadku niezbyt wielu hierarchii klas). Jednak w przypadku aplikacji ze złożonymi hierarchiami obiektów obiektowych a prawdopodobnie lepszym rozwiązaniem jest DataMapper . Podczas gdy ActiveRecord zakłada stosunek 1: 1 między tabelami a obiektami danych, ten rodzaj relacji staje się nieporęczny w przypadku bardziej złożonych domen. W swojej książce o wzorcach Martin Fowler zwraca uwagę, że ActiveRecord ma tendencję do załamywania się w warunkach, w których twój Model jest dość złożony, i sugeruje DataMapper jako alternatywę.

Przekonałem się, że jest to prawdą w praktyce. W przypadkach, gdy masz dużo dziedziczenia w swojej domenie, trudniej jest zmapować dziedziczenie do RDBMS niż mapowanie powiązań lub kompozycji.

Sposób, w jaki to robię, to posiadanie obiektów „domeny”, do których mają dostęp kontrolery za pośrednictwem tych klas DataMapper (lub „warstwy usług”). Nie odzwierciedlają one bezpośrednio bazy danych, ale działają jako reprezentacja obiektu zewnętrznego dla jakiegoś obiektu ze świata rzeczywistego. Załóżmy, że masz klasę User w swojej domenie i potrzebujesz mieć odniesienia do lub kolekcje innych obiektów, które są już załadowane podczas pobierania tego obiektu User. Dane mogą pochodzić z wielu różnych tabel, a wzorzec ActiveRecord może sprawić, że będzie to naprawdę trudne.

Zamiast bezpośredniego ładowania obiektu User i uzyskiwania dostępu do danych za pomocą interfejsu API w stylu ActiveRecord, kod kontrolera pobiera obiekt User, na przykład wywołując interfejs API metody UserMapper.getUser (). To ten program odwzorowujący jest odpowiedzialny za ładowanie wszystkich powiązanych obiektów z odpowiednich tabel i zwracanie ukończonego obiektu „domeny” użytkownika do obiektu wywołującego.

Zasadniczo dodajesz tylko kolejną warstwę abstrakcji, aby kod był łatwiejszy w zarządzaniu. To, czy Twoje klasy DataMapper zawierają surowy niestandardowy SQL, czy wywołania API warstwy abstrakcji danych, czy nawet same uzyskują dostęp do wzorca ActiveRecord, nie ma tak naprawdę znaczenia dla kodu kontrolera, który otrzymuje ładny, wypełniony obiekt użytkownika.

W każdym razie tak to robię.


5
Wygląda na to, że po prostu nie znasz ActiveRecord. „ActiveRecord zakłada stosunek 1: 1 między tabelami”. Po prostu nie jest to prawda. ActiveRecord ma wszystkie rodzaje niesamowitej magii relacyjnej. Zobacz api.rubyonrails.org/classes/ActiveRecord/Associations/…
tybro0103

16
@ JoãoBragança - być może zamiast sarkastycznego komentarza, mógłbyś właściwie wyjaśnić trudności, które pojawiają się, gdy czyjeś dane są fragmentowane - aby reszta z nas mogła się czegoś nauczyć :)
Taryn East,

11

Myślę, że istnieje bardzo inny zestaw powodów między tym, dlaczego ludzie „nienawidzą” ActiveRecord, a tym, co jest z nim „nie tak”.

Jeśli chodzi o nienawiść, jest dużo jadu na wszystko, co dotyczy Railsów. Jeśli chodzi o to, co jest z nią nie tak, jest prawdopodobne, że jest jak każda technologia i są sytuacje, w których jest to dobry wybór i sytuacje, w których są lepsze możliwości. Sytuacja, w której nie możesz skorzystać z większości funkcji Rails ActiveRecord, z mojego doświadczenia, to sytuacja, w której baza danych jest źle skonstruowana. Jeśli uzyskujesz dostęp do danych bez kluczy podstawowych, z rzeczami, które naruszają pierwszą normalną formę, gdzie istnieje wiele procedur składowanych wymaganych do uzyskania dostępu do danych, lepiej jest użyć czegoś, co jest bardziej zwykłym opakowaniem SQL. Jeśli twoja baza danych jest stosunkowo dobrze zorganizowana, ActiveRecord pozwoli ci to wykorzystać.

Aby dodać do tematu odpowiadanie komentatorom, którzy twierdzą, że rzeczy są trudne w ActiveRecord, z powtórzeniem fragmentu kodu

@Sam McAfee Załóżmy, że masz klasę użytkownika w swojej domenie i musisz mieć wczytane odwołania do lub kolekcje innych obiektów, gdy pobierasz ten obiekt użytkownika. Dane mogą pochodzić z wielu różnych tabel, a wzorzec ActiveRecord może sprawić, że będzie to naprawdę trudne.

user = User.find(id, :include => ["posts", "comments"])
first_post = user.posts.first
first_comment = user.comments.first

Korzystając z opcji dołączania, ActiveRecord pozwala zastąpić domyślne zachowanie ładowania z opóźnieniem.


8

Moja długa i spóźniona odpowiedź, nawet niepełna, ale dobre wyjaśnienie DLACZEGO nienawidzę tego schematu, opinii, a nawet niektórych emocji:

1) wersja skrócona: moduł Active Record tworzy „ cienką warstwę ” „ silnego powiązania ” między bazą danych a kodem aplikacji. Co nie rozwiązuje żadnych problemów logicznych, żadnych problemów, żadnych problemów. IMHO, nie dostarcza ŻADNEJ WARTOŚCI, z wyjątkiem pewnej składniowej cukru dla programisty (który może następnie użyć „składni obiektowej”, aby uzyskać dostęp do niektórych danych, które istnieją w relacyjnej bazie danych). Wysiłek mający na celu zapewnienie programistom komfortu powinien (IMHO ...) lepiej zainwestować w niskopoziomowe narzędzia dostępu do baz danych, np. Niektóre odmiany prostego, łatwego, prostegohash_map get_record( string id_value, string table_name, string id_column_name="id" ) i podobnych metod (oczywiście koncepcje i elegancja znacznie się różnią w zależności od używany język).

2) wersja długa: W każdym projekcie opartym na bazach danych, w którym miałem „koncepcyjną kontrolę” nad rzeczami, unikałem AR i było dobrze. Zwykle buduję architekturę warstwową (prędzej czy później dzielisz oprogramowanie na warstwy, przynajmniej w projektach o średniej i dużej wielkości):

A1) sama baza danych, tabele, relacje, nawet jakaś logika, jeśli pozwala na to DBMS (MySQL również jest teraz dorosły)

A2) Bardzo często jest coś więcej niż tylko magazyn danych: system plików (bloby w bazie danych nie zawsze są dobrą decyzją ...), starsze systemy (wyobraź sobie "jak" będą one dostępne, możliwe jest wiele odmian ... ale to nie o to chodzi ...)

B) warstwa dostępu do bazy danych (na tym poziomie metody narzędziowe, pomoce w łatwym dostępie do danych w bazie danych są bardzo mile widziane, ale AR nie zapewnia tutaj żadnej wartości, z wyjątkiem cukru syntaktycznego)

C) Warstwa obiektów aplikacji: „obiekty aplikacji” czasami są prostymi wierszami tabeli w bazie danych, ale w większości przypadków są złożone obiekty i mają dołączoną wyższą logikę, więc inwestowanie czasu w obiekty AR na tym poziomie jest po prostu bezużyteczne , strata cennego czasu programistów, ponieważ „rzeczywista wartość”, „wyższa logika” tych obiektów i tak musi być zaimplementowana na obiektach AR - z i bez AR! I na przykład, dlaczego chcesz mieć abstrakcję „obiektów wpisów dziennika”? Zapisuje je kod logiki aplikacji, ale czy powinien mieć możliwość ich aktualizacji lub usunięcia? brzmi głupio, a App::Log("I am a log message")niektóre wielkości są łatwiejsze w użyciu niżle=new LogEntry(); le.time=now(); le.text="I am a log message"; le.Insert();. Na przykład: użycie „obiektu wpisu dziennika” w widoku dziennika w aplikacji będzie działać dla 100, 1000 lub nawet 10000 wierszy dziennika, ale prędzej czy później będziesz musiał zoptymalizować - i założę się, że w większości przypadków po prostu użyj tej małej, pięknej instrukcji SQL SELECT w logice aplikacji (co całkowicie łamie ideę AR ...), zamiast zawijać tę małą instrukcję w sztywne, ustalone ramki pomysłów AR z dużą ilością zawijania kodu i ukrywania go. Czas spędzony na pisaniu i / lub budowaniu kodu AR mógł zostać zainwestowany w znacznie sprytniejszy interfejs do czytania list wpisów do dziennika (na wiele, wiele sposobów, nieograniczone są możliwości). Programiści powinni odważyć się wymyślić nowe abstrakcje, aby zrealizować swoją logikę aplikacji, która pasuje do zamierzonej aplikacji, a nie głupio ponownie wdrażać głupie wzorce, brzmi dobrze na pierwszy rzut oka!

D) logika aplikacji - implementuje logikę interakcji obiektów oraz tworzenia, usuwania i wyświetlania (!) Obiektów logiki aplikacji (NIE, zadania te rzadko powinny być zakotwiczone w samych obiektach logiki aplikacji: czy mówi kartka papieru na biurku) masz nazwy i lokalizacje wszystkich innych arkuszy w twoim biurze? zapomnij o "statycznych" metodach wyliczania obiektów, to głupie, zły kompromis stworzony po to, by ludzki sposób myślenia pasował do [nie-całkowicie-AR-podobnych -] Myślenie AR)

E) interfejs użytkownika - cóż, to, co napiszę w kolejnych wierszach, jest bardzo, bardzo, bardzo subiektywne, ale z mojego doświadczenia wynika, że ​​projekty oparte na AR często zaniedbywały część UI aplikacji - czas został zmarnowany na tworzenie niejasnych abstrakcji . W końcu takie aplikacje zmarnowały wiele czasu programistów i sprawiają wrażenie aplikacji tworzonych przez programistów dla programistów, zorientowanych technicznie wewnątrz i na zewnątrz. Koderzy czują się dobrze (ciężka praca w końcu wykonana, wszystko skończone i poprawne, zgodnie z koncepcją na papierze…), a klienci „muszą się tylko nauczyć, że tak musi być”, bo to „profesjonalnie” .. ok przepraszam, błądzę ;-)

Cóż, co prawda, to wszystko jest subiektywne, ale jest to moje doświadczenie (z wyłączeniem Ruby on Rails, może być inaczej i nie mam żadnego praktycznego doświadczenia z tym podejściem).

W płatnych projektach często słyszałem żądanie, aby rozpocząć od tworzenia obiektów „aktywnego rekordu” jako elementu składowego dla logiki aplikacji wyższego poziomu. Z mojego doświadczenia wynika, że ​​częstobył swego rodzaju wymówką dla tego, że klient (w większości przypadków firma zajmująca się tworzeniem oprogramowania) nie miał dobrej koncepcji, szerokiego spojrzenia, przeglądu tego, jaki powinien być ostatecznie produkt. Ci klienci myślą w sztywnych ramach („w projekcie dziesięć lat temu to działało dobrze…”), mogą kształtować byty, mogą definiować relacje encji, mogą rozbijać relacje danych i definiować podstawową logikę aplikacji, ale potem przestają i przekaż ją tobie i pomyśl, że to wszystko, czego potrzebujesz ... często brakuje im pełnej koncepcji logiki aplikacji, interfejsu użytkownika, użyteczności itd., i tak dalej ... brakuje im dużego widoku i brakuje im miłości do szczegóły, i chcą, żebyś podążał tą drogą w rzeczywistości rozszerzonej, ponieważ ... no cóż, to działało w tym projekcie lata temu, dzięki czemu ludzie są zajęci i milczą? Nie wiem Ale „szczegóły” oddzielać mężczyzn od chłopców, czyli ... jak wyglądało oryginalne hasło reklamowe? ;-)

Po wielu latach (dziesięć lat aktywnego doświadczenia w programowaniu), gdy klient wspomina o „wzorcu aktywnego nagrywania”, dzwoni dzwonek alarmowy. Nauczyłem się próbować doprowadzić ich z powrotem do tej niezbędnej fazy koncepcyjnej , pozwolić im pomyśleć dwa razy, spróbować pokazać ich koncepcyjne słabości lub po prostu ich unikać, jeśli nie są rozeznani (w końcu wiesz, klient, który jeszcze nie wie, czego chce, może nawet myśli, że wie, ale nie, lub próbuje za darmo przekazać mi pracę koncepcyjną, kosztuje mnie wiele cennych godzin, dni, tygodni i miesięcy mojego czasu, życie jest zbyt krótkie ...).

W końcu: TO WSZYSTKO jest powodem, dla którego nienawidzę tego głupiego „wzorca aktywnego nagrywania” i robię to i będę tego unikać, kiedy tylko będzie to możliwe.

EDYCJA : nazwałbym to nawet bez wzoru. Nie rozwiązuje żadnego problemu (wzorce nie mają tworzyć cukru syntaktycznego). Stwarza wiele problemów: źródłem wszystkich problemów (wymienionych w wielu odpowiedziach tutaj ..) jest to, że po prostu ukrywa stary dobry, dobrze rozwinięty i potężny SQL za interfejsem, który jest z definicji bardzo ograniczony.

Ten wzór zastępuje elastyczność cukrem syntaktycznym!

Pomyśl o tym, jaki problem rozwiązuje dla Ciebie AR?


1
Jest to wzorzec architektoniczny źródła danych. Może powinieneś przeczytać Wzorce architektury aplikacji korporacyjnych Fowlera? Miałem podobne przemyślenia do twoich przed faktycznym użyciem wzorca / ORM i stwierdzeniem, jak bardzo to uprościło sprawę.
MattMcKnight,

1
Podzielam twoje uczucia. Czuję coś złego, gdy framework nie obsługuje kluczy złożonych ... Unikałem wszelkiego rodzaju ORMów przed SQLAlchemy i często używamy go na niższym poziomie, jako generatora SQL. Implementuje Data Mapper i jest bardzo elastyczny.
Marco Mariani

1
Od dwóch dni jestem zaangażowany w projekt wykorzystujący "state-of-the-art" ORM, być może implementacje są już dojrzałe (w porównaniu z tym, z czym pracowałem kilka lat temu). Może to się zmieni, zobaczymy za trzy miesiące :-)
Frunsi

2
Projekt jest skończony, a wiesz co? ORM nadal jest do bani, straciłem tyle czasu na problemy z mapowaniem, które można łatwo wyrazić w sposób relacyjny na zbiór „kodu zorientowanego obiektowo”. Cóż, oczywiście ORM zapewniał sposoby wyrażania zapytań w rodzaju OOP + SQL-Mix - oczywiście w składni podobnej do OOP - ale zajęło to więcej czasu niż zwykłe napisanie zapytania SQL. Wyciekła abstrakcja, „OOPSQLExperiment” na szczycie OOP - zezwolenie użytkownikom na pisanie SQL w składni OOP było najgorszym pomysłem w historii. Nie, nigdy więcej.
Frunsi

1
Przez wiele lat pisałem surowy SQL do wszystkiego. Rails AR czasami mnie frustruje i w przypadku pasywnych zapytań prawie się z tobą zgadzam, ale oto, co rozwiązuje: 1) odpowiednio utrudnia zapisanie danych, które nie przeszły weryfikacji. 2) Śledzenie zmian w pamięci od czasu ostatniego wystąpienia. 3) Wykorzystanie punktu 2 do zapisania rozsądnych before_savewywołań zwrotnych w celu zachowania spójności w rekordzie 4) after_commitprzechwycenia wyzwalaczy usług zewnętrznych. 5) Dobre DSL do organizowania zmian DDL w zestawy zmian (migracje). (Nadal jest ból, ale brak wzorca jest gorszy, gdy> 1 programista).
Adamantish

6

Niektóre wiadomości wprawiają mnie w zakłopotanie. Niektóre odpowiedzi to „ORM” kontra „SQL” lub coś w tym rodzaju.

Faktem jest, że AR to tylko wzorzec programowania upraszczający, w którym wykorzystujesz obiekty domeny do pisania tam kodu dostępu do bazy danych.

Te obiekty zwykle mają atrybuty biznesowe (właściwości fasoli) i pewne zachowanie (metody, które zwykle działają na tych właściwościach).

AR po prostu mówi „dodaj kilka metod do tych obiektów domeny” do zadań związanych z bazą danych.

I muszę powiedzieć, z mojej opinii i doświadczenia, że ​​wzór mi się nie podoba.

Na pierwszy rzut oka może brzmieć całkiem nieźle. Niektóre nowoczesne narzędzia Java, takie jak Spring Roo, używają tego wzorca.

Dla mnie prawdziwy problem dotyczy tylko OOP. Wzorzec AR zmusza cię w jakiś sposób do dodania zależności od obiektu do obiektów infrastruktury. Te obiekty infraestruktury pozwalają obiektowi domeny na wysyłanie zapytań do bazy danych za pomocą metod sugerowanych przez AR.

Zawsze mówiłem, że dwie warstwy są kluczem do sukcesu projektu. Warstwa usług (w której znajduje się logika biznesowa lub może być wyeksportowana za pomocą jakiejś technologii zdalnej, na przykład usług internetowych) i warstwa domeny. Moim zdaniem, jeśli dodamy pewne zależności (nie są naprawdę potrzebne) do obiektów warstwy domeny w celu rozwiązania wzorca AR, nasze obiekty domeny będą trudniejsze do udostępnienia innym warstwom lub (rzadkim) aplikacjom zewnętrznym.

Implementacja AR w Spring Roo jest interesująca, ponieważ nie opiera się na samym obiekcie, ale na niektórych plikach AspectJ. Ale jeśli później nie będziesz chciał pracować z Roo i będziesz musiał refaktoryzować projekt, metody AR zostaną zaimplementowane bezpośrednio w twoich obiektach domeny.

Inny punkt widzenia. Wyobraź sobie, że nie używamy relacyjnej bazy danych do przechowywania naszych obiektów. Wyobraź sobie, że aplikacja przechowuje nasze obiekty domeny na przykład w bazie danych NoSQL lub po prostu w plikach XML. Czy zaimplementowalibyśmy metody, które wykonują te zadania w naszych obiektach domeny? Nie sądzę (na przykład w przypadku XM dodalibyśmy zależności związane z XML do naszych obiektów domeny ... Naprawdę smutne, myślę). Dlaczego więc musimy implementować metody relacyjnej bazy danych w obiektach domeny, jak mówi wzorzec Ar?

Podsumowując, wzorzec AR może brzmieć prościej i dobrze dla małych i prostych aplikacji. Ale kiedy mamy złożone i duże aplikacje, myślę, że klasyczna architektura warstwowa jest lepszym podejściem.


Witamy w SO. Doceniliśmy twój komentarz, ale to pytanie zostało zamknięte jako nie konstruktywne przez NullUserException w dniu 17 grudnia 2011 o 1:17
Tony Rad

3

Pytanie dotyczy wzorca projektowego Active Record. To nie jest narzędzie orm.

Oryginalne pytanie jest oznaczone tagami rails i odnosi się do Twittera zbudowanego w Ruby on Rails. Framework ActiveRecord w Railsach jest implementacją wzorca projektowego Fowlera Active Record.


2

Główną rzeczą, jaką widziałem w odniesieniu do skarg dotyczących modułu Active Record, jest to, że kiedy tworzysz model wokół stołu i wybierasz kilka instancji modelu, w zasadzie robisz „wybierz * z ...”. Jest to dobre w przypadku edytowania rekordu lub wyświetlania rekordu, ale jeśli chcesz, powiedzmy, wyświetlić listę miast dla wszystkich kontaktów w Twojej bazie danych, możesz zrobić „wybierz miasto z ...” i uzyskać tylko te miasta . Zrobienie tego z Active Record wymagałoby wybrania wszystkich kolumn, ale tylko użycia City.

Oczywiście różne implementacje radzą sobie z tym inaczej. Niemniej jednak jest to jeden problem.

Teraz możesz to obejść, tworząc nowy model dla konkretnej rzeczy, którą próbujesz zrobić, ale niektórzy ludzie twierdzą, że to więcej wysiłku niż korzyści.

Ja kopie „Active Record”. :-)

HTH


2
„Zrobienie tego z Active Record wymagałoby wybrania wszystkich kolumn, ale tylko użycia City”. W rzeczywistości niezwykle łatwo jest określić klauzulę wyboru.
MattMcKnight,

1

Uwielbiam sposób, w jaki SubSonic robi tylko jedną kolumnę.
Zarówno

DataBaseTable.GetList(DataBaseTable.Columns.ColumnYouWant)

lub:

Query q = DataBaseTable.CreateQuery()
               .WHERE(DataBaseTable.Columns.ColumnToFilterOn,value);
q.SelectList = DataBaseTable.Columns.ColumnYouWant;
q.Load();

Ale Linq nadal jest królem, jeśli chodzi o leniwe ładowanie.


1

@BlaM: Czasami po prostu zaimplementowałem aktywny rekord wyniku połączenia. Nie zawsze musi to być relacja Tabela <--> Rekord aktywny. Dlaczego nie „Wynik instrukcji Join” <--> Active Record?


1

Opowiem o Active Record jako wzorcu projektowym, nie widziałem ROR.

Niektórzy programiści nienawidzą Active Record, ponieważ czytają inteligentne książki o pisaniu czystego i schludnego kodu, a te książki stwierdzają, że aktywny zapis narusza zasadę pojedynczej odpowiedzialności, narusza zasadę DDD, że obiekt domeny powinien być upartym ignorantem i wiele innych zasad z tego rodzaju książek .

Po drugie, obiekty domenowe w module Active Record są zazwyczaj 1-do-1 z bazą danych, co może być uważane za ograniczenie w niektórych systemach (głównie n-warstwowych).

To tylko abstrakcyjne rzeczy, nie widziałem rzeczywistej implementacji tego wzorca w Ruby on Rails.


0

Problem, który widzę z Active Records polega na tym, że zawsze jest to tylko jedna tabela. To jest w porządku, o ile naprawdę pracujesz tylko z tą jedną tabelą, ale kiedy pracujesz z danymi, w większości przypadków będziesz mieć gdzieś jakieś sprzężenie.

Tak, łączenie jest zwykle gorsze niż brak łączeń w ogóle, jeśli chodzi o wydajność, ale łączenie zwykle jest lepsze niż „fałszywe” łączenie , najpierw czytając całą tabelę A, a następnie wykorzystując zdobyte informacje do czytania i filtrowania tabeli B.


@BlaM: Masz całkowitą rację. Chociaż nigdy nie korzystałem z modułu Active Record, korzystałem z innych przykręconych systemów ORM (szczególnie NHibernate) i mam dwa poważne zastrzeżenia: głupie sposoby tworzenia obiektów (tj. Plików .hbm.xml, z których każdy otrzymuje skompilowane do własnego zestawu), a wydajność wynikająca z samego ładowania obiektów (NHibernate może przez kilka sekund zwiększyć wydajność pojedynczego rdzenia, wykonując zapytanie, które w ogóle nie ładuje, podczas gdy równoważne zapytanie SQL prawie nie wymaga przetwarzania). Oczywiście nie jest to specyficzne dla Active Record, ale wydaje mi się, że większość systemów ORM (i systemów podobnych do ORM) wydaje się być
TheSmurf

Istnieje wiele alternatyw dla korzystania z plików hbm.xml. Zobacz na przykład NHibernate.Mapping.Attributes i fluent-nhibernate.
Mauricio Scheffer

Jeśli chodzi o wydajność tworzenia obiektów, nigdy nie miałem takich problemów z perfekcją, możesz zapytać o to profilera.
Mauricio Scheffer

@mausch: Nie potrzebujesz profilera. To dość dobrze znany problem. Nie wiem, czy dotyczy to najnowszej wersji (której jeszcze nie używam w pracy). ayende.com/Blog/archive/2007/10/26/…
TheSmurf

4
Użycie komendy: joins lub: include w wynikach IE Customer.find (: all,: include =>: contact,: conditions => "active = 1") spowoduje połączenie SQL, a nie pełne skanowanie tabeli.
Tilendor,

0

Problem z ActiveRecord polega na tym, że zapytania, które generuje automatycznie, mogą powodować problemy z wydajnością.

W końcu wykonujesz kilka nieintuicyjnych sztuczek, aby zoptymalizować zapytania, które sprawiają, że zastanawiasz się, czy pisanie zapytania ręcznie nie byłoby bardziej efektywne czasowo.


0

Chociaż wszystkie inne komentarze dotyczące optymalizacji SQL są z pewnością słuszne, moim głównym zarzutem dotyczącym wzorca aktywnego rekordu jest to, że zwykle prowadzi on do niedopasowania impedancji . Lubię utrzymywać moją domenę w czystości i odpowiednio hermetyzowanej, co zwykle niszczy wszelkie nadzieje związane z aktywnym rekordem.


ActiveRecord w rzeczywistości rozwiązuje problem niedopasowania impedancji, umożliwiając kodowanie w sposób obiektowy w stosunku do schematu relacyjnego.
Mauricio Scheffer

Możesz rozwinąć temat? Ogólny konsensus jest taki, że obiekty modelowane na podstawie relacyjnej bazy danych z definicji nie są zorientowane obiektowo (ponieważ relacyjne bazy danych nie obracają się wokół pojęć OO, takich jak dziedziczenie i polimorfizm).
Kevin Pang

Istnieją trzy znane sposoby odwzorowania dziedziczenia na schemat relacyjny. Ref: castleproject.org/ActiveRecord/documentation/trunk/usersguide/…
Mauricio Scheffer

Myślę, że mylisz projekt Castle Active Record OSS z Active Record jako wzorzec projektowy. Oryginalne pytanie (i moja odpowiedź) odnoszą się do wzorca projektowego. Projekt Castle Active Record ma wypieczone rzeczy, które pomagają w rozwoju obiektu obiektowego, ale sam wzorzec nie.
Kevin Pang

Cytuję Castle'a jako odniesienie. RoR's ActiveRecord implementuje tylko dziedziczenie pojedynczej tabeli ( martinfowler.com/eaaCatalog/singleTableInheritance.html ), ale rozważane są inne strategie ( blog.zerosum.org/2007/2/16/ ... )
Mauricio Scheffer,

0

Spróbuj wykonać wiele do wielu relacji polimorficznych. Nie takie proste. Zwłaszcza, gdy nie używasz chorób przenoszonych drogą płciową.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.