AI potrafi napisać aplikację. Ale kto dopilnuje, żeby cała mówiła to samo?
Co lepsze: AI czy deterministyczny generator kodu? Zobacz, jak GOAT CLI wykorzystuje jeden model, by utrzymać spójność bazy, API i frontendu.
AI potrafi napisać aplikację. Ale kto dopilnuje, żeby cała mówiła to samo?
Wyobraź sobie niewielką zmianę: pole slug w systemie treści ma być obowiązkowe i unikalne w obrębie języka.
Brzmi jak pięć minut pracy. Do momentu, gdy policzysz miejsca, w których ta decyzja istnieje: schemat bazy, migracja, model backendu, walidacja API, DTO, formularz w panelu, komunikat błędu, routing strony i testy.
Możesz poprosić AI o poprawienie każdego z nich. Możesz też zapisać decyzję raz i pozwolić, by reszta została z niej wyprowadzona.
To dwie zupełnie różne wizje generowania kodu. Pierwsza dominuje dziś w nagłówkach. Druga ma ponad ćwierć wieku intelektualnej historii — i właśnie do niej należy GOAT CLI.
W epoce AI wąskim gardłem nie jest już produkcja kodu. Jest nim utrzymanie jednej decyzji w wielu warstwach aplikacji.
Generator kodu to worek, do którego wrzuciliśmy zbyt wiele
„Generator kodu” może oznaczać szablon tworzący trzy pliki, kompilator Protocol Buffers, makro, narzędzie budujące klienta ze specyfikacji OpenAPI albo model językowy odpowiadający na prompt.
Łączy je tylko ogólna idea: jedna reprezentacja zostaje przekształcona w program lub jego fragment. Różni je niemal wszystko, co praktycznie ważne.
Generator deterministyczny działa jak maszyna. Dostaje poprawny schemat i stosuje jawne reguły. Ten sam input powinien prowadzić do tego samego wyniku. Model językowy działa raczej jak bardzo szybki współpracownik: rozumie niepełne polecenie, uzupełnia luki i proponuje rozwiązanie, ale część decyzji podejmuje za nas.
To nie jest spór o to, który mechanizm jest „lepszy”. Jeśli dopiero szukamy rozwiązania, elastyczność AI jest cenna. Jeżeli jedna ustalona reguła ma obowiązywać w bazie, API i interfejsie, zgadywanie jej trzy razy jest wadą, nie zaletą.
Wielka idea z 2000 roku nie polegała na drukowaniu plików
Kiedy Krzysztof Czarnecki i Ulrich W. Eisenecker opublikowali w 2000 roku książkę *Generative Programming: Methods, Tools, and Applications*, generatory oczywiście już istniały. Programiści znali makra, kompilatory, generatory parserów i narzędzia CASE. Dziesięć lat wcześniej raport FODA opisał analizę domeny przez cechy wspólne oraz zmienne.
Wkładem Czarneckiego i Eiseneckera nie było więc wynalezienie funkcji „utwórz plik”. Zebrali wcześniejsze nurty w spójne podejście do półautomatycznego wytwarzania rodzin systemów.
Najpierw poznajesz domenę. Następnie identyfikujesz to, co wspólne dla produktów, i to, co może się między nimi różnić. Opisujesz dopuszczalne warianty oraz zależności. Dopiero potem automatycznie wybierasz i składasz komponenty potrzebne do konkretnego systemu.
W tej perspektywie generator jest końcem procesu, nie jego początkiem. Najcenniejszym aktywem nie jest tysiąc wyprodukowanych linii. Jest nim skondensowana wiedza, dzięki której wiadomo, dlaczego właśnie te linie powinny powstać.
To przesunięcie nadal ma znaczenie. „Wygenerowałem 20 tysięcy linii” mówi niewiele o wartości. „Zapisałem regułę uprawnień raz i nie może się rozjechać w pięciu warstwach” mówi niemal wszystko.
Jedno pole, wiele konsekwencji
GOAT opisuje się jako generator i zestaw narzędzi do budowania aplikacji opartych na danych. Jego centralnym artefaktem jest plik herd/_model.goat.
Model może zawierać metadane aplikacji, języki, role, encje, pola, relacje, ograniczenia, uprawnienia oraz moduły takie jak CRUD, SEO czy SSR. Na tej podstawie generator tworzy elementy wielu warstw: modele Go, repozytoria i DAO, DTO, API, migracje SQL, formularze, widoki administracyjne oraz frontend Angular.
Istotne jest nie to, że narzędzie potrafi „napisać dużo”. Istotne jest, że typ pola może oznaczać więcej niż typ kolumny.
web_slug może nieść decyzje o przechowywaniu, walidacji, serializacji i prezentacji. Relacja owner może znaleźć konsekwencje w SQL-u, API, formularzu i panelu. Uprawnienie odczytu lub zapisu nie musi być osobno odtwarzane po obu stronach sieci.
Właśnie tu widać pokrewieństwo z programowaniem generatywnym: model nie opisuje pojedynczej linijki implementacji. Opisuje zamiar w domenowym słowniku, a generator propaguje jego konsekwencje.
Nisza GOAT CLI: między scaffolderem, frameworkiem i agentem AI
Scaffolder jest świetny pierwszego dnia. Tworzy katalogi, konfigurację i podstawowe komponenty. Później często znika z procesu, a aplikacja rozwija się już ręcznie. Wartość startera maleje z każdym commitem.
Platforma low-code utrzymuje spójność dłużej, lecz często robi to przez ukrycie kodu albo zamknięcie użytkownika w swoim środowisku. Z kolei framework CRUD daje wspólne zachowania podczas działania programu, ale nie zawsze łączy jeden model z bazą, API i niezależnym klientem.
Agent AI jest najbardziej elastyczny. Może pracować z niemal dowolnym stosem i napisać nietypową funkcję. Nie ma jednak z definicji jednej, formalnej semantyki domeny. Jeśli trzy razy poprosimy go o implementację tej samej reguły, otrzymamy trzy wiarygodne propozycje — niekoniecznie jeden kontrakt.
GOAT wchodzi pomiędzy te kategorie:
- jest bardziej długowieczny niż jednorazowy starter, bo model uczestniczy w kolejnych zmianach;
- daje więcej kontroli niż typowa platforma no-code, bo wynikiem pozostaje zwykły kod, który można przeglądać, zmieniać i commitować;
- obejmuje więcej warstw niż generator pojedynczego klienta lub ORM;
- oferuje mniej swobody niż AI, ale większą przewidywalność dla decyzji już zapisanych w modelu.
Najkrócej: GOAT zajmuje niszę model-first, full-stack code generation dla aplikacji data-driven, których właściciel chce zachować kod.
„Kod jest twój” nie kończy rozmowy o lock-inie
Jawny kod wynikowy jest ważną przewagą. Nie oznacza jednak automatycznie braku zależności.
Jeżeli zespół przestanie używać generatora, może dalej rozwijać wyprodukowaną aplikację. Traci jednak możliwość taniego propagowania kolejnych zmian z modelu. Realnym aktywem są więc jednocześnie kod, model i wiedza o narzędziu.
To prowadzi do pytań, które warto zadać każdemu generatorowi, nie tylko GOAT:
- Które pliki można bezpiecznie edytować?
- Co zrobi kolejna generacja z ręczną zmianą?
- Jak wyglądają migracje między wersjami generatora?
- Czy różnicę można normalnie przejrzeć w Git?
- Jak testowana jest zgodność bazy, backendu i klienta?
- Ile wyjątków mieści model, zanim DSL staje się drugim, gorzej udokumentowanym frameworkiem?
To nie są zarzuty. To cena dojrzałej automatyzacji. Generator nie usuwa złożoności; przenosi ją z wielu implementacji do modelu, transformacji i procesu regeneracji.
Kiedy taki model daje największy zwrot
GOAT powinien być szczególnie interesujący dla aplikacji, w których powtarzają się encje, relacje, formularze, uprawnienia, operacje CRUD, panel administracyjny, publiczne strony SSR i wymagania SEO. Im więcej warstw musi respektować tę samą decyzję, tym większa wartość jednego źródła prawdy.
Nie każde oprogramowanie pasuje do tego wzoru. Jeśli istotą produktu jest nietypowy edytor czasu rzeczywistego, algorytm optymalizacyjny lub wysoce eksperymentalny interfejs, model danych może obejmować tylko niewielką część problemu. Generator nie powinien udawać, że domena jest stabilna, kiedy zespół nadal jej szuka.
To najważniejsza lekcja płynąca z podejścia generatywnego: automatyzować warto nie to, co wygląda podobnie, lecz to, co reprezentuje tę samą, dostatecznie dojrzałą decyzję.
AI i GOAT nie muszą ze sobą konkurować
Badania nad program synthesis definiują problem szeroko: chodzi o znalezienie programu zgodnego z intencją wyrażoną w specyfikacji. Dzisiejsze LLM-y radykalnie obniżyły koszt przejścia od nieprecyzyjnego opisu do pierwszej implementacji. Nie unieważniły jednak potrzeby formalizacji tego, co ma pozostać spójne.
Najciekawszy workflow może być hybrydowy:
- człowiek i AI eksplorują problem, prototypują i odkrywają pojęcia domeny;
- stabilne pojęcia trafiają do jawnego modelu;
- deterministyczny generator wyprowadza z niego powtarzalne artefakty;
- AI pomaga implementować nietypową logikę oraz recenzować zmianę;
- testy rozstrzygają, czy całość spełnia kontrakt.
AI dobrze radzi sobie z szerokim zakresem i niepełną instrukcją. Generator domenowy dobrze radzi sobie z wąskim zakresem i mocną gwarancją powtarzalności. Próba zastąpienia jednego drugim odbiera nam zalety obu.
Nie pytaj, ile kodu powstało
W 2000 roku Czarnecki i Eisenecker porównywali programowanie generatywne do przejścia od ręcznego składania pojedynczych wyrobów do produkcji rodzin produktów. Dziś metafora fabryki może brzmieć mniej efektownie niż „aplikacja z jednego promptu”. Jest za to bardziej uczciwa.
Fabryka działa świetnie, gdy wiadomo, co ma produkować, jakie warianty są dozwolone i jak kontrolować jakość. Działa fatalnie, gdy każda sztuka jest eksperymentem.
Dlatego właściwe pytanie nie brzmi: „czy GOAT wygeneruje mi aplikację?”. Brzmi:
Które decyzje w mojej aplikacji są już na tyle stabilne, że chcę zapisać je raz — i nigdy więcej ręcznie synchronizować ich konsekwencji?
Jeśli odpowiedź obejmuje bazę, API, panel i frontend, GOAT nie konkuruje wyłącznie o czas pisania kodu. Konkuruje o coś cenniejszego: o liczbę miejsc, w których projekt może przestać mówić sam ze sobą jednym głosem.
Do dyskusji
Wolisz generator, który zachowuje się przewidywalnie w wąskiej domenie, czy agenta, który potrafi zrobić prawie wszystko, ale wymaga dokładniejszego review? A może sensowny development zaczyna się dopiero wtedy, gdy oba narzędzia pracują razem?
Wybrana bibliografia
- K. Czarnecki, U. W. Eisenecker, *Generative Programming: Methods, Tools, and Applications*, Addison-Wesley, 2000.
- K. Kang i in., *Feature-Oriented Domain Analysis (FODA) Feasibility Study*, CMU/SEI, 1990.
- S. Gulwani, O. Polozov, R. Singh, *Program Synthesis*, 2017.
- M. Alharbi, M. Alshayeb, *Automatic Code Generation Techniques: A Systematic Literature Review*, 2026.
- Dokumentacja GOAT, w tym Model danych i generowanie kodu, dostęp 10.09.2026.