Jak poradzić sobie z refaktoryzacją, która trwa dłużej niż jeden sprint?

49

Pracuję z bazą kodu, która ma ponad 500 000 linii kodu. Poważnie potrzebuje refaktoryzacji. Zidentyfikowano wysiłki refaktoryzacyjne, które potrwają dłużej niż normalny dwutygodniowy sprint. Nie można ich podzielić na mniejsze zadania, jak sugerowałem w innych odpowiedziach na tej stronie. Produkt musi działać pod koniec iteracji, a częściowe refaktoryzacja pozostawi system w stanie niezdatnym do użytku, ponieważ zależność między elementami jest straszna. Więc jaki byłby najlepszy sposób na zbliżenie się do tej przeszkody? Ponownie wspominam, że rozbicie go na mniejsze części nie jest opcją, co już zostało zrobione.

Aktualizacja: Wydaje się, że ludzie potrzebują wyjaśnienia, dlaczego nie można tego dopasować do dwutygodniowego sprintu. W sprincie chodzi o coś więcej niż tylko pisanie kodu. Mamy zasady braku kodu bez testów. Ta polityka nie zawsze istniała i znaczna część bazy kodu jej nie ma. Również niektóre z naszych testów integracyjnych są nadal testami ręcznymi. Nie chodzi o to, że samo refaktoryzowanie jest tak duże. Wynika to z faktu, że niewielkie zmiany mają wpływ na wiele części systemu i musimy upewnić się, że te części nadal działają poprawnie.

Nie możemy odłożyć ani przedłużyć sprintu, ponieważ mamy comiesięczne poprawki. Tak więc zmiana rozciągająca się po sprincie nie może zatrzymać innych prac dodawanych do poprawki.

Refaktoryzacja a przeprojektowanie: Tylko dlatego, że nasz proces rozwoju nie jest wystarczająco wydajny, aby poradzić sobie z refaktoryzacją w cyklu dwutygodniowym, nie gwarantuje zmiany nazwy na przeprojektowanie. Chciałbym wierzyć, że w przyszłości moglibyśmy wykonać dokładnie to samo zadanie w ciągu dwóch tygodni, gdy nasz proces ulegnie poprawie. Kod, o którym tu mowa, nie musiał się zmieniać od bardzo dawna i jest dość stabilny. Teraz, gdy kierunek działalności firmy staje się coraz bardziej dostosowywalny do zmian, chcemy, aby ta część podstawy kodu była równie elastyczna jak reszta. Co wymaga refaktoryzacji. Na podstawie odpowiedzi tutaj widać, że brakuje rusztowań niezbędnych do tego, aby refaktoryzacja działała w czasie normalnych sprintów.

Odpowiedź:

Zamierzam wykonać podejście rozgałęzienia i scalenia, które zaproponował Corbin March po raz pierwszy, abyśmy mogli dowiedzieć się więcej o tych obszarach problemowych i jak zidentyfikować brakujące testy. Myślę, że idąc naprzód, powinniśmy zastosować podejście zaproponowane przez Buhb w celu zidentyfikowania obszarów, w których brakuje testów, i najpierw je wdrożyć, a następnie dokonać refaktoryzacji. Pozwoli nam to zachować normalny dwutygodniowy cykl sprintu, tak jak wielu tutaj mówiło, że zawsze powinno być tak w przypadku refaktoryzacji.

Charles Lambert
źródło
23
Na marginesie, jest to z definicji przeprojektowanie na dużą skalę, a nie refaktoryzacja . Mam nadzieję, że nie traktujesz tego jako głupoty - IMHO jest ważne, aby używać jasnej terminologii, aby uniknąć problemów z komunikacją :-)
Péter Török
9
@Charles: „Refaktoryzacja jest zwykle wykonywana małymi krokami. Po każdym małym kroku pozostaje ci działający system, który funkcjonalnie pozostaje niezmieniony. Cytat ze strony, którą zamieściłem powyżej.
Péter Török
2
@Charles: refaktoryzację zawsze można wykonać przyrostowo, utrzymując system w działaniu. umieść duży komentarz „Trwa proces refaktoryzacji” u góry klasy / pakietu / modułu, który jest refaktoryzowany, i rób części pojedynczo. Jeśli wycinasz tymczasowe wydanie, gdy model obiektu jest w trakcie przejścia, to w porządku.
Sean McMillan
7
Jeśli wykonujesz tak duże kroki, że nie możesz regularnie mieć działającego kodu, to jest właśnie definicja, kiedy refaktoryzacja staje się przeprojektowana. Nie gniewaj się na ludzi za to, że dzwonią do ciebie z powodu niewłaściwego użycia tego słowa. Nie ma nic złego w pytaniu o przeprojektowanie. Komentatorzy starają się jedynie wskazać, że nie dostaniesz pożądanych odpowiedzi, ponieważ niewłaściwie używasz tego słowa, co już się stało.
jprete
5
Wiem, że to trochę nie na temat, ale martwisz mnie, jakie są okoliczności, które uniemożliwiają refaktoryzację małymi krokami. Proszę podzielić się nieco więcej na ten temat.
Buhb

Odpowiedzi:

14

Jeśli masz luksus opóźniania refaktoryzacji, sugeruję skoncentrowanie nadchodzących iteracji na dodaniu testu jednostkowego i automatycznych testów integracji do punktu, w którym możesz wygodnie refaktoryzować bazę kodu, a następnie refaktoryzować w jednym sprincie.

Buhb
źródło
68

Moja sugestia:

  1. Utwórz oddział
  2. Łącz codziennie z pnia do oddziału i rozwiązuj konflikty.
  3. Pracuj, aż to się skończy. Twoja gałąź może być poza podstawowym rozwojem przez kilka sprintów.
  4. Scal z powrotem do bagażnika.

Nie można obejść faktu, że prawdopodobnie stanie się brzydka. Nie zazdroszczę ci. Z mojego doświadczenia wynika, że ​​gdy drastycznie zmienisz projekt, łatwiej jest połączyć ciągły rozwój w nowy paradygmat, a nie jakoś scalić nowy paradygmat w zmieniony teraz bagażnik po zakończeniu. Nadal będzie bolało.

Corbin March
źródło
1
Omówiliśmy stosowanie tego podejścia i jeśli żadne inne pomysły nie pojawią się, zanim je rozwiążemy, właśnie to planujemy zrobić.
Charles Lambert
3
Obawiam się, że będziesz mieć dużo kosztów ogólnych łączących się w tę iz powrotem między pniem a gałęzią, jeśli chcesz przeprowadzić tak dokładne refaktoryzację.
Giorgio
W większości przypadków (mam nadzieję) te scalone zmiany nie wpłyną na omawiany kod tutaj. Nie miałbym nic przeciwko przedłużeniu osi czasu dla tej zmiany, jeśli zapewni ona wiarygodny wynik.
Charles Lambert
1
Biorąc pod uwagę zmienność, którą wydaje się sugerować Twoja prezentacja, być może powinieneś rozważyć Git , ponieważ ułatwia to spekulacyjne rozgałęzianie i łączenie.
John Tobler,
1
@Giorgio: ja też, codzienne łączenie wydaje się nieco paranoiczne, ale tak naprawdę zależy to od wielkości zespołu. Im więcej osób, tym więcej zmian i tym częściej powinieneś się łączyć. Dzienny wydaje się jednak dolny limit, jeśli chcesz mieć czas na pracę.
Matthieu M.,
40

Nie każde zadanie można wykonać w (sztucznym) 2-tygodniowym sprincie, dlatego potrzebny jest zdrowy rozsądek. Jeśli nie można go już rozbić i trzeba to zrobić, po prostu idź i zrób to. Proces ten nie jest ważniejszy niż wynik końcowy i powinien być postrzegany raczej jako wytyczna niż prawo, którego nigdy nie należy łamać.

Chris Card
źródło
3
Twoja odpowiedź to bardzo dobra informacja na ten temat. Jestem tutaj, aby „wsiąść i zrobić to”, jak mówisz. Zadałem to pytanie w nadziei, że uzyskam trochę informacji, żebym mógł wymyślić proces równoległy do ​​mojego istniejącego lub w jakiś sposób zmodyfikować bieżący proces, aby rozwiązać moją obecną sytuację. Potrzebuję czegoś, aby powiedzieć programistom, aby mieli wytyczne, w których powinni pracować, ponieważ będzie to miało miejsce przynajmniej 2 razy.
Charles Lambert
+1 za „Proces ten nie jest ważniejszy niż wynik końcowy i powinien być postrzegany raczej jako wytyczna niż nigdy nie łamane prawo”. - Ludzie naprawdę to zapominają.
Bjarke Freund-Hansen
32

Po prostu zrób 3, 4 lub 5 tygodniowy sprint. Kogo to obchodzi? Jesteś oczywiście przekonany, że nic nie da się zrobić w krótszym czasie, więc przestań z tym walczyć.

Tylko nie mów swoim towarzyszom w Royal Society of Blind Agile Adherance.

JeffO
źródło
wydaje się, że ze względów organizacyjnych (comiesięczne poprawki), 2-tygodniowe sprinty są dość trudne do zmiany.
Steve Bennett,
10

Polecam zacząć od książki Efektywnie działający z kodem Legacy autorstwa Michaela Feathersa. Obejmuje różne techniki zmniejszania zakresu zmian w stylu refaktoryzacji.

kdgregory
źródło
Dobra książka na pewno, ale nie sądzę, że obejmuje dzielenie refaktoryzacji na wiele sprintów.
Adam Lear
4
Daję +1, ponieważ jest to prawdopodobnie najlepsza książka na początek, kiedy zaczniesz uczyć się, jak mówi tytuł, efektywnej pracy ze starszym kodem. Jest odpowiedni dla kogoś, kto może zadać to pytanie i nie rozumie, co wiąże się z dzieleniem rzeczy na mniejsze kroki.
Charles Lambert
@Anna - wtedy możesz (ponownie) przeczytać rozdział 25, który mówi o technikach przełamywania rodzajów połączeń, które zapobiegają drobnym zmianom.
kdgregory,
@kdgregory Do przyjęcia. :) Czy możesz dodać tę odpowiedź do swojej odpowiedzi, aby była bardziej niesamowita?
Adam Lear
7

W naszym sklepie, gdy mamy duże zadania refaktoryzacji lub przepisywania, których nie można wykonać w oknie wydania, pozostawiamy funkcjonalność taką, jaka jest w systemie. Ale zaczynamy od nowych, odnowionych funkcji klocków Lego, jeśli czas na to pozwala. W końcu dochodzimy do stanu, w którym mamy wystarczająco dużo klocków Lego, że sprint zapewnia wystarczającą ilość czasu, aby podłączyć klocki Lego do aplikacji i włączyć ją dla użytkowników.

Mówiąc ściślej, rozkładamy lub przerabiamy duże funkcje przy użyciu nowych nazw. Następnie na koniec używamy naszej przemianowanej, przebudowanej pracy zamiast nieprzyjemnego starego kodu.

Amy Anuszewski
źródło
To dobry pomysł, ale wdrożenie go wymagałoby wysokiego poziomu komunikacji. Na przykład, gdy koduję, jeśli zidentyfikuję metodę, która nigdzie nie jest używana i nie jest publiczna, usunę ją.
Charles Lambert,
5

Poświęć jeden sprint, aby dowiedzieć się, jak utrzymać prawidłowe działanie kodu w środku refaktora. Może to przybrać formę przestarzałych metod i klas, opakowań, adapterów i tym podobnych. Refaktoryzacja może spowodować, że kod stanie się bardziej brudny przez krótki czas, aby zapewnić czystsze działanie w dłuższej perspektywie; W porządku. W tej chwili mówisz, że nie da się tego zrobić. Nie sądzę, że to prawda - pomyśl o tym, jak przebiegałby Twój proces, gdyby można go było wykonać, pomyśl, jakie kroki możesz podjąć, aby to zrobić. Następnie zanurkuj.

Carl Manaster
źródło
Zrobiliśmy już to wszystko. Z tego powodu jasno wyraziłem, że nie można go rozbić.
Charles Lambert
Naprawdę? Spędziłeś cały sprint, po prostu planując refaktoryzację bez zepsucia systemu, i nic nie wymyśliłeś? Trudno mi uwierzyć, że dedykowany sprint planowania nie przyniósł niczego; być może musisz przyprowadzić konsultanta (i nie, nie jestem jednym, nie próbuję dostać koncertu).
Carl Manaster
1
Nic takiego nie powiedziałem. Mówiłem, że przeszliśmy przez proces podobny do tego, który opisałeś i wyszliśmy na drugim końcu z kodem, którego nie można zrefaktorować za pomocą jednego sprintu.
Charles Lambert
Powiedziałem: „Poświęć jeden sprint, aby dowiedzieć się, jak utrzymać prawidłowe działanie kodu w środkowej fazie refaktora”. Powiedziałeś: „Zrobiliśmy już to wszystko”. Czy teraz mówisz inaczej? Przepraszam, jeśli to brzmi spornie, ale nie rozumiem.
Carl Manaster
5

+1 od odpowiedzi Corbin Marcha, dokładnie o tym myślałem. Wygląda na to, że baza kodu jest trochę brzydka i jej wyczyszczenie zajmie więcej niż jeden cykl sprintu.
Tak jak powiedział Corbin:

  1. rozgałęzić w „projekt refaktoryzacji”
  2. sprawdź swoją zmianę oddziału
  3. promuj w swoim środowisku testowym do testowania jakości
  4. przyrostowo scal je z powrotem do bagażnika, aż do zakończenia refaktoryzacji.

Jestem pewien, że nie miałbyś żadnych problemów ze sprzedaniem tego swojemu menedżerowi programistów, jeśli twoi premierzy mają trudności z zobaczeniem tego, to wyjaśnij im, że Rzym nie został zbudowany w ciągu jednego dnia i sprzątając wszystkie śmieci wyrzucone do Rzymu ulice też nie zostaną ukończone w ciągu jednego dnia. Refaktoryzacja zajmie trochę czasu, ale ostatecznie będzie tego warta pod względem łatwiejszej konserwacji, szybszych wydań ulepszeń, mniej biletów produkcyjnych i bardziej spełnionego SLA.

bkdraper
źródło
1
Mam całą amunicję, której potrzebuję, aby nakłonić wszystkich. Potrzebuję tylko oficjalnego planu jego wykonania, kiedy go przedstawię. Z odpowiedzi tutaj nie mam wątpliwości, że wymyślę powtarzalne rozwiązanie.
Charles Lambert
4

Chociaż przeprojektowanie, które naprawdę chcesz zrobić, jest dużym zadaniem, czy byłoby możliwe przefakturowanie mniejszych elementów w celu rozbicia / oddzielenia poszczególnych zależności? Wiesz - w razie wątpliwości dodaj pośrednictwo. Każde z tych oddzieleń powinno być mniejszym zadaniem niż gigantyczne, którego nie można wykonać.

Po usunięciu zależności powinieneś być w stanie rozbić pozostałe zadania refaktoryzacji, aby uzyskać je w ramach sprintu.

Matthew Flynn
źródło
3

W projekcie, nad którym obecnie pracuję, używamy 4-tygodniowych sprintów. Czasami nie możemy ukończyć historii użytkownika i po prostu restartujemy ją podczas następnego sprintu.

Jednak IMHO powinno być możliwe rozbicie refaktoryzacji na mniejsze historie pasujące do 4-tygodniowego sprintu. Jeśli nie możesz doprowadzić kodu do spójnego stanu w ciągu 4 tygodni, mam wrażenie, że przepisujesz aplikację, a nie ją refaktoryzujesz.

Giorgio
źródło
powinien to obejmować 4-tygodniowy sprint. Nie możemy jednak zatrzymać bieżących 2-tygodniowych sprintów z powodu innych poprawek błędów itp. Musiałoby to obejmować więcej niż jeden sprint. Stąd sedno mojego problemu.
Charles Lambert
Jak powiedziałem, używamy 4 tygodniowych sprintów, a jeśli historia nie zostanie ukończona w ciągu 4 tygodni, po prostu planujemy ją na następny sprint. Czy możesz mieć przynajmniej system w spójnym stanie pod koniec 2-tygodniowego sprintu (a następnie kontynuować podczas następnego sprintu)?
Giorgio
Nie weryfikowalne spójne państwo.
Charles Lambert
Muszę dodać falę do wysiłku, jaki inni włożyli w nadzieję, że znajdziesz inne słowo do użycia zamiast „refaktoryzacji”. Refaktoryzacja jest dobrze zdefiniowana, a jej zakres jest znacznie bardziej bezpośredni i krótkoterminowy niż masywne i czasochłonne przeprojektowanie i przeprogramowanie, które należy wykonać.
John Tobler,
2

Zalecam, aby w przypadku gdy niektóre zadania potrwają dłużej niż 2-tygodniowy cykl sprintu, zadanie zostanie zaplanowane na inny czas. Twój zespół stwierdził potrzebę refaktoryzacji i to jest ważne. Czasami nie ma innej opcji ... i tak, to jest do kitu.

Kiedy nadejdzie czas na rozpoczęcie refaktoryzacji, po prostu zawiesisz normalne sprinty. Nie masz wyboru. Używaj inteligentnej kontroli wersji - rozgałęzianie, refaktoryzacja, testowanie, scalanie. Zawsze jest moment, w którym refaktoryzacja niektórych dużych projektów ma pierwszeństwo przed funkcjami. Jeśli to możliwe, spróbowałbym również rozdzielić obawy dotyczące większej elastyczności.

rev. IAbstract
źródło
Nie możemy odłożyć tego na zawsze, a twoja odpowiedź nie dotyczy sposobu przeprowadzenia refaktoryzacji.
Charles Lambert
@Charles: „planowane na inny czas”. ;) Nie powiedziałem, że anuluj projekt.
IAbstract
2

Po tym, jak ostatnio przeszedłem ten sam problem z częścią naszej bazy kodów (która jest również nieco większa), mam nadzieję, że mogę podzielić się z tobą kilkoma spostrzeżeniami. W mojej sytuacji baza kodu została opracowana przez inny zespół, więc nikt z pierwotnych programistów nie był zaangażowany w to refaktoryzowanie. Moje doświadczenie z bazą kodową trwało około 1 roku, a inny programista zlecił to 2 lata.

Proszę pozwolić mi na dwie małe notatki dotyczące innych odpowiedzi tutaj:

  • Rozgałęzienie pomoże ci założyć plac zabaw dla siebie, ale nigdy nie łącz swoich zmian w pień w jednym dużym zestawie zmian. Wpadniesz w poważne kłopoty z resztą zespołu.
  • Musisz to robić stopniowo i można to zrobić. Bez wymówek. Przeczytaj Efektywna praca ze starszymi kodami od początku do końca. Przeczytaj to ponownie.
  • Myślenie, że możesz to zrobić, jeden duży krok jest błędem. Chociaż wydaje się, że to więcej pracy, robienie tego stopniowo jest znacznie łatwiejsze do zarządzania.

Pozornie brak rezerwacji przez dwa tygodnie lub dłużej nie pozostanie niezauważony. Musisz zapewnić wsparcie ze strony kierownictwa projektu, a co ważniejsze, zespołu. Jeśli zespół nie jest zaangażowany w tę refaktoryzację (a to oznacza, zrób to teraz, nie w odległej przyszłości), wpadniesz w kłopoty.

Nie rób tego sam, użyj programowania par. Nie oznacza to ściśle, że musisz cały czas siedzieć przed tą samą klawiaturą, ale możesz indywidualnie obsługiwać małe i wąskie zadania (np. Pisać testy, które wychwytują zachowanie tej klasy).

Wykonaj refaktoryzację Scratch i traktuj ją jako taką. (Coś w rodzaju „wyrzucania” prototypów, bit „wyrzucania” jest ważny!) Szczerze mówiąc, jest mało prawdopodobne, abyś wiedział, jakie będą implikacje, jakie będzie miało to działanie. Refaktoryzacja od zera pomoże ci pod pewnymi względami:

  • Odkryjesz elementy systemu, o których istnieniu nigdy nie wiedziałeś.
  • Będziesz miał znacznie lepszy widok na sposób łączenia modułów
  • Odkryjesz nowy sposób grupowania systemu w moduły, prawdopodobnie znacznie różniący się od obecnego zrozumienia. Omów spostrzeżenia ze swoim partnerem. Spróbuj wyrazić swój nowy pogląd. Napisz krótki oficjalny dokument dotyczący architektury (lub narysuj schemat), który mówi, gdzie obecnie są rzeczy i gdzie powinny one logicznie należeć.

Po zakończeniu refaktoryzacji mam nadzieję, że odkryjesz, że nie możesz po prostu wszystko zmienić. Będziesz się źle czuć, to po prostu wielki tłusty bałagan i nie możesz po prostu nacisnąć przełącznika i sprawić, by działał. Tak mi się stało, może być inaczej w twojej sytuacji.

Jednak mój partner i ja lepiej rozumiemy nasz system. Teraz byliśmy w stanie zidentyfikować indywidualne, mniejsze (choć wciąż duże) refaktoryzacje / przeprojektowania. Uchwyciliśmy naszą wizję systemu na schemacie i udostępniliśmy go zespołowi wraz z elementami zaległości, które wymyśliliśmy, aby zrealizować tę wizję. Dzięki wspólnemu konsensusowi zdecydowaliśmy, które elementy będziemy wdrażać w trakcie następnej iteracji.

Ostatnią rzeczą, która pomogła nam, była duża tablica. W twojej głowie jest zbyt wiele rzeczy. Bardzo ważne jest, aby robić notatki. Napisz notatkę podsumowującą na koniec dnia, rejestrując to, co zrobiłeś dzisiaj i chcesz zrobić jutro. Pomaga zrelaksować się w dużych czasach i potrzebujesz relaksu, jeśli chcesz nadążyć za tym zadaniem. Powodzenia!

Johannes Rudolph
źródło
1

Uruchom okno konserwacji, podczas którego nie będzie przeprowadzany dalszy rozwój. Wykonaj przeprojektowanie, a następnie wznów sprinty programistyczne.

Christopher Mahan
źródło
0

Mamy do dyspozycji dwa rodzaje prac:

  1. Roboczogodziny
  2. Geniusz działa

Refaktoryzacja zazwyczaj składa się z pierwszego rodzaju pracy, ponieważ wiele metod jest już znanych programistom, takim jak DRY , SRP , OCP , DI itp. Tak więc kiedy projekt wymaga refrakcji przez dwa miesiące, po prostu zajmuje dwa miesiące , nie da się tego obejść. Tak więc moją propozycją byłoby, aby nie refaktoryzować oryginalnego projektu i pozwolić mu działać w obecnej sytuacji. Przestań otrzymywać nowe zapytania i wymagania od interesariuszy i właściciela produktu . Następnie pozwól zespołowi pracować nad projektem, aż zostanie on zrefaktoryzowany i gotowy do pracy.

Saeed Neamati
źródło
0

Jedna sugestia, która może pomóc: Jeśli masz niesprawdzony kod i nie masz wystarczającej ilości czasu na jego refaktoryzację i ponowne przetestowanie w ciągu dwutygodniowego sprintu, rozważ najpierw wprowadzenie innych niepowiązanych niewielkich zmian w kodzie, abyś mógł się skupić na pisanie testów dla pierwszego lub dwóch sprintu. Być może możesz zidentyfikować kilku nieprzetestowanych klientów kodu, który chcesz refaktoryzować; wybierz jednego klienta i dokonaj innych użytecznych zmian w firmie, które zmuszą cię do napisania testów dla tego klienta. Po zapoznaniu się z kodem, po pracy z nim i przeprowadzeniu większej liczby testów, i być może wykonałeś kilka drobnych poprawek, będziesz w znacznie lepszej sytuacji, aby dokonać refaktoryzacji i (teraz łatwiej ) testowanie obu w jednej iteracji.

Innym podejściem jest wykonanie kopii niepoprawnego kodu, refaktoryzacja go, a następnie przenoszenie klientów pojedynczo do nowego kodu. Ta praca może być podzielona na wiele iteracji.

I nie poddawaj się: nie akceptuj, że dużego refaktoryzacji nie można podzielić na mniejsze etapy. Najłatwiejsze / najszybsze / najlepsze podejście może potrwać dłużej niż iteracja. Ale to nie znaczy, że nie ma możliwości robienia kawałków wielkości iteracji.

Jeff Grigg
źródło