kłołt Commit Driven Development ankłołt

23

Kilka miesięcy temu natknąłem się na bardzo ciekawą koncepcję dotyczącą sposobu budowania commitów (a jak można wydedukować po niedawnym poście – zwracam na to dość dużą uwagę). W polskiej blogosferze nie znalazłem odniesienia do proponowanej przez Arialdo Martini metody (nie on to wymyślił, ale u niego przeczytałem o tym najpierw), więc ja będę tutaj jej “przedstawicielem”:).

Najprostszym określeniem opisywanego podejścia jest “Commit driven development”. Jednak to raczej nawiązanie-z-mrugnięciem do wszystkich popularnych “development driverów” z ostatnich lat, stąd też “kłołty” w tytule.

W TDD najpierw piszemy testy, a potem kod. W BDD najpierw definiujemy dokładne zachowanie kodu (także poprzez pisanie testów, ale nieco innych), a potem kod. W Commit Driven Development – najpierw piszemy commit message, a dopiero potem “doklejamy” do takiego pustego commita kolejne kawałki kodu aż do momentu, gdy jego zawartość zgadza się z opisem.

Jest to zdecydowane odwrócenie “normalnego” sposobu commitowania pracy. Zwykle najpierw modyfikujemy kod, a dopiero potem go opisujemy i wysyłamy “gdzieś”. Co może dać takie eksperymentalne, świeże spojrzenie na ów proces?

Po pierwsze – definiujemy co dokładnie mamy osiągnąć w ciągu najbliższych minut/kwadransów/godzin. Dość regularnie zdarza mi się na chwilę zawiesić przy pracy. Może to już taki wiek po prostu;). Mając gotowe commit message – wystarczy zerknąć na jedną linijkę tekstu (git log -n1) aby ponownie wpaść w odpowiedni kontekst.

Po drugie – skupiamy się na implementacji tej jednej rzeczy, która jest aktualnie naszym celem. Nie ma miejsca na nagłe rozproszenie typu “o, literówka w nazwie metody, poprawię od razu za jednym zamachem“. A potem się okazuje że ta literówka była z jakiegoś powodu konieczna (bo np ktoś gdzieś w jakimś XMLu też jej użył i system się po zmianie wywali). Po prostu – określamy co mamy do zrobienia, a potem dążymy do – najlepiej niewielkiego – celu.

Efektem pobocznym opisywanej praktyki jest piękna historia projektu. Nie znajdziemy modyfikacji kodu procedury składowanej (fu!) w commicie mającym zmienić kolor przycisku na stronie bo ktoś “akurat pomyślał że fajnie byłoby przy okazji w końcu tą procedurę tknąć“. Trzymając się napisanej wcześniej commit message – nikt nie będzie robił zmian “pobocznych” bo najzwyczajniej w świecie nie będą one pasować do całej reszty commita.

Ciekawe zjawisko, które da się zaobserwować, to inny typ treści komentarzy do commitów. Nie znajdziemy tam opisu implementacji – ponieważ na etapie pisania comit message nie jesteśmy w stanie dokładnie określić jak ta implementacja wygląda. Opisy będą zawierać treści zrozumiałe nawet dla nowego programisty za pół roku ze względu na brak odniesień do klas czy komponentów. Tylko informacje “biznesowe”. “Co się zmieniło w zachowaniu systemu” vs “jak zmodyfikowałem kod“.

Czy to dobrze czy nie – nie jestem w stanie na tą chwilę z całą pewnością określić. Dlatego poruszam to jako “ciekawe zjawisko”, a nie zaletę.

W Gicie bardzo łatwo jest wypróbować taki workflow – wystarczy utworzyć pusty checkin (git commit –allow-empty). A potem “dorzucać” do niego zmiany (git commit –amend).

Co o tym sądzicie? Nie będę ukrywał, nie jest sposób jaki bym zawsze zdecydowanie rekomendował. Warto jednak czasem odświeżyć umysł takim nowym podejściem i zobaczyć jak to działa. Ja zrobiłem eksperyment i zastosowałem to kilka razy – w pewnych okolicznościach naprawdę się sprawdza!

Oryginalny post Arialdo: “Preemptive commit comments“.

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.

23 Comments

  1. Ciekawa koncepcja. Mnie jednak nurtuje jedno – czy commit to dobre miejsce i czas na opisywanie zmian językiem “biznesowym” jak to ująłeś. Wg mnie opis commita powinien nieść informacje techniczne.

  2. “Język biznesowy” to może za dużo powiedziane. Chodziło o to, że w commit msg zobaczę:
    “items added to cart are saved in cookie”
    zamiast
    “modified CookieManager.Store() method to save additional data”

    To jaka metoda w jakiej klasie się zmieniła mogę podpatrzeć w diffie, a rzut oka na logi pokaże jak zmodyfikowano zachowanie systemu.

  3. No to tez zalezy… ;) jak masz dobre komentarze w kodzie to jak najbardziej, jednak jesli sa one nazwijmy to… gorszej jakosci to ja bym jednak wolal przynajmniej przy commitcie miec wiecej informacji co w kodzie zostalo zmodyfikowane.
    A po drugie, jak uzywasz zaawansowanych narzedzi do zarzadzania projektami jak np. TFS, opierasz sie na taskach etc. to tam masz opisania co dana zmiana powinna zmienic w dzialaniu systemu, a commit wtedy moze Ci posluzyc jako szybka informacja o zmiane technicznej nie biznesowej :)

  4. Tomek,
    Komentarze w kodzie moim zdaniem świadczą o tym że kod jest zły i baaardzo sporadycznie spotykam sytuacje w których faktycznie są one potrzebne. Kod mówi sam za siebie. A jak commit jest taki jak powinien być (o czym pisałem w podlinkowanym poście) to zmian nigdy nie będzie tyle żeby diff nie był do ogarnięcia bez żadnych komentarzy.
    Co do softu do zarządzania projektami (czy to TfuFS czy innego) to jak najbardziej taski powinny zawierać pełen opis. Ale 1 commit !=1 task i commity powinny pokazywać całą ścieżkę w implementacji danego ficzera, a nie duplikować informacje ze specyfikacji.

  5. +1 do komentarza Procenta

    jednak jakos mi do gustu w pelni nie przypadlo PDD jeszcze, czasami jest super, czasami jest PITA ;)

  6. Gutek,
    PDD? To teraz u mnie jest, Pieluchy-Drive-Development, programowanie tylko wtedy gdy pielucha nie wymaga zmiany:)

  7. ech… to przez to Preemptive commit comments, Twoj tytul posta, oraz post Arialdo zmieszane w jedno ;)

  8. Maciek, wybacz, ale nie wierze w kod, który mowi sam za siebie ;) za dużo tego w zyciu widziałem, żeby nadal zyc mzonka, ze ludzie tak pisza i będą pisali kod… :( sad but true…
    Jak sie mocno trzyma zespol albo pisze cos w pojedynke to jak najbardziej sie zgodze, ale w każdym innym przypadku… sorry…
    Co do narzedzi, to pytanie na jakim etapie i kto chce wydobyc jakas informacje. Bo pewne rzecyz można grupować, wydowac zbiorcze podsumowania dla biznesu i scenariusz wiele taskow = jeden ficzer jest jak najbardziej realizowalny, tylko trzeba umiec tym zarzadzac od strony technicznej jak i biznesowej, odpowiednio wykorzystując możliwości softu do tego przeznaczonego :)

  9. Tomek,
    Jak ktoś pisze kod wymagający komentarzy to i komentarze nie będą zbyt pomocne – też tego sporo widziałem:)

    // get user id
    int id = db.GetUserId(“nickname”);
    a pod spodem 20 linii w których nie wiadomo o co chodzi, bez komentarza, albo z komentarzem niezgodnym z kodem (bo było copy/paste, bo kod się zmienił a komentarz nie, bo…)

    To chyba będzie dobry temat na posta:)

    A, i zwracam uwagę że nie napisałem “1 task != 1 ficzer” tylko “1 commit != 1 task”. Wiadomo że “biznes” nie będzie się grzebał w logach repozytorium, ale obstaję przy swoim: commit msg jest o wiele bardziej pomocne jeśli jest napisane “co się zmieniło w systemie” a nie na poziomie szczegółowości zmian w pojedynczych plikach, bo to mam w diffie.

    • na komentarze Uncle Bob mówi:

      “ITS A LIE !!!!!”

      warto zapamiętać, nie pisać komentarzy a jesli kod nie jest wystarczająco czytelny żeby się obronił sam to trzeba to poprawić

  10. Tomek,
    +1 dla samo-komentującego się kodu. Tak, jest to możliwe nawet w pracy zespołowej, ale pod warunkiem, że Lead tego pilnuje (czyli na początku powie jakie są zasady). Nie twierdzę, że komentarze są złe. Jeśli trzeba to należy wręcz dodać komentarz. Ale jeśli “komentarz” można wyrazić poprzez nazwę metody, zmiennej czy innej właściwości to należy tak postępować :)

  11. Maciek: sorry, chodzilo mi o commit ;) Komentarz musi oczywiscie trzymac poziom oczywiscie, a np dla osob wchodzacych w projekt komentarze bardzo czesto sa duzo latwiejszym sposobem na ogarniecie calosci niz analiza kodu

    Wojtek: W koncu mielismy na grupie sesje Raymonda na temat samokomentujacego sie kody wiec da sie, ale trzeba do tego odpowiednio podejsc

  12. Bardzo dobry wpis, dziś będę testował cdd jak się sprawdzi w praktyce.

    Swoją drogą co sądzicie o git flow ? Miał, ktoś z was doczynienia z tym??

  13. Paweł,
    Z gitflow jako narzędzia nie korzystałem, ale idea takiej organizacji repozytorium bardzo mi odpowiada.

  14. Wydaje mi sie ze samo to podejscie dosyc czesto jest uzywane ale w nieco inaczej sformulowany sposob -> e.g. JIRA task driven development. Najpierw pojawia sie wymaganie (uzasadnienie) zmiany, po czym dokonujemy powiazanych zmian w kodzie zalaczajac za kazdym razem nr ticketa.

    Idac dalej, mozna wykorzystac takie narzedzia jak TeamCity, ktore mozna zmapowac do task management tool’a (JIRA, TFS, whatever) – daje nam to powiazanie konkretnej wersji oprogramowania z konkretnymi wymaganiami biznesowymi.

    Granulacja danych taskow daje nam pewna dowolnosc, ale czesto narzedzia do zarzadzania takimi wymaganiami sa wygodniejsze w uzyciuniz logi commitow.

    Z drugiej strony, gdzie zamiescic skrotowe informacje dotyczace zmian technicznych? Nadal bliskosc do kodu odczuwam wlasnie podczas komitowania, gdzie czesto dodaje taki opis (w celu unikniecia doglebniejszej analizy zmian).

    Podejscie ciekawe, ale przy zastosowania numerow ticketow wydaje mi sie powielac zadanie.

  15. Jacek,
    Linkowanie do zadań to osobna kwestia, oczywiście należy stosować bez dwóch zdań. Tutaj chodzi właśnie dokładnie o to co napisałem – strukturyzację commitów. Nie ma to zastąpić softu do zarządzania projektami, nie ma to wygenerować jakichś wypasionych raportów. Ma pomóc w rozwijaniu oprogramowania przez programistów, z ich perspektywy tylko i wyłącznie.

  16. Odnoszę wrażenie, że odwrócono kota ogonem. Bo niejako narzędzie zaczyna definiować metodykę, zamiast ewentualnie ją wspomagać.

    To co napisałeś (o “zawieszaniu”) jest udziałem każdego programisty. Dlatego przed przystapieniem do implementacji algorytmu/funkjonalności/przypadku użycia, po prostu trzeba sobie przygotować plan – tak a nie inaczej będzie to zrobione, a następnie ów plan realizować (jeśli okaże się, że dany punkt planu jest zbyt ogólny – rozbić go, itd.). Wówczas taki plan staje się niejako gotowymi komentarzami do repozytorium.

    Rozważana przez Ciebie metodyka nosi dodatkowo nie tylko piętno narzędzia, ale _konkretnego_ narzędzia. Bo inne repozytorium może nie dopuszczać pustych zatwierdzeń, a jeśli już dopuści, to może się okazać, że widzą to wszyscy i traktują de facto jako zrealizowane (a takie nie jest). Z tego co piszez na blogu o GIT, on niejako ma swoją piaskownicę. Zatem tylko dla niego scenariusz pustych zatwierdzeń ma sens.

    Ja bym to jednak widział (tak jak zostało tu już napisane) bardziej na zasadzie integracji narzędzi. System zleceń pozwala wiązać zatwierdzanie zmian w repozytorium z odpowiednim zleceniem. System ten wspomaga tworzenie planu realizacji zlecenia (jak pisałem wyżej – co składa się na jego wykonanie) i na tym poziomie także wiąże z repozytorium. Samo repozytorium może wówczas mieć jeszcze swój system komentarzy, które mogą dodawać nową jakość do zatwierdzanego kodu lub być pomijane.

    Czyli raczej nie metodyka, a bardziej odpowiednie możliwości narzędzia byłyby tutaj przydatne.

  17. PaSkol,
    To nie jest metoda “rekomendowana”, a ciekawostka. Sam z ciekawości zobaczyłem jak to się sprawdza, i raz z tego można spokojnie skorzystać (wtedy mi pomagało), a raz nie. I tak, zgadza się – piszę w kontekście Gita, który jest jedynym słusznym systemem kontroli wersji (chociaż w HG też można takie coś osiągnąć, nawet jeśli nie przez tworzenie pustego commita to przez doklejanie kolejnych zmian), więc problem zawężenia w tym zakresie dla mnie nie istnieje.

    Integracja z systemem do zarządzania projektami nie ma tutaj, jak już pisałem w innych komentarzach, nic do rzeczy.

    • Wiem, że tego nie rekomendujesz, niemniej prosiłeś o opinię – więc taka jest moja ;). Choć rozumiem tak potrzebę panowania nad powstawaniem kodu, jak i pokusę wykorzystania istniejącego narzędzia do czegoś więcej, to jednak wolałbym zorganizować to w inny sposób niż proponowany. Szczególnie, że nie lubię kiedy “chlebak jak sama nazwa wskazuje służy do noszenia granatów” ;).

  18. Nie stosuję CDD, ale wiem jedno – warto przed przystąpieniem do pracy (edycją plików podlegających kontroli wersji) wpisać coś identyfikującego twój przyszły commit. Przypomina mi to nie tylko jaki problem/zagadnienie poruszam w kodzie, ale również np. nazwę shelva.
    Jest to coś w rodzaju good practices.

  19. PaSkol,
    Tak, wiem, gites i dzięki:). A co do wykorzystywania narzędzia tak a nie inaczej… ja wykorzystam każde narzędzie jak tylko się da, nawet jeśli niekoniecznie zostało do tego zaprojektowane (ale akurat tuaj to nie ma zastosowania, bo wykorzystanie gita w ten sposób jest jak najbardziej zgodne z problemem który on rozwiązuje). Akurat jeśli chodzi o gita to widziałem nawet projekt który korzysta z niego zamiast bazy danych, wraz z dostępem do danych zbudowanym na górze – i też jest to bardzo ciekawe. Każda zmiana = commit:), a dane to po prostu pliki tekstowe porozrzucane po odpowiednich folderach. Ale to taka ciekawostka.

  20. Pingback: Kilka słów komentarza o… komentarzach | Maciej Aniserowicz o programowaniu

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ą!