Nie zgadzaj się na rozwijanie czegoś, czego nie rozumiesz

Nie zgadzaj się na rozwijanie czegoś, czego nie rozumiesz

Od początku 2018 roku zajmuję w zespole stanowisko lead/boss/lead developer – nazwij to jak chcesz, ale chodzi o to, że jestem całkowicie odpowiedzialny za jeden z modułów i za wszystkich pracujących developerów na tym. To stanowisko daje mi nowe spojrzenie na proces rozwoju, ponieważ angażuję się w większą liczbę projektów i aktywniej uczestniczę w podejmowaniu decyzji. Ostatnio dzięki tym dwóm rzeczom nagle zdałem sobie sprawę, jak bardzo miara zrozumienia wpływa na kod i aplikację.

Chcę podkreślić, że jakość kodu (i produktu końcowego) jest ściśle powiązana ze świadomością tego, co robią ludzie, którzy projektują i piszą kod.

Być może teraz myślisz: „Dzięki, kapitanie. Oczywiście miło byłoby ogólnie zrozumieć, co piszesz. W przeciwnym razie równie dobrze możesz wynająć grupę małp, aby naciskały dowolne klawisze i tak zostawić. I masz całkowitą rację. W związku z tym uważam za oczywiste, że zdajesz sobie sprawę, że konieczne jest posiadanie ogólnego pojęcia o tym, co robisz. Można to nazwać zerowym poziomem zrozumienia i nie będziemy tego szczegółowo analizować. Przyjrzymy się szczegółowo, co dokładnie musisz zrozumieć i jak wpływa to na decyzje, które podejmujesz każdego dnia. Gdybym wiedział o tym wcześniej, zaoszczędziłoby mi to dużo zmarnowanego czasu i wątpliwego kodu.

Chociaż poniżej nie zobaczysz ani jednej linijki kodu, nadal uważam, że wszystko, co tu zostało powiedziane, ma ogromne znaczenie dla pisania wysokiej jakości, wyrazistego kodu.

Pierwszy poziom zrozumienia: dlaczego to nie działa?

Programiści zazwyczaj osiągają ten poziom na bardzo wczesnym etapie swojej kariery, czasem nawet bez pomocy innych – przynajmniej z mojego doświadczenia. Wyobraź sobie, że otrzymałeś raport o błędzie: jakaś funkcja w aplikacji nie działa, należy to naprawić. Jak będziesz postępować?

Standardowy schemat wygląda następująco:

  1. Znajdź fragment kodu, który jest przyczyną problemu (jak to zrobić, to osobny temat, omawiam to w mojej książce o starszym kodzie)
  2. Wprowadź zmiany w tym fragmencie
  3. Upewnij się, że błąd został naprawiony i nie wystąpiły żadne błędy regresji

Teraz skupmy się na drugim punkcie – wprowadzaniu zmian w kodzie. Istnieją dwa podejścia do tego procesu. Pierwszym z nich jest zagłębienie się w to, co dokładnie dzieje się w bieżącym kodzie, zidentyfikowanie błędu i naprawienie go. Po drugie: poruszaj się według wyczucia — dodaj, powiedzmy, +1 do instrukcji warunkowej lub pętli, sprawdź, czy funkcja działa w żądanym scenariuszu, a następnie spróbuj czegoś innego i tak w nieskończoność.

Pierwsze podejście jest prawidłowe. Jak wyjaśnia Steve McConnell w swojej książce Code Complete (którą swoją drogą bardzo polecam), za każdym razem, gdy zmieniamy coś w kodzie, powinniśmy być w stanie z pewnością przewidzieć, jak wpłynie to na aplikację. Cytuję z pamięci, ale jeśli poprawka błędu nie działa zgodnie z oczekiwaniami, powinieneś być bardzo zaniepokojony i powinieneś zakwestionować cały swój plan działania.

Podsumowując to, co zostało powiedziane, aby dobrze naprawić błąd, który nie pogorszy jakości kodu, musisz zrozumieć zarówno całą strukturę kodu, jak i źródło konkretnego problemu.

Drugi poziom zrozumienia: Dlaczego to działa?

Poziom ten jest rozumiany znacznie mniej intuicyjnie niż poprzedni. Ja, będąc jeszcze początkującym programistą, nauczyłem się tego dzięki mojemu szefowi, a później wielokrotnie tłumaczyłem nowicjuszom istotę sprawy.

Tym razem wyobraźmy sobie, że otrzymałeś dwa raporty o błędach jednocześnie: pierwszy dotyczy scenariusza A, drugi dotyczy scenariusza B. W obu scenariuszach dzieje się coś złego. W związku z tym najpierw zajmiesz się pierwszym błędem. Korzystając z zasad, które opracowaliśmy dla zrozumienia poziomu XNUMX, możesz zagłębić się w kod odnoszący się do problemu, dowiedzieć się, dlaczego powoduje to, że aplikacja zachowuje się w taki sposób, w jaki zachowuje się w scenariuszu A, i wprowadzić rozsądne zmiany, które dają pożądany rezultat. . Wszystko idzie świetnie.

Następnie przechodzisz do scenariusza B. Powtarzasz scenariusz, próbując sprowokować błąd, ale – niespodzianka! — teraz wszystko działa tak, jak powinno. Aby potwierdzić swoje przypuszczenia, cofasz zmiany wprowadzone podczas pracy nad błędem A, a błąd B powraca. Twoja poprawka rozwiązała oba problemy. Mający szczęście!

W ogóle na to nie liczyłeś. Wymyśliłeś sposób na naprawienie błędu w scenariuszu A i nie masz pojęcia, dlaczego zadziałał w scenariuszu B. Na tym etapie bardzo kusząca jest myśl, że oba zadania zostały pomyślnie wykonane. To całkiem logiczne: chodziło o wyeliminowanie błędów, prawda? Ale praca jeszcze się nie skończyła: nadal musisz dowiedzieć się, dlaczego Twoje działania naprawiły błąd w scenariuszu B. Dlaczego? Ponieważ może to działać na złych zasadach i wtedy trzeba będzie poszukać innego wyjścia. Oto kilka przykładów takich przypadków:

  • Ponieważ rozwiązanie nie zostało dostosowane do błędu B, biorąc pod uwagę wszystkie czynniki, być może nieświadomie uszkodziłeś funkcję C.
  • Możliwe, że gdzieś czai się trzeci błąd, związany z tą samą funkcją i od niego zależy poprawność działania systemu w scenariuszu B. Wszystko wygląda teraz dobrze, ale pewnego dnia ten trzeci błąd zostanie zauważony i naprawiony. Wtedy w scenariuszu B błąd pojawi się ponownie i dobrze, żeby tylko tam.

Wszystko to wprowadza chaos do kodu i pewnego dnia spadnie na Twoją głowę - najprawdopodobniej w najbardziej nieodpowiednim momencie. Będziesz musiał zebrać siłę woli, aby zmusić się do spędzenia czasu na zrozumieniu, dlaczego wszystko wydaje się działać, ale warto.

Trzeci poziom zrozumienia: Dlaczego to działa?

Moje ostatnie spostrzeżenie odnosi się właśnie do tego poziomu i prawdopodobnie to właśnie ten poziom przyniósłby mi najwięcej korzyści, gdybym wpadł na ten pomysł wcześniej.

Aby było to jaśniejsze, spójrzmy na przykład: Twój moduł musi być kompatybilny z funkcją X. Nie jesteś szczególnie zaznajomiony z funkcją X, ale powiedziano Ci, że aby być z nią kompatybilnym, musisz użyć frameworka F. Inne moduły integrujące się z X działają dokładnie z nim.

Twój kod od pierwszego dnia swojego życia w ogóle nie miał styczności z frameworkiem F, dlatego jego wdrożenie nie będzie takie proste. Będzie to miało poważne konsekwencje dla niektórych części modułu. Jednak poświęcasz się programowaniu: spędzasz tygodnie na pisaniu kodu, testowaniu, wdrażaniu wersji pilotażowych, zbieraniu informacji zwrotnych, naprawianiu błędów regresji, odkrywaniu nieprzewidzianych komplikacji, niedotrzymywaniu pierwotnie ustalonych terminów, pisaniu większej ilości kodu, testowaniu, uzyskiwaniu informacji zwrotnych, korygowanie błędów regresji - wszystko to w celu wdrożenia frameworku F.

I w pewnym momencie nagle zdajesz sobie sprawę – lub może od kogoś słyszysz – że być może framework F w ogóle nie zapewni kompatybilności z funkcją X. Być może cały ten czas i wysiłek został włożony w to zupełnie niewłaściwie.

Coś podobnego przydarzyło się kiedyś podczas pracy nad projektem, za który byłem odpowiedzialny. Dlaczego się to stało? Ponieważ nie bardzo rozumiałem, czym jest funkcja X i jaki ma ona związek ze strukturą F. Co powinienem był zrobić? Poproś osobę wyznaczającą zadanie programistyczne, aby jasno wyjaśniła, w jaki sposób zamierzony sposób działania prowadzi do pożądanego rezultatu, zamiast po prostu powtarzać to, co zostało zrobione w przypadku innych modułów lub wierzyć jej na słowo, że właśnie to musi zrobić funkcja X.

Doświadczenie związane z tym projektem nauczyło mnie, aby nie rozpoczynać procesu tworzenia oprogramowania, dopóki nie zrozumiemy, dlaczego jesteśmy proszeni o wykonanie pewnych rzeczy. Odmów wprost. Kiedy otrzymujesz zadanie, pierwszym odruchem jest natychmiastowe podjęcie się go, aby nie tracić czasu. Jednak polityka „zamrożenia projektu do czasu poznania wszystkich szczegółów” może zmniejszyć stratę czasu o rzędy wielkości.

Nawet jeśli będą próbowali wywrzeć na Ciebie presję, zmusić Cię do podjęcia pracy, mimo że nie rozumiesz, dlaczego to robi, stawiaj opór. Najpierw zastanów się, dlaczego postawiono przed Tobą takie zadanie i zdecyduj, czy jest to właściwa droga do celu. Musiałem się tego wszystkiego nauczyć na własnej skórze – mam nadzieję, że mój przykład ułatwi życie tym, którzy to przeczytają.

Czwarty poziom zrozumienia: ???

W programowaniu zawsze można się więcej nauczyć i wydaje mi się, że dopiero zarysowałem powierzchnię tematu zrozumienia. Jakie inne poziomy zrozumienia odkryłeś przez lata pracy z kodem? Jakie decyzje podjąłeś, które miały pozytywny wpływ na jakość kodu i aplikacji? Jakie decyzje okazały się błędne i nauczyły Cię cennej lekcji? Podziel się swoimi doświadczeniami w komentarzach.

Źródło: www.habr.com

Dodaj komentarz