W pewnym momencie program się rozwija. Funkcje są dodawane, usuwane lub zmieniane przez cały czas. Każda wersja jest niczym innym jak prototypem. Nie marnuję wtedy dużo czasu na pisanie super czystego kodu, ponieważ nigdy nie wiem, jak długo coś trwa. Oczywiście staram się zachować jakość kodu zgodnie z pewnymi standardami, ale czas zawsze stanowi problem.
Potem przychodzi moment, w którym program jest zakończony, a decydenci mówią: „to jest to”. W tej chwili mam działający prototyp, ale kod w środku jest nieco niechlujny ze wszystkich stron podczas fazy programowania. Oczekuje się, że zacznę testowanie / końcowe debugowanie, ale mój żołądek mówi, że powinienem teraz jakoś posprzątać i / lub przepisać rzeczy, aby nadać mu odpowiednią architekturę, która ułatwia konserwację itp.
Gdy rzeczy zostaną przetestowane i zatwierdzone, przepisywanie nie ma sensu. Regularnie stoję tam z działającym „gotowym” prototypem i dostaję błąd podczas testowania i widzę, że jest to wynik niemądrego kodowania, które jest wynikiem całego procesu rozwoju. Jestem w trakcie testowania, a poprawka byłaby przepisana ... to bałagan!
Jestem pewien, że istnieją lepsze / podręcznikowe sposoby. Ale muszę pracować w prawdziwym środowisku pracy, w którym nie wszystko jest podręcznikiem.
Jak więc przenieść mój działający prototyp do wersji z stabilną bazą kodu? Może nie powinienem uważać rozwoju za zakończony, kiedy to zrobię, i faktycznie postrzegam to jako fazę oczyszczania ... Nie wiem, potrzebuję tutaj pomocy.
EDYTOWAĆ
Chcę wyjaśnić kilka rzeczy.
Jestem w 100% po stronie robienia tego tuż przed, a nie później, kod jest czysty i czytelny. Ale muszę też załatwić sprawę i nie mogę marzyć o pięknie kodu, który jest czysty i błyszczący. Muszę znaleźć kompromis.
często nowa funkcja jest naprawdę po prostu czymś, co chcemy wypróbować i przekonać się, czy sensowne jest wdrożenie czegoś takiego. (szczególnie w aplikacjach mobilnych, aby uzyskać rzeczywisty wygląd na rzeczywistym urządzeniu). Jest to więc coś małego, co (imho) nie usprawiedliwia zbyt dużej pracy w pierwszej iteracji „zobaczmy”. Czasami jednak pojawia się pytanie KIEDY mam zapłacić ten tech.debt? O to właśnie chodzi w tym pytaniu.
Jeśli wiem, że połowa funkcji zostanie usunięta dzień później (wystarczająco dużo doświadczenia w naszej firmie), naprawdę trudno mi uwierzyć, że najlepszym sposobem na rozwiązanie mojego problemu jest zainwestowanie dodatkowego czasu, aby napisać wszystko czyste, nawet jeśli większość zostanie upuszczona wkrótce potem. Wydaje mi się, że zaoszczędzę czas, jeśli zrobię jedno wielkie porządki, gdy wszystko będzie solidne, stąd moje pytanie.
źródło
Odpowiedzi:
Nie wiedząc, jak długo coś trwa, nigdy nie powinno być usprawiedliwieniem niechlujstwa - wręcz przeciwnie. Najczystszym kodem jest IMHO, który nie wchodzi Ci w drogę, gdy musisz coś zmienić. Tak więc zalecam: zawsze staraj się pisać najczystszy kod, jaki możesz - szczególnie podczas kodowania prototypu. Ponieważ łatwiej będzie go dostosować, gdy trzeba coś zmienić (co na pewno się wydarzy).
Nie zrozumcie mnie źle - moje rozumienie „najczystszego kodu” nie ma nic wspólnego z upiększaniem kodu ze względu na piękno. To jest rzeczywiście coś, co może cię spowolnić. Z mojego punktu widzenia czysty kod to kod, który jest w większości samoobjaśniający (nie trzeba pisać tylu dokumentów - powoduje przyspieszenie), łatwy do zrozumienia (mniej błędów, więc mniej potrzeba debugowania - przyspieszenie, mniej czasu potrzebnego na znalezienie poprawnego miejsce do zmiany - przyspieszenie), rozwiązuje zadany problem z najmniejszą ilością niezbędnego kodu (mniej kodu do debugowania - oczywiste przyspieszenie), jest SUCHY (tylko jedno miejsce do zmiany, gdy coś musi zostać zmienione - przyspieszenie - i mniejsze ryzyko wprowadzenia nowe błędy, zapominając o zmianie drugiego miejsca), przestrzega standardów kodowania (mniej kłopotliwe rzeczy do myślenia - przyspieszenie), używa małych,
Późniejsze „czyszczenie” nigdy nie działa. Rozważ oczyszczenie przed wdrożeniem nowej funkcji lub rozpoczęciem jej wdrażania, ale nie później. Na przykład za każdym razem, gdy zaczniesz dotykać metody dla funkcji i zauważysz, że staje się ona dłuższa niż 10 linii, zastanów się, czy nie zmienić jej na mniejsze metody - natychmiast , zanim funkcja zostanie ukończona. Ilekroć wykryjesz istniejącą nazwę zmiennej lub funkcji, nie wiesz dokładnie, co to znaczy, dowiedz się, do czego to nadaje się, i zmień nazwę rzeczy, zanim zrobisz cokolwiek innego. Jeśli robisz to regularnie, utrzymujesz swój kod przynajmniej w stanie „wystarczająco czystym”. I zaczynasz oszczędzać czas - ponieważ potrzebujesz dużo mniej czasu na debugowanie.
... co jest faktycznym dowodem na to, co napisałem powyżej: bycie „brudnym” prześladuje cię natychmiast, gdy zaczniesz debugować kod i sprawi, że zwolnisz.
Możesz tego uniknąć prawie całkowicie, jeśli natychmiast wykonasz czyszczenie. Wówczas poprawki błędów będą w większości oznaczały niewielkie zmiany w kodzie, ale nigdy poważną zmianę architektoniczną. Jeśli naprawdę wykryjesz dowody na ulepszenie architektury podczas testowania, opóźnij je, umieść w swoim systemie śledzenia problemów i zaimplementuj go następnym razem, gdy zaimplementujesz funkcję korzystającą z tej zmiany ( zanim zaczniesz z tą funkcją).
Wymaga to oczywiście pewnej dyscypliny i doświadczenia w programowaniu. Jest to podobny pomysł, jak pomysł „rozwoju opartego na testach”, polegającego na robieniu tych rzeczy wcześniej, a nie później (TDD może również pomóc, ale to, co napisałem, działa nawet wtedy, gdy nie używasz TDD). Gdy konsekwentnie to zrobisz, nie będziesz potrzebować żadnej specjalnej „fazy czyszczenia” przed wydaniem.
źródło
Masz dwa oddzielne problemy, oba z tym samym objawem (niechlujny kod):
Problem nr 1: Niewystarczająca kontrola wymagań Nie chodzi mi o to, że twoi interesariusze zbyt często zmieniają twoje wymagania, mam na myśli to, że zezwalasz na zmiany wymagań podczas naprawy / cyklu testu. Nawet zwinne metodologie tego nie obsługują; budujesz, testujesz, dostarczasz, wstrzykujesz nowe wymagania.
Problem nr 2: Uważasz, że to, co piszesz, to „na razie” W rozwoju oprogramowania „na razie” kod jest naprawdę niezwykle rzadki. Zauważyłeś, że po spełnieniu wymagań użytkownika, rygor podaży i popytu bardzo utrudniają uzasadnienie powrotu i ponownego wdrożenia funkcji „gotowe”. Co z tym zrobić? Zawsze pisz kod produkcyjny. Funkcjonalnie dla Ciebie, oznacza to, że twoje szacunki dla interesariuszy muszą być znacznie większe, abyś miał trochę czasu, aby zrobić to dobrze.
Proszę również zrozumieć, że pracujesz na najtrudniejszej pozycji jako programista: przeczytaj, jak Joel Spolsky przedstawia życie programisty wewnętrznego . Musisz więc zachować szczególną czujność, jeśli chcesz zachować nienaruszony rozsądek.
źródło
Jest to powszechny problem - zwłaszcza podczas tworzenia czegoś, co zasadniczo jest balonem próbnym z oprogramowaniem .
Istnieje wiele metod, które mogą pomóc. Po pierwsze, podejście TDD może pomóc zredukować bazę kodu do tego, co jest ściśle wymagane. Jeśli twoje testy idą w parze z twoim kodem, możesz przynajmniej mieć pewność, że Twój kod zachowuje się tak, jak powinien.
Poświęć trochę czasu na refaktoryzację. Gdy masz już prototyp, a klient jest bardzo chętny, aby go zdobyć, trudno jest powiedzieć, że potrzebujesz czasu na dopracowanie tego, co jest dla nich ukończone. Lubię odprawić się codziennie, a następnie sprawdzić refaktor, ale YMMV.
Programiści, którzy szybko piszą kod, są często poszukiwani - mieliśmy takiego programistę w moim ostatnim dziale. Każda drużyna go chciała, ponieważ pracował bardzo szybko. Gdy jednak nadszedł czas na przetestowanie i wydanie kodu, koła szybko odpadły. Wszędzie zakodowane na stałe rzeczy, hacki i skróty. Jego akcje wkrótce spadły - masowo.
Wycinanie kodu produkcyjnego od samego początku może wydawać się trudne, ale w zależności od środowiska istnieje wiele narzędzi, które mogą oderwać się od rozwoju, takich jak Ghostdoc i Stylecop .
Warto od samego początku zachować właściwy sposób myślenia o rozwoju. Byłbyś zaskoczony, jak wiele systemów typu back-of-fag-packet, które miały być po prostu rozwiązaniami typu stop-gap, stają się podstawowymi aplikacjami.
źródło
Bez przerwy
Szybkość rozwoju jest głównym powodem pisania czystego, czytelnego i testowalnego kodu; nie zrobiono tego dla piękna ani innych abstrakcyjnych wartości. Dlaczego miałbym temu zaprzeczać i robić to dopiero później dla jakiegoś przyszłego programisty?
Jasne, że mogą wystąpić zmiany, które są w większości kosmetyczne i dlatego nie są konieczne; Twierdziłbym, że o wiele bardziej przydatne jest posiadanie umiarkowanie ładnego kodu teraz podczas programowania, niż bałagan w tej chwili i mam nadzieję, że uda się go później ulepszyć (co, szczerze mówiąc, nigdy się tak nie stanie, nawet gdybyś miał czas).
źródło
Robisz to, rozróżniając między kodem „Próbuję tylko zobaczyć, jak to działa”, a kodem „trafia to do produktu”. Można to zrobić na wiele sposobów.
Jeden rozgałęzia się lub cokolwiek to słowo jest w twoim systemie kontroli źródła. Tworzysz gałąź dla nowego raportu lub nowego układu importu lub cokolwiek innego. Jeśli ludziom się to podoba, zadanie odzyskania go z powrotem do głównej gałęzi jest osobną pracą, którą można prześledzić. Można go przypisać komuś i zgłosić, i nie oczekuje się, że po prostu magicznie się wydarzy, dzień zarządzania (lub sprzedaży) zgadza się, że funkcja należy do produktu.
Kolejne to kolce. Nie wprowadzasz tej zmiany w produkcie. Wchodzisz w jakąś oddzielną aplikację, super prostą, która istnieje tylko po to, abyś miał miejsce na umieszczenie kodu. Możesz być tak niechlujny, jak chcesz, ponieważ po prostu eksplorujesz nowy interfejs API lub cokolwiek innego. I znowu, jeśli wrócisz i powiesz „tak, możemy to zrobić, zorientowałem się, jak” istnieje możliwe do śledzenia, raportowalne, możliwe do przypisania zadanie napisania gotowego kodu produktu w produkcie, aby zrobić to, co chcesz.
W obu przypadkach gotowość do produktu oznacza czytelność, porządek, przestrzeganie standardów nazewnictwa, testy i przestrzeganie stylu kodu i celów wydajnościowych. W obu przypadkach sprawisz, że ta praca będzie widoczna. Zgadzam się, że nie chcesz wykonywać wszystkich tych prac za każdym razem, gdy ktoś może wycofać tę funkcję z produktu. Ale nie chcesz, aby ta praca stała się niewidoczna. Praca w osobnych egzemplarzach produktu lub w niepowiązanym produkcie, który jest zaledwie czymś więcej niż uprzężą testową, pozwala odkryć pracę nad przygotowaniem kodu produktu, gdy ktoś zdecyduje, że czegoś chce.
Minusem jest to, że nie mogą zdecydować, że czegoś chcą i wysłać to (co oznacza na wpół osamotnioną, niechlujną, nieprzetestowaną, nieudokumentowaną, być może powolną pół-wersję, którą wdrożyliście jako dowód koncepcji) jutro. Kiedy po raz pierwszy dostaniesz odepchnięcie na tym froncie, po prostu pytaj, czy powinieneś to robić za każdym razem na dłuższy (droższy) sposób, na wszelki wypadek, spowalniając ścieżkę do odrzuconych funkcji. Jeśli zapytasz poprawnie, otrzymasz „nie”.
źródło
Naprawdę myślę, że już rozumiesz problem. Problem polega na tym, że Twój styl kodowania wymaga zbyt dużej ilości przeróbek. Powodem, dla którego wymaga zbyt dużej ilości przeróbek, jest to, że (a) zestawiono go z niewystarczającym prognozowaniem i planowaniem oraz (b) przyrostowe łatki krótkoterminowe regularnie wprowadzane podczas rozwoju kombinatorycznie zwiększają złożoność wszelkich wymaganych przeróbek.
Dlatego odpowiedź brzmi:
(a) zmień swój styl rozwoju nieco bardziej w stronę wodospadu i nieco mniej zwinny. Nie idź jednak na całość, ponieważ klasyczny wodospad ma swoje własne pułapki. Należy zachować zdrową równowagę. Wiem, że czasami może to dotyczyć tylko myślenia o rzeczach przez kilka dni, jakby nie robiono żadnych prac rozwojowych, ale musisz zaufać temu procesowi. W inżynierii nie można po prostu skuwać gwoździ, a następnie gwoździ na wierzchu, mając nadzieję na eleganckie rozwiązanie. Jeśli nikt nie zajmuje się architekturą i projektowaniem technicznym na wyższym poziomie, oznacza to, że jest to Twoja praca. Zapłaciłeś za zaniedbanie tej pracy.
(b) staraj się unikać łatania. Nie myśl długoterminowo tylko wtedy, gdy przyjdzie czas na kontrolę jakości. Naprawdę powinieneś testować każdy budowany kawałek przez cały czas i obejmować wszystkie przypadki wprowadzania, również te, które nie znajdują się na ścieżce szczęścia. Łata / hack jest prawie z definicji krótkoterminową naprawą, która może mieć długoterminowy koszt, uderza w klientów Całkowity koszt posiadania w systemie. Ponownie pojawia się presja na usunięcie kodu, więc trzeba zachować równowagę. Ale staraj się nie wprowadzać krótkoterminowych poprawek, szczególnie. te, które ściśle łączą elementy, które naprawdę powinny być luźno połączone. Nastąpi ponowna praca, więc zrób to WCZESNIE, aby było to znacznie łatwiejsze, aby uniknąć włamań i łatek, które będą się montować z czasem i staną się niemożliwe do zarządzania.
źródło
Ty piszesz:
Wersja zameldowana może być „prototypem”, ponieważ brakuje jej funkcji lub niektóre funkcje nie są dopracowywane, ale cały kod powinien być kodem jakości produkcyjnej, który niekoniecznie wymaga czyszczenia.
Myślę, że zbytnio odkładasz czas „sprzątania”.
Moja ogólna zasada brzmi:
W tym momencie zatwierdzony kod może nadal zawierać pewne obejścia lub „zadłużenie techniczne”, które byłoby miło posprzątać, a może wyczyszczę go, gdy będzie to naturalne dla następnej podfunkcji, ale to będzie OK, jeśli ten kod zostanie zwolniony w obecnej postaci.
źródło