Co powinienem zrobić jako recenzent, gdy kod „musi być” zły?

18

Pracuję w źle zaprojektowanym, nadinżynieryjnym projekcie, w którym kilka miesięcy temu wprowadzono obowiązkowe przeglądy kodu.

Poproszono mnie o zapoznanie się z dużym fragmentem kodu, który implementuje nową funkcję. Ma te same wady, co reszta naszej bazy kodów. Rozumiem, że w dużym stopniu te wady wkradają się do nowego kodu, np. poprzez konieczność dziedziczenia po źle zaprojektowanej klasie lub implementacji źle zaprojektowanego interfejsu przy jednoczesnym zachowaniu kompatybilności, a tak naprawdę nie mogę zaoferować znacznie lepszego rozwiązania, które nie wymagałoby przepisywania połowy bazy kodu. Ale czuję, że z inżynieryjnego punktu widzenia nie ma już nic dobrego dla już złamanej bazy kodu, że łamiemy ją jeszcze bardziej. Kod, który recenzuję, jest zdecydowanie zły, ale musi być, jeśli funkcja ma zostać zaimplementowana.

Jak mam się zachowywać w odniesieniu do tej konkretnej recenzji? Czy jest jakiś sposób, aby zachować uczciwość i zachować konstruktywność?

Pamiętaj, że w tym kontekście pytam o granicę przeglądu kodu. Zdaję sobie sprawę, że problem jest spowodowany innymi czynnikami, w tym organizacją i kulturą pracy, ale chcę wiedzieć, jak sobie z tym poradzić.

Czerwony
źródło
1
Czy programista udokumentował, dlaczego tak się dzieje, a może nawet napisał problem dotyczący podstawowego problemu w narzędziu do śledzenia problemów?
Luc Franken,
Skąpo i nie.
Czerwony
4
Czy Twoja organizacja ma apetyt na robienie czegoś w sprawie długu technicznego?
Robert Harvey,
5
Jeśli kod nie jest zły, biorąc pod uwagę środowisko, nie zaatakowałbym go. Głównie odkąd napisałeś, nie widzisz w tej chwili realnej poprawy. Spowodowałoby to konflikt bez możliwości poprawy. Chciałbym nauczyć lepiej dokumentować jako pierwszy krok. Po drugie, stwórz procedurę pozwalającą im pisać jasne problemy. Spowoduje to dwie rzeczy: dokumentację dotyczącą problemu, aby następny mógł działać szybciej. Oprócz tego otrzymujesz listę konkretnych problemów, które potencjalnie można rozwiązać. Podoba mi się wzmianka o GitHub, ponieważ widzisz, ile razy powtarza się, jeśli go otagują.
Luc Franken,
1
powiązane (być może duplikat): Jak poradzić sobie ze zbyt dużym pragmatyzmem w projekcie?
komara

Odpowiedzi:

25

Prosty:

1. Dokumentuj swój dług techniczny

Zidentyfikowałeś fragment kodu, który działa, ale masz z nim pewne problemy techniczne. To dług techniczny . Podobnie jak inne rodzaje długów, z czasem pogarsza się, jeśli nie zostanie uregulowane.

Pierwszym krokiem w radzeniu sobie z długiem technicznym jest jego udokumentowanie. Zrób to, dodając elementy do śledzenia problemów, które opisują dług. Pomoże to uzyskać wyraźniejszy obraz skali problemu, a także pomoże w opracowaniu planu rozwiązania tego problemu.

2. Stopniowo spłacaj swój dług

Zmodyfikuj proces tworzenia oprogramowania, aby uwzględnić spłatę zadłużenia technicznego. Może to obejmować sporadyczny sprint twardnienia lub po prostu rozwiązywanie długów w regularnych odstępach czasu (np. 2 przedmioty tygodniowo). Ważna część, aby upewnić się, że spłacasz swój dług szybciej niż narasta (dług, nawet techniczny, ma na nim odsetki).

Po osiągnięciu punktu, w którym nie masz już deficytu technicznego , jesteś w drodze do zdrowszej bazy kodów :)

MetaFight
źródło
5

Na marginesie: poszukaj nowej pracy. Ten nie byłby lepszy.

Cele sprawdzanego kodu to:

  • Aby wysłać funkcję, która powinna działać zgodnie z wymaganiami.

  • Ograniczenie wzrostu zadłużenia technicznego.

Pierwszy cel jest weryfikowany przez sprawdzenie, czy testy jednostkowe, integracyjne, systemowe i funkcjonalne są tutaj, czy są odpowiednie i czy obejmują wszystkie sytuacje, które muszą zostać przetestowane. Musisz także sprawdzić przekonania autora na temat języka programowania, co może prowadzić do subtelnych błędów lub kodu udającego, że robi coś innego niż to, co faktycznie robi.

Drugi cel to ten, na którym koncentruje się twoje pytanie. Z jednej strony nie oczekuje się, że nowy kod zwiększy zadłużenie techniczne. Z drugiej strony zakresem przeglądu jest sam kod, ale w kontekście całej bazy kodu. Odtąd jako recenzent możesz oczekiwać dwóch podejść od oryginalnego autora:

  • Kod zewnętrzny nie jest moją winą. Po prostu implementuję tę funkcję i nie dbam o całą bazę kodu.

    W tej perspektywie kod skopiuje wady bazy kodu, a zatem nieuchronnie zwiększy techniczny dług: więcej złego kodu jest zawsze gorsze.

    Chociaż jest to prawidłowe podejście krótkoterminowe, w perspektywie długoterminowej spowodowałoby to zwiększenie opóźnień i niską wydajność, a ostatecznie doprowadziłoby do tak kosztownego i ryzykownego procesu rozwoju, że produkt przestałby ewoluować.

  • Napisanie nowego kodu jest okazją do refaktoryzacji starszego kodu.

    W tej perspektywie wpływ wad starego kodu na nowy może być ograniczony. Co więcej, dług techniczny można zmniejszyć lub przynajmniej nie zwiększyć proporcjonalnie do wzrostu kodu.

    Chociaż jest to prawidłowe podejście długoterminowe, wiąże się z nim ryzyko krótkoterminowe. Głównym z nich jest, że krótkotrwałe, to czasami wymaga więcej czasu, aby wysyłać funkcji konkretnego. Innym ważnym aspektem jest to, że jeśli starszy kod nie zostanie przetestowany, jego refaktoryzacja stwarza ogromne ryzyko wprowadzenia regresji.

W zależności od perspektywy, którą chcesz zachęcić, możesz być skłonny doradzić recenzentom, aby dokonali większego refaktoryzacji. We wszystkich przypadkach nie oczekuj bezbłędnego, czystego fragmentu kodu z ładną architekturą i designem w kiepskiej bazie kodu. To, czego nie powinieneś zachęcać, to zachowanie, w którym dobrze poinformowany programista, który musi pracować nad kiepską bazą kodu, stara się dobrze wykonać swoją rolę . Zamiast upraszczać, tylko komplikuje je przedtem. Teraz, zamiast jednolitego, złego kodu, masz część ze wzorami projektowymi, inną część z czystym, przejrzystym kodem, inną część, która z biegiem czasu została gruntownie zreformowana, i nie ma żadnej jedności.

Wyobraź sobie na przykład, że odkrywasz starszą bazę kodów witryny średniej wielkości. Jesteś zaskoczony brakiem jakiejkolwiek zwykłej struktury i faktem, że rejestrowanie, gdy jest zrobione, polega na ręcznym dodawaniu elementów do pliku tekstowego, zamiast korzystania z frameworka rejestrowania. Ty decydujesz, aby nowa funkcja korzystała z MVC i środowiska rejestrowania.

Twój kolega wdraża kolejną funkcję i jest bardzo zaskoczony brakiem ORM, w którym można uzyskać idealny rozmiar. Więc zaczyna używać ORM.

Ani ty, ani twój kolega nie jesteście w stanie przejść przez setki tysięcy wierszy kodu, aby wszędzie korzystać z MVC, frameworka rejestrowania lub ORM. W rzeczywistości wymagałoby to miesięcy pracy: wyobraź sobie wprowadzenie MVC; ile to zajmie? A co z ORM w sytuacjach, w których zapytania SQL były chaotycznie generowane przez konkatenację (z okazjonalnymi miejscami dla SQL Injection) wewnątrz kodu, którego nikt nie rozumiał?

Myślisz, że wykonałeś świetną robotę, ale teraz nowy programista, który dołącza do projektu, musi stawić czoła znacznie większej złożoności niż wcześniej:

  • Stary sposób traktowania próśb,

  • Sposób MVC,

  • Stary mechanizm rejestrowania,

  • Ramy rejestrowania,

  • Bezpośredni dostęp do bazy danych dzięki zapytaniom SQL budowanym w locie,

  • ORM.

Przy jednym projekcie, nad którym pracowałem, były używane cztery (!) Struktury rejestrowania obok siebie (plus rejestrowanie ręczne). Powodem jest to, że za każdym razem, gdy ktoś chciał się zalogować, nie było wspólnego podejścia do tego, więc zamiast uczyć się nowego frameworka (który we wszystkich przypadkach był używany tylko w 5% bazy kodu), wystarczy dodać kolejny już wie. Wyobraź sobie bałagan.

Lepszym rozwiązaniem byłoby przefakturowanie bazy kodu krok po kroku. Biorąc jeszcze raz przykład rejestrowania, refaktoryzacja składałaby się z następujących małych kroków:

  • Znajdź wszystkie miejsca, w których odbywa się rejestrowanie starszego typu (tj. Gdy plik dziennika jest uzyskiwany bezpośrednio) i upewnij się, że wszystkie wywołują te same metody.

  • Przenieś ten kod do dedykowanej biblioteki, jeśli dotyczy. Nie chcę logować pamięci masowej w mojej klasie koszyka.

  • W razie potrzeby zmień interfejs metod rejestrowania. Na przykład możemy dodać poziom wskazujący, czy wiadomość jest nieformalna, czy jest ostrzeżeniem lub błędem.

  • Użyj nowo zreformowanych metod w nowej funkcji.

  • Przeprowadź migrację do środowiska rejestrowania: jedynym kodem, którego dotyczy problem, jest kod z dedykowanej biblioteki.

Arseni Mourzenko
źródło
1
Świetna odpowiedź do ostatniego akapitu. Bez względu na to, czy zamierzałeś, czy nie, sugerujesz, że w nowym kodzie nie należy stosować dobrych praktyk. -1
RubberDuck,
2
@RubberDuck: nie chodzi o dobre praktyki, chodzi o radykalne pisanie kodu różniącego się od pozostałej bazy kodu. Byłem programistą i widziałem konsekwencje tego, co zrobiłem: posiadanie drastycznie lepszego kodu wśród złego kodu tylko pogarsza sytuację; co sprawia, że ​​lepiej jest ulepszyć bazę kodu poprzez małe etapy refaktoryzacji. Dodaję przykład do mojej odpowiedzi za kilka minut.
Arseni Mourzenko
Zrobiłbym ponownie DV, gdybym mógł. Edycja jeszcze gorzej. Posiadanie czterech różnych metod robienia czegoś w nowy sposób jest złe, ale jest to wina faceta, który dodaje drugą strukturę rejestrowania. Nie jest źle samo w sobie rysować linii w piasku i mieć czysty kod obok zgniłego kodu.
RubberDuck,
@RubberDuck: Nie chodzi o dodanie drugiego środowiska rejestrowania, ale pierwszego. Facet, który dodaje drugą strukturę rejestrowania, robi to tylko dlatego, że pierwsza jest używana tylko z jedną małą funkcją; jeśli baza kodów zostałaby przebudowana zgodnie z zaleceniem, tak by się nie stało.
Arseni Mourzenko
Myślę, że zgadzamy się z tobą, ale twoje odpowiedzi brzmią w sposób zniechęcający do poprawy. Po prostu nie mogę się z tym pogodzić.
RubberDuck,
3

Jeśli przeglądasz kod w ramach procesu programowania; następnie musisz ustalić zasady, według których „oceniasz” kod, który przeglądasz.

Powinno to być zgodne z „definicją ukończenia” i może być przewodnikiem po stylu, dokumentem architektury bazy danych lub analizą statyczną, sprawdzającym wymagania prawne, niezależnie od tego, co firma zdecyduje o wymaganiach dotyczących „jakości kodu”

Po wprowadzeniu tego przeglądu recenzje stają się oczywiste, czy przestrzegano przewodnika po stylach, czy mamy wymagany procent pokrycia testowego itp.

Jeśli nie masz tego na swoim miejscu, recenzje kodu mogą stać się po prostu bitwą o to, kto ma największe kodowanie lub, podobnie jak w twojej sytuacji, kwestionowaniem wezwań do oceny refaktoryzacji vs funkcji wykonanych przed upływem terminu. Co jest stratą czasu każdego.

Ewan
źródło
3

Twoim głównym problemem jest to, że przegląd kodu znaczącej nowej funkcji jest nieodpowiednim czasem na rozmowę. W tym momencie jest już za późno, aby dokonać drobnych zmian. Właściwe miejsce znajduje się na etapie planowania lub najpóźniej we wstępnym przeglądzie projektu. Jeśli Twoja firma nie przeprowadza tych wczesnych recenzji, przynajmniej nieformalnie, powinieneś najpierw zmienić tę kulturę.

Następnym krokiem jest zaproszenie Cię na te spotkania i produktywne pomysły na tych spotkaniach. Przeważnie oznacza to, że nie próbujesz zmieniać wszystkiego z dnia na dzień, ale szukasz kawałków wielkości kęsa, które możesz izolować i rozwiązywać. Te fragmenty z czasem znacznie się zsumują.

Innymi słowy, kluczem do sukcesu jest regularne sugerowanie mniejszych zmian na początku projektów, a nie rezygnacja z sugerowania większych zmian pod koniec.

Karl Bielefeldt
źródło
2

W miejscach, w których robiłem przegląd kodu, zaakceptowałbym i zatwierdziłbym przesłanie kodu, jeśli wiąże się to ze zobowiązaniem do (przynajmniej) częściowego refaktoryzacji. Czy to jako zgłoszony błąd, jako historia, czy też obietnica wysłania kolejnej recenzji z (niektórymi) dokonanymi refaktoryzacjami.

W takich przypadkach, jeśli jestem osobą, która pisze kod do recenzji, zwykle przygotowuję dwie zmiany, jedną z moimi nowymi funkcjami lub poprawkami błędów, a następnie drugą, która ma ORAZ pewne poprawki. W ten sposób zmiany czyszczenia nie zmniejszają nowych funkcji ani poprawek, ale można je łatwo wskazać jako token „tak, wiem, że to nie rozwiązuje tych problemów, ale tam jest” czyste „czyszczenie”.

Vatine
źródło