Czy powinienem zmienić kod oznaczony jako „nie zmieniaj”?

148

Mam do czynienia z dość dużą bazą kodu i dano mi kilka miesięcy na zmianę istniejącego kodu. Proces refaktoryzacji jest potrzebny, ponieważ wkrótce będziemy musieli dodać wiele nowych funkcji do naszego produktu, a na razie nie jesteśmy już w stanie dodać żadnej funkcji bez zepsucia czegoś innego. W skrócie: niechlujny, ogromny, błędny kod, który wielu z nas widziało w swojej karierze.

Podczas refaktoryzacji od czasu do czasu spotykam klasę, metodę lub wiersze kodu, które mają podobne komentarze

Upłynął limit czasu, aby dać modułowi A trochę czasu na zrobienie czegoś. Jeśli nie będzie tak ustawiony, to się zepsuje.

lub

Nie zmieniaj tego. Zaufaj mi, zepsujesz wszystko.

lub

Wiem, że używanie setTimeout nie jest dobrą praktyką, ale w tym przypadku musiałem go użyć

Moje pytanie brzmi: czy powinienem przefakturować kod, gdy napotkam takie ostrzeżenia od autorów (nie, nie mogę się skontaktować z autorami)?

kukis
źródło
157
Gratulacje! Jesteś teraz autorem kodu.
12
Nie możesz tego naprawić, dopóki nie dowiesz się, co ma robić i co faktycznie robi (musisz znać to drugie, aby zrozumieć pełne konsekwencje swoich zmian). Wygląda na to, że problem polega na synchronizacji i usuwaniu takich problemów powinna być refaktoryzacja zadania nr 1, w przeciwnym razie sytuacja będzie się pogarszać z każdą zmianą. Pytanie, które powinieneś zadać, to jak to zrobić. W tym pytaniu istnieje spora zależność od języka i platformy. np .: stackoverflow.com/questions/3099794/finding-threading-bugs
sdenham
14
W następstwie komentarza @ sdenham: jeśli jeszcze nie masz zautomatyzowanych testów jednostkowych, które wykorzystują bazę kodu, sugeruję, abyś spędził czas na tworzeniu takich testów jednostkowych, zamiast marnować czas na „refaktoryzację polowania na czarownice” z AFAICT, bez wyraźnych celów w myślach. Kiedy już będziesz mieć pakiet testów jednostkowych, które dokładnie sprawdzą twoją bazę kodu, będziesz w obiektywny sposób wiedzieć, czy twój kod nadal działa, jeśli / kiedy musisz przepisać jego fragmenty. Powodzenia.
Bob Jarvis,
17
Jeśli autorzy są tak paranoiczni, że kod złamie się, jeśli ktoś tak blisko niego zacznie oddychać, prawdopodobnie jest już uszkodzony i niezdefiniowane zachowanie po prostu działa tak, jak tego chce. Ten pierwszy w szczególności brzmi, jakby miał warunek wyścigu, który zakłócili, więc to działa przez większość czasu. sdenham ma rację. Zastanów się, co powinien zrobić i nie zakładaj, że tak właśnie działa.
Ray
7
@Ethan To może nie być takie proste. Zmiana kodu może go zepsuć w sposób, który nie jest od razu widoczny. Czasami pęka na długo po tym, jak zapomniałeś, że ten obecny refaktor mógł to spowodować, więc wszystko, co masz, to „nowy” błąd z tajemniczą przyczyną. Jest to szczególnie prawdopodobne, gdy wiąże się to z czasem.
Paul Brinkley,

Odpowiedzi:

225

Wygląda na to, że refaktoryzujesz „na wszelki wypadek”, nie wiedząc dokładnie, które części bazy kodu zostaną zmienione, kiedy nastąpi rozwój nowych funkcji. W przeciwnym razie wiedziałbyś, czy istnieje prawdziwa potrzeba przefakturowania kruchych modułów, czy możesz je zostawić takimi, jakie są.

Mówiąc wprost: myślę, że jest to skazana na niepowodzenie strategia refaktoryzacji . Inwestujesz czas i pieniądze swojej firmy w coś, na co nikt nie wie, czy to naprawdę przyniesie korzyść, a ty jesteś na skraju pogorszenia sytuacji poprzez wprowadzenie błędów w działającym kodzie.

Oto lepsza strategia: wykorzystaj swój czas na

  • dodaj testy automatyczne (prawdopodobnie nie testy jednostkowe, ale testy integracyjne) do zagrożonych modułów. Zwłaszcza te kruche moduły, o których wspomniałeś, będą wymagały pełnego zestawu testów, zanim cokolwiek w nich zmienisz.

  • refaktoryzuj tylko te bity, które są potrzebne do przeprowadzenia testów. Spróbuj zminimalizować dowolne niezbędne zmiany. Jedynym wyjątkiem jest sytuacja, w której testy ujawniają błędy - a następnie napraw je natychmiast (i dokonaj korekty w stopniu, w jakim musisz to zrobić bezpiecznie).

  • naucz swoich kolegów zasady „harcerstwa” (AKA „oportunistyczne refaktoryzowanie” ), więc kiedy zespół zacznie dodawać nowe funkcje (lub naprawiać błędy), powinni poprawić i przefaktoryzować dokładnie te części kodu, które muszą zmienić, nie mniej, nie więcej.

  • zdobądź kopię książki Feather „Efektywna praca ze starszym kodem” dla zespołu.

Kiedy więc nadejdzie czas, kiedy na pewno będziesz wiedział , że musisz zmienić i przefiltrować kruche moduły (albo z powodu rozwoju nowej funkcji, albo dlatego, że testy dodane w kroku 1 ujawniają pewne błędy), wtedy ty i twój zespół jesteście gotowi przebuduj moduły i mniej lub bardziej bezpiecznie zignoruj ​​te ostrzeżenia.

W odpowiedzi na niektóre komentarze : aby być uczciwym, jeśli podejrzewa się, że moduł w istniejącym produkcie jest przyczyną problemów na bieżąco, szczególnie moduł oznaczony jako „nie dotykaj”, zgadzam się ze wszystkimi ty. Powinien zostać poddany przeglądowi, debugowany i najprawdopodobniej zrefaktoryzowany w tym procesie (przy wsparciu wspomnianych testów i niekoniecznie w tej kolejności). Błędy stanowią silne uzasadnienie zmiany, często silniejsze niż nowe funkcje. Jest to jednak decyzja indywidualna. Trzeba bardzo uważnie sprawdzić, czy naprawdę warto jest zmienić coś w module oznaczonym jako „nie dotykaj”.

Doktor Brown
źródło
70
Kusi mnie, by oddać głos, ale powstrzymam się. Widziałem, że ta mentalność wielu projektów prowadzi do znacznie gorszego produktu. Kiedy awarie w końcu się zdarzają, są często katastrofalne i znacznie trudniejsze do naprawienia ze względu na ich okopanie. Regularnie naprawiam osad, który widzę, i wydaje się, że w najgorszym przypadku powoduje tyle problemów, ile naprawia, aw najlepszym razie nie pozostawia żadnych znanych problemów; ogólnie jest to ogromny plus. ORAZ kod jest lepszy do przyszłego rozwoju. Ścieg w czasie oszczędza dziewięć, ale zignorowany problem może się pogorszyć.
Aaron,
98
Twierdziłbym, że każdy kod oznaczony komentarzem „Upłynął limit czasu, aby dać modułowi A trochę czasu na zrobienie czegoś. Jeśli nie jest tak ustawiony, to się zepsuje” już ma błąd. To szczęście, że remis nie został trafiony.
17 z 26
10
@ 17of26: niekoniecznie błąd. Czasami, gdy pracujesz z bibliotekami stron trzecich, musisz zmuszać się do wszelkiego rodzaju „eleganckich” ustępstw w celu uruchomienia go.
whatsisname
30
@ 17of26: jeśli podejrzewa się, że moduł ma błędy, dodanie testów przed jakimkolwiek refaktoryzacją jest jeszcze ważniejsze. A kiedy testy te ujawnią błąd, musisz zmienić ten moduł, a więc uzasadnić natychmiastowe zrefaktoryzowanie go. Jeśli testy nie ujawnią żadnych błędów, lepiej pozostaw kod bez zmian.
Doc Brown,
17
@Aaron: Nie rozumiem, dlaczego według ciebie dodanie testów lub przestrzeganie zasady harcerstwa obniżyłoby jakość produktu.
Doc Brown,
142

Tak, należy dodać kod przed dodaniem innych funkcji.

Problem z takimi komentarzami polega na tym, że zależą one od konkretnych okoliczności środowiska, w którym działa baza kodu. Limit czasu zaprogramowany w określonym punkcie mógł być naprawdę potrzebny, gdy został zaprogramowany.

Ale istnieje wiele rzeczy, które mogą zmienić to równanie: zmiany sprzętu, zmiany systemu operacyjnego, niezwiązane zmiany w innym składniku systemu, zmiany w typowych woluminach danych, nazywacie to. Nie ma gwarancji, że w dzisiejszych czasach jest to nadal konieczne lub że nadal jest wystarczające (integralność rzeczy, którą miała chronić, mogła zostać uszkodzona przez długi czas - bez odpowiednich testów regresji, których nigdy nie zauważysz). Dlatego zaprogramowanie stałego opóźnienia w celu umożliwienia zakończenia działania innego komponentu jest prawie zawsze nieprawidłowe i działa tylko przypadkowo.

W twoim przypadku nie znasz oryginalnych okoliczności i nie możesz też zapytać oryginalnych autorów. (Przypuszczalnie nie masz również odpowiednich testów regresji / integracji lub możesz po prostu przejść dalej i pozwolić, aby testy wykazały, czy coś złamałeś).

Może to wyglądać na argument za niezmienną zmianą; ale mówicie, że i tak będą musiały nastąpić poważne zmiany, więc już teraz istnieje niebezpieczeństwo zakłócenia delikatnej równowagi, która była osiągana w tym miejscu. Jest o wiele lepiej zdenerwowany koszyka jabłko teraz , kiedy jedyne co robisz to refaktoryzacji, i mieć pewność, że jeśli coś złamać to był refaktoryzacji, który spowodował to, niż czekać, aż robisz dodatkowych zmian jednocześnie i nigdy być pewnym.

Kilian Foth
źródło
46
Najlepsza odpowiedź tutaj; szkoda, że ​​jest słabszy. Przyjęta powyżej odpowiedź nie jest dobrą radą, zwłaszcza nacisk na „skazaną”. Spędziłem ostatni rok pracując nad największym (~ 10 ^ 6LOC tylko dla mojej sekcji), starszym, okropnym kodem, jaki kiedykolwiek widziałem, i przyzwyczajam się do naprawiania wraków pociągów, które widzę, kiedy mam czas, nawet jeśli nie jest częścią komponentu, nad którym pracuję. Robiąc to, znalazłem i naprawiłem błędy, o których istnieniu nie wiedział nawet zespół deweloperów (chociaż prawdopodobnie byli to nasi użytkownicy końcowi). W rzeczywistości jestem poinstruowany. W rezultacie produkt został ulepszony.
Aaron,
10
Nie nazwałbym tego refaktoryzacją, ale naprawianie błędów.
Paŭlo Ebermann
7
Ulepszenie projektu bazy kodu jest refaktoryzacją. Jeśli przeprojektowanie ujawnia błędy, które można naprawić, to naprawia błędy. Chodzi mi o to, że pierwszy często prowadzi do drugiego i że drugi jest często bardzo trudny bez pierwszego.
Kramii,
10
@Aaron, masz szczęście, że masz przy tym wsparcie kierownictwa / programistów. W większości środowisk znane i nieznane błędy spowodowane złym projektowaniem i kodem są akceptowane jako naturalny porządek rzeczy.
Rudolf Olah,
5
@nocomprende Argumentowałbym, że jeśli nie rozumiesz systemu wystarczająco dobrze, aby napisać dla niego jakieś testy, nie musisz zmieniać sposobu jego działania.
Patrick M
61

Moje pytanie brzmi: czy powinienem przefakturować kod, gdy napotkam takie ostrzeżenia od autorów

Nie, a przynajmniej jeszcze nie. Sugerujesz, że poziom automatycznych testów jest bardzo niski. Potrzebne są testy, aby można było pewnie refaktoryzować.

na razie nie jesteśmy już w stanie dodać żadnej funkcji bez zepsucia czegoś innego

W tej chwili musisz skupić się na zwiększeniu stabilności, a nie na refaktoryzacji. Możesz dokonać refaktoryzacji w ramach zwiększenia stabilności, ale jest to narzędzie do osiągnięcia twojego prawdziwego celu - stabilnej bazy kodu.

Wygląda na to, że stał się on starszą bazą kodu, więc musisz potraktować to trochę inaczej.

Zacznij od dodania testów charakteryzujących. Nie martw się o żadną specyfikację, po prostu dodaj test potwierdzający bieżące zachowanie. Pomoże to zapobiec zerwaniu przez nowe funkcje istniejących funkcji.

Za każdym razem, gdy naprawisz błąd, dodaj skrzynkę testową, która dowodzi, że błąd został naprawiony. Zapobiega to bezpośredniej regresji.

Kiedy dodajesz nową funkcję, dodaj przynajmniej kilka podstawowych testów, czy nowa funkcja działa zgodnie z przeznaczeniem.

Być może otrzymasz kopię „Efektywnej pracy ze starszym kodem”?

Dano mi kilka miesięcy na zmianę istniejącego kodu.

Zacznij od zwiększenia zasięgu testu. Zacznij od obszarów, które najbardziej się psują. Zacznij od obszarów, które najbardziej się zmieniają. Następnie, gdy zidentyfikujesz złe projekty, zamień je jeden po drugim.

Prawie nigdy nie można zrobić jednego wielkiego reaktora, ale zamiast tego ciągły przepływ małych reaktorów co tydzień. Jeden duży refaktor ma ogromne ryzyko zepsucia i trudno jest dobrze go przetestować.

Daenyth
źródło
10
+1 za dodanie testów charakteryzujących. Jest to właściwie jedyny sposób na zminimalizowanie regresji podczas modyfikowania niesprawdzonego starszego kodu. Jeśli testy zaczną się nie powieść po rozpoczęciu wprowadzania zmian, możesz sprawdzić, czy poprzednie zachowanie było rzeczywiście poprawne, biorąc pod uwagę specyfikację, lub czy nowe zmienione zachowanie jest prawidłowe.
Leo
2
Dobrze. Lub jeśli nie ma użytecznej specyfikacji, sprawdź, czy poprzednie zachowanie jest rzeczywiście pożądane przez osoby płacące za lub zainteresowane oprogramowaniem.
bdsl
Być może otrzymasz kopię „Efektywnej pracy ze starszym kodem”? Ile tygodni zajmie mu przeczytanie tej książki? A kiedy: w godzinach pracy w miejscu pracy, w nocy, kiedy wszyscy śpią?
Billal Begueradj
23

Pamiętaj o ogrodzeniu GK Chestertona : nie zdejmuj ogrodzenia blokującego drogę, dopóki nie zrozumiesz, dlaczego został zbudowany.

Możesz znaleźć autora (ów) kodu i komentarze oraz skonsultować się z nimi, aby uzyskać zrozumienie. Możesz przejrzeć wiadomości zatwierdzenia, wątki e-mail lub dokumenty, jeśli istnieją. Wtedy albo będziesz mógł refaktoryzować zaznaczony fragment, albo napiszesz swoją wiedzę w komentarzach, aby następna osoba, która utrzyma ten kod, mogła podjąć bardziej świadomą decyzję.

Twoim celem jest zrozumienie, co robi kod i dlaczego oznaczono go wówczas ostrzeżeniem oraz co by się stało, gdyby ostrzeżenie zostało zignorowane.

Wcześniej nie dotknąłem kodu oznaczonego „nie dotykaj”.

9000
źródło
4
OP mówi „nie, nie mogę skontaktować się z autorami”.
FrustratedWithFormsDesigner,
5
Nie mogę się skontaktować z autorami ani nie ma żadnej dokumentacji.
kukis
21
@kukis: Nie możesz skontaktować się z autorami, ekspertami domeny i nie możesz znaleźć żadnych e-maili / wiki / dokumentów / przypadków testowych dotyczących danego kodu? Cóż, zatem jest to szeroko zakrojony projekt badawczy w dziedzinie archeologii oprogramowania, a nie proste zadanie refaktoryzacji.
9000
12
Nie jest niczym niezwykłym, że kod jest stary i autorzy odeszli. Jeśli w końcu pracują dla konkurenta, omawianie tego może naruszyć czyjąś NDA. W kilku przypadkach autorzy są trwale niedostępni: nie można zapytać Phila Katza o PKzip, ponieważ zmarł lata temu.
pjc50,
2
Jeśli zamienisz „znalezienie autora” na „zrozumienie, jaki problem rozwiązał kod”, jest to najlepsza odpowiedź. Czasami te fragmenty kodu są najmniej okropnym rozwiązaniem dla błędów, które zajęły tygodnie lub miesiące pracy, aby znaleźć i wyśledzić i poradzić sobie z nimi, często błędy, których normalne testy jednostkowe nie mogą znaleźć. (Chociaż czasami są one wynikiem działania programistów, którzy nie wiedzieli, co robią. Twoim pierwszym zadaniem jest zrozumienie, co to jest)
grahamparks
6

Kod z komentarzami podobnymi do tych, które pokazałeś, znalazłby się na szczycie mojej listy rzeczy do refaktoryzacji, jeśli i tylko wtedy, gdybym miał ku temu powód . Chodzi o to, że kod tak śmierdzi, że nawet wąchasz komentarze. Nie ma sensu wtrącać żadnych nowych funkcji do tego kodu, taki kod musi umrzeć, gdy tylko trzeba go zmienić.

Pamiętaj też, że komentarze nie są co najmniej pomocne: dają tylko ostrzeżenie i bez powodu. Tak, to znaki ostrzegawcze wokół akwarium rekinów. Ale jeśli chcesz coś zrobić w pobliżu, jest niewiele punktów, aby spróbować pływać z rekinami. Imho, najpierw powinieneś pozbyć się tych rekinów.

To powiedziawszy, absolutnie potrzebujesz dobrych testów, zanim odważysz się pracować nad takim kodem. Kiedy już będziesz mieć te przypadki testowe, pamiętaj, aby zrozumieć każdy drobiazg, który zmieniasz, aby upewnić się, że tak naprawdę nie zmieniasz zachowania. Postaw na swój najwyższy priorytet zachowanie wszystkich osobliwości behawioralnych w kodzie, dopóki nie udowodnisz, że są one bezskuteczne. Pamiętaj, że masz do czynienia z rekinami - musisz być bardzo ostrożny.

Tak więc, w przypadku przekroczenia limitu czasu: Pozostaw go, dopóki nie zrozumiesz dokładnie, na co czeka kod, a następnie napraw przyczynę, dla której limit czasu został wprowadzony, zanim przystąpisz do jego usunięcia.

Upewnij się także, że twój szef rozumie, jakie przedsięwzięcie podejmujesz i dlaczego jest potrzebne. A jeśli powiedzą „nie”, nie rób tego. W tym absolutnie potrzebujesz ich wsparcia.

cmaster
źródło
1
Czasami kod kończy się bałaganem, ponieważ musi działać poprawnie na próbnych próbkach krzemu, których rzeczywiste zachowanie nie odpowiada dokumentacji. W zależności od natury obejść, zastąpienie kodu może być dobrym pomysłem, jeśli kod nigdy nie będzie musiał działać na błędnych układach, ale zmiana kodu bez poziomu analizy inżynierskiej wymaganej od nowego kodu prawdopodobnie nie jest dobra pomysł.
supercat
@ superupat Jednym z moich argumentów było to, że refaktoryzacja musi idealnie zachowywać zachowanie. Jeśli nie zachowuje zachowania, to jest więcej niż refaktoryzacja w mojej książce (i wyjątkowo niebezpieczne, gdy mamy do czynienia z takim starszym kodem).
cmaster,
5

Prawdopodobnie nie jest to dobry pomysł, aby refaktoryzować kod za pomocą takich ostrzeżeń, jeśli wszystko działa poprawnie.

Ale jeśli musisz dokonać refaktoryzacji ...

Najpierw napisz kilka testów jednostkowych i testów integracyjnych, aby przetestować warunki, o których ostrzegają ostrzeżenia. Staraj się jak najbardziej naśladować warunki produkcji . Oznacza to tworzenie kopii lustrzanej produkcyjnej bazy danych na serwerze testowym, uruchamianie tych samych innych usług na komputerze itp., Cokolwiek możesz zrobić. Następnie spróbuj refaktoryzować (oczywiście na odizolowanym oddziale). Następnie uruchom testy nowego kodu, aby sprawdzić, czy możesz uzyskać takie same wyniki jak w przypadku oryginału. Jeśli możesz, prawdopodobnie wdrożenie refaktoryzacji w produkcji jest w porządku. Ale bądź przygotowany na wycofanie zmian, jeśli coś pójdzie nie tak.

FrustratedWithFormsDesigner
źródło
5

Mówię śmiało i zmień to. Wierzcie lub nie, ale nie każdy programista jest genialny, a takie ostrzeżenie oznacza, że ​​może być miejscem do poprawy. Jeśli stwierdzisz, że autor miał rację, możesz (wstrzymać oddech) DOKUMENT lub WYJAŚNIĆ przyczynę ostrzeżenia.

JES
źródło
4

Rozszerzam swoje komentarze na odpowiedź, ponieważ uważam, że niektóre aspekty konkretnego problemu są albo pomijane, albo wykorzystywane do wyciągania błędnych wniosków.

W tym momencie pytanie, czy dokonać refaktoryzacji, jest przedwczesne (mimo że prawdopodobnie odpowie na to konkretne pytanie „tak”).

Głównym problemem tutaj jest to, że (jak zauważono w niektórych odpowiedziach), cytowane komentarze silnie wskazują, że w kodzie występują warunki wyścigu lub inne problemy z współbieżnością / synchronizacją, takie jak omówione tutaj . Są to szczególnie trudne problemy z kilku powodów. Po pierwsze, jak zauważyłeś, pozornie niezwiązane zmiany mogą wywołać problem (inne błędy również mogą mieć ten efekt, ale prawie zawsze robią to błędy współbieżności). Po drugie, bardzo trudno je zdiagnozować: błąd często objawia się w miejscu, które jest odległe w czasie lub w kodzie od przyczyny, a wszystko, co zrobisz, aby go zdiagnozować, może spowodować jego zniknięcie ( Heisenbugs). Po trzecie, błędy współbieżności są bardzo trudne do znalezienia w testach. Częściowo dzieje się tak z powodu eksplozji kombinatorycznej: jest wystarczająco zły dla kodu sekwencyjnego, ale dodanie ewentualnych przeplotów współbieżnego wykonania powoduje, że problem sekwencyjny staje się nieznaczny w porównaniu. Ponadto nawet dobry przypadek testowy może sporadycznie wywoływać problem - Nancy Leveson obliczyła, że ​​jeden ze śmiertelnych błędów w Therac 25wystąpił w 1 z około 350 przebiegów, ale jeśli nie wiesz, co to jest błąd, a nawet że istnieje, nie wiesz, ile powtórzeń stanowi skuteczny test. Ponadto w tej skali wykonalne jest tylko automatyczne testowanie, i możliwe jest, że sterownik testowy nałoży subtelne ograniczenia czasowe, tak że nigdy nie uruchomi błędu (ponownie Heisenbugs).

Istnieją pewne narzędzia do testowania współbieżności w niektórych środowiskach, takie jak Helgrind dla kodu korzystającego z pthreads POSIX, ale nie znamy tutaj szczegółów. Testy należy uzupełnić analizą statyczną (czy to odwrotnie?), Jeśli istnieją odpowiednie narzędzia dla twojego środowiska.

Aby zwiększyć tę trudność, kompilatory (a nawet procesory w czasie wykonywania) często mają swobodę reorganizacji kodu w taki sposób, że czasami rozumowanie dotyczące bezpieczeństwa wątków jest bardzo sprzeczne z intuicją (być może najbardziej znanym przypadkiem jest podwójna kontrola blokuj idiom, chociaż niektóre środowiska (Java, C ++ ...) zostały zmodyfikowane w celu poprawy.)

Ten kod może mieć jeden prosty problem, który powoduje wszystkie objawy, ale bardziej prawdopodobne jest, że masz problem systemowy, który może spowodować, że twoje plany dodania nowych funkcji zostaną zatrzymane. Mam nadzieję, że przekonałem cię, że możesz mieć poważny problem na rękach, być może nawet egzystencjalne zagrożenie dla twojego produktu, a pierwszą rzeczą, którą musisz zrobić, to dowiedzieć się, co się dzieje. Jeśli ujawni to problemy z współbieżnością, zdecydowanie radzę najpierw je naprawić, zanim jeszcze zadasz pytanie, czy powinieneś dokonać bardziej ogólnej refaktoryzacji i zanim spróbujesz dodać więcej funkcji.

sdenham
źródło
1
Gdzie widzisz „warunki wyścigu” w komentarzach? Gdzie to w ogóle sugeruje? Robisz tutaj bardzo dużo technicznych założeń, nawet bez korzyści z patrzenia na kod.
Robert Harvey,
2
@RobertHarvey „Upłynął limit czasu, aby dać modułowi A trochę czasu na zrobienie czegoś.” - właściwie definicja warunków wyścigu, a limity czasu nie są prostym sposobem na poradzenie sobie z nimi. Nie jestem jedynym, który wyciąga takie wnioski. Jeśli nie ma tutaj problemu, to dobrze, ale pytający musi wiedzieć, biorąc pod uwagę, że te komentarze są czerwonymi flagami dla źle obsługiwanej synchronizacji.
sdenham,
3

Mam do czynienia z dość dużą bazą kodu i dano mi kilka miesięcy na zmianę istniejącego kodu. Proces refaktoryzacji jest potrzebny, ponieważ wkrótce będziemy musieli dodać wiele nowych funkcji do naszego produktu [...]

Podczas refaktoryzacji od czasu do czasu spotykam klasę, metodę lub wiersze kodu, które mają komentarze takie jak [„nie dotykaj tego!”]

Tak, należy te części byłaby szczególnie . Ostrzeżenia te zostały tam umieszczone przez poprzednich autorów w celu oznaczenia: „bezczynnie manipuluj przy tych rzeczach, jest to bardzo skomplikowane i istnieje wiele nieoczekiwanych interakcji”. Ponieważ Twoja firma planuje dalszy rozwój oprogramowania i dodanie wielu funkcji, specjalnie zleciła Ci wyczyszczenie tego. Więc nie leniwie go manipulujesz, celowo masz za zadanie oczyszczenie go.

Dowiedz się, co robią te skomplikowane moduły, i podziel je na mniejsze problemy (co powinni zrobić pierwotni autorzy). Aby wydostać się z bałaganu kod, który można utrzymać, dobre części muszą zostać ponownie przetworzone, a złe części muszą zostać przepisane .

DepressedDaniel
źródło
2

To pytanie jest kolejną odmianą debaty na temat tego, kiedy / jak refaktoryzować i / lub oczyścić kod z odrobiną „jak odziedziczyć kod”. Wszyscy mamy różne doświadczenia i pracujemy w różnych organizacjach z różnymi zespołami i kulturami, więc nie ma żadnej właściwej lub złej odpowiedzi, z wyjątkiem „rób to, co uważasz za konieczne, i rób to w sposób, który Cię nie zwolni” .

Nie sądzę, aby było wiele organizacji, które przychyliłyby się do obalenia procesu biznesowego, ponieważ aplikacja wspierająca wymagała czyszczenia kodu lub refaktoryzacji.

W tym konkretnym przypadku komentarze do kodu podnoszą flagę, że zmiana tych sekcji kodu nie powinna być wykonana. Jeśli więc przejdziesz dalej, a firma upadnie na bok, nie tylko nie masz nic do pokazania, by poprzeć twoje działania, tak naprawdę istnieje artefakt, który działa przeciwko twojej decyzji.

Jak zawsze, powinieneś postępować ostrożnie i wprowadzać zmiany dopiero po zrozumieniu każdego aspektu tego, co zamierzasz zmienić, i znaleźć sposoby na przetestowanie tego, zwracając szczególną uwagę na pojemność, wydajność i czas z powodu komentarze w kodzie.

Ale mimo to kierownictwo musi zrozumieć ryzyko związane z tym, co robisz, i zgodzić się, że to, co robisz, ma wartość biznesową przewyższającą ryzyko i że zrobiłeś wszystko, co można zrobić, aby zmniejszyć to ryzyko.

Teraz wróćmy do naszych własnych ZADAŃ, a rzeczy, które wiemy, można ulepszyć w tworzeniu własnych kodów, gdyby tylko było więcej czasu.

Thomas Carlisle
źródło
1

Tak, absolutnie. Są to wyraźne oznaki, że osoba, która napisała ten kod, była niezadowolona z tego kodu i prawdopodobnie wtrącała się w niego, dopóki nie zadziałał. Możliwe, że nie zrozumieli prawdziwych problemów lub, co gorsza, zrozumieli je i byli zbyt leniwi, aby je naprawić.

Jest to jednak ostrzeżenie, że trzeba będzie wiele wysiłku, aby je naprawić i że takie poprawki będą wiązały się z ryzykiem.

W idealnym przypadku możesz dowiedzieć się, na czym polegał problem i rozwiązać go poprawnie. Na przykład:

Upłynął limit czasu, aby dać modułowi A trochę czasu na zrobienie czegoś. Jeśli nie będzie tak ustawiony, to się zepsuje.

To zdecydowanie sugeruje, że moduł A nie wskazuje poprawnie, kiedy jest gotowy do użycia lub kiedy zakończy przetwarzanie. Być może osoba, która to napisała, nie chciała zawracać głowy naprawą modułu A lub z jakiegoś powodu nie mogła. Wygląda to na katastrofę czekającą na nadejście katastrofy, ponieważ sugeruje, że szczęście zależy od czasu, a nie od właściwego sekwencjonowania. Gdybym to zobaczył, bardzo chciałbym to naprawić.

Nie zmieniaj tego. Zaufaj mi, zepsujesz wszystko.

To niewiele ci mówi. Zależy to od tego, co robi kod. Może to oznaczać, że ma coś, co wydaje się oczywistymi optymalizacjami, które z tego czy innego powodu faktycznie złamią kod. Na przykład może się zdarzyć, że pętla pozostawi zmienną o określonej wartości, od której zależy inny fragment kodu. Lub zmienną można przetestować w innym wątku, a zmiana kolejności aktualizacji zmiennych może uszkodzić ten inny kod.

Wiem, że używanie setTimeout nie jest dobrą praktyką, ale w tym przypadku musiałem go użyć.

To wygląda na łatwe. Powinieneś być w stanie zobaczyć, co setTimeoutsię dzieje i być może znaleźć lepszy sposób, aby to zrobić.

To powiedziawszy, jeśli tego rodzaju poprawki są poza zakresem refaktora, są to oznaki, że próba refaktoryzacji wewnątrz tego kodu może znacznie zwiększyć zakres twojego wysiłku.

Przynajmniej przyjrzyj się kodowi, którego dotyczy problem, i sprawdź, czy możesz przynajmniej ulepszyć komentarz do tego stopnia, że ​​lepiej wyjaśnia, na czym polega problem. To może uratować kolejną osobę przed stawieniem czoła tej samej tajemnicy, z którą się stykasz.

David Schwartz
źródło
2
Możliwe, że warunki zmieniły się do tego stopnia, że ​​stare problemy już w ogóle nie istnieją, a komentarze ostrzegawcze stały się jak na starych mapach z napisem „Oto smoki”. Zanurz się i dowiedz się, jaka była sytuacja, lub przekonaj się, że przeszła ona do historii.
2
W prawdziwym świecie niektóre urządzenia nie zapewniają wiarygodnego wskazania gotowości, ale zamiast tego określają maksymalny czas braku gotowości. Wiarygodne i wydajne wskazania gotowości są fajne, ale czasami utkniesz, używając rzeczy bez nich.
supercat
1
@supercat Może, może nie. Nie możemy powiedzieć z komentarza tutaj. Warto więc zbadać, aby, jeśli nie inaczej, poprawić komentarz ze szczegółami.
David Schwartz,
1
@DavidSchwartz: Komentarz z pewnością może być bardziej pomocny, ale czasami nie jest jasne, ile czasu programista powinien poświęcić próbując zmapować wszystkie dokładne sposoby, w jakie urządzenie nie przestrzega specyfikacji, szczególnie jeśli nie jest jasne, czy problem jest oczekiwany być czymś tymczasowym lub stałym.
supercat
1

Autor komentarzy najprawdopodobniej nie do końca zrozumiał sam kod . Gdyby faktycznie wiedzieli, co robią, napisaliby naprawdę pomocne komentarze (lub nie wprowadzili warunków wyścigowych w pierwszej kolejności). Komentarz w rodzaju „ Zaufaj mi, rozwalisz wszystko ” wskazuje, że autor próbuje zmienić coś, co spowodowało nieoczekiwane błędy, których nie do końca zrozumieli.

Kod jest prawdopodobnie opracowywany na podstawie zgadywania i prób i błędów bez pełnego zrozumienia tego, co się faktycznie dzieje.

To znaczy:

  1. Zmiana kodu jest ryzykowna. Oczywiście zrozumienie zajmie trochę czasu i prawdopodobnie nie przestrzega dobrych zasad projektowania i może mieć niejasne efekty i zależności. Najprawdopodobniej nie jest wystarczająco przetestowany, a jeśli nikt nie w pełni rozumie, co robi kod, trudno będzie napisać testy, aby upewnić się, że nie zostaną wprowadzone żadne błędy ani zmiany w zachowaniu. Warunki wyścigowe (podobnie jak w komentarzach) są szczególnie uciążliwe - jest to jedno miejsce, w którym testy jednostkowe cię nie uratują.

  2. Niebezpiecznie jest nie zmieniać kodu. Istnieje duże prawdopodobieństwo, że kod zawiera nieznane błędy i warunki wyścigowe. Jeśli w kodzie wykryty zostanie błąd krytyczny lub zmiana wymagań biznesowych o wysokim priorytecie zmusi cię do zmiany tego kodu w krótkim czasie, masz poważne kłopoty. Teraz masz wszystkie problemy opisane w 1, ale pod presją czasu! Ponadto takie „ciemne obszary” w kodzie mają tendencję do rozprzestrzeniania się i infekowania innych części kodu, których dotyka.

Kolejna komplikacja: testy jednostkowe cię nie uratują . Zwykle zalecanym podejściem do takiego starszego kodu poprawki jest najpierw dodanie testów jednostkowych lub integracyjnych, a następnie ich wyodrębnienie i refaktoryzacja. Ale warunki wyścigowe nie mogą być uchwycone przez automatyczne testy. Jedynym rozwiązaniem jest usiąść i przemyśleć kod, dopóki go nie zrozumiesz, a następnie przepisać, aby uniknąć warunków wyścigowych.

Oznacza to, że zadanie jest znacznie bardziej wymagające niż rutynowe refaktoryzowanie. Będziesz musiał zaplanować to jako prawdziwe zadanie programistyczne.

Być może będziesz w stanie zakodować uszkodzony kod w ramach regularnego refaktoryzacji, więc przynajmniej niebezpieczny kod zostanie odizolowany.

JacquesB
źródło
-1

Pytanie, które zadałbym, brzmi: dlaczego ktoś napisał: NIE EDYTUJ w pierwszej kolejności.

Pracowałem nad wieloma kodami, a niektóre z nich są brzydkie i zajęły dużo czasu i wysiłku, aby zacząć działać, w ramach określonych ograniczeń w tym czasie.

Założę się, że w tym przypadku tak się stało i osoba, która napisała komentarz, stwierdziła, że ​​ktoś to zmienił, a następnie musiał powtórzyć całe ćwiczenie i ustawić go z powrotem tak, aby wszystko działało. Następnie, z frustracji ścinaniem, napisali ... NIE EDYTOWAĆ.

Innymi słowy, nie chcę tego ponownie naprawiać, ponieważ mam lepsze rzeczy do zrobienia z moim życiem.

Mówiąc „NIE EDYTUJ”, to sposób na powiedzenie, że wiemy wszystko, co kiedykolwiek będziemy wiedzieć teraz, a zatem w przyszłości nigdy nie nauczymy się niczego nowego.

Powinien być przynajmniej komentarz na temat przyczyn braku edycji. Jak powiedzenie „Nie dotykaj” lub „Nie wchodź”. Dlaczego nie dotknąć ogrodzenia? Dlaczego nie wejść? Czy nie lepiej byłoby powiedzieć: „Ogrodzenie elektryczne, nie dotykaj!” lub „Miny lądowe! Nie wchodź!”. To oczywiste, dlaczego, a jednak nadal możesz wejść, ale przynajmniej poznaj konsekwencje, zanim to zrobisz.

Założę się również, że system nie ma testów wokół tego magicznego kodu i dlatego nikt nie może potwierdzić, że kod będzie działał poprawnie po każdej zmianie. Umieszczenie testów charakterystyki wokół kodu problemu jest zawsze pierwszym krokiem. Wskazówki dotyczące przełamywania zależności i testowania kodu przed przystąpieniem do zmiany kodu można znaleźć w części „Praca ze starszym kodem” autorstwa Michaela Feathersa.

Wydaje mi się, że w końcu nałożenie ograniczenia na refaktoryzację i pozwolenie na ewolucję produktu odbywa się w sposób naturalny i organiczny.

BigA
źródło
2
wydaje się, że nie oferuje to nic istotnego w porównaniu z punktami poczynionymi i wyjaśnionymi w poprzednich 9 odpowiedziach
komnata