O mnieBlogGitHub

Marten - dole i niedole

30 April, 2020 - 4 min read

Jest sobie taka biblioteka o nazwie Marten, która umożliwia korzystanie z bazy PostgreSQL jako bazy dokumentowej albo bazy do event sourcingu - w aplikacji .NET. (Co ciekawe, jest współautorem - a przynajmniej jednym z tych, którzy obecnie ją utrzymują - jest nasz krajan, Oskar Dudycz). Jeśli Ty lub ktoś w Twoim zespole rozważa jej użycie - przeczytajcie kilka przestróg.

Dlaczego ludzie wpadają na taki pomysł? Wiadomo, event sourcing, NoSQL - to wszystko brzmi fajnie i modnie. Kolejny argument - jeśli działasz na Azure, to fakt, że baza PostgreSQL jest tańsza od MS (sic!) oraz, że nie ma "z pudełka" innych baz NoSQL (typu MongoDB - co nie jest do końca prawdą): to wszystko może być kuszące. No i jeszcze do tego pokusa - robimy mikroserwisy, więc czemu nie zrobić w każdym serwisie innej bazy danych? ;)

A teraz na serio - jeśli chcesz robić event sourcing, to ta biblioteka brzmi ciekawie i może pozwolić łatwo zrobić event store. Ja tego nie sprawdzałem, więc się nie wypowiem. W ogóle mam jednak takie wrażenie, że autorzy oryginalnie chcieli zrobić po prostu event store na PostgreSQL, więc potrzebowali do tego document store - żeby trzymać eventy jako dokumenty. Tak więc niejako przy okazji możemy sobie za pomocą Martena zrobić po prostu bazę dokumentową. I tu zaczynają się schody.

Technicznie rzecz biorąc od kilku wersji PostgreSQL posiada typ danych JSON (w także JSONB - czyli JSON z informacją o typach). Marten przykrywa to dla nas w ten sposób, że po prostu dla każdego obiektu (dokumentu) tworzy wiersz w odpowiedniej tabelce, gdzie oprócz kolumny z właściwymi JSON-owymi danymi, jest kilka kolumn z metadami (choćby identyfikator). To brzmi na pierwszą myśl dziwnie, ale gdybyśmy mieli to implementować sami, to szybko przyznamy: dobrze, że tę pracę ktoś wykonał za nas.

Gdy wczytamy się w dokumentację, dowiemy się, że z tej roboty wykonanej za nas - to nawet ktoś zaimplementował Linq. Tak więc - wydawałoby się - bomba! Po prostu Entity Framework dla bazy dokumentowej. Tak więc podpinamy NuGeta, tworzymy projekt i... zaczynają się schody. Niestety, dokumentacja przedstawia najprostsze przykłady, o ograniczeniach milczy albo wspomina zdawkowo. Tymczasem rzeczywistość brutalnie rewiduje pierwotne założenia. Pierwsze schody zaczynają się, gdy chcemy zrobić trochę bardziej skomplikowane zapytanie - ot, choćby coś tam odfiltrować na bazie tego, co jest w podkolekcji. Dla prostych przykładów, np. listy stringów, możemy użyć Contains, ale gdy chcemy użyć czegoś bardziej skomplikowanego w predykacie Where, to niestety Marten się wysypuje wyjątkiem w runtime'ie. Co gorsze, to jest jakiś randomowy wyjątek z nullem lub o collection has no elements. Kolejne schody zaczynają się, gdy chcemy zrobić sobie jakąś agregację lub wyciąć tylko fragment dokumentu (inna sprawa, jak dużo powinniśmy wrzucać do dokumentu...). Próby użycia Linqu i extension methods kończą się wyjątkami, zostaje więc goły SQL zapisany w C#. Co gorsza, jest to stricte "postgresowy" SQL (dzień dobry standard, który jednak w detalach się różni), a do tego - operujemy na JSON-ie w PostgreSQL, czyli musimy nauczyć się całej nowej składni (te wszystkie ->, json_array_elements itp.). Dla człowieka, który - na studiach czy to w pracy - raczej głównie bazował na bazach typu MySQL bądź SQL Server, to jest bardzo przykre doświadczenie. Marten ma też opcję "projekcji", czyli kodu javascriptowego, który jest za pomocą C# ładowany do bazy SQL-owej i tam trzymany jako bazodanowa funkcja. Słyszeliście? JS ładowany w C# do SQL-a! Mindfuck gotowy!

Dodatkowym problemem z Martenem jest też to, że niestety nie jest zbyt aktywnie rozwijany - niby ostatnie wersje są wydawne co miesiąc, ale sporo issues na Githubie wisi ponad rok. (Tu oczywiście nie mam pretensji do autorów, jedynie stweirdzam fakt.) To też dodaje frustracji, bo na ficzery, których nam brakuje, możemy się nie doczekać.

To, co napisałem wyżej, jest oczywiście zabarwione pewnym uprzedzeniem do PostgreSQL (wychowałem się jednak na MySQL i SQL Serwerze od Microsoftu) oraz lenistwem (nie zawsze chce mi się czytać dokładnie dokumentację). Przyznaję jednak, że moje doświadczenia z Elasticsearchem lub MongoDB były o niebo lepsze (a przecież, gdy pierwszy raz z nimi się stykałem, też pewne koncepcje i składnia dla kwerend była novum). Wydaje mi się zatem, że pomysł pt. Marten jako baza dokumentowa w C# - to nie jest najlepsze rozwiązanie. Prawdopodbnie popełniłem sporo błędów i częściowo używałem biblioteki w niewłaściwy sposób - ale DX (developer experience) nie jest zadowalające: tych wszystkich frustracji, co miałem, to już nikt ich nie wymaże z pamięci. ;)

© 2020, Built with Gatsby