Istnieje wiele odpowiedzi w moim poprzednim pytaniu na temat prostoty związanej z czytelnością, która pomogła mi zobaczyć moją definicję, a zrozumienie prostoty w kodzie było, być może, niepoprawne.
Jak zdefiniować prostotę w kodzie? Jakie pomiary i metryki oprogramowania są dostępne do pomiaru prostoty kodu?
code-quality
Richard
źródło
źródło
Odpowiedzi:
Najczęstsze miary do pomiaru złożoności (lub prostoty, jeśli uważasz, że prostota jest przeciwieństwem złożoności) to Cyklomatyczna złożoność McCabe i Metryka złożoności Halsteada .
Cyklomatyczna złożoność mierzy liczbę różnych ścieżek przez daną jednostkę, zwykle metodę lub funkcję, chociaż można ją również obliczyć dla klasy. Wraz ze wzrostem liczby ścieżek trudniej jest zapamiętać przepływ danych przez dany moduł, co wiąże się z koncepcją pamięci roboczej . Wysoka złożoność cykliczna wskazuje na trudności w testowaniu modułu - potrzeba więcej przypadków testowych, aby pokryć różne ścieżki w systemie. Istnieją również badania, które połączyły wysoką złożoność cyklomatyczną z wysokimi wskaźnikami wad. Zazwyczaj cykliczna złożoność wynosząca 10 wskazuje, że jednostka powinna zostać poddana przeglądowi i być może ponownie przetworzona.
Miary złożoności Halsteada wykorzystują dane wejściowe całkowitych i odrębnych operatorów i operandów do obliczenia objętości, trudności i wysiłku fragmentu kodu. Trudność, którą jest (liczba unikalnych operatorów / 2) * (całkowita liczba argumentów / liczba unikalnych argumentów), wiąże się ze zdolnością do czytania i rozumienia kodu dla zadań takich jak nauka systemu lub przegląd kodu. Ponownie można to policzyć na poziomie systemu, klasy lub metody / funkcji. Jest kilka postów na temat obliczania tych pomiarów tutaj i tutaj .
Po prostu zliczanie linii kodu może również dać ci wyobrażenie o złożoności. Więcej wierszy kodu oznacza, że w module jest więcej do odczytania i zrozumienia. Wahałbym się, czy wykorzystać to jako samodzielny pomiar. Zamiast tego użyłbym go do innych pomiarów, takich jak liczba defektów w danym module, aby uzyskać gęstość defektów. Wysoka gęstość defektów może wskazywać na problemy z pisaniem testów i przeglądaniem kodu, które mogą, ale nie muszą być spowodowane złożonym kodem.
Wachlowanie i wachlowanie to dwa inne wskaźniki związane z przepływem danych. Jak zdefiniowano tutaj , wejście wentylatora to suma wywoływanych procedur, odczyt parametrów, a odczyt zmiennych globalnych i wyciągnięcie wentylatora to suma procedur, które wywołują daną procedurę, parametry zapisywane (narażone na użytkowanie przez użytkowników zewnętrznych, przekazane przez referencję), i zmienne globalne zapisane do. Ponownie, wysokie wejście i wyjście może wskazywać na moduł, który może być trudny do zrozumienia.
W określonych paradygmatach mogą być przydatne inne miary lub wskaźniki. Na przykład w świecie zorientowanym obiektowo można zastosować monitorowanie sprzężenia (pożądane niskie), kohezji (pożądane wysokie) i głębokości dziedziczenia (pożądane niskie), aby ocenić, jak prosty lub skomplikowany jest system.
Oczywiście ważne jest, aby zdawać sobie sprawę, że wiele miar i wskaźników to po prostu wskaźniki. Musisz użyć swojej oceny, aby ustalić, czy konieczne jest dokonanie refaktoryzacji w celu zwiększenia prostoty, czy też nie warto tego robić. Możesz dokonywać pomiarów, obliczać metryki i poznawać kod, ale nie chcesz projektować systemu na podstawie liczb. Ostatecznie rób to, co ma sens.
źródło
Zamiast patrzeć na formalny tryb definiowania prostoty, wolałbym zdefiniować prostotę jako atrybut jakości pisania kodu.
Nie stawiam pewnej prostoty, ale kiedy nazywasz coś prostym, czy nie.
1. Przejście kodu:
jak łatwo poruszać się po kodzie? Czy łatwo jest zauważyć, gdzie są zapisane funkcje API? Czy łatwo jest zrozumieć przepływy wywołań, na przykład, które metody wywołują inne (i dlaczego) - czy są zaimplementowane dobre maszyny stanów lub algorytmy jednoznacznie określone?
Gdy przejście do kodu jest łatwe, kod jest prosty do naśladowania.
2. Nazewnictwo
Podczas gdy inne standardy kodowania sprawiają, że kod wygląda na bardziej przejrzysty - najważniejsze jest nazywanie klas / instancji obiektów / Zmiennych / metod. Stosowanie jasnych i jednoznacznych nazw jest wyraźnie ma ogromny wpływ na Prostota kodu. Kiedy trudno jest zidentyfikować prostą nazwę, jest to znak, że możesz chcieć ponownie przemyśleć pomysł, że jest to zmienna / metoda.
3. Interpretacja i odniesienia
Czy każda z metod ma do odegrania wyraźną rolę. Czy każdą zmienną / atrybut można łatwo określić, jaką rolę odgrywają? Gdy fragment kodu robi coś, co implikuje założenia lub wpływa na niepowiązany zestaw zmiennych, może stać się koszmarem konserwacyjnym.
4. Zależność lub sprzężenie
Trudno to ocenić na podstawie samego kodu, ale staje się bardzo widoczne, jeśli ktoś próbuje naprawić twoje błędy. Kiedy jakieś inne rzeczy zmieniają się w innym obiekcie, czy operacja tutaj się zmienia? Czy te zmiany są oczywiste? Czy musisz tak często zmieniać interfejs API, aby uwzględnić różne rzeczy. Sugerują one, że relacje między modułami nie są proste
5. Dane wejściowe użytkownika lub aplikacji
Wreszcie, jak proste są dane wejściowe użytkownika lub aplikacja są akceptowane w interfejsie API / UI? Kiedy wielu możliwych użytkowników / aplikacji (do różnych celów) musi ci dać - czy są oczywiste? Czy istnieją stany / szczegóły, które nie są związane z wyższą abstrakcją, ale wciąż przechodzą do przodu i do tyłu?
Proste pytanie, które zazwyczaj zadałbym, brzmi następująco: Jeśli zamiast programu, gdybym poprosił człowieka o tę samą funkcję, czy wypełniłbym tę informację w formie papierowej ? Jeśli nie, nie jestem tutaj wystarczająco prosty .
Nie powiem, że ta lista jest wyczerpująca, ale sądzę, że kryteria są takie, jak łatwe lub trudne jest używanie i modyfikowanie oprogramowania. To jest proste.
źródło
Nie znam żadnych istniejących dobrych wskaźników dotyczących prostoty kodu (nie oznacza to, że nie istnieją - po prostu nie wiem o nich). Mógłbym zaproponować niektóre, może niektóre pomogą:
Prostota zastosowanych funkcji językowych: jeśli język ma funkcje, które można uznać za „zaawansowane” i „proste”, można policzyć liczbę wystąpień funkcji zaawansowanych. Sposób definiowania „zaawansowany” może być nieco bardziej subiektywny. Podejrzewam, że niektórzy mogliby powiedzieć, że jest to również pomiar „sprytności” programu. Typowy przykład: niektórzy mogą powiedzieć, że
?:
operator powinien być funkcją „zaawansowaną”, inni mogą się nie zgodzić. Nie wiem, jak łatwo byłoby napisać narzędzie, które może to przetestować.Prostota konstrukcji w programie: Możesz zmierzyć liczbę parametrów akceptowanych przez funkcję. Jeśli masz> n % wszystkich funkcji z> m parametrów, można wybrać się liczyć je jako nie prosty, w zależności od sposobu zdefiniowania n i m (n = 3 może i m = 6?). Myślę, że istnieją pewne narzędzia analizy statycznej, które mogą to zmierzyć - myślę, że JTest po prostu mierzył funkcje z parametrami > m .
Możesz spróbować policzyć liczbę zagnieżdżonych pętli lub struktur kontrolnych. Myślę, że to właściwie nie jest zły wskaźnik i myślę, że ma na to swoją nazwę (nie mogę sobie przypomnieć z góry głowy). Ponownie myślę, że istnieją narzędzia (ponownie, takie jak JTest), które mogą to zmierzyć do pewnego stopnia.
Możesz spróbować zmierzyć „refaktowalność”. Jeśli Twój kod zawiera wiele fragmentów kodu, które mogą zostać ponownie przetworzone, ale nie są , być może nie byłoby to takie proste. Pamiętam też z czasu, gdy współpracowałem z JTestem, że on również próbował to zmierzyć, ale pamiętam, że często nie zgadzałem się z tym w tym przypadku, więc YMMV.
Możesz spróbować zmierzyć liczbę warstw między różnymi częściami systemu. Na przykład: ile różnych fragmentów kodu dotknie danych pochodzących z formularza internetowego, zanim zostanie on zapisany w bazie danych? Właściwy pomiar może być trudny ...
źródło
?:
są problemem, gdy są zagnieżdżone 5 głęboko. Jeśli chodzi o warstwy, czysto oddzielone warstwy są lepsze niż jedna zwinięta warstwa. Ale 7 przeważnie nadmiarowych warstw, gdy potrzebne były tylko 2 lub 3, to zła rzecz.