Grinder – Jeszcze mniej pracy, jeszcze więcej programowania

Możliwe, że spotkaliście się kiedyś z problemem z build_runner’em. Patrząc na niego z boku biblioteka jest bardzo przydatna. Ma jednak jedną zasadniczą wadę, która mnie razi, a zwięźle nazywa się: flutter pub run build_runner build –delete-conflicting-outputs.

Niektórzy z was pewnie używają biblioteki fvm, która pozwala zarządzać wersjami Fluttera. Może napotkaliście też na problem, w momencie kiedy w Android Studio używacie pluginu intl. Przy niższych wersjach Fluttera potrafimy dostawać błędy przy generowaniu plików z tekstami. Najlepszym rozwiązaniem tego jest wygenerowanie ich ręcznie komendą flutter –no-color pub global run intl_utils:generate.

Na pewno nie jednej osobie zdarzyło się zapomnieć tych komend na początku swojej kariery. Na pewno wielu z was ma już dodane je jako aliasy systemowe. Dzisiaj postaram się przedstawić Wam opcję którą ja preferuje, rozwiązującą te i inne problemy, w czasie, kiedy musimy wyjść z IDE do konsoli.

Uwaga

Na urządzeniach z systemem windows, biblioteki Dartowe, które dodają własne komendy wykonują się podwójnie (Stan na październik 2021), jest to spowodowane kolejnością wczytywania zmiennej Path w systemie, więcej informacji m.in. w tym issue – [BUG] fvm runs commands twice on [Windows] · Issue #227 · leoafarias/fvm.

Grinder

Grinder to potężnym narzędziem pozwalającym na pisanie własnych komend, czy raczej aliasów dla podprogramów dartowych. Działa on o tyle prosto, że wystarczy dodać komendę w kodzie z odpowiednią adnotacją i gotowe!

@Task('build model')
2void build() {
3 try {
4 log('building...');
5
6 run(
7 'fvm flutter pub run build_runner build --delete-conflicting-outputs --no-fail-on-severe --verbose > build_log.txt',
8 quiet: isQuiet(),
9 runOptions: RunOptions(runInShell: true),
10 );
11 } catch (error) {
12 handleError(error);
13 }
14}

// komenda dla build_runnera

Pozwala nam to skrócić tę potwornie długą komendę do prostego grind build. Możemy nawet się pokusić o dodatkowe funkcje np zapisujące logi do pliku.

To rozwiązanie doskonale sprawdza się w połączeniu z opisywanym już przeze mnie Masonem (link do artykułu o masonie). Pozwala ona przenosić nasze programy do nowych projektów bez konieczności pamiętania o nich. Można także spróbować połączyć oba rozwiązania i utworzyć system, który będzie wykonywać jeszcze więcej roboty za nas!

Wracając do sedna artykułu, Grinder nie jest jednak bez kilku wad, z którymi na ten moment jeszcze walczę. Przede wszystkim, jak możecie zauważyć, używam metody handleError, która obsługuje błędy. Jest to powiązane bezpośrednio z problemem na jaki natrafiłem w momencie obsługiwania tej komendy. Przy uruchamianiu komend build_runner dostajemy na Windowsie błąd z kodem -1073741819. Zapytanie się wykonuje poprawnie, zwraca jednak błąd, dlatego ustawiłem error handling na ignorowanie tego jednego błędu jako hotfix.

1void handleError(final dynamic error) {
2 if (error is ProcessException && error.exitCode == -1073741819) {
3 // do nothing no idea why this happens only with build_runner
4 } else {
5 throw error;
6 }
7}

Innym błędem są problemy z uruchomieniem tego samego skryptu zarówno na MacOS jak i Windowsie. Wymaga to czasami dodatkowej pracy.

Dlaczego polecam używanie Grindera?

Pewnie wielu z was zadało by mi w tym momencie to proste pytanie – dlaczego?

Argumenty za:

Grinder nie jest dla wszystkich – wiele osób preferuje opisywanie własnych skryptów oraz aliasów w domyślnych narzędziach. Jest jednak kilka zalet korzystania z Grindera ponad zwykłe skrypty.

Przede wszystkim, jeżeli pracujemy w większym zespole, bardzo korzystne jest posiadanie rozwiązania które wiemy że na 100% będzie działać tak samo u wszystkich (ignorując wcześniej wspomniane problemy na MacOS oraz Windows, które są raczej jednorazowe na instalacje). Jeżeli już przejdziemy podstawową instalacje narzędzia, jesteśmy pewni, że nasz skrypt będzie działać tak samo dla każdej osoby w teamie.

Pracuje aktualnie w projekcie, który używa skryptów bash do pobierania tekstów z zewnętrznego serwera i budowania klasy, która daje do nich prosty dostęp w kodzie. Rozwiązanie te działa dobrze. Ma jednak jedną wadę – instalowanie go trwa. Wymaga on kilku dodatkowych bibliotek, które trzeba zainstalować osobno dla każdego pracownika. Nie licząc tego, wymaga ona utrzymywania dwóch wersji tego samego kodu dla różnych systemów (ponownie Windows i MacOS, tylko zakładając, że ktoś tak jak ja preferuje Windowsa).

Łatwo zauważyć że w tym miejscu mielibyśmy bardzo duży zysk poprzez użycie Grindera. Biblioteki zarządzane są w projekcie przez nasz pubspec.yaml. Każda więc osoba będzie mieć dokładnie takie biblioteki, jakich potrzebujemy (chyba że nie uruchomi pub get ale to raczej nie jest realne). Dodatkowo pozwala nam to pisać w naszym ulubionym języku Dart bez potrzeby zajmowania się innymi językami. Daje nam to swobodę w edycji naszych komend oraz nie wymaga od mniej biegłych w bash’u, aby szukali wiedzy w internecie dla każdej najprostszej zmiany.

Argumenty przeciw:

Grinder na pewno na pierwszy rzut oka brzmi dobrze, ale nawet pomijając problemy z implementacją dla niektórych może być wciąż narzędziem drugorzędnym.

Po pierwsze, osoby które pracują same lub w małym teamie developerskim prawdopodobnie nie zyskają tak dużej różnicy od skryptów systemowych. Duża część poprzedniego argumentu skupia się na sprowadzeniu komend na wspólną platformę. Jeżeli nie posiadamy takich, raczej nie jest to sprawa priorytetowa.

Drugim argumentem przeciw, może być fakt, że Grinder nie jest natywnym narzędziem. Jest uruchamiany w konsoli i pozwala wywoływać komendy systemowe. Nie będzie jednak mieć swobody, jaką zyskujemy przy pracy z zasobami natywnymi.

Pół argumentem może być fakt, że trzeba definiować Grindera dla każdego projektu z osobna. Może to powodować zmiany między projektami, które trzeba rozwiązywać. Częściowo problem przenoszenia między projektami poprawia nam np Mason, który doskonale normalizuje narzut, który pozyskujemy poprzez poszerzanie swojego zasobu narzędzi.

Ostatnim argumentem, jaki widzę, jest implementacja. Jak wcześniej wspomniałem, moja praca z narzędziem nie obyła się bez problemów. Grinder wymaga pracy aby go ustabilizować. Prawdopodobnie jest ona mniejsza, niż instalacja zależności dla skryptów natywnych, jednak na ten moment, dla mnie, wygląda ta biblioteka bardziej jak fajny bajer, niż pełnoprawne narzędzie.

Zakończenie

Grinder jest narzędziem, które mnie zainspirowało. Osobiście będę starał się dalej go używać. Wcześniej używałem już nie wspieranej biblioteki Derry do dodawania aliasów w pubspec.yaml, jednak Grinder szybko zajął jej miejsce i wpasował się bez problemu. Polecam go osobom, które pracują w różnych środowiskach, ponieważ pomimo pierwszych problemów ufam, że da się nim zastąpić większość niezrozumiałych dla większości skryptów.

This site is registered on wpml.org as a development site.