Zastanawiam się, czy mogę przełączyć się z Javy na Scalę w projekcie Spring + Hibernate, aby skorzystać z niektórych funkcji Scali, takich jak dopasowanie wzorca, Option i co wydaje mi się ogólnie czystszą składnią. Domyślnie szukałem ORM w ekosystemie Scala i odkryłem, że myśli jak Aktywacja (ale głównie próbuję sprawdzić, czy Hibernacji można używać ze Scalą). Szukając tego, przeczytałem to w dokumentacji Play na temat JPA + Scala.
Ale najważniejsze jest to: czy naprawdę potrzebujesz mapera relacji do obiektów, gdy masz moc funkcjonalnego języka? Prawdopodobnie nie. JPA to wygodny sposób na wyodrębnienie braku mocy Javy w transformacji danych, ale naprawdę źle się czuje, gdy zaczniesz go używać ze Scali.
Nie mam głębokiego zrozumienia, jak używać programowania funkcjonalnego do tworzenia kompletnych aplikacji (dlatego zamierzam używać Scali, aby móc to zrozumieć stopniowo, ponieważ łączy OO + funkcjonalne), więc nie mogę zrozumieć dlaczego nie potrzebowałbym ORM z funkcjonalnym językiem i jakie byłoby funkcjonalne podejście do radzenia sobie z trwałością modelu domeny.
Podejście DDD do logiki biznesowej nadal ma sens w Scali, prawda?
źródło
Odpowiedzi:
Cóż, jedną rzeczą, którą należy zrobić, gdy mamy taką dyskusję, jest wyraźne rozróżnienie między obiektowymi obiektami mapującymi obiekty („ORM”) a warstwami abstrakcji bazy danych . ORM jest rodzajem warstwy abstrakcji bazy danych, ale nie wszystkie warstwy abstrakcji bazy danych są ORM. Jednym z dobrych narzędzi do nauki, aby to zrozumieć, jest popularna biblioteka SQLAlchemy Pythona , która wystawia rachunek jako „zestaw narzędzi SQL i obiektowy obiektowy mapator” (moja pogrubiona czcionka), z myślą, że są to różne rzeczy. Po umieszczeniu go na stronie z kluczowymi funkcjami :
Pierwsza strona opisuje ORM w następujący sposób:
Kluczową ideą ORM jest próba pokonania słynnego niedopasowania impedancji relacyjnej względem obiektu . Oznacza to zdefiniowanie zależności między klasami zdefiniowanymi przez użytkownika a tabelami w schemacie bazy danych oraz zapewnienie automatycznych operacji „zapisywania” i „ładowania” klas aplikacji.
Natomiast warstwy abstrakcji baz danych inne niż ORM są bardziej zaangażowane w relacyjny model danych i SQL, a wcale nie w orientację obiektową. Zamiast więc oferować „odwzorowania” między tabelami i klasami i ukrywać schemat bazy danych przed programistą, mają tendencję do wystawiania bazy danych programistom, ale z lepszymi interfejsami API i abstrakcjami. Na przykład konstruktory zapytań SQL umożliwiają programowe generowanie złożonych zapytań SQL, bez manipulacji ciągami, takich jak ten ( przykład z biblioteki jOOQ dla Java ):
Teraz środowisko Play nie wydaje się być w 100% zgodne z tym, co właśnie opisałem , ale ich argument wydaje się być w tej ogólnej przestrzeni: praca z modelem relacyjnym bezpośrednio zamiast przekładania go na klasy iz powrotem.
Biblioteka jOOQ jest warte studiowania jako kontrapunkt do ORMs. Mają też kilka odpowiednich wpisów na blogu, które warto przeczytać:
źródło
Trudno to wyjaśnić, dopóki nie wykonasz dużo programowania funkcjonalnego. W programowaniu obiektowym dane utknęły w jednym obiekcie i tam pozostają. Ten obiekt jest nieco przekazywany i modyfikowany, ale zazwyczaj zasadniczo pracujesz z tą samą „tożsamością” przez cały okres życia tych danych.
ORM są ogólnie projektowane wokół tego paradygmatu. Pobierasz niektóre dane z bazy danych, przenosisz je do obiektu, potencjalnie modyfikujesz kilka, a kiedy skończysz, nadal masz ten sam obiekt, który możesz zapisać z powrotem do bazy danych.
Programowanie funkcjonalne działa inaczej. Twoje dane nie zachowują jednej tożsamości przez cały okres użytkowania. Dzieli się, kopiuje, udostępnia i przekształca. W pewnym sensie przepływa przez szereg funkcji, a następnie zostaje ponownie złożony w potrzebną formę wyjściową. Aby każdy interfejs API bazy danych wydawał się naturalny w języku funkcjonalnym, musi to wziąć pod uwagę, a JPA tego nie robi.
źródło
W scali nadal przydatne jest mapowanie tabel bazy danych na obiekty, a jest na to kilka sposobów.
Jednym z popularnych frameworków w świecie Scali jest zręczny . To nie jest ORM, ponieważ robi mniej (a mianowicie nie pobiera relacji bez wyraźnego polecenia łączenia).
Więc nadal odwzorowujesz obiekty na wiersze bazy danych, ale twoje obiekty są niezmienne (stąd brak opróżniania stanu) i jawnie wykonujesz zapytania za pomocą monadycznej DSL. W rezultacie otrzymujesz wiele „dobrych” części ORM bez problemów związanych ze zmiennością i nieprzewidywalnymi problemami N + 1.
Należy zauważyć, że ludzie odnieśli wielki sukces, używając znacznie cieńszych bibliotek, takich jak anorm lub prosty JDBC, wykorzystując funkcjonalne techniki, aby zachować piękny kod.
Jedną fantastyczną biblioteką, która stosuje techniki funkcjonalne na JDBC, jest również doobie .
Masz więc wiele opcji dostępu do bazy danych, ale Hibernacja (która wydaje się być de facto ORM) nie jest jedną z najlepszych, ponieważ jest tendencyjna do zmienności.
źródło
Nie potrzebujesz ORM nawet w językach zorientowanych obiektowo.
Po pierwsze, kto powiedział, że twoje dane powinny być fizycznie skopiowane z twojego trwałego miejsca przechowywania do twojego obiektu? Alan Kay , człowiek stojący za Smalltalk, chciał, aby obiekty pozbyły się danych . Zasugerował, że obiekt może mieć odniesienie tylko do pewnego obszaru, w którym przechowywane są jego dane.
Po drugie - jaki jest najlepszy sposób na osiągnięcie tego? Zalecam identyfikowanie obiektów według ich obowiązków i nie myślenie o posiadanych przez nich danych. Jeśli słyszałeś o zbliżaniu się do kart CRC, to właśnie do tego służy.
I na koniec, na wypadek, gdybyś kiedykolwiek powrócił do pola OO, oto sposób na jego wdrożenie .
źródło