Jednym problemem jaki mam z elixir (i jak sprawdziłem google) nie tylko ja, to problem jak dane są reprezentowane. Pochodzę ze świata obiektowego i ciągle myślę w kwestiach jak opisać coś a nie jak wykorzystać/przetransformować. Co powoduje problemy. W zeszłym tygodniu napisałem o strukturze reprezentacji pliku torrent a przez ostatni tydzień siedziałem i się zastanawiałem, jak to zrobić.

Może (i pewnie) przesadzam i niepotrzebnie sobie tym głowę zawracam. Ale za każdym razem jak chcę stworzyć mapę, strukturę czy rekord to zapala mi się czerwona lampka – po co, do czego i na co to? Dlaczego muszę coś reprezentować? I już miałem się dziś pochwalić rozwiązaniem, ale dosłownie 2h temu je całkowicie zmieniłem :) więc kodu dużo nie będzie, ale trochę słów o czym myślałem i dlaczego tak/nie jako wybór danego rodzaju przechowywania danych.

Map

Pierwsza rzecz, która przyszła mi namyśl to reprezentowanie danych w postaci mapy. Plik torrent się do tego nawet nadaje. Mapa jest dynamiczna, nie muszę nic określać, jedynie później trzeba wyciągać dane za pomocą dopasowania wzorcowego. Działa to bardzo dobrze i już bencoding napisany zwraca mi właśnie taką postać – czyli nic nie musze mapować. Minusem jest brak informacji dla innych jak i co taka mapa może zawierać, jak i łatwo o jakąś literówkę. Mapa walidowana jest dopiero real time.

Struct

Struktury były kolejnym pomysłem, rozszerzają one mapy o weryfikację w trakcie kompilacji. Także struktury są o tyle fajne, że pozwalają na dopasowanie wzorcowe do funkcji. To znaczy, możemy mieć wiele struktur które mają dwa takie same pola. I możemy napisać jedną funkcję, która będzie je obsługiwała. Jednak struktury to już prawie jak klasy. Mogą implementować protokoły i ogólnie są bardzo fajną i przydaną opcją do reprezentowania danych, ale… są bardzo wymagające. Może dla takiego projektu jak torrent to nie będzie miało znaczenia, ale są one ogólnie ciężkie i bardzo często nie potrzebujemy armaty by wykopać drzwi w mieszkaniu. Jednak nie zmienia to faktu, że struktury są naprawdę w porządku w elixir i warto się o nich więcej dowiedzieć. Plusem struktur jest to, że mogą być także współdzielone na zewnątrz, zwracane itp..

Record

Na końcu został mi tak zwany record – coś co pochodzi z erlanga, i reprezentuje dane wewnętrzne. Robi to bardzo wydajnie i szybko oraz daje weryfikacje w trakcie kompilacji. Ale nie pozwala uż robić tego co struktury – czyli nie ma dopasowania wzorcowego – czyli dal dwóch różnych rekordów z tymi samymi polami dwie osobne metody sa potrzebne. Do tego reord nie różni się zbytnio od tuple, raczej bazuje na tuple. Jest to też dość rozsądny sposób reprezentowania danych. I to jest opcja za którą poszedłem.

Decyzja

Nie potrzebowałem nic co dają mi struktury (mam jeden rekord), nie ma sensu robić dopasowania wzorcowego dla różnych typów/struktur/rekordów. Dane są małe, szybkie i zwinne i szybo trzeba się ich pozbyć. Do tego naprawdę struktury mi klasy przypominają a to mi się już tak nie podoba.

I wszystko byłoby fajnie, gdyby nie to, że stwierdziłem iż record to jednak nie to. Po pierwsze nie interesuje mnie ponad połowa tych parametrów które są w pliku torrent – ale, możliwe, że będzie mnie to interesowało. Teraz więc mogłem albo zrobić mega rekord ze wszystkimi parametrami i wszystko wszędzie przypisywać albo później jak zajdzie potrzeba zmieniać kod w wielu miejscach. Po drugie, ja mam tylko 2-3 różne formaty wewnętrzne danych i nie muszę mieć tego więcej. Dosłownie jakbym miał liczyć “instancje” to może jedna.

Wybrałem więc opcję bez problemową – dane są zwracane jako mapa. Jest to dość proste i szybkie rozwiązanie które daje mi wszystko to co potrzebuje – zwinność, szybkość i brak skomplikowania. Do tego jest to też format który traktuje jako zgodny z tym, że struktura danych jest nieważna a ważne są transformacje ich. Przynajmniej tak mi się zdaje :)

Czy to będzie najlepsza opcja? Nie wiem, uczę się :) jak się uda to super, jak nie to cofnę się i poprawię dane.

No chyba, że już teraz możesz mi powiedzieć: BASTA, wiem, że to musi być: XYZ :)