Gdzie refaktoryzacja kodu i optymalizacja powinny mieścić się w ramach osi czasu zwinnego i wodospadowego?

10

Wydaje się, że zespół zarządzający projektem uważa, że ​​„to działa” oznacza, że ​​należy go uznać za w 100% kompletny. Większość programistów wie, że nie zawsze tak jest. Jeśli próbuję zastosować alternatywne metody, aby uruchomić jakąś funkcjonalność, nie musi to wcale oznaczać, że znalazłem najlepsze rozwiązanie, albo nie będzie wymagać ponownej pracy po przejrzeniu z innymi programistami. Często skończę z czymś, cofam się, a potem zadaję sobie pytanie, co mogę zrobić lepiej po spełnieniu reguł biznesowych. Czy ten czas „mogę zrobić lepiej” rzeczywiście mieści się gdzieś na osi czasu? Uważam, że najlepszym podejściem jest to, że zawsze zostawiasz kod lepiej niż wtedy, gdy go znalazłeś (do pewnego stopnia), co może oznaczać refaktoryzację po uruchomieniu. Jednak,


źródło

Odpowiedzi:

13

Istnieje jedna nadrzędna zasada, która reguluje potrzebę refaktoryzacji i optymalizacji, zarówno w wodospadzie, jak i Agile: YAGNI (You Ain't Gonna Need It). Druga zasada jest następstwem pierwszej: „Przedwczesna optymalizacja jest źródłem wszelkiego zła”, kodującym odpowiednikiem ogólnego przysłowie „wrogiem doskonałości jest doskonałość”.

Weźmy progi i zastosujmy je. Wymagane jest zbudowanie algorytmu ETL, który pobiera plik określonego typu, wyodrębnia jego informacje, a następnie umieszcza te informacje w bazie danych. Twoim celem na ten tydzień (dla naszych celów nie ma znaczenia, czy jesteś w sklepie Agile, czy SDLC), jest to zrobić.

Jesteś sprytnym człowiekiem i dostrzegłeś duży obraz. Wiesz, że nie jest to jedyny typ pliku, dla którego projekt będzie wymagał ETL. Rozważamy więc implementację tego algorytmu ETL, aby działał on również na innym typie pliku, który ma tylko niewielkie różnice. Takie postępowanie naruszyłoby YAGNI. Twoim zadaniem nie jest opracowanie algorytmu dla tego innego pliku; ma opracować algorytm dla jednego pliku, który jest potrzebny do końca tygodnia. Aby osiągnąć ten cel i przejść testy akceptacyjne, musisz opracować ten algorytm i sprawić, by działał poprawnie. Nie będziesz potrzebował dodatkowego kodu, aby działał z innym plikiem. Możesz myśleć, że zaoszczędzi ci to czasu, aby włączyć go teraz, i możesz mieć rację, ale możesz także być w strasznym błędzie; algorytm dla drugiego pliku może wymagać użycia w obszarze systemu, w którym nie można użyć kodu lub wymagania dla nowego pliku mogą być inne niż dla twojego w sposób, którego nie znasz (w Agile, te wymagania mogą jeszcze nie istnieć). W międzyczasie zmarnowałeś czas i niepotrzebnie zwiększyłeś złożoność algorytmu.

Teraz jest w przyszłym tygodniu i jako wątpliwa nagroda za doskonałą pracę nad pierwszym algorytmem, otrzymałeś zadanie stworzenia algorytmów dla dwóch nowych typów plików. Teraz potrzebujesz dodatkowego kodu, aby Twój algorytm działał z większą liczbą plików. Możesz rozszerzyć istniejący algorytm za pomocą wzorca metody szablonowej, który będzie wykorzystywał podstawowy wzorzec z indywidualnymi krokami specyficznymi dla pliku, lub możesz po prostu uzyskać wspólny interfejs z istniejącego algorytmu, opracować dwa nowe, które podążają za interfejsem, i podłączyć je do obiekt, który może wybrać, którego algorytmu użyć.

Podczas opracowywania wiesz, że masz wymagania, aby system mógł przetwarzać 10 KB nieprzetworzonych danych na sekundę. Wykonujesz test obciążenia i okazuje się, że początkowy algorytm ciągu obsługuje 8 KB / s. Cóż, to nie przejdzie AAT. Spójrz i przekonaj się, że w twoim algorytmie jest struktura pętli złożoności O (mój Boże); usprawnisz go i uzyskasz 12 KB / s. „Całkiem nieźle”, myślisz, „ale jeśli miałbym tę kiepską pętlę w kodzie, co jeszcze mógłbym się ogolić?”. buzz Właśnie naruszyłeś zasadę „przedwczesnej optymalizacji”. Twój kod działa i spełnia wszystkie wymagania. Jesteś „skończony”, dopóki wymagania nie zostaną zaktualizowane i wymagają 15 KB / s. Jeśli i kiedy tak się stanie, to następnie ściągasz kod z powrotem i szukasz rzeczy do poprawy.

Postępuj zgodnie z tym prostym procesem podczas opracowywania, czy to w Agile, czy w tradycyjnych SDLC: „Przy pierwszym przejściu spraw, by działało. Przy drugim przejściu spraw, aby było ładnie. Przy trzecim przejściu spraw, aby było SOLID”. Oznacza to, że kiedy tworzysz wiersz kodu, spraw, aby kod działał poprawnie i bezbłędnie, ale nie zwracaj zbytniej uwagi na reguły projektowania w tym kodzie, jak na razie wiesz, że „ Nigdy więcej nie dotknę tego obszaru. Następnym razem, gdy odwiedzasz ten wiersz kodu, po prostu udowodniłeś, że się mylisz; nie jest to już jednorazowy element systemu. Przeprowadź refaktoryzację pod kątem czytelności, zwięzłości kodu i / lub zasad DRY (być może skopiowałeś jakiś kod, aby zrobić coś pięć razy; refaktoryzuj go w pętli i / lub wywołanie metody). Za trzecim razem, gdy pracujesz w tym wierszu kodu lub wokół niego,

KeithS
źródło
3
+1 za, O(my God)-complexityjeśli nic więcej, rozśmieszyło mnie!
Joel C
+1 za Pierwsze uruchomienie. Zbyt wiele osób próbuje pisać wzorce i przedwcześnie optymalizować nietoperza.
Justin Shield,
Uważam to za jeden z najtrudniejszych problemów do pokonania jako programista. Inżynierowie mają wrodzoną chęć eksperymentowania, rozwijania i udoskonalania, ale ostatecznie zarabiasz za wydajność. Co dobrego jest idealnym produktem, jeśli spędzasz tyle czasu i / lub pieniędzy, że został anulowany z powodu przekroczeń?
ToddR
Podoba mi się pragmatyczne podejście, ale mam problem z „Przy drugim przejściu, zrób to ładnym”: jeśli drugie przejście jest rok później i nie masz pewności, że nazwy zmiennych i metod są znaczące, a liczby magiczne zostały zastąpione symbolicznymi stałymi prawdopodobnie masz problemy ze zrozumieniem kodu. Jak sobie z tym poradzić? „Zrób to ładnie” 1 godzinę po „zrób to ładnym” jest znacznie tańsze niż „zrób to ładnie” po miesiącu lub roku. Zgadzam się, że „uczyń to ładnym”, gdy konieczna jest następna zmiana kodu, jest przydatne, jeśli „uczyń to ładnym” nie zostało zrobione w pierwszej kolejności.
k3b
W Agile / TDD z mojego doświadczenia wynika, że ​​drugie przejście zwykle następuje wkrótce po pierwszym. W przypadku SLDC podobnych do Waterfall masz więcej racji; funkcja ma tendencję do pisania raz, a następnie siedzi tam, dopóki nie przejdzie kolejna runda wymagań, która dotknie tej metody. Tak więc niektóre dobre praktyki kodowania muszą mieć miejsce za pierwszym razem, takie jak kodowanie samodokumentujące, aby po powrocie rok później można było pamiętać, co robi kod i dlaczego go napisano w ten sposób.
KeithS
10

jeśli to działa i zostało przetestowane, to po co to naprawiać?

Może to być sprzeczne z twoim osobistym temperamentem jako inżyniera / programisty, ale jeśli to działa, jaka jest wartość biznesowa, abyś mógł go dalej doskonalić? Czy ułatwi to utrzymanie z czasem? Jeśli tak, to pracując zgodnie z metodologią zwinną, powinieneś być w stanie tworzyć nowe elementy w swoim dzienniku zaległości w celu udoskonalenia i refaktoryzacji istniejącego kodu, a te będą traktowane priorytetowo z innymi pozycjami w dzienniku. To część wartości zwinnego procesu: zespół wspólnie decyduje, co jest najważniejsze i co dalej.

Nasz zespół śledzi również to, co nazywamy „długiem technicznym”, więc jeśli coś działa, ale wiesz, że można to zrobić lepiej, rejestrujesz to jako dług techniczny. Używamy scrum, a czasami całą pracę kończysz wcześnie w sprincie (powinieneś ukończyć trochę wcześniej mniej więcej połowę czasu, jeśli jesteś dość blisko z szacunkami), ale nie masz wystarczająco dużo czasu, aby wciągnąć zupełnie nowy historię użytkownika, więc spędzamy dodatkowy czas, wracając i zmniejszając zadłużenie techniczne. Nie jest to formalnie śledzone, jak nasze historie użytkowników w naszym zaległości, i możemy nad nim popracować, ilekroć mamy dostępny czas.

Jest to również mniej więcej wezwanie do osądu, gdy nazwiesz zadanie „zrobione”; jeśli nie podoba ci się stan kodu, nie oznaczaj zadania jako ukończonego.

Joel C.
źródło
2
Stałem się fanem koncepcji „długu technicznego”, +1 za poruszenie go w tym kontekście.
Patrick Hughes,
Zupełnie zapomniałem o „długu technicznym”; dobry termin. Nauczono mnie jednak, że należy unikać wszystkiego, co kwalifikuje się jako „dług techniczny”, co oznacza, że ​​jego refaktoryzacja wymagałaby znacznych cykli deweloperskich; „zrób to światło” wciąż oznacza „zrób to dobrze”, po prostu nie używaj „wieży z kości słoniowej” na kodzie, który może być jednorazowy.
KeithS,
5

Czy ten czas „mogę zrobić lepiej” rzeczywiście mieści się gdzieś na osi czasu?

Tak.

Tuż przed rozpoczęciem kodowania następnego wydania.

Nie refaktoryzuj w oparciu o „intuicję”.

Refaktoryzacja oparta na faktach z następnego sprintu.

S.Lott
źródło
2

Nie zaznaczaj kodu jako 100% kompletnego, dopóki nie będziesz zadowolony z refaktoryzacji. Musisz tylko stale oceniać koszty / korzyści związane z refaktoryzacją kodu, ponieważ jeśli przestudiujesz wystarczająco dużo, zawsze znajdziesz sposoby na ulepszenie kodu.

Używam metody TDD z czerwonym zielonym refaktorem. Więc moje refaktoryzacja jest wbudowane w mój rozwój. W przypadku dużych refaktoryzacji, takich jak zmiana modelu bazowego lub coś podobnego, chciałbym uzyskać wpis od zarządu, aby spędzić ten czas jako pierwszy.

mpenrow
źródło
1
Kod nie jest „w 100% kompletny”, dopóki wszystkie produkty, w których on się znajduje, nie są martwe. Podobnie jak nie jesteś „kompletny” jako osoba, dopóki twoje serce nie przestanie bić na stałe; zawsze będziesz wchłaniać nowe informacje i będziesz musiał robić określone rzeczy, których nigdy wcześniej nie robiłeś, lub robić to samo w nowy, bardziej wydajny lub tańszy sposób. Podobnie, twoja baza kodu ZAWSZE będzie wymagała pracy - nowych funkcji i starych poprawek - dopóki nikt już nie użyje oprogramowania.
KeithS,
2

„Refaktoryzacja po uruchomieniu” ma ukryty koszt w testach regresyjnych i czas kontroli jakości, które ignorujesz, a także niesie koszt alternatywny braku pracy w przypadku zgłoszonych błędów oraz nowych / żądanych funkcji i zmian. TANSTAAFL

Jeśli warto to zrobić, warto zrobić zadanie, aby uzyskać priorytet w ramach normalnego procesu, a nie jako specjalny wyjątek. W końcu należysz do zespołu, który wpływa na wspólne cele i arbitralne wydłużanie harmonogramu w celu dostosowania poprawnego kodu roboczego.

Prawdziwa odpowiedź: jeśli wiesz, że będziesz chciał dokonać refaktoryzacji, zaplanuj ten czas w ramach zadania. Jeśli wykonujesz scrum / agile, czas wyczyść zadanie. Jeśli jesteś wodospadem / spiralą, włącz refaktor do procesu przeglądu kodu i zaakceptuj moduły.

Patrick Hughes
źródło
0

Jeśli próbuję zastosować alternatywne metody, aby uruchomić funkcjonalność, niekoniecznie oznacza to, że znalazłem najlepsze rozwiązanie,

... W takim przypadku nie jesteś jeszcze w 100% gotowy ...

lub nie będzie wymagać ponownej przeróbki po zapoznaniu się z innymi programistami.

Jeśli recenzje kodu i późniejsze przeróbki są częścią cyklu życia programisty, funkcja ta nie zostanie wykonana, dopóki wszystkie z nich nie zostaną zakończone.

Często skończę z czymś, cofam się, a potem zadaję sobie pytanie, co mogę zrobić lepiej po spełnieniu reguł biznesowych. Czy ten czas „mogę zrobić lepiej” rzeczywiście mieści się gdzieś na osi czasu?

To zależy. Jeśli oznacza to refaktoryzację, powinno być częścią pierwotnego zadania programistycznego. Jeśli oznacza to eksperymentowanie z potencjalnie lepszym algorytmem, może to być osobne zadanie.

Uważam, że najlepszym podejściem jest to, że zawsze zostawiasz kod lepiej niż wtedy, gdy go znalazłeś (do pewnego stopnia), co może oznaczać refaktoryzację po uruchomieniu. Jednak zespoły projektowe są często bardzo niewygodne z tym podejściem, ponieważ ponownie, jeśli działa i zostało przetestowane, to po co to naprawiać?

W skrócie, ponieważ kod może zostać złamany na wielu poziomach.

To jedna rzecz, która teraz działa. Zupełnie inną rzeczą jest to, czy w dłuższej perspektywie jest czyste, rozszerzalne i konserwowalne.

Aby uzyskać bardziej szczegółowe odpowiedzi, zobacz ten wątek .

Péter Török
źródło
0

O ile widzę i czytałem, jest to nierozwiązane pytanie. Dlatego odpowiedzi dotyczące unikania, takie jak „YAGNI” i odpowiedzi „zrób to dobrze” za pierwszym razem. Faktem jest, że w Agile nie ma miejsca na refaktoryzację - ale argumentowałbym, że tak powinno być.

Najlepsza jak dotąd odpowiedź wspomina o długu technicznym. Niestety, jest to smutna rzeczywistość oprogramowania w wielu przedsiębiorstwach, w których pośpiech, aby wyciągać rzeczy z domu, czy to w zwinnej, czy nie zwinnej metodologii, jest powszechny - ale pod Agile szybkie i brudne rozwiązania są zracjonalizowane jako coś dobrego: „spełnia minimalne wymagania biznesowe” i „YAGNI” (w odniesieniu do utrzymania kodu w czystości).

Byłoby wspaniale, gdyby wszyscy zrobili TDD, i byłoby wspaniale, gdyby wszyscy programiści dokonali refaktoryzacji za drugim lub trzecim razem, jak sugeruje jedna odpowiedź. Ale tak się nie dzieje w prawdziwym świecie. Deweloperzy o różnych poziomach umiejętności prawie zawsze mają zaokrąglone kąty w pogoni za szybkimi rozwiązaniami. W rezultacie kod rozpada się w góry nieusuwalnego kodu, którego rozszyfrowanie zajmuje nowym programistom dni, co szkodzi wydajności i opóźnia terminy. Przez „niemożliwy do utrzymania” mam na myśli rozwiązania kopiuj i wklej, 5000 klas linii itp. Cały ten kod i te poprawki po poprawkach są kluczowe dla biznesu! - Twierdzę, że w tych przypadkach rozwiązań addytywnych nie ma czegoś takiego jak YAGNI! Będziesz potrzebował czystego kodu - ZAWSZE. Jeśli kod nie jest czysty, na pewno nie będziesz go potrzebował - zobaczysz samospełniającą się przepowiednię? Programiści dołożyli wszelkich starań, aby w ogóle nie używać tego kodu, ponieważ jest to zbyt bolesne, aby na nie patrzeć. A błędne koło trwa i trwa, aż cała wielka kula błota musi się wyrzucić i przepisać.

Mówię więc - mimo że refaktoryzacja kodu nie jest właściwą, odrębną, wartą swojej własnej koncepcji Agile - powinniśmy znaleźć czas na refaktoryzację. Niektóre sklepy wymagają teraz od drużyn wydawania 20% swoich sprintów na zadłużenie techniczne. Mamy nadzieję, że zwinni zwolennicy zmienią zdanie na temat YAGNI i utworzą miejsce do refaktoryzacji jako osobnej działalności z przydzielonym czasem. A jeśli już to zrobili i nie słyszałem o tym, proszę wskazać, gdzie to jest opisane, ponieważ jestem bardzo zainteresowany.

blindcodifier9734
źródło
„Faktem jest, że w Agile nie ma miejsca na refaktoryzację” - nie sądzę, żeby to było prawdziwe stwierdzenie. W zwinnym jest miejsce na wszelkiego rodzaju rozwój, w tym na refaktoryzację, o ile przemawia za tym uzasadnienie biznesowe. Jeśli nie ma uzasadnienia biznesowego, dlaczego to robisz?
Bryan Oakley,
Myślę, że masz rację, choć nieco uproszczoną. Teoretycznie deweloper może sfabrykować uzasadnienie biznesowe dla naprawienia tandetnego kodu, nawet jeśli nie spowoduje to żadnych zmian funkcjonalnych, ale nie byłoby to zgodne z duchem zwinności - używając biznesu jako proxy do usprawiedliwienia pracy. Argumentowałbym wtedy, że działalność refaktoryzacji leży poza sferą zwinności - coś w rodzaju aktywności CYA, jeśli chcesz - naprawiając niemożliwy do utrzymania kod, aby nie kosztował biznesu w dłuższej perspektywie, a deweloperów ponosi winę. Nazwij to „sprintem refaktoryzacji” lub czymkolwiek, ale musi istnieć formalne miejsce.
blindcodifier9734 10.04.17