Podsumowanie obecności mojej i Star Trek API w DSP

Oto krótki post podsumowujący mój udział w DSP z projektem Star Trek API.

Postępy projektu

Przez trzy miesiące projekt zdecydowanie posunął się do przodu.

Przez marzec i kwiecień napisałem parsery do sześciu encji: lokalizacje, jedzenie, organizacje, książki, serie książek i kolekcje książek. Przez cały maj przygotowywałem stronę Star Trek API, której odpalenie zaanonsowałem w poprzednim poście. Można ją obejrzeć tutaj.

Dane liczbowe

Przez czas trwania projektu udało mi się napisać 22 posty, z 27, których napisanie założyłem sobie w pierwszym poście. Większość z postów, które nie powstały, nie powstały dlatego, że tematy, które przygotowałem, wydały mi się za słabe, a miałem krótką listę rezerwową.

Wykonałem w sumie 228 commitów. Commitowałem przez 83 dni z 92 dni, przez które trwał konkurs. W kwietniu i w maju commitowałem codziennie. Dodałem do repozytorium ponad 69 tysięcy linii, a usunąłem 20 tysięcy linii. To lepsza średnia, niż w miesiącach poprzedzających konkurs.

Wrażenia z blogowania

Ciężko było mi znaleźć odpowiednią ilość tematów do postów, i to mimo tego, że zaczynałem z okoła 20 tematami na początku marca. Część z nich się jednak wykruszyło, a nowe nie dochodziły tak szybko, jak bym chciał. Miałem tutaj i tak dużo łatwiej, niż ci uczestnicy konkursu, którzy projekty zaczynali z końcem lutego lub na początku marca. Miałem doświadczenia zbierane od października zeszłego roku.

Myślę, że po okresie konkursu będzie sukcesem, jeśli opublikuję na blogu jeden wpis w miesiącu. Tym niemniej, blog zostaje w sieci. Na pewno do czegoś mi się przyda.

STAPI – plany na przyszłość

Star Trek API, jak już zapowiadałem w marcu, będzie kontynuowane. To dalej zadanie, które mnie fascynuje, i projekt, który chcę mieć w swoim portfolio – jako programista i jako fan Star Treka.

DSP – podsumowanie

W samym konkursie brakowało mi jakichś punktów przełomowych i kogoś, kto prowadził by narrację nad całością. Konkurs trwał, były rozmowy na Slacku, obserwowaliśmy swoje projekty i blogi, ale brakowało jednego miejsca, w którym to wszystko by się spinało. Ale być może to tylko moje wrażenie, bo po prostu nie uczestniczyłem zbytnio w żadnych aktywnościach z innymi uczestnikami i wolałem siedzieć w swojej niszy.

A teraz – czekamy na oba głosowania, i oczywiście na galę finałową!

Star Trek API jest już w sieci!

Star Trek API trafiło w końcu do sieci!

Zmiana priorytetów

Ostatni miesiąc poświęciłem w dużej mierze na doprowadzanie do działania strony głównej STAPI. Musiałem napisać dokumentację API, dorobić zliczanie statystyk encji i statystyk użycia endpointów, napisać trochę tekstów na stronę i pozamykać TODO, które oczekiwały na lepsze czasy. Tym niemniej dziś, w dniu końca konkursu, strona jest gotowa do pokazania światu.

Serwer

STAPI zostało postawione na serwerze dedykowanym Kimsufi. Tutaj moje doświadczenie było słabe. Na stronie Kimsufi.pl widnieje przechwałka, że serwer zostanie uruchomiony w 120 sekund. Uruchomienie mojego zabrało prawie 3 dni. Zamówiłem go w piątek po 17:00. 20 minut później wysłałem maila ponaglającego do supportu, który pozostał bez odpowiedzi aż do 14:30 w niedzielę. Wtedy dostałem odpowiedź, że w 120 sekund stawiane są serwery dla powracających klientów, a od nowych zazwyczaj wymaga się dokumentów potwierdzających tożsamość. U mnie obyło się bez wysyłania dokumentów, ale weryfikacja płatności trwała do 16:15 w poniedziałek. Przez cały poniedziałek wysłałem 4 kolejne maile ponaglające, które pozostały bez odpowiedzi.

System

System operacyjny w Kimsufi instaluje się przez webowy panel administracyjny. Na system wybrałem Ubuntu, które znam stosunkowo najlepiej. Na początku zainstalowałem wersję 17.04 (Zesty Zapus), ale ponieważ tutoriale na blogach, z których korzystałem, nie były z nią kompatybilne, cofnąłem się do wersji 16.04 (Xenial Xerus), która jest LTS-em.

Java i Oracle

Po tym, jak zainstalował się system, trzeba było zainstalować Javę 8. To robi się trzema łatwymi do wygooglania poleceniami, więc nie będę się nad tym rozwodził.

Grubszy problem wystąpił z bazą danych Oracle XI 11g, która nie jest oficjalnie wspierana na Ubuntu. Ponieważ jednak wśród wspieranych przez Oracle’a dystrybucji Linuxa nie było żadnej, którą można było zainstalować z panelu Kimsufi, postanowiłem pójść za najlepiej widocznym w Google tutorialem na temat instalacji Oracle’a na Ubuntu, jaki znalazłem. Jedyne, co musiałem zmienić w całej procedurze (napisanej dla Ubuntu 12.04), to sposób zaktualizowania parametrów jądra. Zamiast polecenia sudo service procps start, które nie chciało działać, wykonałem polecenie sysctl --system.

Deployment

Następnie trzeba było zasilić bazę z gotowego dumpu, który wygenerowałem kilka dni temu, oraz wrzucić wygenerowany plik WAR na Tomcata. Na tym etapie życia projektu proces deploymentu jest jeszcze mocno ręczny, ale w przyszłości na pewno go sobie zautomatyzuję. Na tę chwilę z automatu podmieniam tylko propertisy i generuje dumpa z innym schematem, niż schemat źródłowy, ale paczkę i bazę wgrywam z palca.

Problemy

Nic nigdy nie działa od pierwszego strzału, i tak samo było tym razem. Po wrzuceniu WAR-a na Tomcata nie było widać dokumentacji, ponieważ kontrakty nie były kopiowane do paczki. Ponadto okazało się, że część endpointów nie odpowiada, ponieważ ich nazwy były krótsze, niż sześć znaków, i leciał wyjątek, bo nie zabezpieczyłem się przed trywialnym StringIndexOutOfBoundsException.

Podsumowanie

Cieszę się, że udało mi się postawić stronę w ostatniej chwili. Dzięki temu lepiej widać, ile udało mi się zrobić przez ostatnie miesiące, i ile jeszcze pracy przede mną. Dodatkowo mam nadzieję, że sprawdzi mi się podejście release early, release often, i fandom Star Treka zainteresuje się tym projektem, zanim przyjdzie mi skończyć go w pojedynkę. Chociaż wcale się przed tym nie uchylam.

CodeNarc – linter do Grooviego

Gdy zaczynałem pracę nad Star Trek API, naturalnym wydało mi się zastosowanie jakiegoś lintera do Javy. Wybór padł na popularny Chekstyle. To żadne zaskoczenie, ale ponad połowa kodu, który w tej chwili znajduje się w repozytorium projektu, to kod testów napisanych w Spocku, czyli w efekcie w Groovym. Udało mi się znaleźć tylko jeden linter do Grooviego, CodeNarc, który opiszę w tym poście.

Instalacja

Jeśli budujemy projekt za pośrednictwem Gradle’a, jak w moim przypadku, instalacja ogranicza się do dodania do Gradle’a pluginu:

apply plugin: 'codenarc'

I skonfigurowania:

codenarc {
configFile = "$rootDir/codenarc.groovy" as File
toolVersion = '0.26.0'
}

Następnie trzeba stworzyć plik codenarc.groovy w katalogu głównym projektu, lub w dowolnym innym, jeśli wskażemy go w konfiguracji. Gdy to zrobimy, mamy dostępne dwie nowe komendy:

gradle codenarcMain
gradle codenarcTest

Pierwsza komenda sprawdza, czy produkcyjny kod w Groovim jest zgodny z aktywowanymi w CodeNarcu regułami, a druga robi to samo dla kodu testów. Ponieważ w projekcie nie mam żadnego kodu produkcyjnego w Groovym, przy walidacji kodu posługuję się tylko tą drugą komendą.

Dodatkowo teraz, gdy wywołujemy komendę gradle check, wykonywane są też walidacje pochodzące z CodeNarcu.

Konfiguracja

Cała konfiguracja Codenarcu odbywa się we wspomnianym już pliku codenarc.groovy. Alternatywnie można skorzystać z konfiguracji przez plik z propertisami, ale ja wybrałem plik Groovy.

Postanowiłem zacząć od wrzucenia pliku ze wszystkimi regułami domyślnie włączonymi, i po kolei rezygnować z tych, które uznałem za bezcelowe lub niemające znaczenia. Mimo wszystko nie zrezygnowałem z dużej liczby reguł, ponieważ kod testów jest z natury prostszy, niż kod produkcyjny, a więc nie tak wiele rzeczy trzeba było poprawiać, żeby walidacje przechodziły.

Ostatecznie mój plik z regułami wygląda tak.

Wyłączone reguły

Oto wybrane reguły, które wyłączyłem w Star Trek API, wraz z powodami wyłączenia:

  • NoTabCharacter – ponieważ w całym projekcie używam tabów.
  • AbstractClassWithoutAbstractMethod – ponieważ czasami moje klasy abstrakcyjne mają tylko pola, których wartości używane są w testach.
  • TrailingComma – w testach rzadko zmienia się kolejność w listach po ich utworzeniu.
  • ClassJavadoc – zgodnie z regułami clean code’u, piszę bardzo mało dokumentacji do kodu. Jeszcze mniej sensu miałoby pisanie jej w testach, gdzie, IMO, dostateczną dokumentację stanowią nazwy metod testowych pisane językiem naturalnym.
  • SpaceAroundMapEntryColon – wydawało mi się nienaturalne, by konstruktor mapy zapisywać jako [ : ], a nie [:]. CodeNarc jest pierwszym miejscem, gdzie spotkałem się z takim zapisem.
  • MethodSize – domyślnie metoda może mieć sto linii. W przypadku metod testowych nie ma sensu robić wygibasów, by je podzielić, zwłaszcza że są już podzielone przez bloki given, when: i then:.
  • AUnnecessaryObjectReferences – reguła zabrania odwoływania się do jednego obiektu więcej, niż domyślne 5 razy. Często natomiast w testach mam sytuację, gdy robię assercje nawet na kilkudziesięciu polach jednego obiektu. Jako alternatywę CodeNarc podaje zapis with. Ten zapis nie jest niestety wspierany przez moje IDE, więc automatyczny refaktor go nie obejmie, i nie można korzystać w bloku with z podpowiadania składni.

Przekonfigurowane reguły

Następujących reguł nie wyłączyłem, ale je przekonfigurowałem:

  • LineLength – dopuszczalna długość linii została ustawiona na 150 znaków, podobnie jak w Checkstyle’u.
  • BuilderMethodWithSideEffects – CodeNarc traktował wszystkie metody, które zaczynały się od create jako metody wytwórcze, które nie mogą mieć efektów ubocznych. Ja natomiast mam metody testowe, których opis w języku naturalnym zaczyna się od create, więc zmieniłem regułę tak, aby były brane pod uwagę tylko te metody, które zaczynają się od create, po którym następuje wielka litera.
  • PackageName – musiałem dopuścić camel case w nazwach paczek.
  • Najczęściej ignorowane reguły

    Oto lista reguł, które najczęściej ignoruję w pojedynczych metodach lub klasach:

    • LineLength – w niektórych miejscach lepiej nie łamać linii, gdy są za długie, bo czytelność jest gorsza. Używam też tego wykluczenia w przypadku testów z datatables.
    • RuntimeException – w niektórych testach asercje wykonuję w pętlach, więc rzucam z nich wyjątki. Nie widziałem potrzeby tworzenia nowego typu wyjątku tylko na ten przypadek, więc dozwoliłem rzucanie wyjątków typu RuntimeException.
    • BracesForMethod – czasami metoda ma długi opis, i wtedy jest zapisywana z trzema cudzysłowami, a nie z jednym. W tym przypadku trzeba wyłączyć regułę BraceForMethod.

    Czego można się dowiedzieć

    Podczas implementowania CodeNarcu dowiedzieć się można kilku ciekawy rzeczy. Ja dowiedziałem się następujących:

    • Ostatnie domknięcie w ciągu metod może być zapisane bez nawiasów okrągłych. Czyli .do { it.stuff() } zamiast .do({ it.stuff() }).
    • Nie powinno się zapisywać metod voidowych jako def something(), ponieważ def oznacza tyle, co Object, a metody voidowe, takie jak metody testowe, niczego nie zwracają.
    • Nie ma sensu zapisywać stringów w podwójnych cudzysłowach, jeśli nie robimy w nich interpolacji. Także z powodów wydajnościowych.

    Podsumowanie

    Zastanawiam się, ile osób używa CodeNarcu w stosunku do produkcyjnego kodu w Groovim. Na GitHubie ma on zaledwie 120 gwiazdek, w porównaniu do 1985 gwiazdek, które ma Checkstyle.

    CodeNarc na pewno poprawia jakość kodu, który piszemy. Pewnie miałbym z niego więcej użytku, gdybym w Groovim nie pisał tylko testów. Mimo wszystko pomaga, choćby w usuwaniu nieużywanych zmiennych i formatowaniu kodu.

    Najgorsze i najlepsze rzeczy na rozmowach kwalifikacyjnych

    Byłem w życiu na kilkunastu rozmowach kwalifikacyjnych. Kilka z nich zapamiętałem szczególnie, i o nich dzisiaj napiszę.

    Sześć na jednego

    Zdarzyło mi się być na rozmowie kwalifikacyjnej, gdzie umówiony byłem z jedną osobą, a przyszło sześć. Nietrudno się domyślić, że taka przewaga, połączona z faktem, że pytania zadawała mi większość osób, zakończyła się tym, że do firmy się nie dostałem.

    Pytania o rzeczy niepraktyczne

    Zdarzyło mi się więcej niż raz być zapytanym o to, jak zaimplementować algorytm sortowania. Jestem przekonany, że w firmach, gdzie o to pytano, nigdy nie implementowało od zera takich algorytmów.

    Więcej niż raz pytano mnie także o hoisting w JavaScripcie, chociaż użycie dowolnego javascriptowego lintera sprawia, że problem z hoistingiem nie ma prawa wystąpić.

    Pisanie kodu na kartce

    To chyba już klasyka rozmów kwalifikacyjnych. Pisanie kodu na kartce lub na tablicy suchościeralnej. Kartka to nie edytor, skreślenia okropnie wyglądają, kartka i tablica szybko się kończą, a mój mózg jest nieprzyzwyczajony do pisania kodu w ten sposób, bo nigdy tak tego nie robię.

    Nie rozumiem, dlaczego problemem jest przyjście na rozmowę kwalifikacyjną z laptopem ze skonfigurowanym środowiskiem, i użycie go do rozmowy kwalifikacyjnej. Z drugiej strony Jakub Nabrdalik mówił o tym, że częścią procesu rekrutacyjnego może być całodniowy pair programming z kandydatem. Są więc firmy, gdzie kartka nie ma prawa bytu.

    Byłem raz umówiony na rozmowę kwalifikacyjną, ale w jednym z późniejszych maili dowiedziałem się, że połowa dwugodzinnej rozmowy to test pisemny. Zrezygnowałem z pójścia na tę rozmowę.

    Podchwytliwe pytania

    Deprymujące są również podchwytliwe pytania. Mają one albo za zadanie udowodnić, że nie powinienem chcieć za wiele pieniędzy, skoro przyjdzie mi pracować z takimi wybitnymi postaciami, albo też po prostu uwalić kandydata. Byłem raz na rozmowie, gdzie jedna z trzech osób rekrutujących mnie była ewidentnie od początku na nie. Oczywiście się nie dostałem.

    Najlepsze są rozmowy o technologii

    Dwie najlepsze rozmowy, jakie miałem, nie były testami. Nie wydawało się też, żeby miały określony scenariusz, a jeśli tak, to był on realizowany dyskretnie. Moje dwie najlepsze rozmowy kwalifikacyjne były po prostu luźnymi rozmowami o programowaniu i architekturze, gdzie moje odpowiedzi w dużej mierze wyznaczały tematykę kolejnych pytań. Po obu tych rozmowach dostałem propozycje pracy. Z jednej ostatecznie skorzystałem.

    Podsumowanie

    Jak się okazuje, mocne wspomnienia mam głównie z nieudanych rozmów kwalifikacyjnych.

    Nie twierdzę, że wiem, jak powinny być przeprowadzane rozmowy kwalifikacyjne, ale wydaje mi się, że jest kilka rzeczy, których należałoby unikać. Na pewno należą do nich testy na kartce i pytania o rzeczy, o których wiedza nie ma w firmie żadnej praktycznej wartości.

    EhCache i Hibernate

    Planuję doprowadzić development Star Trek API do końca. Będę przez jakiś czas, być może całkiem długi czas, jedyną osobą, która będzie płaciła za utrzymanie serwera, na którym API będzie działało. Nie planuję inwestować w taki serwer zbyt wielu środków, dlatego w moim interesie jest, by zrealizować wydajne cache’owanie. Przyda mi się ono na pewno, biorąc pod uwagę fakt, że do tej pory do Pokéapi zostało wykonane 175 milionów zapytań.

    Wymagania

    Wymagania dotyczące cache’u w Star Trek API są relatywnie proste, w porównaniu do innych systemów. Dane, które trafią do bazy, czeka jeden z dwóch scenariuszy. W pierwszym scenariuszu dane nie będą się zmieniać, gdy już trafią do bazy, ponieważ zasilenie dokona się poza serwerem aplikacyjnym, i serwerowi aplikacyjnemu zostanie tylko wskazana napełniona baza. Drugi scenariusz jest taki, że dane zmienią się co prawda, ale będę mógł kontrolować moment, gdy się to stanie, i wówczas będzie można wyczyścić cache. Problem inwalidacji cache’y w zasadzie nie będzie istniał.

    Instalacja i konfiguracja

    A móc używać EhCache, po pierwsze trzeba dodać do projektu zależności. Ja dodałem dwie:

    compile group: 'net.sf.ehcache', name: 'ehcache'
    compile group: 'org.hibernate', name: 'hibernate-ehcache'

    Po drugie, trzeba skonfigurować przynajmniej domyślny cache. EhCache pozwala na składowanie cache’owanych zasobów w wielu regionach, ale zdecydowałem na początek, że przynajmniej póki nie będę wiedział więcej o tym, jakie zasoby są najczęściej kwerendowane, nie chcę przekombinować z konfiguracją. Moja obecna konfiguracja wygląda więc tak, i jest najbardziej podstawową wersją, jaka może być.

    Integracja z Hibernatem

    EntityManagerFactory musi dostać kilka dodatkowy propertisów, widocznych tutaj. Trzeba więc między innymi włączyć cache drugiego poziomu, a także wskazać EhCache jako fabrykę regionów cache’u. Oznacza to klasę implementującą interfejs zdefiniowany przez Hibernate’a, który gwarantuje wytworzenie kilku kolejnych obiektów, odpowiedzialnych kolejno za cache’owanie między innymi kolekcji, wyników zapytań, i encji.

    Strategia cache’owania

    Wymyśliłem, że dodatkowo będę miał własną strategię cache’owania. Interfejs jest prosty i wygląda tak. Strategia dostanie QueryBuilder, czyli obiekt, w którym przed wykonaniem zapytania gromadzone są jego parametry (kryteria zawężające, sortowanie, relacje do pobrania). Strategię cache’owania można zdefiniować w propertisach aplikacji. Napisałem trzy strategie. Jedną, która zawsze zwraca prawdę, druga, która zawsze zwraca fałsz, i trzecią, najciekawszą, której chce domyślnie używać, i która zwraca prawdę warunkowo, gdy jedynym kryterium w zapytaniu jest UID, czyli unikalny identyfikator obiektu.

    Cache’owanie encji

    Gdy już mamy wszystko zintegrowane, trzeba wyznaczyć encje, które będą cache’owane. W moich przypadku są to wszystkie encje, które trafiają do REST-owego i SOAP-owego API. Do encji trzeba było dodać adnotację @Cache, tak jak zostało zrobione tutaj. Dodatkowo napisałem test, który z pomocą refleksji pilnuje, żeby wszystkie encje, poza jawnie określonymi, miały zawsze adnotację @Cache. Napisałem też drugi test, który to samo robi dla pól zawierających relacje jeden do wielu i wiele do wielu.

    Testy

    Pozostało mi przetestować ten setup. Testy manualne polegały na zapytaniu kilku endpointów i obserwowaniu, jakie zapytania odkładają się w logach za pierwszym i za kolejnymi razami. Za kolejnymi razami było tych zapytań zdecydowanie mniej, chociaż ciągle jeszcze jakieś się pojawiają i będę musiał wrócić do tematu, żeby maksymalnie wyżyłować EhCache. Prędkość odpowiedzi endpointów za kolejnymi zapytaniami znacząco wzrosła.

    Podsumowanie

    Przewiduję, ze klienty będą wykonywać relatywnie mało zapytań przeszukujących bazę, w których zestaw kryteriów zapytania jest słabo powtarzalny, a relatywnie dużo zapytań, które pytają o konkretny zasób za pośrednictwem UID. To założenie może z łatwością okazać się nieprawdziwe, a wtedy trzeba będzie przestrajać cache. Ale to może być temat na kolejny post, za kilka miesięcy.

    Powody mojego odchodzenia od frontendu

    W ciągu ostatnich miesięcy coraz bardziej wzbraniam się przed wykonywaniem zadań frontendowych. Nie wzbraniam się oczywiście w pracy, bo tam nie mam luksusu wybierania sobie tasków, ale jeśli chodzi o projekty po godzinach, to wybieram takie, gdzie jest możliwie mało frontendu. Star Trek API jest przykładem takiego projektu, do którego dopiero w ostatnich dniach dopisuję jakikolwiek frontend, a wcześniej był do tylko kod produkcyjny w Javie i testy w Groovim.

    W tym poście opiszę, jakie są powody mojego odchodzenia od frontendu.

    Ciekawsze problemy

    Problemy rozwiązywane na backendzie są ciekawsze. Złożone operacje biznesowe, wielkie zbiory danych, współbieżność, modelowanie domeny – to wszystko odbywa się na backendzie. Frontend, w idealnym świecie, dba tylko o odbieranie i zapisywanie danych za pośrednictwem wystawionego przez backend API o uproszczonym modelu. Można się spotkać z praktyką realizowania logiki biznesowej na frontendzie, ale abstrahując od wszystkich innych powodów, by tak nie robić, jeden wydaje mi się przesądzający. Nie należy rozbijać realizacji logiki biznesowej na frontend i backend, ponieważ nie sposób wyznaczyć, co powinność być realizowane na frontendzie, i dlaczego.

    Mniejsza powtarzalność

    Wolę nie robić w kółko tego samego. Wolę nowe rzeczy, i nie tylko jeśli chodzi o implementację nowych funkcjonalności, którą preferuję ponad realizację utrzymania istniejącego kodu. Wolę nowe rzeczy także jeśli chodzi o rozwiązywanie nowych problemów. A problemy na frontendzie mogą być powtarzalne, przynajmniej jeśli realizuje się typowy frontend dla aplikacji B2B albo B2C. Trzeba pociąć layout z PSD. Trzeba napisać kontroler w Angularze lub w innym frameworku. Kontroler pobiera jakieś dane, i może jakieś zapisuje. Trzeba poprawić CSS-y, bo znów inaczej wyglądają na Chromie i na IE. I tak dalej.

    Upraszczam tutaj problem, ale wyzwania frontendowe to pewna dość wąska specjalizacja, w której łatwo popaść w rutynę. Są naturalnie ciekawe wyzwania frontendowe, ale jest ich relatywnie mało, przynajmniej takich, które bym nie pociągały. A pociągałaby mnie np. praca przy frameworkach do wizualizacji danych. Na pewno byłaby trudna, ale dająca satysfakcję.

    Technologia

    Na frontendzie nie ma alternatywy dla JavaScriptu. Jest długa lista języków i dialektów, które transpilują się do JavaScriptu, ale ostatecznie, w przypadku debuggowania kodu, i gdy zawodzą sourcemapy, zmuszeni jesteśmy do przedzierania się przez sieczkę, jaką jest kod wygenerowany przez transpiler.

    JavaScript ciągle jest dość okropnym językiem, nawet jeśli piszemy w ES6. Ilość problemów nierozwiązanych do tej pory w JavaScripcie, a rozwiązanych lub nigdy nie istniejących w innych językach skłania mnie do myśli, że JS nigdy nie zostanie naprawiony, bo ciągnie za sobą ogon zbyt wielu złych decyzji podjętych na początku jego istnienia.

    Ekosystem

    Ekosystem javascriptowy jest pełen ciągle nowych frameworków, pluginów do tych frameworków, integracji między tymi frameworkami i tak dalej. Duże frameworki są finansowane przez biznes, któremu zależy na ich jakości, ale wokół nich wypączkowują różne mniejsze inicjatywy, często ciągnięte do przodu tylko przez jedną osobą. Często ta jedna osoba traci w końcu zainteresowanie swoim projektem, więc mamy bardzo dużo średnio działającego, niezbyt aktualnego, marnie napisanego oprogramowania. Kto nie wierzy, niech zobaczy na GitHubie, jak są napisane javascriptowe projekty, które mają tysiące gwiazdek. Wiele z nich nie przeszło by nigdzie wewnątrzfirmowego code review, gdyby podobny kod powstał w Javie albo C Sharpie.

    I to kolejny problem JavaScriptu. Brak jest w tym ekosystemie znajomości i chęci stosowania dobrych praktyk, jeśli chodzi o wytwarzanie oprogramowania. Ciągle powstaje dużo kodu bez testów, stosowanie wzorców projektowych jest sporadyczne, a kod spaghetti ciągnie się kilometrami.

    Podsumowanie

    Nie jest tak, że narzekam na frontend, bo go nie znam. Przeciwnie, w obecnej firmie zostałem zatrudniony w dużej mierze ze względu na kwalifikacje frontendowe, bo na Javę dopiero chciałem się przekwalifikować. Po prostu, po tych paru latach, frontend mało mnie już ekscytuje, a na backend ciągle mam ochotę, zarówno jeśli chodzi o poszukiwanie nowych wyzwań zawodowych, jak i o poszukiwanie nowych tematów na projekty realizowany po godzinach.

    Różnice między modelem z uniwersum Star Treka i modelem z prawdziwego świata

    W trakcie pracy nad Star Trek API spotykam dwa rodzaje modeli. Jedne to modele dotyczące uniwersum Star Treka, a drugie to modele dotyczące prawdziwego świata. Do modeli dotyczących uniwersum zaliczyć można lokalizacje, obiekty astronomiczne, jedzenie czy statki kosmiczne, a do modeli z prawdziwego świata – filmy, aktorów, komiksy czy firmy pracujące nad produkcją. Istnieją między nimi różnice, które opiszę w tym poście.

    Ilość

    Pierwsza różnica to różnica w ilości modeli. Tych z prawdziwego świata jest trochę mniej. Obecnie mam ich zrealizowanych 13, a zaplanowanych kolejne 6. W przypadku modeli z uniwersum zrealizowanych jest 6, a zaplanowanych do realizacji – kolejne 17. Postęp moich prac można śledzić tutaj. Także ilość krotek w modelach różni się. Osób pracujących nad Star Trekiem jest ponad 6000, a aktorów, kaskaderów i innych wykonawców widocznych na ekranie – ponad 5000. Jeśli chodzi o modele z uniwersum, najwięcej, około 5000, jest postaci, a potem są już obiekty astronomiczne i miejsca, jedne i drugie z wynikiem poniżej 2000 krotek.

    Relacje

    Modele z prawdziwego świata mają znacznie więcej relacji, niż modele z uniwersum, i są one znacznie lepiej uporządkowane. Przykładowo, ksiązki mają aż 11 relacji wiele do wielu: serie książek, autorów, artystów, edytorów, narratorów audiobooków, wydawców, wydawców audiobooków, postacie, identyfikatory wydań książek (ISBN, ASIN) i identyfikatory wydań audiobooków, oraz kolekcje książek. Modele z uniwersum, które mają najwięcej relacji, to obiekt astronomiczny, seria książek i seria komiksów. Mają one relacje do nadrzędnego elementu i do podrzędnych elementów tego samego typu. Większość modeli z uniwersum nie ma żadnych relacji.

    Modele z uniwersum mają jednak na ogół więcej flag booleanowych. Każda kategoria, np. dotyczące lokalizacji, może być przetłumaczona na jedną flagę w modelu. I tak w encji Localization znajdujemy takie flagi, jak bodyOfWater, colony czy school. Większość flag dla większości krotek będzie naturalnie ustawiona na fałsz.

    Kompletność

    Model z prawdziwego świata ma zazwyczaj więcej danych, niż model z uniwersum, z oczywistego powodu: wydarzenia muszą mieć daty, ludzie nazwiska, a książki zawsze określoną ilość stron. W przypadku modeli z uniwersum wiemy tylko tyle, ile powiedziano w kanonicznych produkcjach. Najczęściej jest tak, że jakiś byt dający się ująć w model występuje w serialu przez chwilę, jest wspomniany raz, i nigdy więcej nie zostaje potem użyty. Przykładem niech będzie ten kawior, o którym wiemy tylko tyle, że był słony, ale nawet ta informacja jest zbyt egzotyczna, by ująć ją w model.

    Model z prawdziwego świata można próbować uzupełniać w innych źródłach. Można spróbować zgadnąć płeć aktora na podstawie płci jego imienia lub znaleźć jego datę urodzenia w IMDb. W przypadku modelu z uniwersum, który nie ma kompletnych danych, można tylko liczyć, że dany byt zostanie jeszcze w przyszłości wspomniany w jakimś medium.

    Podsumowanie

    Mogąc wybierać między modelami z prawdziwego świata i tymi z uniwersum, wolę pisać kod parsujący te drugie. Jest to łatwiejsze, szybsze i odkrywam wówczas model, który jakoś nakłada się na moje wspomnienia z oglądania kolejnych sezonów Star Treka. Ale żeby API było kompletne, nic nie może zostać potraktowane po macoszemu. Z drugiej strony, przez ostatnie miesiące częściej brałem się za modele z prawdziwego świata, niż za modele z uniwersum. Robiłem tak dlatego, żeby nie stracić zainteresowania projektem i najlepsze zostawić sobie na koniec.