Przejdź do treści

DevStyle - Strona Główna
Kilka słów o tabelach w obiektowym świecie – ORM czy SQL?

Kilka słów o tabelach w obiektowym świecie – ORM czy SQL?

Rafał Hryniewski

24 września 2018

Backend

Jakie języki programowania przewijają się najczęściej w ofertach pracy? Cokolwiek, w czym jesteś w stanie stworzyć jakiś back-end, nieśmiertelny JS i niemalże równie wszechobecny SQL tego lub innego sortu.

Na rozmowie czasem zdarzy nam się odpowiedzieć na pytanie dotyczące where’ów, selectów i innych joinów i… bywa, że jest to ostatni raz, gdy masz do czynienia w SQL-em w tej konkretnej firmie.

Słowem wstępu

Założę, że programujesz obiektowo. W takim razie niemalże na pewno zdarzyło Ci się stanąć przed wyborem bibliotek w momencie tworzenia rozwiązania lub przeglądać stos technologiczny istniejącego projektu. Myślę, że się nie pomylę, jeżeli napiszę, że w większości, jeśli nie we wszystkich przypadkach przed Twoimi oczami mignął jakiś ORM. Czasem okazuje się też, że SQL jest wymagany tylko i wyłącznie dlatego, że ten konkretny maper stoi nad tą, a nie inną technologią bazodanową.

Pozwól jednak, że nieco odejdę od tematu i się przedstawię, bo prawdopodobnie nie mieliśmy jeszcze okazji się poznać. Nazywam się Rafał Hryniewski i na co dzień pracuję z technologiami Microsoftu – głównie o nich będę Ci opowiadał. Goszczę tu po raz drugi, wliczając cykl „Wasze Historie”. Tym razem planuję zostać na dłużej i zająć się tematyką baz danych z perspektywy programisty obiektowego lub osoby, która nigdy wcześniej nie pracowała z bazą danych. Pokażę Ci, jak ogarnąć podstawy, jakie narzędzia masz do wyboru i jakie są ich mocne oraz słabe strony, jak podejrzeć i zabrać się za optymalizację tego, co wypluje z siebie Entity Framework, i wiele innych rzeczy, o których możesz nie wiedzieć, jeśli za bardzo nie wychylasz się zza używanego przez Ciebie ORM-a. Postaram się, by co jakiś czas dać Ci coś ciekawego do przeczytania niezależnie od tego, czy dopiero zaczynasz z bazami danych, czy masz już z nimi trochę doświadczenia.

Ale ja programuję obiektowo!

Wróćmy do tematu. Moim zdaniem bardzo mocno zaniedbaliśmy znajomość technologii bazodanowych. Pewnie, możemy napisać parę klasek, nadać kilka atrybutów, odpalić migrację i wszystko śmiga, baza stoi, ma nawet jakąś sensowną strukturę. To o wiele szybsze rozwiązanie niż składanie tabel do kupy ręcznie, zastanawianie się nad typami danych dla każdej kolumny i różne inne „pierdoły”. Podobnie sprawa ma się z pisaniem zapytań do naszej bazy – niby po co mielibyśmy męczyć się z czystym SQL-em w stringach, skoro możemy użyć doskonale znanego nam LINQ (w przypadku C#)?

Programujesz obiektowo? Jeśli tak, to jestem przekonany, że czujesz się o wiele bardziej komfortowo w świecie obiektów i kolekcji niż tabel i rekordów. Mogło Ci się też zdarzyć strukturyzować dane w bazie, myśląc o nich w kontekście klas, kolekcji i biorąc pod uwagę zasady pisania czystego kodu. Jak jednak mają się dobre praktyki obiektowe do dobrych praktyk bazodanowych? Najczęściej nijak i jeśli tylko wszystko będzie działać, to gdy liczba rekordów skoczy nam do kilkuset tysięcy lub więcej, możemy się obudzić z poważnymi problemami z wydajnością.

W SQL-u też należy dbać o porządek!

Wspomniałem o czystym kodzie. Niepokojącym mnie zwyczajem jest bezpośrednie mapowanie tabel na model obiektowy i działanie bezpośrednio na nim. Czy jest w tym coś złego? A nie brakuje Ci może jakiejkolwiek sensownej warstwy abstrakcji między bazą danych a DAL-em (data access layer)? Kilka drobnych zmian w bazie i dane mogą przestać się modyfikować albo odczytywać.

Co możemy zrobić? Tak samo jak w kodzie obiektowym posługujemy się np. interfejsami do wystawienia publicznych metod, tak w SQL-u możemy skorzystać z trzech różnych widoków zawierających wyłącznie dane specyficzne dla – powiedzmy – użytkownika, klienta i adresata paczki, używając w nich jednej tabeli Users. Podobnie możemy zrobić z przeróżnymi procedurami i funkcjami, a wszystko to ładnie zmapować w naszym ORM-ie.

Czy jest to bardziej pracochłonne? Tak. A co zyskujemy? Przede wszystkim to, że tak długo, jak nasz widok czy funkcja poprawnie zwraca dane w określonej strukturze, nie musimy się martwić o tym, jak to wszystko składane jest pod spodem do kupy. Mieliśmy plątaninę joinów, którą zastąpiliśmy implementacją grafów w SQL Server? Wystarczy, że przepiszemy kod naszego widoku i wszystko pozostanie w jak najlepszym porządku. Ba, możemy sobie pozwolić na całkiem spore optymalizacje, denormalizację w celu uproszczenia formy odczytywanych danych czy co jeszcze przyjdzie nam do głowy. A wiesz, co jest najpiękniejsze? Widoki, procedury i funkcje same w sobie na ogół nie przechowują danych, ich modyfikacje są błyskawiczne i nie wymagają zatrzymywania aplikacji.

Świat, którego nie znasz

Sam SQL zawiera mnóstwo narzędzi, które mogą Ci znacząco ułatwić życie. Zdarzyło Ci się kiedyś pisać skomplikowane wersjonowanie treści w kodzie obiektowym? SQL Server 2016 i wyższe mają funkcję zwaną Temporal Tables, która ogarnia wersjonowanie out of the box. Podobnie ma się sprawa z aplikacjami multi-tenant i row level security, maskowaniem danych, konstruktami znanymi z grafowych baz danych czy otwieraniem JSON-ów jako tabele. SQL potrafi zrobić naprawdę bardzo dużo z naszymi danymi, trzeba się z nim tylko troszeczkę zapoznać i przede wszystkim zgłębić jego możliwości.

O praktycznie każdym z elementów, które wymieniłem gdzieś wyżej, można stworzyć oddzielny wpis. O niektórych nawet kilka. Dlatego też nie opiszę ich wszystkich w tym miejscu – jeśli ciekawi Cię jakiś konkretny temat, daj znać w komentarzu, a postaram się napisać o tym coś więcej. Chciałem Ci tylko pokazać, że na tym poziomie istnieje naprawdę wiele rzeczy, o których można nie wiedzieć, jeśli wszystko przesłaniają Ci różowe okulary z ORM-ów. Nieco więcej na ten temat opowiadałem chociażby na swojej sesji na tegorocznym 4 Developers, nagranie możesz obejrzeć poniżej, a z prezentacją pewnie od czasu do czasu wyskoczę w Polskę, więc może nawet spotkamy się na żywo.

To w końcu używać czy nie?

Tytuł tego wpisu jest pytaniem, a ja wciąż nie udzieliłem na nie odpowiedzi. Wychwalam SQL-e pod niebiosa, płaczę, jakie te ORM-y są ubogie. Myślę, że doskonale wiesz, że odpowiedź brzmi jak zwykle: to zależy. Ja osobiście niemalże nie używam ORM-ów w swoich projektach, ale… czasem mi się zdarza i pracuję z nimi na co dzień, więc przydaje mi się wiedza o tym, co dokładnie leci do bazy danych po użyciu kilku metod w LINQ.

Używanie zarówno ORM, jak i czystego SQL ma swoje wady i zalety. Development np. z takim Entity Frameworkiem jest niesamowicie szybki, a szlifowanie procedur i widoków z każdej zbędnej milisekundy z pewnością nie jest zadaniem dla każdego (i – co ważniejsze – istotnym w każdym projekcie!) i może sprawić, że terminy realizacji staną się nierealne. Oba podejścia mają swoje wady, ale za najgorsze z nich uważam to trzecie, w którym zamykamy się na jakąś opcję dla zasady. „ORM to smutny syf i nie użyję go nawet do CRUD-a”, ”Nie dotknę SQL-a – jestem programistą obiektowym”.

Na tytułowe pytanie musisz odpowiedzieć samodzielnie. Pamiętaj jednak, że jeśli dobrze skonstruujesz swojego SQL-a, to raczej nie zaistnieje potrzeba przepisania go na jakiegokolwiek ORM-a, zwłaszcza jeśli zadbasz o odpowiednią abstrakcję po stronie bazy danych. I myślę, że to tego tematu możesz się ode mnie spodziewać w najbliższym czasie – jakich narzędzi użyć, by zbudować solidną warstwę abstrakcji między Twoją aplikacją a Twoją bazą.

To… o czym chcesz poczytać w przyszłości?

Zobacz również