Refactoring sprint? Plażo, please…

10

Nie ma kodu idealnego. Jest kod “wystarczająco dobry”. Ale oczywiście… większość tego, co widzimy na co dzień, nie wpada w tę definicję. Zwykle mamy do czynienia z kodem niedostatecznie dobrym lub wręcz wzorowo złym. Ale smutas ze mnie, nie? Czy po prostu: realista?

Akcja: BLOGvember! Post nr 11.
W listopadzie w każdy roboczy poranek na devstyle.pl znajdziesz nowy, świeżutki tekst. W sam raz do porannej kawy na dobry początek dnia.
Miłej lektury i do przeczytania jutro! :)

Oczywiście prawie z każdego bagna da się wydostać. Potrzeba jedynie wystarczająco dużo czasu, determinacji i… umiejętności.

Co zatem robimy?

Refaktorujemy!!! Or Die Trying

Skoro kod jest ohydny, to trzeba go “uładnić”. Często drobne, kosmetyczne zmiany, nie wystarczą. Nałóż szminkę na świnię, a pod spodem dalej będziesz miał parszuka. Trzeba ten spód właśnie zamienić na coś innego, żeby szminki nie potrzebowało.

W tekście “3 sprawdzone sposoby na wprowadzanie testów do istniejącego kodu” liznąłem zagadnienie dość popularnego podejścia do poprawy jakości kodu. Czyli: “refactoring sprint“. Jak to wygląda?

Mówimy biznesowi/klientowi: potrzebujemy X dni/tygodni na usprawnienie naszej pracy. W tym czasie nie będziemy dostarczać nowych rzeczy ani poprawiać błędów, ale za to POTEM RUSZYMY Z KOPYTA! Teraz mamy “dług technologiczny”, stare biblioteki, średni design, ale jak to ponaprawiamy to zobaczysz jacy będziemy błyskawiczni!

Ci mniej doświadczeni może się na to nabiorą. Pozostali sparsują sobie taką przemowę. Usłyszą: narobiliśmy pod siebie tak bardzo, że grzęźniemy. Nie mieliśmy odpowiednich kompetencji, by zrobić dobrze za pierwszym razem, więc chcemy drugą szansę. Zaufaj, że się nauczyliśmy na własnych błędach. Płać za to, że skalamy się sprzątaniem swojego syfu. Jak myślisz: zgodzi się?

Często się nie zgodzi. A programiści będą narzekać, że “klient chce mieć brzydki kod, to będzie go miał!”. Co najważniejsze: to biznes ma w tym przypadku rację. Prawdopodobnie widział to nieraz. Zresztą sami to widzieliśmy, a nadal naiwnie wierzymy, że “tym razem się uda”.

Tak często narzekamy na stronę “biznesową” programowania, ale to naprawdę nie są głupi ludzie. Posłuchaj zresztą “DevTalk#42 – O sprzedaży w IT z Michałem Wójcikiem” i przekonaj się na własne uszy.

Ale załóżmy, że wysłaliśmy bardzo przekonującą delegację do “rozmów z krawaciarzami”. I udało się: mamy cały sprint dla siebie! Jaki jest tego efekt? Bez odpowiedniego, dokładnie przemyślanego planu, zmarnujemy ten czas. Tutaj poprawimy literówki, tam dodamy komentarze, gdzieś indziej sformatujemy rozjechany kod. Pousuwamy konkatenacje stringów i wrzucimy w ich miejsce StringBuildera, żeby zwiększyć wydajność (LOL). Pozamieniamy taby na spacje, bo przecież kod w systemie ma być spójny, co nie?

Wreszcie pod koniec, gdy uporamy się z takimi oczywistościami, zabieramy się za faktyczne problemy w designie. I trafiamy na ścianę. Bo… co faktycznie chcemy osiągnąć? Z tym kodem ciężko się pracuje, ale bez konkretnego zadania nie mamy odpowiedniej perspektywy. Robimy wszystko “na zapas”, bez wyraźnej potrzeby podyktowanej ficzerem. Więc… dłubiemy, dłubiemy, dorzucamy wzorczyk jeden czy drugi, wychodzi kod może i ładniejszy, ale… znowu zły.

Może to już nie jest ta świnia wymazana szminką. Może efekt naszej pracy faktycznie łatwiej będzie utrzymać, ale NIE WIEMY jak się sprawdzi w praktyce. Dowiemy się dopiero, gdy przyjdzie odpowiedni task i znowu będziemy musieli ów kod dotknąć. Zmodyfikować. To po to spaliliśmy teraz dwa tygodnie, żeby zaraz znowu dany fragment zmieniać? To tak jak pomalować pokój, a potem powiesić niepasujące firanki. Firanek ruszyć nie możemy – bo to ficzer. Więc ponownie przemalowujemy pokój. Jest prościej, bo ściany już wygładzone, podkład położony, ręce rozruszane, wałki kupione, ale… gdzie tu sens?

Jak inaczej? CR – Continuous Refactoring

Jakość kodu to nie jest wartość, którą da się zbudować dzikim dwutygodniowym refaktoringiem raz do roku. System świątecznych porządków się nie sprawdzi. W domu sprzątam, żeby nie było syfu – to jest cel. W kodzie… niekoniecznie. Syf mi nie przeszkadza, dopóki robi swoje i nie muszę go tykać.

Jedyny sposób na zapewnienie sobie utrzymywalnego, sprawiającego frajdę kodu, to ciągłe dbanie o jego jakość. To zastanawianie się przy każdym zadaniu: jakie będzie najlepsze rozwiązanie tego problemu? I jakie drobne zmiany muszę wprowadzić w już napisanym kodzie, żeby je zastosować? Przy takim podejściu nie trzeba rozpiżdżać wszystkiego w drobny mak i przepisywać tysięcy linii kodu. Ewolucja, a nie rewolucja jest kluczem do sukcesu.

Oczywiście, zadania będą wykonane nieco dłużej. NIECO, a nie kilkukrotnie dłużej. Ale porządna robota potrzebuje czasu, o czym zresztą wszyscy doskonale wiemy obserwując remonty NOWYCH autostrad w naszym pięknym kraju. Co ważne: ten czas dodany do realizacji tasków w profesjonalny sposób jest inwestycją, a nie czasem spalonym. To się zwraca. Te inwestycje się potęgują, wspierają wzajemnie.

Postanowienie poprawy

Następnym razem nie bądź tępym generatorem kodu. Nie doklejaj bezmyślnie kolejnych warstw kupy na śmierdzący kopiec. Nie masz tego dość?

Zamiast tego: PRZED napisaniem kodu zastanów się, jak możesz zrobić swoją robotę prawdziwie profesjonalnie. I co Cię przed tym powstrzymuje. A następnie: zwalcz te przeszkody. Da się! I na dłuższą metę wszyscy będą zadowoleni.

Pro tip: gapienie się w monitor przez 30 sekund nie podpada pod definicję “zastanów się”.

Pro tip 2: przesłuchaj “DevTalk#41 – O legacy code z Jarosławem Pałką“.

Share.

About Author

Programista, trener, prelegent, pasjonat, blogger. Autor podcasta programistycznego: DevTalk.pl. Jeden z liderów Białostockiej Grupy .NET i współorganizator konferencji Programistok. Od 2008 Microsoft MVP w kategorii .NET. Więcej informacji znajdziesz na stronie O autorze. Napisz do mnie ze strony Kontakt. Dodatkowo: Twitter, Facebook, YouTube.

10 Comments

  1. W tym temacie można polecić świetną książkę: “Working Effectively with Legacy Code” Michael’a Feathers’a

    • Darek,
      Prawda, klasyka, masa osób poleca. Choć przyznaję bez bicia, że nie czytałem :). Rozmawiamy o niej w podlinkowanym devtalku o legacy code.

  2. Continuous Refactoring, niby oczywiste, najlepsze rozwiązanie, praktycznie bez wad, oprócz odrobiny więcej czasu dodanego do wyceny zadania, a jednak rzadko stosowany w projektach w których dotychczas miałem okazje pracować. Chyba zacznę ‘przemycać’ trochę czasu przy każdym zadaniu na taki refaktor. Sam wpis świetny jak zawsze :)

  3. Wedlug mnie najlepszym sposobem na pisanie dobrego kodu i wspomnianego CR jest code review. Nic bardziej nie zmusi programisty do przemyslenia tego, co i jak chce napisac niz pozniejszy wglad w jego kod przez innych, najlepiej bardziej doswiadczonych (i nie mowie tutaj o X latach klepania kodu) kolegach.
    Jezeli taka osoba bedzie pisala slabo, ktos powinien na to zwrocic uwage i przedstawic standardy jakie powinny sie pojawic.
    W firmie, w ktorej obecnie pracuje mamy pewne standardy co do klepania, glownie utrzymywania kodu. Przed rozpoczeciem pracy nad zadaniem zastanawiamy sie, czy mozna w tym fragmencie cos poprawic i jak mozna to zrobic. Jezeli jest cos do poprawy, doliczamy potrzebny czas.

  4. Stosujemy w zespole CR, ale nie zawsze wystarcza.

    Uwzględnianie refaktoru w planie implementacji ficzerów to w zasadzie bardzo logiczna rzecz i aż dziwne, że kogoś to zaskakuje. Dostałaś nowe wymagania – masz wybór: albo dostosowujesz do nich architekturę systemu, albo na szybko doklejasz nowy kod do reszty taśmą klejącą. Bardzo o tym było ładnie napisane tutaj: http://ronjeffries.com/xprog/articles/refactoring-not-on-the-backlog/

    Mimo tego są pewne zmiany, które są po prostu zbyt duże, by wprowadzać je w ten sposób. Np odważnie wybrałeś do projektu frontendowy framework X, a pół roku później okazuje się że hype na X minął i bardziej przeszkadza niż pomaga, podczas gdy w innych projektach Y sprawdza się naprawdę nieźle. Jakie są opcje?

    a. Brniemy dalej w X
    b. Przepisujemy cały projekt z X na Y na raz
    c. Przechodzimy z X na Y krok po kroku przez dłuższy czas

    ‘c’ może wyglądać następująco: Znajdujemy metodę używania X równocześnie z Y w jednym projekcie, piszemy w Y nowe części, a stare w X albo utrzymujemym, albo przepisujemy jedna po drugiej na Y gdy akurat trzeba coś tam zmienić.

    Nie oszukujmy się: ‘a’ będzie w 80% przypadków właściwą opcją, bo rewrite jest drogi i lepiej jest płacić znany narzut przy nowych ficzerach, niż za trudny do oszacowania koszt takiego rewrite, który też nie wiadomo jak się spłaci.

    ‘c’ jest kuszącą opcją, bo zespół ma możliwość poprawiać coś w kodzie mniej więcej na bieżąco. Niemniej wad jest też sporo: trzeba utrzymywać taką technologiczną “hybrydę” przez cały okres przejściowy, a nie każdy koder w zespole będzie czuł się na tyle swobodnie by uczestniczyć w tym progresywnym rewrite. Ponadto płacimy koszt odkładania tego rewrite i wracania do niego wiele razy – context switche są drogie.

    Da się zatem znaleźć przypadki gdzie ‘b’ to wskazana opcja – ale i wtedy trzeba uważać, by nie ugrzęznąć z na w pół skończoną, niemożliwą do dołączenia gałęzią, gdy tymczasem product owner puka do drzwi i oczekuje nowych rzeczy…

  5. devamator on

    Za czasów studiów wbijali mi do głowy, że wszystko można zrobić dokładniej, dopieszczać w nieskończoność, ale dobry inżynier to taki, który potrafi określić kiedy jest “good enough”.
    Podkreślę jeden ważny aspekt, który poruszyłeś, a często nie zwracamy na niego uwagi. Nie ma co za wcześnie refaktoryzować kodu, który jest na styku kilku zadań i będzie modyfikowany przy każdym z nich. Szkoda czasu i wysiłku.

  6. Pingback: 3 sposoby na testowanie istniejącego kodu | devstyle.pl

  7. Moim ulubionym pojęciem jest “hardening sprint”, co tłumaczy się zazwyczaj na polski jako “sprint utwardzający”. Trochę szersze pojęcie, trochę inne od “Refactoring sprint” ale pokazuje tą samą denną mentalność. Lepmy z piachu a potem się utwardzi na beton.
    Bardzo dobry post!

  8. U nas w trudnościach z komunikacją zastosowaliśmy taktykę, że jak trzeba refactor, to trudno, sprzątamy, ale jak trzeba “ficzer na czwartek” to mówiliśmy – OK, zrobimy to teraz tak, żeby było, ale zaraz po tym musimy zrobić to dobrze, aby nie mieć w przyszłości długu. Czyli zamiast informować daleko PO to informowaliśmy PRZED. Taki trochę środek antycośtam.

Newsletter: devstyle weekly!
Dołącz do 1000 programistów!
  Zero spamu. Tylko ciekawe treści.
Dzięki za zaufanie!
Do przeczytania w najbliższy piątek!
Niech DEV będzie z Tobą!