Dziś trochę o matematycznej walidacji kodu czyli o metrykach. LCOM (lack cohesion of methods) umożliwia obliczenie jak bardzo nasze metody są spójne. Do obliczania tej wartości istnieją gotowe narzędzia takie jak nDepend, ale aby w pełni zrozumieć znaczenie metryki obliczymy sami jej wartość dla prostej klasy.
Powinno dążyć się do jak największej spójności a tym samym do jak najniższej wartości LCOM. Przed wyjaśnieniem czym jest metryka LCOM wprowadźmy następujące pojęcia:
M – zbiór metod danej klasy (M1,M2…Mn),
Ii – zbiór zmiennych składowych klasy wykorzystywanych przez metodę Mi.
Wartość LCOM jest równa:
Innymi słowy, LCOM ma na celu wyeliminowanie zmiennych składowych, które wykorzystywane są tylko w jednej metodzie. Zmienne składowane, które wywoływane są wyłącznie w jednej metodzie powinny być przeniesione do tej metody i zadeklarowane w jej ciele.
Pełna definicja LCOM wygląda następująco:
Rozważny poniższy fragment kodu:
public class ClassA { private int m_Var1 = 0; private int m_Var2 = 0; private int m_Var3 = 0; private int m_Var4 = 0; void Method1() { m_Var1 = 0; m_Var2 = 1; } void Method2() { m_Var1 = 0; m_Var3 = 4; } void Method3() { m_Var4 = 5; } }
Na podstawie kodu można wyznaczyć:
I1 = {m_Var1,m_Var2}
I2 = {m_Var1,m_Var3}
I3 = {m_Var4}
Następnie należy wyznaczyć wszystkie kombinacje metod których jest:
Występują dwa zbiory puste zatem wartość metryki LCOM wynosi dwa.
Na podstawie metryki można stwierdzić, że klasa została źle zaprojektowana. Powinno dążyć do zerowej wartości LCOM poprzez przenoszenie składowanych wykorzystywanych tylko w jednej metodzie do ciała tej metody. Pola składowe powinny być wykorzystywane przez jak największą liczbę metod a najlepiej wszystkie. Powinniśmy unikać sytuacji gdzie jedna metoda korzysta z pól całkowicie innych niż druga metoda tej samej klasy!
Metrykę LCOM można również wyrazić za pomocą:
gdzie:
M – liczba metod,
F – liczba pól,
MF – liczba pól wykorzystywanych przez daną metodę. Wyrażenie sum(MF) określa sumę wykorzystywanych pól przez każdą z metod.
Metryka wyliczana na podstawie wzoru przyjmuje wartości między 0 a 1. Wartość 0 oznacza maksymalną spójność, z kolei 1 brak spójności. W praktyce kryterium LCOM ciężko spełnić i dlatego wprowadzono pewną modyfikację o szerszym zasięgu:
LCOM HS przyjmuje wartości od 0 do 2. W przypadku wykrycia klasy z LCOM HS > 1.0 należy koniecznie klasę zrefaktoryzować.
“Fajosko” 🙂 Przy okazji: ostatnio “służbowo” czytałem sobie odrobinę o metrykach sprawdzanych w Visual Studio i doszedłem do wniosku, że dużo ciekawsze są od nich metryki “Uncle Boba” – z tym, że nie znalazłem żadnego oprogramowania, które by je liczyło. Czy słyszałeś o tych metrykach?
Ponadto z dzisiejszego tekstu wnoszę, że jesteś dość zdecydowanym zwolennikiem metryk – czy możesz powiedzieć jakie widzisz ich zalety oraz ew. wady?
Pozdrawiam
@Paweł:
Metryki to oprócz CodeReview bardzo dobry sposób walidacji jakości kodu. nDepend np. mozna zainstalowac na buildmachine i gdy tylko z commitowany kod nie spełnia wymagań wtedy jest coś typu build failure.
Ponadto fajna opcja to okreslenie ze tylko NOWY kod musi spelniac metryki. Dodali to po to poniewaz dla kodow bez ciaglej walidacji metryk zawsze jest kilkadziesiat bledow.
Wady?Nie widze wad jesli ktos dobrze z nich korzysta… Jedyna uwaga to taka zeby metryki nie zastapily code review – musza byc wylacznie uzupelnieniem.
Hej,
Właśnie ja się zastanawiam, czy aby metryki nie powinny być postrzegane jako lampka kontrolna – powiedzmy: wysoki Maintainability Index to wskazówka, że może coś z kodem jest nie tak. Ale mam obawy, czy używanie tego wskaźnika przez managerów do sprawdzania jakości kodu jest dobrym pomysłem – i tak np. jeżeli kod ma MI >75 to kod jest do poprawki – a spotkałem się z tego rodzaju pomysłami, stąd moje pytanie do Ciebie.
To zależy od metryki. Progi tez muza byc odpowiednio dobrane. To nie jest tak ze wszystkie metryki musza miec perfekcyjne wartosci bo swiat nie jest perfekcyjny np. ze wzgledu, ze dziedziczymy kod po kims i nie ma czasu na jego doszlifowanie.
Nalezy jednak dazyc do sytuacji gdzie wszystko jest perfekcyjne:) Czyli jak metryka jest zlamana bo MI>75 to nalezy sie temu przyjrzec blizej.
Ja po prostu węszę takie zagrożenie, że jakiś PM dowiedziawszy się o metrykach odrzuca w czambuł wszystko, co choćby o włos przekracza ustalone wartości.
Co ma PM do kodu?
Co ma ta uwaga do ogólnej myśli przewodniej dyskusji? W miejsce PM wstaw sobie kogokolwiek odpowiedzialnego za kod.
Za kod powinna byc odpowiedzialna osoba techniczna – team leader itp. Project czy Product Manager nie moga podjemowac decyzji technicznych chyba, ze klient o to poprosi.
Osoba techniczna z kolei doskonale wie, ze metryki wymagaja analizy przez osobe majaca pojecie o kodzie.
Jesli jakas metryka przekroczy wartosc i ma to jakies logiczne usprawiedliwienie nie widze powodu aby leader mialby odrzucic kod.
Moim zdaniem wadą metryk jest to, że wartości
“optymalne” są dobierane czysto subiektywnie, co nieco psuje ich pozornie absolutny i obiektywny sposób oceny. Nie istnieje jedyna słuszna, idealna wartość LCOM, DIT czy WMC. Przydają się, owszem, ale raczej jako wskaźniki problemów z projektem lub wykonaniem, nie jako bezwzględne (i jedynie słuszne) wskaźniki jakości kodu. Z tego względu moim zdaniem przyjmowanie jakichkolwiek sztywnych wartości dowolnej metryki za prawdę objawioną i ew. odrzucanie kodu, który ją przekroczył, jest czystym niezrozumieniem, czym i po co jest metryka. Dokładnie tak, jak Piotr napisał – metryki nie zastąpią code review, testowania czy zdrowego rozsądku. Pełnią rolę pomocniczą. Mogą świetnie wspomóc programistę w wykrywaniu błędów czy przewidywaniu potencjalnych problemów, ale mogą też wybitnie uprzykrzyć mu życie. Zwłaszcza, jeżeli celem nie jest stworzenie dobrego projektu wysokiej jakości, a dążenie do osiągnięcia pożądanych przez kogoś wartości metryk.