Przez wiele lat branża oprogramowania traktowała specyfikację i implementację jako dwa zupełnie różne byty. Specyfikacja opisywała to, co należy zbudować. Samo oprogramowanie było tym, co miało wartość. Specyfikacja była jedynie wejściem do procesu produkcyjnego, podobnie jak projekt techniczny przekazywany na halę fabryczną. Kod stanowił produkt, a języki programowania były podstawowym medium, w którym intencja człowieka zamieniała się w zachowanie maszyny. Ten podział zaczyna się obecnie zacierać.
Wchodzimy w erę, w której specyfikacja oprogramowania coraz częściej staje się produktem samym w sobie, podczas gdy języki programowania są spychane niżej w stosie abstrakcji. W tej nowej strukturze język programowania zaczyna przypominać to, czym kiedyś był kod maszynowy: nadal niezbędny, nadal rzeczywisty, ale nie będący już główną warstwą, na której definiowana jest większość wartości produktu. To nie jest drobna zmiana techniczna. To zmiana strukturalna w sposobie, w jaki oprogramowanie jest projektowane, wytwarzane, utrzymywane i sprzedawane. Aby zrozumieć dlaczego, warto najpierw przypomnieć, czym był kod maszynowy we wcześniejszych generacjach informatyki.
Czym był kod maszynowy wcześniej
Na początku kod maszynowy był oprogramowaniem. Praktycznie nie istniało rozróżnienie pomiędzy intencją a wykonaniem. Instrukcje były zapisywane w formie bezpośrednio konsumowanej przez sprzęt. Następnie pojawił się język asemblera, tworząc cienką warstwę abstrakcji nad architekturą zestawu instrukcji procesora. Później języki wyższego poziomu, takie jak C, Pascal, Java, C sharp, Python i wiele innych, umożliwiły programistom wyrażanie intencji w sposób bliższy logice biznesowej, strukturom danych oraz wielokrotnie używalnym konstrukcjom sterującym. Każdy kolejny krok przenosił wysiłek człowieka wyżej, a szczegóły wykonawcze niższego poziomu spychał w dół.
W tym procesie nie chodziło o to, że niższe warstwy zniknęły. Stały się mniej istotne z punktu widzenia ekonomicznej tożsamości produktu. Bardzo niewielu klientów kupuje produkt ze względu na elegancję jego instrukcji maszynowych. Większość kupuje go dlatego, że rozwiązuje problem biznesowy, automatyzuje proces, kontroluje operację lub tworzy określone doświadczenie użytkownika.
Ten sam typ zmiany zachodzi teraz poziom wyżej
Przez długi czas języki programowania pozostawały głównym miejscem, w którym intencja musiała zostać precyzyjnie rozstrzygnięta. Wymaganie biznesowe mogło być niejasne. Model procesu mógł być niekompletny. Historia użytkownika mogła być aspiracyjna. Ale kod musiał być jednoznaczny. Inżynier oprogramowania był osobą, która dokonywała kompresji z niejednoznaczności do determinizmu. Ta rola pozostaje istotna, ale narzędzia wokół niej zmieniają ekonomię miejsca, w którym musi istnieć precyzja.
Modele językowe dużej skali, narzędzia generatywne, platformy dziedzinowe, deklaratywne systemy konfiguracji, silniki workflow, architektury model-driven oraz coraz bogatsze narzędzia budowy interfejsów użytkownika wskazują w jednym kierunku. Zmniejszają ilość wartości wynikającej z ręcznego pisania imperatywnej logiki linia po linii i zwiększają wartość wynikającą z poprawnego zdefiniowania systemu na wyższym poziomie abstrakcji.
Tym wyższym poziomem jest specyfikacja
Przez specyfikację nie rozumiem wyłącznie tradycyjnych dokumentów wymagań zapisanych w plikach biurowych i zapomnianych po warsztatach. Mam na myśli całą ustrukturyzowaną definicję tego, co system ma robić: reguły biznesowe, przepływy procesów, uprawnienia, niezmienniki, integracje, kontrakty danych, logikę walidacji, ograniczenia jakościowe, oczekiwane zachowania użytkowników, przypadki brzegowe, wymagania niefunkcjonalne, postawę bezpieczeństwa, granice operacyjne oraz intencję komercyjną.
W starszym podejściu do tworzenia oprogramowania większość tych elementów była rozproszona: częściowo w dokumentach, częściowo w rozmowach, częściowo w zadaniach, a częściowo w głowach kilku doświadczonych osób. Końcowy produkt powstawał dopiero po przetłumaczeniu tej rozproszonej intencji na kod.
Krok translacji ulega kompresji i automatyzacji
Gdy wystarczająco bogata specyfikacja może zostać przekształcona w działające oprogramowanie przy znacznie mniejszym nakładzie ręcznego kodowania, specyfikacja zyskuje nowy status. Nie jest już tylko dokumentacją produktu. Staje się głównym zasobem, z którego produkt może być generowany, regenerowany, adaptowany, audytowany i rozwijany.
To prowadzi do głębokich konsekwencji.
Zmienia się to, co jest zasobem rzadkim
Historycznie jednym z głównych ograniczeń w oprogramowaniu była zdolność do tworzenia niezawodnego kodu. Dobrzy programiści byli rzadcy, ponieważ przekształcenie niejasnej intencji w stabilny system wymagało głębokiego osądu technicznego, cierpliwości i dyscypliny. To nadal jest prawdą, ale nowe wąskie gardło przesuwa się w stronę zdolności do definiowania intencji z odpowiednią jasnością, kompletnością, spójnością i realizmem operacyjnym.
Innymi słowy, zasobem rzadkim przestaje być wyłącznie umiejętność kodowania. Staje się nim jakość specyfikacji.
Słaba specyfikacja powoduje teraz szkody wcześniej i bardziej widocznie. Jeżeli systemy generatywne lub wysoko wydajne zespoły są w stanie szybko tworzyć implementację, to niejednoznaczności, sprzeczności i braki w specyfikacji stają się główną przyczyną porażek. Problem przesuwa się „w górę strumienia”. Szybkość implementacji nie ratuje niejasnego myślenia. Wręcz przeciwnie – karze je. Zła specyfikacja może zostać zamieniona w złe oprogramowanie szybciej niż kiedykolwiek wcześniej.
Co oznacza posiadanie produktu programowego
W starym modelu własność często była utożsamiana z kontrolą nad kodem źródłowym. Repozytoria, pipeline’y wydawnicze i zespoły inżynierskie stanowiły centrum ciężkości. Dokumenty wymagań były artefaktami drugorzędnymi.
Jeżeli jednak produkt może być odtworzony na podstawie wysokiej jakości specyfikacji, to najcenniejszym zasobem staje się ustrukturyzowana definicja domeny i zachowania systemu, a nie tylko zapis implementacji w konkretnym języku programowania. Ma to szczególne znaczenie w oprogramowaniu klasy enterprise.
Wiele systemów biznesowych nie wyróżnia się innowacyjnością algorytmiczną. Wyróżniają się poprawnym odwzorowaniem domeny biznesowej, egzekwowaniem polityk, obsługą trudnych przypadków brzegowych, integracją z rzeczywistymi procesami operacyjnymi oraz dopasowaniem do krajobrazu regulacyjnego i bezpieczeństwa organizacji.
Wartość tkwi często w nagromadzonych decyzjach zapisanych w specyfikacji: kto może co robić, kiedy proces eskaluje, jak obsługiwane są wyjątki, co stanowi poprawne dane, które systemy są źródłem prawdy, co musi być audytowalne, jakie czasy odpowiedzi są akceptowalne, co dzieje się w przypadku częściowej awarii oraz jak regulacje wpływają na zachowanie systemu.
Jeżeli to wszystko jest jasno określone, znaczną część implementacji można coraz częściej syntetyzować, szkieletyzować lub automatyzować. Kod pozostaje konieczny, ale jego rola przesuwa się w dół. Staje się bardziej artefaktem skompilowanej intencji.
Jak powinniśmy myśleć o językach programowania
Języki programowania nie znikają. Takie założenie byłoby naiwne. Systemy generowane nadal wymagają deterministycznych fundamentów: wydajności wykonania, zachowania pamięci, semantyki współbieżności, izolacji awarii, walidacji wejścia, systemów typów, celów wdrożeniowych, poprawności kryptograficznej, efektywności sieciowej i integracji z systemem operacyjnym.
Ktoś nadal musi rozumieć te mechanizmy. Zmienia się jednak względna rola języka.
Język programowania przestaje być miejscem, w którym powstaje produkt, a staje się miejscem, w którym jest on kodowany do wykonania. To bardzo bliskie temu, czym był kod maszynowy.
Nie oznacza to, że tworzenie oprogramowania staje się trywialne. Oznacza to przesunięcie granic abstrakcji.
Najwyższej jakości specyfikacje intencji biznesowej
Wygrywające organizacje nie będą tymi, które generują najwięcej kodu. Będą to te, które potrafią tworzyć najbardziej precyzyjne i wierne rzeczywistości specyfikacje intencji biznesowej.
To zmienia także rolę starszego inżyniera. Mniej wysiłku będzie poświęcane na ręczne pisanie kodu, a więcej na architekturę specyfikacji.
Architektura specyfikacji obejmuje takie kwestie jak: dekompozycja domeny, granice odpowiedzialności, własność danych, kontrakty interfejsów, logika przejść stanów, założenia bezpieczeństwa, kryteria odporności, ograniczenia regulacyjne, wymagania obserwowalności oraz tryby operacyjne.
Są to pytania definiujące produkt, a nie niskopoziomowe szczegóły implementacyjne.
Rzeczywistość komercyjna modelowania oprogramowania
Firmy mogą odkryć, że tym, co faktycznie posiadają, nie jest tylko aplikacja, lecz wielokrotnie używalna specyfikacja domeny.
Własność intelektualna przesuwa się w stronę modelu, a nie składni kodu. To sprawia, że jakość specyfikacji staje się zagadnieniem na poziomie zarządu, a nie jedynie kwestią dokumentacji.
Wpływ na utrzymanie oprogramowania
Utrzymanie przestaje oznaczać jedynie modyfikację kodu. Coraz częściej oznacza aktualizację modelu i ponowną generację implementacji.
Pojawia się jednak nowe ryzyko: rozproszenie specyfikacji zamiast rozproszenia kodu. Dlatego kluczowe staje się zarządzanie i nadzór.
Przyszłość narzędzi i kompetencji
Należy oczekiwać rozwoju języków specyfikacji, formalnych systemów reguł biznesowych, środowisk modelowania domenowego oraz lepszej śledzalności pomiędzy intencją a działającym systemem.
Najbardziej wartościowi specjaliści będą potrafili poruszać się pomiędzy semantyką biznesową a formalizmem technicznym bez utraty precyzji.
Wyjątki
Istnieją dziedziny, w których głęboka optymalizacja implementacyjna pozostaje kluczowa: systemy niskopoziomowe, silniki baz danych, kryptografia, systemy operacyjne czy systemy czasu rzeczywistego.
Jednak dla ogromnej części oprogramowania biznesowego kierunek zmian jest już wyraźny.
Produkt staje się modelem
Kod staje się jego wykonaniem.
Język programowania staje się medium tej transformacji.
Powinno to zmienić sposób rekrutacji, współpracy zespołów oraz definiowania jakości oprogramowania.
Najważniejsze jest jednak to, że zmienia się definicja rzemiosła programistycznego.
Dotychczas była ona związana głównie z jakością kodu. W przyszłości będzie coraz bardziej związana z umiejętnością tworzenia specyfikacji tak precyzyjnej i kompletnej, że implementacja stanie się w dużej mierze procesem mechanicznym.
Specyfikacja staje się produktem, ponieważ zawiera istotę systemu.
Język programowania staje się nowym kodem maszynowym, ponieważ pozostaje niezbędny do wykonania, ale przestaje być głównym nośnikiem intencji produktu.
Jak w każdej wcześniejszej zmianie poziomu abstrakcji, wygrają ci, którzy opanują nową warstwę, nie tracąc zrozumienia tej, która nadal znajduje się poniżej.