Do napisania tej notki zainspirowała mnie… lekcja angielskiego. A na tej lekcji jedno ćwiczenie. Było ono bardzo proste i polegało na tym, że jedna osoba widzi cały obrazek, pozostałe mają kartki z jego częścią. Wybraniec opowiada o tym, co widzi a pozostałe osoby rysują niewidoczne dla nich elementy. Bardzo proste, gdy się o tym pomyśli. Bardzo trudne, gdy przychodzi zrobić to dobrze. Zdjęcie poniżej przedstawia mój szkic.
Rysunek dolny pokazuje jak bardzo słabo rysuję, ale to nieistotne. Najważniejsze, co uświadamia to ćwiczenie to fakt, że
niezwykle trudno jest znaleźć wspólny język.
Szkic na górze jest bardzo prosty, kilka drzewek, jakieś wzgórza, domek. Raj dla trzylatków. Ten na dole ma także te wszystkie elementy, ale czy jest taki sam? Oczywiście, że nie. Drzewka niby są, ale nie tam gdzie trzeba. Wzgórze przesunięte, rzeczka toczy się prosto a podczas rysowania trawki dopadła mnie frustracja i przekreśliłem to wszystko mocnym zygzakiem.
Zamieńmy teraz rysunek na oprogramowanie
Klient miał wizję. Chciał oprogramowanie, które pomoże mu w (tu wstaw cokolwiek). Przyszedł do programistów i zaczął im o tym opowiadać. Programiści pisali sobie w swoich kajecikach to, jak zrozumieli wymagania klienta, a po owocnym spotkaniu poszli to wszystko implementować. Jak sądzicie, czy po X miesiącach czekania na upragniony software, klient będzie zadowolony?
Skoro można tak skopać rysunek składający się z garści kresek, to jak bardzo można niezrozumieć idei drzemiacej u kogoś w głowie? Totalnie. Gigantycznie. Cała ta robota może okazać się nieprzydatnym gniotem, ponieważ obaj – klient i programista nie mieli wspólnej wizji i nie znaleźli wspólnego języka, żeby opisać swoje myśli.
Tu na myśl przychodzi niezmiennie stary, śmieszny rysunek – „co klient chciał a co dostał”:
To, jak bardzo ten rysunek jest prawdziwy wie każdy doświadczony programista czy nawet dowolny człowiek związany z wytwarzaniem oprogramowania – na każdym szczeblu i stanowisku. Jest to też fakt, którego nie potrafią – mimo najszczerszych chęci – zrozumieć ludzie, którzy zajmowali się wcześniej „produkcją mydła”, a teraz trafili do projektów IT. Za cholerę nie chcą uwierzyć, że może być „aż tak źle”. Ale jest.
Oprogramowanie bardzo trudno włożyć w sztywne ramy procedur, opisów itp. Zawsze jest miejsce na domysły, interpretacje, dywagacje, no i do tego pomyłki w zrozumieniu. Dlatego już od pierwszej chwili powinniśmy zadbać o ustalenie
wspólnego języka.
Angielskie „ubiquitous language” (wszechobecny język), to pojęcie wprowadzone przez Erica Evansa w wiekopomnym, często wspominanym i bardzo często jedynie przekartkowanym dziele „Domain driven design (…)”. Mimo przyznanej mu palmy pierwszeństwa nie będę się zagłębiał w szczegóły postulowane przez p. Evansa. Mamy przecież tak piękne i przydatne polskie określenie (wspólny język), którego znaczenie jest oczywiste, a przy tym w zupełności wystarczające dla potrzeb tego wpisu.
Wizualizacja terminu”wszędobylski język”, źródło: http://www.userdrivendev.com
Bez wspólnego języka nie będzie możliwe przekazanie żadnych istotnych informacji na tyle precyzyjnie, by dało się z tego coś stworzyć. Każdy doświadczony programista wie, że bez jasno określonych wymagań nie da się napisać nic większego, a wydobycie tych wymagań jest często dużo bardziej pracochłonne niż sama ich późniejsza implementacja. Wielokrotnie zdarza się, że po kilka razy dopraszamy się o coraz dalsze uszczegóławianie, ponieważ w trakcie pracy wychodzą problemy, których nie sposób było przewidzieć przed jej rozpoczęciem.
Jeżeli do tego dołożymy niejednoznaczne pojęcia, wieloznaczności językowe itp., to porażka zbliża się wielkimi krokami.
Bardzo dobrym pomysłem jest ustalenie pewnego rodzaju słownika,
który będzie zawierał podstawowe, najczęściej używane wyrażenia i zwroty. Jego zawartość będzie się różniła w zależności od domeny – czyli od tego, czy oprogramowanie ma wspomagać zbieranie danych z liczników elektrycznych, grę na giełdzie czy jeszcze inne procesy. Słownik zawiera czasami (a nawet bardzo często) pojęcia bardzo proste. W moim przypadku (sieci energetyczne) będą to na przykład „meter name”, „meter id”, „substation”, „grid” itp. itd., ale też i bardziej skomplikowane czy wieloznaczne – „incident”, „deviation”, „process”.
Kolejnym dobrym pomysłem jest interesowanie się domeną.
Oczywiście, jeżeli robimy projekt dwumiesięczny, to ciężko wgłębić się w temat w tak krótkim czasie. Ale jeżeli zakotwiczymy gdzieś na dłużej, to zbieranie wiedzy domenowej czyni z nas naprawdę dużo bardziej wartościowych pracowników, niż zwykły klepacz zainteresowany tylko swoją klawiaturą i różnicami między Angularem a inszym tałatajstwem. Stopniowo oswajając się ze środowiskiem i pojęciami, z których pochodzi klient stajemy się mu bliźsi, coraz lepiej go rozumiemy, potrafimy wczuć się w jego potrzeby i po jakimś czasie następuje bardzo fajna przemiana – już nie piszemy prostego łańcucha prostych metod przetwarzających dane z postaci A do B a, powiedzmy, rozwiązujemy bardzo ciekawy problem kolekcji danych w pewnym szczególnym przypadku, czy jeszcze co tam innego sobie wymyślimy. A przecież oczywistością jest, że rozumiejąc co piszemy, będziemy robić to lepiej. Same korzyści.
Nie da się też nie wspomnieć o ciągłej kontroli,
która, jak wiadomo z mądrości wielkiego poprzednika Koryfeusza Kultury, jest podstawą zaufania.
W IT realizujemy ją bardzo prosto – wprowadzając częste rewizje wykonanej pracy. Obojętnie, czy robimy to w sposób przypominający Scrum (piszę „przypominający”, bo nigdy nie spotkałem się z pełną implementacją tej techniki), Kanban czy jeszcze inne autorskie/zdroworozsądkowe pomysły. Ważne jest, aby klient miał możliwość częstego wglądu do aktualnego stanu produktu i nanoszenia swoich uwag i zgłaszania poprawek. Oczywiście „klient” to pojęcie względne – rzadko kiedy chyba prawdziwy klient ma czas, ochotę czy też jest dopuszczony tak blisko centrum akcji. Częściej to „product owner” czy ktoś w tym rodzaju. A jeżeli już o nim mówimy, to też należy pamiętać, że często taki Owner ma tyle wspólnego z prawdziwym klientem co tata dilera z mercedesami i jego pomysły mogą być trafione jak kulą w płot. Też to wielokrotnie przerabiałem, więc
bierzmy jego pomysły szczególnie pod lupę i często je dyskutujmy.
O DDD, języku itp. można rozmawiać i rozmawiać. Nie chcę przedłużać tego wpisu bo nadal szukam najodpowiedniejszej dla bloga formy – być może krótsze notki lepiej się sprawdzą. Najbardziej istotną myślą tego artykułu jest to, że jeżeli chcemy być dobrymi programistami, inżynierami oprogramowania, czy jak tam zwał, to musimy wyjść poza swoje ramki monitora i zauważyć, że gdzieś tam jest prawdziwy świat, z prawdziwymi problemami, które nasze oprogramowanie powinno rozwiązać. Nikogo nie interesuje, że wykorzystujemy super-sexi framework javowy, jeżeli nie zaimplementowaliśmy funkcjonalności, o którą prosił klient. To wszystko co pod maską ma znaczenie tak naprawdę tylko dla naszej próżności i samozadowolenia zawodowego – żeby nie wpaść w ordynarniejsze określenia (jak np. onanizm technologiczny). Oczywiście – pośrednio to wszystko może (podkreślam – może) wpływać na większą niezawodność programu i satysfakcję klienta, ale równie dobrze można program napisać solidnie nie deliberując tygodniami jakiego stacka technologicznego użyć – to sprawa drugorzędna.
Pierwszorzędne jest zrozumienie potrzeb, jasne określenie co ma być zrobione i przejrzysta, zgodna z zasadami „software craftsmanship” implementacja. O tym pamiętajmy i tego się trzymajmy.