Kontekst: Jestem programistą korporacyjnym w sklepie MS.
Czy ktoś może polecić dobry sposób obiektywnego pomiaru możliwości utrzymania części kodu lub aplikacji?
Dlaczego łatwość konserwacji : Mam dość wskaźników „jakości” w mojej grupie, które dotyczą jedynie liczby błędów i pokrycia kodu. Oba wskaźniki są łatwe do grania, szczególnie gdy nie mierzysz łatwości konserwacji. Krótkowzroczność i terminy skutkują ogromnymi długami technicznymi, które tak naprawdę nigdy nie zostaną rozwiązane.
Dlaczego umiejętność obiektywnego pomiaru : pracuję w dużej grupie przedsiębiorstw. Jeśli nie możesz obiektywnie tego zmierzyć, nie możesz pociągać ludzi do odpowiedzialności za to, ani sprawić, by byli w tym lepsi. Subiektywne pomiary albo się nie zdarzają, albo nie są konsekwentne.
Patrzę na metryki kodu VS2010 , ale zastanawiam się, czy ktoś ma jakieś inne rekomendacje.
źródło
Odpowiedzi:
Rzeczywistość jest taka, że jeśli nie masz konkretnych dowodów na to, że kodu nie da się utrzymać tak, jak jest ... to ... naprawienie błędu spowodowało N niepotrzebnych godzin z powodu niemożliwego do utrzymania kodu; wtedy posiadanie nogi do stania będzie z natury trudne. W tym przykładzie mogło to być spowodowane faktem, że zastosowano zbyt złożoną metodologię, gdy wystarczyłoby coś znacznie prostszego. Wkraczanie w obszar, w którym próbujesz zmierzyć metodologie, paradygmaty i najlepsze praktyki, staje się coraz trudniejsze, przynosząc niewielki lub żaden długoterminowy zysk.
Zejście tą ścieżką jest niestety drogą do nikąd. Skoncentruj się na odkrywaniu głównych problemów, które mają istotne zalety i nie są związane z osobistymi odczuciami na temat problemu, takimi jak brak konwencji nazewnictwa w całej bazie kodu i znajdź sposób pomiaru sukcesu i porażek wokół tego głównego problemu. Pozwoli to na rozpoczęcie zestawiania zestawu bloków konstrukcyjnych, z których następnie możesz zacząć formułować rozwiązania.
źródło
Miarą, której używam lub lubię myśleć, że używam jest:
Dla każdego niezależnego, pojedynczego, jednowierszowego wymagania funkcjonalnego typu „weź lub zostaw”, wykonaj migawkę podstawy kodu przed jego wdrożeniem. Następnie zaimplementuj go, w tym znajdując i usuwając wszelkie błędy wprowadzone w tym procesie. Następnie uruchom
diff
między bazą kodu przed i po.diff
Pokaże listę wszystkich insercji, delecji i modyfikacji wprowadzonych zmian. (Jak wstawienie 10 kolejnych wierszy kodu to jedna zmiana.) Ile było zmian? Im mniejsza jest ta liczba, tym kod jest łatwiejszy w utrzymaniu.Nazywam to redundancją kodu źródłowego, ponieważ jest to jak redundancja kodu korygującego błędy. Informacje były zawarte w 1 części, ale zostały zakodowane jako N części, które wszystkie muszą być wykonane razem, aby były spójne.
Myślę, że taki jest pomysł DRY, ale jest to trochę bardziej ogólne. Powodem, dla którego ta liczba jest niska, jest fakt, że jeśli potrzeba N zmian, aby zaimplementować typowe wymaganie, a jako zawodny programista dostaniesz tylko N-1 lub N-2 z nich poprawnie zrobionych, na początku umieściłeś 1 lub 2 błędy. Oprócz wysiłków związanych z programowaniem O (N), błędy te muszą zostać wykryte, zlokalizowane i naprawione. Dlatego małe N jest dobre.
Konserwowalność niekoniecznie oznacza czytelność dla programisty, który nie nauczył się, jak działa kod. Optymalizacja N może wymagać robienia pewnych rzeczy, które tworzą krzywą uczenia się dla programistów. Oto przykład. Jedną z rzeczy, która pomaga, jest to, że programista próbuje przewidzieć przyszłe zmiany i pozostawia wskazówki w komentarzu do programu.
Myślę, że gdy N jest wystarczająco zredukowane (optymalne jest 1), kod źródłowy czyta się bardziej jak język specyficzny dla domeny (DSL). Program nie tyle „rozwiązuje” problem, co „stwierdza” problem, ponieważ idealnie każde wymaganie jest przekształcane jako pojedynczy fragment kodu.
Niestety nie widzę ludzi, którzy dużo się uczą, jak to robić. Wydaje się raczej, że myślą, że rzeczowniki mentalne powinny stać się klasami, a czasowniki metodami, a jedyne, co muszą zrobić, to obrócić korbą. Z mojego doświadczenia wynika, że kod to N równy 30 lub więcej.
źródło
Utrzymanie nie jest tak naprawdę wymierne. Jest to subiektywne spojrzenie na osobę oparte na jej doświadczeniach i preferencjach.
Aby uzyskać kawałek kodu, wymyśl idealną formę.
Następnie dla każdego odchylenia prawdziwego kodu od tego idealnego zmniejsz wartość 100 o pewną liczbę. Od tego, co dokładnie zależy od konsekwencji wyboru niedoskonałego podejścia.
Przykład:
Fragment kodu odczytuje i importuje pewien format danych i może wyświetlać komunikat o błędzie, jeśli coś jest nie tak.
Idealne rozwiązanie (100) zawierałoby komunikaty o błędach przechowywane w jednym wspólnym miejscu. Jeśli w twoim rozwiązaniu są one zakodowane na stałe jako stałe łańcuchowe bezpośrednio w kodzie, zdejmujesz, powiedzmy 15, off. Tak więc twój wskaźnik utrzymania wynosi 85.
źródło
Jednym z rezultatów kodu, który jest trudny w utrzymaniu, jest to, że naprawienie błędów zajmie ci więcej czasu (średnio). Na pierwszy rzut oka wydaje się, że jednym pomiarem jest czas potrzebny na naprawienie błędu od momentu przypisania (tj. Poprawka jest uruchomiona) do momentu „gotowości do przetestowania”.
Teraz zadziała to naprawdę tylko po naprawieniu rozsądnej liczby błędów, aby uzyskać „średni” (cokolwiek to znaczy) czas. Nie możesz użyć tej liczby do żadnego konkretnego błędu, ponieważ to, jak trudno jest wyśledzić, nie zależy tylko od „łatwości konserwacji” kodu.
Oczywiście, gdy naprawiasz więcej błędów, kod staje się „łatwiejszy” do utrzymania, ponieważ poprawiasz go (a przynajmniej powinieneś być) i zaczynasz się lepiej zaznajomić z kodem. Przeciwdziałanie temu polega na tym, że błędy będą bardziej niejasne, a zatem trudniejsze do wyśledzenia.
Ma to również problem z tym, że jeśli ludzie będą spieszyć się z poprawkami błędów, aby uzyskać niższy wynik, albo powodując nowe błędy, albo nieprawidłowo naprawiając istniejący, co prowadzi do jeszcze większej pracy i być może nawet gorszego kodu.
źródło
Uważam, że Visual Studio Code Metrics jest całkiem przyzwoite, ponieważ zapewnia szybką miarę „łatwości konserwacji”. Przechwytywanych jest 5 podstawowych wskaźników:
Indeks konserwacji jest dla mnie przydatny. Jest to indeks złożony oparty na:
Czasami przyjrzę się moim metodom z niskim indeksem konserwacji (niski = zły dla tego). Niemal bezbłędnie, metody w moim projekcie o najniższym wskaźniku utrzymania są najbardziej potrzebne do przepisania i najtrudniejsze do odczytania (lub utrzymania).
Więcej informacji na temat obliczeń znajduje się w białej księdze .
źródło
Dwa, które będą miały znaczenie, to cykliczność i sprzężenie klas. Nie możesz wyeliminować złożoności, wszystko, co możesz zrobić, to podzielić ją na części możliwe do zarządzania. Te 2 miary powinny dać ci wyobrażenie o tym, gdzie można znaleźć trudny w utrzymaniu kod, a przynajmniej gdzie najtrudniej szukać.
Cyklomatyczna złożoność jest miarą liczby ścieżek w kodzie. Każda ścieżka powinna zostać przetestowana (ale prawdopodobnie nie jest). Coś o złożoności powyżej około 20 należy podzielić na mniejsze moduły. Moduł o cyklicznej złożoności wynoszącej 20 (można by to powielić za pomocą 20 kolejnych
if then else
bloków) będzie miał górną granicę 2 ^ 20 ścieżek do przetestowania.Sprzężenie klas jest miarą tego, jak ściśle powiązane są klasy. Przykład złego kodu, z którym pracowałem u mojego poprzedniego pracodawcy, zawiera komponent „warstwy danych” zawierający około 30 elementów w konstruktorze. Osoba w większości „odpowiedzialna” za ten komponent dodawała parametry biznesowe i parametry interfejsu użytkownika do wywołań konstruktora / otwartych, dopóki nie była to naprawdę wielka kula błota. Jeśli pamięć służy mi poprawnie, było około 15 różnych nowych / otwartych wywołań (niektóre już nieużywane), wszystkie z nieco innymi zestawami parametrów. Zainicjowaliśmy recenzje kodu wyłącznie w celu powstrzymania go przed robieniem więcej takich rzeczy - i aby nie wyglądać, jakbyśmy go wyróżniali, sprawdziliśmy kod każdego zespołu, więc zmarnowaliśmy około pół dnia na 4-6 ludzie każdego dnia, ponieważ my nie
źródło
Podsumowując, łatwość konserwacji można naprawdę zmierzyć tylko wtedy, gdy jest to wymagane, a nie wcześniej . Oznacza to, że można tylko stwierdzić, czy fragment kodu jest możliwy do utrzymania, kiedy trzeba go zachować.
Względnie oczywiste jest zmierzenie, jak łatwo było dostosować kawałek kodu do zmieniających się wymagań. Jest prawie niemożliwe zmierzyć z wyprzedzeniem, jak zareaguje na zmiany wymagań. Oznaczałoby to, że musisz przewidzieć zmiany wymagań. A jeśli możesz to zrobić, powinieneś dostać cenę nobla;)
Jedyne, co możesz zrobić, to uzgodnić ze swoim zespołem, na podstawie konkretnych zasad (takich jak zasady SOLID), które według wszystkich ogólnie zwiększają łatwość utrzymania.
Jeśli zasady są dobrze wybrane (myślę, że dobrym pomysłem byłoby skorzystanie z SOLID, na początek), możesz dość wyraźnie wykazać, że są łamane i pociągnąć autorów do odpowiedzialności.
Będziesz miał bardzo trudny czas, starając się promować absolutną miarę łatwości utrzymania, a jednocześnie stopniowo przekonywać swój zespół do przestrzegania ustalonego zestawu ustalonych zasad, które wydają się realistyczne.
źródło
Co z długiem technicznym, który jest „wyprzedzany przez wydarzenia”?
Piszę kiepski kod i pędzę go do produkcji.
Zauważysz - poprawnie - że nie da się tego utrzymać.
Kod ten jest jednak ostatnią rundą funkcji dla linii produktów, która zostanie wycofana z eksploatacji, ponieważ zmienił się kontekst prawny i linia produktów nie ma przyszłości.
„Dług techniczny” zostaje wyeliminowany przez zmianę legislacyjną, która powoduje, że wszystko staje się przestarzałe.
Wskaźnik „łatwości konserwacji” zmienił się z „zły” na „nieistotny” ze względów zewnętrznych.
Jak można to zmierzyć?
źródło
Kolejną najlepszą rzeczą do recenzji kodów równorzędnych jest stworzenie sprawnej architektury przed kodowaniem jednostki lub produktu. Refaktor czerwono-zielony to całkiem fajny sposób. Poproś starszego mężczyznę, aby opracował sprawny interfejs i podzielił się pracą. Każdy może wziąć swój kawałek układanki i czerwono-zielony drogę do zwycięstwa. Po tym, przegląd kodu równorzędnego i refaktor byłyby w porządku. To działało całkiem nieźle na poprzednim ważnym produkcie, nad którym pracowałem.
źródło
Ankieta
Co powiesz na zrobienie anonimowego kwestionariusza dla programistów, który będzie wypełniany raz na miesiąc? Pytania będą wyglądać następująco:
(Możesz dodać dodatkowe pytania, które Twoim zdaniem byłyby przydatne w pomiarze łatwości konserwacji w komentarzach, a ja je dodam).
źródło
Mogę wymyślić dwa sposoby spojrzenia na łatwość konserwacji (jestem pewien, że istnieje więcej nadziei, że inni mogą wymyślić dobre definicje.
Modyfikacja bez zrozumienia.
Czy narzędzie do naprawy błędów może wejść do kodu i rozwiązać problem bez konieczności rozumienia działania całego systemu.
Można to osiągnąć, zapewniając kompleksowe testy jednostkowe (testy regresji). Powinieneś być w stanie sprawdzić, czy jakakolwiek zmiana w systemie nie zmienia sposobu, w jaki zachowuje się system, przy jakimkolwiek konkretnym dobrym wejściu.
W tej sytuacji narzędzie do naprawy błędów powinno być w stanie naprawić (prosty) błąd przy minimalnej znajomości systemu. Jeśli poprawka działa, żaden z testów regresji nie powinien zakończyć się niepowodzeniem. Jeśli jakiekolwiek testy regresji zakończą się niepowodzeniem, musisz przejść do etapu 2.
Modyfikacja ze zrozumieniem.
Jeśli usunięcie błędu stanie się nietrywialne i musisz zrozumieć system. Jaka jest dokumentacja systemu. My nie mówimy dokumentację API zewnętrznym (są stosunkowo bezużyteczne). Musimy zrozumieć, w jaki sposób system działa w przypadku sprytnych sztuczek (czytających hacków) wykorzystywanych we wdrożeniach itp.
Ale dokumentacja to za mało, kod musi być przejrzysty i zrozumiały. Aby zmierzyć zrozumiałość kodu, możemy użyć małej sztuczki. Po tym, jak programista zakończy kodowanie, daj mu miesiąc na pracę nad czymś innym. Następnie poproś ich, aby wrócili i udokumentowali system w takim stopniu, że molo może teraz zrozumieć system. Jeśli kod jest stosunkowo łatwy do zrozumienia, powinien być szybki. Jeśli jest źle napisany, więcej czasu zajmie opracowanie tego, co zbudowali i napisanie dokumentacji.
Być może moglibyśmy wymyślić coś takiego:
źródło
Często stwierdzam, że rozwiązanie „najkrótszego odpowiednika” wydaje się być najłatwiejsze w utrzymaniu.
Tutaj najkrótsza oznacza najmniej operacji (nie linii). Odpowiednik oznacza, że krótsze rozwiązanie nie powinno mieć gorszej złożoności czasu lub przestrzeni niż poprzednie rozwiązanie.
Oznacza to, że wszystkie logicznie podobne powtarzające się wzorce należy wyodrębnić do odpowiedniej abstrakcji: Podobne bloki kodu? Wyodrębnij go do działania. Zmienne, które wydają się występować razem? Wyodrębnij je do struktury / klasy. Klasy, których członkowie różnią się tylko rodzajem? Potrzebujesz ogólny. Wygląda na to, że w wielu miejscach przeliczyłeś to samo? Oblicz na początku i zapisz wartość w zmiennej. Spowoduje to skrócenie kodu. Zasadniczo taka jest zasada OSUSZANIA.
Możemy również zgodzić się, że nieużywane abstrakcje powinny zostać usunięte: klasy, funkcje, które nie są już potrzebne, są martwym kodem, więc należy je usunąć. Kontrola wersji zapamięta, czy kiedykolwiek będziemy musieli ją przywrócić.
Często dyskutowane są abstrakcje, do których odwołuje się tylko jeden raz: funkcje bez oddzwaniania, które są wywoływane tylko raz, bez powodu, aby być wywoływanym więcej niż raz. Generyczny, który jest tworzony przy użyciu tylko jednego typu i nie ma powodu, aby kiedykolwiek był tworzony przy użyciu innego typu. Interfejsy, które są zaimplementowane tylko raz i nie ma żadnego rzeczywistego powodu, że byłby kiedykolwiek implementowany przez jakąkolwiek inną klasę i tak dalej. Moim zdaniem te rzeczy są niepotrzebne i powinny zostać usunięte, to w zasadzie zasada YAGNI.
Powinno być więc narzędzie wykrywające powtórzenia kodu, ale myślę, że problem ten jest podobny do znalezienia optymalnej kompresji, która jest problemem złożoności Kołmogorowa, który jest nierozstrzygalny. Ale z drugiej strony niewykorzystane i słabo wykorzystane abstrakcje są łatwe do wykrycia na podstawie liczby referencji: sprawdzenie tego można zautomatyzować.
źródło
Wszystko to jest subiektywne i wszelkie pomiary oparte na samym kodzie są ostatecznie nieistotne. Ostatecznie wszystko sprowadza się do twojej zdolności do sprostania wymaganiom. Czy nadal możesz dostarczyć żądane funkcje, a jeśli tak, to jak często powrócą do Ciebie, ponieważ coś jeszcze nie jest w porządku i jak poważne są te problemy?
Właśnie (ponownie) zdefiniowałem łatwość konserwacji, ale nadal jest subiektywna. Z drugiej strony może to nie mieć większego znaczenia. Musimy po prostu zadowolić naszego klienta i cieszyć się nim, do tego właśnie dążymy.
Najwyraźniej czujesz, że musisz udowodnić swojemu szefowi lub współpracownikom, że należy coś zrobić, aby poprawić stan bazy kodu. Twierdzę, że wystarczy, aby powiedzieć, że jesteś sfrustrowany faktem, że za każdą drobną rzeczą, którą musisz zmienić lub dodać, musisz naprawić lub rozwiązać 10 innych problemów, których można było uniknąć. Następnie nazwij znany obszar i zrób skrzynkę, aby odwrócić go do góry nogami. Jeśli to nie zwiększy poparcia w twoim zespole, możesz być lepiej gdzie indziej. Jeśli ludzi wokół ciebie to nie obchodzi, udowodnienie, że nie masz zamiaru zmienić zdania.
źródło