Szczególnie dwa przypadki prowadzą do niezwykle rozbudowanej konfiguracji:
- Korpopotwory sprzedawane innym firmom. M.in. systemy ERP. Jest nacisk, że wdrożenia (którzy nie są programistami) mają mieć możność dostosowywania programu pod potrzeby klientów bez konieczności zaglądania do kodu źródłowego i bez konieczności rekompilacji. Dlatego nic nie można napisać konkretnie, wszystko, kazdy wymóg biznesowy musi być od razu uogólniony i zgeneralizowany, tak by wdrożeniowcy dopiero mogli sobie wyklikać w konfiguracji to, czego potrzebują.
- Gry. Tutaj z kolei zamiast wdrożeniowców mamy designerów, którzy mają mieć możność ustawiania sobie wszystkiego i dostrajania gry, modyfikowania balansu itp, znów bez konieczności zaglądania do kodu źródłowego (bo nie chcemy musieć przekompilowywać, bo designerzy nie sa i nie mają być programistami). Dlatego znowu, nic nie można zaimplementować po prostu, wszystko musi być od razu uogólnione i zgeneralizowane, tak by designer mógł w edytorze Unity, klikając w same komponenty, bez zaglądania do plików .cs wyklikać sobie to, czego potrzebuje.
Wszyscy upierają się, że postępowanie takie, jak opisałem wyżej jest konieczne. Cóż, zazwyczaj jeśli wszyscy cos podkreślają, a ja miałbym inne zdanie, to jednak to ja się mylę... więc pewnie mylę się i tym razem. Niemniej nie rozumiem tego podejścia.
W praktyce, moim zdaniem, to podejście prowadzi donikąd. Mam dokument z wymogami biznesowymi. Przepisując je do kodu C# zaimplementowałbym to w 2 dni. Nie wolno, bo to hardcoding. Muszę więc robić skomplikowaną konfigurację, która dopiero pozwoli wyklikać to, co jest potrzebne. Niektóre fragmenty dokumentu z wymogami bizensowymi są trudne do uogólnienia, bo zawierają w zasadzie arbitralną logikę (np. "zwróć 5 jeśli fizzlewumpy mają zakończenia będące grumpywumpami, a jednocześnie pole XXX opisywane dwa akapity wyżej ma wartość YYY"). Jakoś jednak się to udaje, zajęło mi to 2 tygodnie, mój kod w zasadzie przypomina interpreter, a nie kod biznesowy, jest więc bardzdziej skomplikowany, niż ot koniecznie, kolejny dzień muszę poświęcić by wyprodukować dokument, który opisuje dokładnie konfigurację, tak by wdrożeniowcy mogli sobie to wyklikać, dokument jest na wiele stron.
Ale niby działa.
Ale teraz uwaga uwaga, DOCHODZI KOLEJNY WYMÓG BIZNESOWY! Np zamiast wartości 5 mam zwracać sumę pól XXX na zakończeniach fizzlewumpów będących grumpywumpami. Ups, tego nie da się obecnie wyklikać w konfiguracji, trzeba dopisywać kolejne dziwne parametry konfiguracyjne, sprawdzać, czy nasze nowe parametry konfiguracyjne w ogóle dobrze współdziałają ze wszystkimi możliwymi kombinacjami istniejących... To jest męka i zajmuje czas. Znowu, gdybym po prostu zahardkodował na pałę ten wymóg w C#, zrobiłbym to natychmiast. Zaraz zaraz, czy nacisk na to, by to było konfigurowalne nie brał się stąd, że wdrożeniowcy mają mieć możliwość wyklikiwania sobie, czego potrzebują BEZ konieczności przechodzenia do kodu? No cóż, nie jest tak. I tak każdy nowy wymóg oznacza konieczność angażowania zespołu programistów i dalszego rozdmuchiwania już i tak gargantuicznej konfiguracji.
A teraz mamy przypadek, że dwóch klientów, każdy o nieco innych wymogach biznesowych korzysta z naszej funkcjonalności. Znowu dochodzi kolejny wymóg, ale tylko od pierwszego klienta, drugi klient chce, by wszystko było po staremu. Dodajemy więc dziesięcziotysiączny parametr konfiguracyjny. Ten sam kod obsługuje różne potrzeby różnych klientów, nasz nowy parametr konfiguracyjny wymaga dostosowania działania istniejących parametrów, by nie byly ze sobą sprzeczne --> ups, właśnie popsuliśmy drugiego klienta, jest wściekły, bo po instalacji jego procesy biznesowe przestały działać. Drugi klient uczula się, że każda nowa wersja naszej aplikacj to potencjalne problemy, dlatego odtąd każda próba aktualizacji czegokolwiek u tego klienta to będzie droga przez mękę, bo co do zasady klient będzie wymagał, by nic nie było aktualizowane, a jeśli już coś jest aktualizowane, to ma być zmienione tylko to, czego on sobie zażyczył, a nic innego - tak więc musimy utrzymywać pięćdziesiąt wersji naszej aplikacji na pięćdziesięciu gałęziach w giciei pilnować, by do każdej wersij wchodziły tylko te commity, które dany klient zamawiał. Ups, ale czy konfiguracja nie miała służyć właśnie temu, byśmy mogli mieć JEDEN kod dla wszystkich klientów pomimo, że ich potrzeby biznesowe się różnią?
Tymczasem konfiguracja jest tak skomplikowana, że nie ogarnia jej nikt, ani programiści, ani wdrożeniowcy. Kod obsługujący tę konfigurację także jest tak ogromny, dziwny, skomplikowany i niekoherentny, że nikt go nie ogarnia. Praca się wlecze i jest męką.
======================
Nic dziwnego, że w praktyce to jest fail. Bo to się nie klei w teorii. Założenie, again, jest takie: Wdrożeniowcy, którzy nie są programistami, mają mieć możliwość wyklikiwania DOWOLNEJ LOGIKI i implementowania DOWOLNYCH WYMOGÓW BIZNESOWYCH poprzez konfigurację. Ma to nie wymagać przechodzenia do kodu źródłowego.
TO JEST SPRZECZNOŚĆ. Platforma, która pozwala na implementowanie DOWOLNEJ LOGIKI nazywa się JĘZYK PROGRAMOWANIA. Tym samym nasza konfiguracja zaczyna być JĘZYKIEM PROGRAMOWANIA - wizualnym, bo możliwym do wyklikania w edytorze konfiguracji, ale nadal jest to JĘZYK PROGRAMOWANIA.
Wyżej pisałem o korpobestiach i istotnie, jakby się zastanowić, to się okaże, że konfiguracja jest tak naprawdę Turing-complete, chociaż nikt nigdy nie zakładał, że tak ma być.
Ale w grach jest to jeszcze bardziej oczywiste. Do wyklikania są bardzo często ZMIENNE, które się nawet nazywają "zmienne" (i oczywiście sa globalne!), do wyklikania są warunki logiczne (mamy możność wyklikania ANDów oraz ORów), i tak dalej!
Napisaliśmy więc język programowania. Niestety, nasz język programowania jest, kolokwialnie mówiąc, do d**y. Ja, musząc pracować z tym wizualnym gównem, które jest w komponentach Unity i które pozwala mi deklarować zmienne oraz implementować pętle oraz ANDy, NOTy i ORy marzę o tym, by móc zapisać to samo, tylko po porstu w pliku .cs. (akurat w gamedevie nie pracowałem, piszę tu na przykładzie tych gównianych szablonów dostępnych w Unity które mają pozwolić mi wyklikać sobie grę bez pisania linijki kodu C# albo na przykładzie RPG Maker, ale zakładam, że zawodowym gamedevie jest tak samo, że programiści dają coś takiego właśnie designerom, którzy sobie klikają.
Wdrożeniowcy i designerzy, którzy mieli nie być programistami, SĄ programistami! Nauka konfiguracji to ilość wiedzy porównywalna z przyswojeniem sobie sensownych podstaw jakiegoś języka programowania.
=============================
Ogólnie zdaje mi się, że ten problem ma trzy rozwiązania:
- Konfiguracja (tak się zawsze robi);
- Hardkodowanie (ZUO!!!);
- Wystawienie API w języku np. LUA i niech wdrożeniowcy piszą sobie kod LUA implementujący dowolną logikę, jakiej potrzebują (np. piszą sobie w LUA, że pole ABC mam mieć wartość 5, jeśli fizzlewumpy mają zakończenia będące grumpywumpami, a oprócz tego opisywane w tym samym dokumencie dwa akapity wyżej pole XXX ma wartość YYY) - czemu tego sie nie robi?
Konfiguracja | Hardkodowanie | Skrypty LUA |
---|---|---|
Zmiana wymogów najczęściej oznacza konieczność zmiany kodu źródłowego wbrew założeniom, a jednocześnie oznacza konieczność zmiany konfiguracji | Zmiana wymogów z założenia wiąże się ze zmianą kodu źródłowego, natomiast nie trzeba zmieniać konfiguracji, bo jej nie ma | Zmiana wymogów oznacza zmianę kodu w LUA, rzadko trzeba także zmieniać kod źródłowy |
Zarówno kod źródłowy, jak i konfiguracja są gigantyczne i skomplikowane ponad wszelką miarę, te same partie kodu odpowiadają za różne potrzeby różnych klientów, każda modyfikacja to męka i wprowadzanie kolejnych bugów | Kod jest prosty, istnieje odpowiedniość 1-1 między kodem a wymogami bizensowymi, różne wymogi są implementowane w różnych plikach .cs, modyfikacja jest szybka i prosta, ale wymaga angażowania programistów | Wymogi są implementowane w plikach LUA, jest osobny plik LUA na każdy wymóg, jest odpowiedniość 1-1 między zawartością plików LUA a wymogami bizensowymi więc pliki LUA powinny być proste a ich modyfikacja szybka i łatwa |
Wdrożeniowcy muszą uczyć się absurdalnie skomplikowanej konfiguracji, której nikt nie ogarnia (a później męczyć programistów wiecznymi pytaniami, na które programiści także nie znaja od razu odpowiedzi, tylko muszą jej szukać) | Wdrożeniowcy nic nie muszą wiedzieć, niech tylko rozmawiaja z klientami i prezentują programistom wymogi | Wdrożeniowcy muszą nauczyć się podstaw LUA, ale ponieważ LUA jest bardziej przyjemny w użyciu, bardziej spójny, bardziej wygodny, bardziej koherentny niż gargantuiczna konfiguracja, to powinno się to opłacić |
Zakładam, że dokładnie analogicznie będzie dla gier, trzeba tylko w powyższej tabeli zastąpić "wdrożeniowców" przez "designerów".
===============================
Podsumowując:
Powszechnie wyklęte hardkodowanie wydaje mi się być DUŻO lepszą opcją, niż powszechnie przyjęte rozbudowywanie konfiguracji!
Najlepsze mogłoby być wystawienie API w Lua, ale przyznaje, że tylko wyobrażam to sobie, bo nigdy tego nie próbowałem. Na pewno rozwiązałoby to problem pojawiającej się ciągle logiki w konfiguracji (na przykład konieczności wyklikiwania, że cośtam ma być sumą cośtamów innych, ale tylko jeśli cos jeszcze innego spełnia arbitralny warunek logiczny).
================================
Gdzie popełniam błąd?
===================================
PS. Ten post jest wynikiem mojej frustracji związanej z pracą.