Wątek przeniesiony 2020-02-28 18:08 z Off-Topic przez Krolik.

Refactoring - Jak robić i kiedy merge?

Odpowiedz Nowy wątek
2020-02-28 18:02
Moderator

Rejestracja: 16 lat temu

Ostatnio: 1 dzień temu

0

Temat trochę pokrewny do poprzedniego o długu technicznym, ale jednak tym razem chodzi mi o coś szerszego.

Powiedzmy, że zespół osiągnął konsensus, że kod to kupa mułu i podjął decyzję: REFAKTORUJEMY. Np. zamieniamy wszędobylski static i singletony na DI.

No i teraz jak to zrobić dobrze?

  1. Bierzemy tego kto zaproponował pomysł refaktoringu, dajemy mu pół roku i biedaczysko poprawia aż będzie dobrze, oczywiście w swojej gałęzi. Jak skończy - robimy wielkie review, dajemy kolejne 3 miesiące na uwzględnienie uwag i naprawienie konfliktów i po kolejnych 3 miesiącach w końcu mamy merge i możemy świętować.

  2. Przerabiamy kod stopniowo - najpierw dodajemy nowa infrastrukturę, potem przerabiamy komponent po komponencie, każdy zespół przerabia swój komponent na nową metodę. Jak już wszystkie komponenty są ok, wywalamy ewentualnie resztki starego kodu, który nie jest już potrzebny i robimy merge.

  3. Robimy jeden komponent, merge, oczekujemy trochę na stabilizację, robimy kolejny, znowu merge itd. W międzyczasie w kodzie musimy utrzymywać infrastrukturę dla obu sposobów - czyli niektóre rzeczy mają statici a niektóre są przeniesione na nowy framework. Możliwe, że po drodze trzeba stworzyć jakieś warstwy kompatybilności. Sprzątamy dopiero na końcu jak wszystkie komponenty są przeniesione.

  4. Inne. Jakie?

Zespół takie decyzje podejmuje co tydzień, niestety biznes nie chce zapłacić :( - Dregorio 2020-02-29 09:02
Biznes zawsze płaci - tylko czasem nieświadomie, jak 2 dni przed wydaniem produkt się sypie i nikt nie wie dlaczego, bo nie idzie się połapać w 20-letnim spaghetti. :D - Krolik 2020-02-29 09:31
To swoją drogą :P - Dregorio 2020-02-29 09:47

Pozostało 580 znaków

2020-02-28 18:26

Rejestracja: 5 lat temu

Ostatnio: 3 minuty temu

Lokalizacja: Poznań

12

Najpierw napiszcie testy! (chyba ze juz macie na wszystko) Najlepiej e2e zeby móc sobie orać kod dowolnie. Potem starcie sie kolejno wydzielać komponenty. Im częściej merge tym lepiej, bo dzięki temu nikt nie będzie "z tyłu"


Spring? Ja tam wole mieć kontrole nad kodem ᕙ(ꔢ)ᕗ
Haste - mała biblioteka do testów z czasem.

Pozostało 580 znaków

2020-02-28 18:26

Rejestracja: 13 lat temu

Ostatnio: 6 minut temu

2

Nie widziałem, żeby 1 zadziałało (co nie znaczy, że się nie da). 2 daje efekty bardzo późno, więc jak nie ma wsparcia z góry, to pewnie zostanie ubite w pewnym momencie. 3 jest okej, ale łatwo jest w połowie pracy stwierdzić, że już wystarczy i zostają dwa niekompatybilne rozwiązania.

Bez kodu trudno wyczuć, ale zacząłbym od podejścia 3.

Pozostało 580 znaków

2020-02-28 18:30

Rejestracja: 11 lat temu

Ostatnio: 6 godzin temu

3

1 i 2 nigdy się nie uda na większych projektach. Tylko 3 ale z dodatkiem testów. Więcej można przeczytać w książce "Praca z zastanym kodem. Najlepsze techniki".

Zespoł musi być świadomy, że to jest potrzebne (jak 1 osoba na 10 w zespole widzi problem to dużo nie zdziała w pojedynkę). W refaktoryzacji nie ma pojęcia "koniec", to proces który powinien być codzienną pracą programisty. Testy to bardzo dobre narzędzie do refaktoru, nawet najlepszy kod bez testów to legacy/zastany kod. Jeżeli napiszecie nowy kod który wydaje Wam się lepszy, fajniejszy itp. ale bez testów - to za kilka lat znowu będziecie musieli przechodzić ten sam proces. Testy jednostkowe i ew. integracyjne tylko dla nowego kodu (ale bez rygoru minimalnego pokrycia, to często prowadzi do testów które nic nie testują), dla legacy często nie da się takich napisać więc wystarczą testy end-to-end. Dodatkowo wszystkie narzędzia które pomagają w trzymaniu jakości kodu np. Sonar i mierzeniu tego co zostało poprawione (zespoł jak widzi wykres, że jest mniej duplikacji, mniej staticów itp. to jest bardziej zmotywowany).

O, nie znałem tej książki. Jest wersja po angielsku? To wyślę architektowi w prezencie. - Krolik 2020-02-28 19:32
Oryginał jest po angielsku ;) - Markuz 2020-02-28 19:32
Tytuł lub autor? - Krolik 2020-02-28 19:33
Working Effectively with Legacy Code, autor ten sam - Michael Feathers - Markuz 2020-02-28 19:33

Pozostało 580 znaków

2020-02-28 18:33

Rejestracja: 16 lat temu

Ostatnio: 1 godzina temu

Lokalizacja: Kraków

4

Również głosuję na 3, żyjemy w czasach agilowych, które nastały właśnie dlatego że big bangowe podejście 1) prawie nigdy się nie sprawdzało bez względu czy tyczy się to refaktoringu czy nowego developmentu. Chcemy jak najszybciej uzyskać feedback że nic nie popsuliśmy i że zmierzamy w dobrym kierunku. Kroimy malutki kawałeczek, przepisujemy go tak by testy były dalej zielone, jak nie mamy testów to pierw testy piszemy, wrzucamy na produkcję i zbieramy metryki(validated learning), robimy retrospekcję, jak wszystko śmiga pięknie powtarzamy całą pętle.


It's easy to hate code you didn't write, without an understanding of the context in which it was written.
edytowany 2x, ostatnio: neves, 2020-02-28 18:53

Pozostało 580 znaków

2020-02-28 18:55

Rejestracja: 3 lata temu

Ostatnio: 1 godzina temu

1
Markuz napisał(a):

1 i 2 nigdy się nie uda na większych projektach. Tylko 3 ale z dodatkiem testów. Więcej można przeczytać w książce "Praca z zastanym kodem. Najlepsze techniki".

E tam się nie uda...
Ja właśnie sam robię refaktoring typu 1, tylko że nie miałem pół roku tylko jakieś 2 tygodnie (miałem dziś skończyć, oczywiście nie skończyłem :D ). Testów nie ma, chyba że je napiszę, ale nie planuję, bo nigdy nie skończę. Review to też może mi zrobi 1-2 osoby, bo nikt więcej nie rozumie co się tam dzieje. Projekt na kilkadziesiąt klas, dość złożony, dużo wielowątkowości, algorytmiki, konwolucyjnych sieci neuronowych, mieszany kod C++/CUDA, przetwarzanie obrazów. W międzyczasie naprawiam biblioteki zależne i budowanie paczek debianowych :)

Pozostaję optymistą :)

Nie przepadam za takimi rozwiązaniami, zazwyczaj pomagasz tylko sobie (będziesz lepiej znał cały system) a nie zespołowi (o ile masz zespoł), dla osoby z zewnątrz to nadal będzie tak samo niezrozumiały kod (i wprowadzanie poprawek bez testów będzie tak samo bolało) - mam nadzieję, że przynajmniej zwiększysz jego wydajność (o ile to badasz w jakiś sposób). Musiałbym Cię mocno lubić/ufać żeby z miejsca nie odrzucić PR z takim refaktorem ;) - Markuz 2020-02-28 19:30
Kilkadziesiąt klas to nie jest duży projekt, chyba że te klasy mają po 10000 linii, ale to wtedy w sumie nawet jakby była jedna, to współczułbym. - Krolik 2020-02-28 19:31
@Markuz: owszem, pomagam sobie, bo pewnie tylko ja będę dalej rozwijał ten projekt. Jeśli mój PR nie będzie zaakceptowany, to równie dobrze można zamrozić ten projekt i go dalej nie rozwijać. @Krolik, nie pisałem że projekt jest duży, natomiast jest dość skomplikowany. - GutekSan 2020-02-28 19:49

Pozostało 580 znaków

2020-02-28 19:57

Rejestracja: 1 rok temu

Ostatnio: 46 minut temu

Lokalizacja: DC

2
Krolik napisał(a):
  1. Bierzemy tego kto zaproponował pomysł refaktoringu, dajemy mu pół roku i biedaczysko poprawia aż będzie dobrze, oczywiście w swojej gałęzi. Jak skończy - robimy wielkie review, dajemy kolejne 3 miesiące na uwzględnienie uwag i naprawienie konfliktów i po kolejnych 3 miesiącach w końcu mamy merge i możemy świętować.

Bardzo optymistyczne założenie o szampanie po roku. Ale bardziej niesamowite byłoby to review półrocznej pracy człowieka posadzonego sam na sam na pół roku z kodem. Oczywiście testów jak nie było wcześniej tak po pół roku też nie będzie.


"Ktoś sobie uświadomił, że pisał pod pseudonimem rzeczy, które lepiej żeby w firmie nie wypatrzyli :-)"
"Kiedy wiedzieć czy zacząć nauke Springa? bo w czystej Javie to nic ciekawego nie zrobie chyba"
Nie bądź takim pesymistą, testy w projekcie są. - Krolik 2020-02-28 22:04
Ale można na nich polegać czy po prostu "są", czytaj "jakieś testy kiedyś napisano i to co pokrywają nie wywalają"? Bo później terminy goniły i już na testy nie było czasu. - BraVolt 2020-02-28 22:11
Płynna granica pomiędzy pesymistą a realistą :) - BraVolt 2020-02-28 22:11
Testy są, pokrycie dość dobre, natomiast większy problem jest taki że wykonanie wszystkich zajmuje kilka godzin na klastrze. No i jest niewielki odsetek testów niestabilnych. - Krolik 2020-02-29 07:57

Pozostało 580 znaków

2020-02-28 22:14
Moderator

Rejestracja: 16 lat temu

Ostatnio: 53 sekundy temu

2
  • Robimy porządne pokrycie testami akceptacyjnymi, integracyjnymi, e2e
  • Wystawiamy jakiś ogólny interfejs modułu, tak żeby pomiędzy sobą moduły w ogóle nie wiedziały o internalsach i komunikowały się tylko i wyłącznie tym abstrakcyjnym interfejsem
  • Przerabiamy ten moduł i podmieniamy

Czyli generalnie opcja 3. Plus jest taki że szybko werfykujesz czy to w ogóle działa. I nie ma też takiego problemu, że dochodzą nowe ficzery i trzeba je klepać 2 razy (raz w nowym raz w starym systemi). Im szybciej wypchniesz coś co działa, tym lepiej.

Ale dużo zależy od tego jak wygląda aktualny stan i co chcecie osiągnąć. Bo może nie warto trzymać się starego interfejsu.?

Opcja 1 czy 2 mają sens jeśli mozecie sobie pozwolić na freeze produktu (bo np. jest tam już tylko maintenance), szczególnie kiedy wiecie ze chcecie to na pewno zaorać i zrobić od nowa. Jeśli da sie coś "uratować" to opcja 3 zawsze będzie lepsza.

Robiłem ostatnio taki "refaktor" gdzie nie dało się uratować nic. Projekt klepany z 10 lat temu, Spring 2, Hibernate w xmlach, a do tego jeszcze jakiś webowy framework który umarł z 5 lat temu i cała logika aplikacji sklejona z tym webowym frameworkiem albo pisane "na piechote". Jakieś oczywistości jak zwrócenie z kontrolera InputStreama pisane ręcznie przez pisanie w pętli do httpservletresponse itd.
Oczywiście monolit więc nawet nie bardzo jak przepisywać coś po kawałku, bo nie da się wydzielić modułu.
W takiej sytuacji po prostu nie da się inaczej niż 1/2.


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...
edytowany 2x, ostatnio: Shalom, 2020-02-28 22:21

Pozostało 580 znaków

2020-02-29 09:45

Rejestracja: 6 lat temu

Ostatnio: 58 minut temu

1

Bierzemy tego kto zaproponował pomysł refaktoringu, dajemy mu pół roku i biedaczysko poprawia aż będzie dobrze, oczywiście w swojej gałęzi

Przez pół roku to można przepisać całą aplikację, a nie tylko zrefaktorować...

Dajcie mu pół tygodnia, niech zrefaktoruje moduł, zmerdżuje się, potem następny moduł itp.

Jak skończy - robimy wielkie review, dajemy kolejne 3 miesiące na uwzględnienie uwag i naprawienie konfliktów i po kolejnych 3 miesiącach w końcu mamy merge i możemy świętować.

= Waterfall.

Nie sądzę, żeby to się sprawdziło.

Przerabiamy kod stopniowo - najpierw dodajemy nowa infrastrukturę, potem przerabiamy komponent po komponencie, każdy zespół przerabia swój komponent na nową metodę. Jak już wszystkie komponenty są ok, wywalamy ewentualnie resztki starego kodu, który nie jest już potrzebny i robimy merge.

No, tu już rozsądniej. Chociaż merge ja bym robił jak najszybciej (Robimy jeden komponent, merge, oczekujemy trochę na stabilizację, robimy kolejny, znowu merge), żeby od razu wykryć, czy coś działa, czy nie.

oczekujemy trochę na stabilizację

Napiszcie sobie testy, to wtedy od razu będziecie wiedzieli, czy nie ma jakichś bugów itp.


((0b10*0b11*(0b10**0b101-0b10)**0b10+0b110)**0b10+(100-1)**0b10+0x10-1).toString(0b10**0b101+0b100);
edytowany 1x, ostatnio: LukeJL, 2020-02-29 09:47
Testy nigdy nie wyłapia wszystkiego, ale oczywiście zgoda - testy są bardzo ważne. - Krolik 2020-02-29 15:10
Nie muszą wyłapać wszystkiego, ważne, żeby wyłapały to, czy dana funkcjonalność działa po refaktorze tak samo poprawnie jak przed refaktorem. - LukeJL 2020-02-29 15:18
Tak, zgoda. Natomiast wyraziłem się trochę nieprecyzyjnie - chodziło mi też o zebranie opinii wśród innych programistów, którzy zetkną się z nowym API. Czyli dajemy szansę nowemu API się trochę ułożyć w projekcie, zanim będzie stosowane wszędzie. - Krolik 2020-02-29 20:28

Pozostało 580 znaków

2020-03-11 12:50

Rejestracja: 4 lata temu

Ostatnio: 2 godziny temu

Lokalizacja: Warszawa

1

Przy refacoringu takich starych kobył mi się sprawdza algorytm postępowania w stylu:

  1. Staram się napisać testy pokrywające wszystkie "odnogi", przypadki refaktorowanego kodu.
  2. Dopiero wtedy siadam do poprawiania.
  3. Na bieżąco sprawdzam/aktualizuje testy.
  4. Przypisuję wyjadaczy projektowych do code review swojego PR (bo czasami wywalasz coś myśląc, że "po co komu to tutaj potrzebne", a gość pracujący 5 lat w projekcie mówi Ci, że jakiś syf, o którym nigdy nie słyszałeś z tego korzysta i bez tego wszystko je**ie).

Dosyć żmudny sposób, ale już się przejechałem na tym, że jak coś się poprawia w projekcie ze sporym długim technicznym, to jest to najrozsądniejszy i najbardziej opłacalny na dłuższą metę sposób.
Chociaż cięższe od samego sposobu jest raczej przekonanie biznesu, że taka robota jest warta zachodu mimo, że nie widzą na oczy żadnych efektów i nie dowozimy im nowych, bajeranckich ficzerów. :D

edytowany 1x, ostatnio: LowSkiller, 2020-03-11 12:56
Chociaż cięższe od samego sposobu jest raczej przekonanie biznesu, że taka robota jest warta zachodu https://www.youtube.com/watch[...]p;feature=youtu.be&t=1789 - iksde 2020-03-28 11:35

Pozostało 580 znaków

2020-03-28 00:44

Rejestracja: 4 lata temu

Ostatnio: 9 minut temu

Lokalizacja: UK

2

Do mniejszego refactoringu najlepiej wprowadzić w życie Boy Scout Rule (lub zależnie od poglądów ideologicznych po prostu Scout Rule). Innymi słowy- poprawiamy kod w ramach codziennej pracy nad taskami.

Jeśli chodzi o większe zmiany to nie obejdzie się bez wkładu/akceptacji biznesu, a szczegóły naprawdę zależą od natury zmian, projektu i kultury pracy. Moim zdaniem najzdrowszym podejściem jest zaangażowanie większości programistów w projekcie. Jeśli w projekcie używa się np. Scrum to poświęcamy całe iteration na refactoring- żadnych nowych funkcjonalności, wszystkie taski napisane pod poprawę istniejącego kodu/architektury.

Obecnie u mnie w pracy będzie to miało miejsce więc zapowiada się ciekawie :)


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Dokładnie, 20% pracy zrobi 80% celu - Charles_Ray 2020-03-28 11:23

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0