Good enough software moim zdaniem

Bogowie

Słuchając wystąpień wujka Boba czy innych wielkich mówiących o czystym kodzie, solidzie, testach, architekturze, devopsach i innych słowach kluczowych można popaść w depresję: „O żesz, mój kod nigdy taki nie będzie, lepiej nikomu go nie pokaże, sam zamknę się w piwnicy i do końca życia będę żywic się ziemniakami i robakami które będą do mnie przypełzać”.
Czy naprawdę tak jest? Czy kod który piszemy musi być jak kryształ?

Obrazek

Słuchając różnych podcastów, usłyszałem taka myśl: Gdy przychodzi do was klient i mówi, że potrzebuje zrobić dziurę w ścianie, żeby wkręcić haczyk, żeby na nim powiesić obrazek. Gdy zaczynają się tańce godowe sprzedawców którzy chcą sprzedać mu komplet wierteł, wiertarek, zaprawy murarskiej, farby, etc. Może pojawić się firmą z którą przegracie, bo zaoferują mu taśmę dwustronnie przylepną. Klient nie chce dziury w ścianie, chce obrazek na ścianie.
Podobnie z naszym wyścigiem zbrojeń, jasne że fajnie mieć super hiper wypasioną architekturę, testy które sprawdzają wszystko, continuos-wszystko i jeszcze więcej, tylko która z tych rzeczy jest tą taśmą dwustronną?

Dorosłość

Ja dojrzewałem do tego parę dobrych lat. Pamiętam jak się pieniłem: „Gdzie są testy?!!! -Pffff amatorzy”, „Ten brąz nazywacie architekturą? Tam jest piwnica i zapas ziemniaków!”. I tak dalej. Dopiero gdy człowiek zacznie zdawać sobie sprawę, że biznes, że klient, że ktoś tam nie chce naszych warstw, nie chce testów, nie chce wzorców – on chce kliknąć i sprzedać swoje usługi. Ja spokorniałem, staram się dostarczyć dla klienta to czego on oczekuje. Nie zawsze mam testy, nie zawsze mam dobrą architekturę, nie zawsze mam taki podział kodu jaki bym chciał – ale wiecie co? Obrazek wisi na ścianie

Nasi bogowie programowania nakładli nam do głów ideałów, przykładów kodu, gdzie patrząc po nazwach plików powinniśmy być w stanie powiedzieć co robi aplikacja, w jakiej technologi i jakie wzorce są tam użyte. Przy okazji wiemy też, kto to pisał, jakiego koloru ma oczy i znamy tez rozmiar buta. Nie wiem jak wy, ale u mnie to tak nie wygląda. Kod i rozwiązania które ja tworze przechodzą raczej przez trzy fazy;

Działa

Rozwiązanie działa i robi to co miało zrobić. Kod jest napisany tak jak jest, wszędzie są dopisane podtrzymujące wszystko if’y, bo np. zapominałem obsłużyć jakiś tam warunek brzegowy. Jest spora szansa, że cała akcja dzieje się w jednej metodzie, bo tak było mi prościej na początku ogarnąć całą logikę i miałem wszystko na ekranie. Generalnie chaos, a w tym chaosie jest metoda – i ona działa.

Porządek

Kiedy rozwiąże problem z którym się spotkałem zaczynam porządki. Generalizuje część rozwiązań, ukrywam lub pozbywam się if’ów (nienawidzę if’ów) gdzie możliwe. Rozbijam kod na mniejsze metody lub klasy. Po tym wszystkim sprawdzam jeszcze raz czy kod działa. Jeśli kod który napisałem jest skomplikowany logicznie i nie czuję pewien, na tym etapie mogę napisać kilka testów, które potwierdzą (lub nie), że to co napisałem działa i będzie działać tak jak powinno.

Optymalizacja

Takie mam [nie]szczęście, że rzadko wracam do tego etapu. Póki co nie pisałem aplikacji, które mielą takie ilości danych, że muszę wracać i profilować aplikację, sprawdzać gdzie się dławi i dusi, że należy ją optymalizować. Ale gdyby tak było, to właśnie tutaj i teraz skupiłbym się na tym, co działa wolno, lub za wolno jak na oczekiwania/wymagania klienta. I poprawił tylko to z czym jest problem. Przedwczesna [mikro]optymalizacja, i inne przedwczesne rzeczy, to zło – nic dobrego się z tego nie urodziło. Wciąż zapominamy, ze częściej czytamy kod, niż go piszemy. Dlatego lepiej mieć czytelny i działający kod, który działa wolno. Niż szybki i nieczytelny kod, który trzeba poprawić – jasne, są wyjątki, zawsze są. Oczywiście – po etapie optymalizacji, sztuczek i odprawienia voodoo na kodem (bo fix, bo optymalizacja, bo coś) powstanie twór, cudak, nieczytelny zlepek słów i sztuczek i paste’ow ze stacka, wtedy i tylko wtedy można ostrzec w komentarzach przyszłych czytelników że kod wygląda tak, bo trzeba było zrobić to-i-tamto.

Jeszcze o wzorce projektowych

Tutaj też często następuje przesada, chcielibyśmy aby wzorce były idealnym rozwiązaniem na każdy problem z którym się stykamy. Znowu, u mnie wzorce pojawiają się na etapie porządkowania, gdy mam coś co działa, wywalam if’y, pętle switch’e czy stringi z kodu i wtedy dostrzegam powtarzające się elementy. Rzadko mi się zdarza, że góry wiem, z jakiego wzorca będą korzystać. Jasne są te oczywiste jak np. Fabryka, na której każdy zjadł zęby. Często wcześniej można wyczuć miejsce gdzie da się wykorzystać fabrykę czy inny singleton. Pomimo tego staram się pisać prototyp bez zaprzęgania wzorców, nie lubię zarzucać sobie kotwicy z rozwiązaniem. Wolę to ogarnąć później, gdy działa, gdy wiem że problem został rozwiązany i wiem jak już to zrobić. Może się wtedy okazać, że lepiej zamiast fabryki zrobić metodę budująca, czy budowniczego, czy jeszcze inaczej. Wtedy znam i widzę cały kontekst problemu i rozwiązania.

Koniec

Jakość tego co tworzymy jest ważna i temu nie przeczę. Podpisujemy to przecież swoim nazwiskiem, emailem czy hashem. Ale nie czarujmy się warstwy, wzorce, i bóg wie co jeszcze moim zdaniem są formą artystycznego popisu przed sobą i kolegami z firmy czy ze społeczności. Klient na końcu chce obrazek swojego pieska na ścianie.

To tyle w niedzielę. Wracam do #dajsiępoznać

ps.
Ja lubię się popisywać i nie lubię brązu. Wujka Boba też lubię.

7 thoughts on “Good enough software moim zdaniem

  1. Pingback: dotnetomaniak.pl
  2. Świetny post! Miałem kiedyś podobne podobne podejście, jednakże…

    Od dłuższego czasu widzę taką tendencję u programistów, że jak już ogarną wszystkie ideały owych bogów programowania – to po jakimś czasie stwierdzają iż są one im w sumie niezbyt przydatne w „codziennym” programowaniu.

    Że to przekombinowane, to za dużo pracy zajmie a tamto to już w ogóle przesada w „naszym” projekcie.

    I po części tak jest. Szczególnie jak patrzymy przez pryzmat porównania: soft = obrazek na ścianie.
    Tylko problem w tym, że soft to wcale nie jest obrazek na ścianie (przynajmniej w większości przypadków). A czemu? Otóż obrazek na ścianie nie posiada czegoś co nazywamy „supportem”.

    Jeżeli soft który piszemy ma być jak taśma dwustronna – użyj raz i zapomnij – to rzeczywiście nie potrzebujemy unit testów, czystego kodu, warstw czy wzorców.

    Ten zestaw narzędzi nie służy do tworzenia aplikacji użytecznych przez klienta, on służy do tworzenia aplikacji tanich w utrzymaniu. Unit testy istnieją po to aby szybko i bez ryzyka móc zmieniać kod, warstwy utrudniają tworzenie uzależnionych od „Frameworka X” komponentów i tak dalej.

    Oczywiście idzie przesadzić w drugą stronę również. Jak wspomniałeś, wzorce wykorzystujemy w momencie kiedy zaczynają się klarować, warstwy wstawiamy kiedy pojawiają się widoczne granice.

    Tylko unit testy piszemy zawsze… w sensie ja piszę…
    Być może to zboczenie czy inna psychoza, ale mi się jakoś przyjemniej pisze się w TDD 🙂

  3. Jest w tym trochę prawdy. Jednak uważam, że warto znać dostępne narzędzia i dobre praktyki. Tylko znać zarówno ich zalety jak i wady, żeby świadomie ich używać i wiedzieć, że niekiedy nie warto wrzucać wszystkich wzorców do jednego kodu.
    Pewnie znalazłoby się na to jakiś antywzorzec 🙂

Dodaj komentarz