W ostatnim czasie zapoznawałem się trochę bliżej z narzędziem o nazwie NDepend. Przez ten czas na pewno nie stałem się ekspertem w korzystaniu z NDepend, chciałbym jednak podzielić się moimi subiektywnymi odczuciami na jego temat. Nie będę tutaj wymieniał jego funkcji (można to znaleźć na stronie producenta lub w wielu innych wpisach), nie będę pisał jak zainstalować (bo to proste, choć mi się nie podobało - lubię instalować a nie rozpakowywać :) ), nie będę się zastanawiać czy warto tego narzędzia używać (niech każdy wyrobi sobie własne zdanie, licencja jest
odpłatna). Skupię się natomiast na elementach, które ja bym wykorzystał, które mi się spodobały lub które nie wywarły najlepszego wrażenia. Zapraszam do lektury.
Na NDepend po raz pierwszy trafiłem już kilka lat temu, gdy
szukałem narzędzia do zobrazowania diagramu zależności pomiędzy
poszczególnymi assembly w projekcie, nad którym pracowałem. Nie
skorzystałem wtedy jednak z NDepend, gdyż znalazłem jakieś
darmowe narzędzie, które było wystarczające, a nie długo później
pojawiło się Visual Studio 2010, w którym w jednej z wersji
udostępniało menu „Architecture” i funcję „Generate
Dependency Graph”. Piszę o tym, bo ukierunkowało to moje
spojrzenie na NDepend i chyba nie do końca właściwe... Myślałem
bowiem o NDepend jako o narzędziu do eksploracji kodu źródłowego,
a tym raczej nie jest.
Ponieważ NDepend służy do analizy kodu źródłowego, trzeba
mieć co co analizować. W niniejszym wpisie będę się odwoływał
do projektu, który był już opisywany na łamach tego bloga, a
mianowicie MeshDiagram3D.
Diagramy
Pierwszym elementem, z którego chciałem skorzystać w NDepend były
diagramy, a w szczególności diagram zależności. Na pierwszy rzut
oka efekt był bardzo udany, po wykonaniu analizy przez NDepend
ujrzeć mogłem:
Otrzymany diagram okazał się nie statyczny, ale nazwałbym go
interaktywnym, gdyż można było na nim wykonywać inne operacje.
Nie mówię tu tylko o przesuwaniu elementów na ekranie, kolorowaniu
ścieżek, ale też wyszukiwaniu poszczególnych elementów
bezpośrednio z diagramu lub pokazywaniu dodatkowych statystyk.
Ponadto, gdybyśmy poczuli się zdezorientowani, pomogą nam
wyświetlane podpowiedzi.
Nie jest jednak tak zupełnie różowo, zaprezentowany powyżej graf
zależności został wygenerowany dla bardzo prostego projektu lub
raczej „Solution”. Jeżeli spróbujemy przeanalizować coś
bardziej skomplikowanego możemy zobaczyć zaplątaną sieć podobną
do poniższej:
W tym przypadku nie wiele pomogą funkcje zbliżania, oddalania,
zaznaczania, czytelność jest mała. Jednak nie należy tego
traktować jako zarzut wielkiego kalibru, sam nie bardzo mam pomysł
jak można by to poprawić (no może jakieś "inteligentne"
filtrowanie tego co chcemy wyświetlać). Z tego problemu zdaje sobie
sprawę sam producent NDepend, i sugeruje w takim przypadku
korzystanie z innego sposobu obrazowania, a mianowicie z matrycy
zależności (Dependency Matrix):
Na tej matrycy łatwiej zauważyć zależności nawet w bardziej
skomplikowanych projektach, a wyświetlane podpowiedzi pomagają w
jej zrozumieniu nawet bez czytania dokumentacji.
W każdym razie po wspomnianych diagramach oczekiwałem pierwotnie
czegoś trochę innego.
Analiza statyczna kodu w NDepend
Po krótkiej przygodzie z diagramami, zacząłem się bardziej
przyglądać NDepend, a dokładniej całej masie uwag, które
otrzymałem na temat mojego kodu źródłowego. W analizie mojego
prostego projektu znalazłem kilka uwag krytycznych i kilkaset
ostrzeżeń. Przyglądając się im dokładniej okazało mi się, że
nie do końca wszystkie są uwagami, które powinny nas skłonić do
wykonania jakichś akcji, ale pokazują one miejsca, na które warto
zwrócić uwagę, mogą to być między innymi:
- metody lub typy zbyt skomplikowane lub za długie,
- metody o zbyt dużej ilości parametrów,
- typy które korzystają z zasobów niezarządzalnych,
- niewykorzystywany kod,
- nieoptymalna widoczność metod lub innych elementów,
- złe nazewnictwo lub organizacja kodu źródłowego,
- i wiele innych (opartych o ponad 200 reguł)
Mocną stroną NDepend jest właściwość pozwalająca na dowolne
modyfikowanie wspomnianych reguł, które zapisywane są w w
specjalnym języku o nazwie CQLinq. Jest to znany nam wszystkim w C#
LINQ, ale wzbogacony o pewne dodatkowe słowa kluczowe i o pewnym
ustalonym źródle danych jakim jest nasz kod.
Zobaczmy przykład:
warnif count > 0 from m in JustMyCode.Methods where m.NbParameters > 8 orderby m.NbParameters descending select new { m, m.NbParameters }
Powyższa reguła ostrzeże nas gdy w naszym kodzie będzie metoda,
przyjmująca więcej niż 8 parametrów. W ramach informacji
otrzymamy listę metod i liczbę parametrów przez nie przyjmujących.
Jeżeli nam się ona nie podoba, np. nie chcemy metod z listą
parametrów dłuższą niż 10, a w wyniku chcemy otrzymać jeszcze
nazwę klasy i assembly, nic prostszego wystarczy że napiszemy:
warnif count > 0 from m in JustMyCode.Methods where m.NbParameters > 10 orderby m.NbParameters descending select new { m, m.NbParameters, m.ParentType, m.ParentAssembly }
Nie martwcie się, nie trzeba się uczyć się potencjalnie
skomplikowanego modelu informacyjnego kodu źródłowego w NDepend -
edytor wykorzystywany podczas wpisywania kwerend jest wyposażony w
podpowiedzi kontekstowe.
Warto wiedzieć, że w NDepend dostępnych jest ponad 80 różnych
metryk pozwalających na ocenę naszego oprogramowania w różnych
aspektach, a dzięki temu dbaniu o jego jakość!
NDepend zadba o ciągłą poprawność.
Kolejną wartościową cechą NDepend jest możliwość wykonywania
nie tylko analiz na żądanie, ale też włączenie ich do właściwego
build'a oraz uruchamianie analizy i weryfikacji w trybie ciągłej
integracji. Mamy tutaj kilka możliwości, ale w najprostszym
przypadku wystarczy dokonać edycji pliku .csproj w naszym Solution i
zamienić <Target Name="AfterBuild"/> na coś
podobnego do:
<Target Name="AfterBuild"> <PropertyGroup> <NDPath>c:\miejsce-instalacji-NDEPEND\NDepend\NDepend_4.0.2.6750\NDepend.Console.exe</NDPath> <NDProject>$(SolutionDir)MeshDiagram3D.ndproj</NDProject> <NDOut>$(TargetDir)NDepend</NDOut> <NDIn>$(TargetDir)</NDIn> </PropertyGroup> <Exec Command='"$(NDPath)" "$(NDProject)" /OutDir "$(NDOut)" /InDirs "$(NDIn)"'/> </Target>
Dzięki takiemu podejściu build nie zakończy się sukcesem gdy
wystąpią uwagi o charakterze krytycznym i nie ma tutaj znaczenia,
czy będziemy budować kod z poziomu Visual Studio, czy linii
poleceń (np. przez MSBuild'a) lub w systemie ciągłej integracji.
W tym momencie chciałbym jeszcze wspomnieć o możliwości
porównywania wybranych build'ów kodu lub historycznych analiz
wykonanych przez NDepend. Dla przykładu zwróćmy uwagę na błąd
występujący podczas build'u, a widoczny na powyższym rysunku:
"API Breaking Changes: Methods"
Co ten błąd oznacza? Mianowicie NDepend wykrył że zmianie uległa
jedna z publicznych metod (a w tym przypadku konstruktor). Więcej
szczegółów można znaleźć w przygotowanym raporcie:
Co w kodzie źródłowym prezentuje się następująco:
Podsumowanie
Niniejszy wpis nie jest kompletnym opisem funkcji NDepend, więcej
informacji można znaleźć na stronie producenta,
gdzie dostępne są nie tylko opisy, ale również filmy
instruktażowe. Ja bym chciał jeszcze wspomnieć tutaj o jednej
funkcjonalności, doskonale uzupełniającej opisane powyżej, a
mianowicie możliwość sprawdzania pokrycia kodu testami. Niestety
nie udało mi się tej funkcji jeszcze wypróbować, ale może kiedyś
ją sprawdzę i opiszę na blogu.
Mam nadzieję że w tym wpisie udało mi się pokazać pewne ciekawe
funkcje NDepend i przedstawić moje subiektywne odczucie, do czego
się to narzędzie nadaje, a do czego raczej nie bardzo. Na pewno
sprawdzi się jako strażnik nie pozwalający na dodawanie
szkodliwego jakościowo kodu (chociaż trzeba rozważnie dobrać
listę reguł), można NDepend wykorzystać również do generowania
statystyk. Gorzej NDepend sprawdzi się w roli narzędzia do
eksploracji kodu (np. w sytuacji, gdy chcemy zrozumieć zupełnie nie
znany nam kod) lub narzędzia dokumentującego kod.
Dochodzę do wniosku, że programista abap ma łatwiej :)
OdpowiedzUsuńBardzo wartościowy post, pozdrawiam:)
OdpowiedzUsuńJako programista C# nigdy nie korzystałem z tego narzędzia. Chyba najwyższy czas zacząć, bo bardzo przyjemne możliwości oferuje.
OdpowiedzUsuńProgramowanie to jest przyszłość. Najbardziej poszukiwani specjaliści w obecnych czasach. Nie trzeba nawet być wybitnym a wystarczy znać podstawy. To jest fenomen na rynku. Jeśli chodzi o programistów to sprawdza się tekst "praca szuka człowieka".
OdpowiedzUsuńBardzo ciekawy wpis
OdpowiedzUsuńSuper wpis
OdpowiedzUsuń