2008-09-19 29 views
5

Niedawno odziedziczyłem aplikację konsoli C#, która wymaga kilku funkcji czyszczenia i czyszczenia. Krótko mówiąc, aplikacja składa się z pojedynczej klasy zawierającej ponad 110 000 linii kodu. Tak, ponad 110 000 linii w jednej klasie. Aplikacja jest oczywiście podstawą naszej działalności, która "aktualizuje dane na bieżąco w dynamicznej witrynie internetowej". Chociaż powiedziano mi, że mój poprzednik był "naprawdę dobrym programistą", to oczywiste, że wcale nie był w OOP (lub kontroli wersji).W jaki sposób programowo identyfikować liczbę odwołań do metody za pomocą C#

W każdym razie ... podczas zaznajamiania się z kodem znalazłem wiele metod, które są zadeklarowane, ale nigdy nie wspomina się o nich. Wygląda na to, że kopiowanie/wklejanie było używane do wersji kodu, na przykład mówię, że mam metodę o nazwie getSomethingImportant(), jest szansa, że ​​istnieje inna metoda o nazwie getSomethingImortant_July2007() (wzorzec to functionName_ [datestamp] w większości przypadków). Wygląda na to, gdy programista został poproszony o zmianę w getSomethingImportant(), którą skopiował/wkleił, a następnie zmienił nazwę na getSomethingImortant_Date, wprowadził zmiany w getSomethingImortant_Date, a następnie zmienił wszystkie wywołania metod w kodzie na nową nazwę metody, pozostawiając starą metodę w kod, ale nigdy nie wspominając o nim.

Chciałbym napisać prostą aplikację konsolową, która przeszukuje jedną wielką klasę i zwraca listę wszystkich metod z liczbą odwołań do każdej metody. Według moich szacunków istnieje ponad 1000 metod, więc zrobienie tego ręcznie zajęłoby trochę czasu.

Czy istnieją klasy w ramach platformy .NET, z których mogę skorzystać w celu zbadania tego kodu? Lub inne przydatne narzędzia, które mogą pomóc w określeniu metod, które są zadeklarowane, ale nigdy nie są do nich odwoływane?

(Pytanie boczne: Czy ktoś jeszcze widział taką aplikację C#, jedną dużą klasę? Jest to mniej więcej jeden wielki proces proceduralny, wiem, że to pierwszy, jaki widziałem, przynajmniej tej wielkości.)

Odpowiedz

12

Możesz spróbować użyć NDepend, jeśli potrzebujesz wyodrębnić kilka statystyk dotyczących swojej klasy. Zauważ, że to narzędzie polega wewnętrznie na Mono.Cecil w celu sprawdzenia złożeń.

0

Nie znam niczego, co zbudowano by obsłużyć tę konkretną sprawę, ale można użyć Mono.Cecil. Odzwierciedlaj złożenia, a następnie licz referencje w IL. Nie powinno być zbyt trudne.

1

Mogę to zrobić za pomocą NDepend, ale nigdy go nie użyłem.

1

okno analizatora w Reflector mogę ci pokazać, gdzie metoda nazywa (używane przez).
Wygląda na to, że uzyskanie informacji w ten sposób zajęłoby bardzo dużo czasu.
Możesz spojrzeć na API, które Reflector zapewnia do pisania dodatków i zobaczyć, czy możesz w ten sposób uzyskać pomijaną analizę. Spodziewam się, że kod źródłowy dla code metrics add-in może powiedzieć ci trochę o tym, jak uzyskać informacje o metodach z interfejsu API reflektora.

Edycja: Pomocny może być także dodatek do reflektora . To dobry sposób na poznanie interfejsu Reflector API.

0

Nie ma łatwego narzędzia do tego w samym środowisku .NET. Jednak nie sądzę, że naprawdę potrzebujesz listy nieużywanych metod naraz. Jak widzę, po prostu przejrzysz kod i dla każdej metody sprawdzisz, czy jest on nieużywany, a potem go skasujesz. Aby to zrobić, skorzystam z polecenia Visual Studio "Znajdź referencje". Alternatywnie możesz użyć Resharpera z jego oknem "Analize".Lub możesz po prostu użyć narzędzia do analizy kodu Visual Studio, aby znaleźć wszystkie nieużywane metody prywatne.

+0

Twoja sugestia, aby usunąć jak idę przez kod była moja pierwsza myśl zbyt. Będę używał tej metody plus NDepend, jak sugerowali inni, do dalszej analizy. – Duffy

0

Czy dostaniesz pieniądze za ReSharper? To idealne narzędzie do refaktoryzacji.

3

Pobierz bezpłatną wersję próbną programu Resharper. Użyj Resharper-> Search-> Find Usages w pliku (Ctrl-Shift-F7), aby podświetlić wszystkie zastosowania. Ponadto na pasku stanu pojawi się liczba. Jeśli chcesz przeszukać wiele plików, możesz to zrobić również przy pomocy Ctrl-Alt-F7.

Jeśli nie podoba ci się to, szukaj tekstu dla nazwy funkcji w Visual Studio (Ctrl-Shift-F), to powinno powiedzieć ile wystąpień znaleziono w roztworze i gdzie one są.

0

Aby odpowiedzieć na twoje "pytanie poboczne", nigdy nie widziałem tak złego, może być dobrym wpisem dla The Daily WTF. Można to nazwać "Ostatecznym powtórnym użyciem kopii/pasty".

-1

Spróbuj, aby kompilator emitował pliki asemblera, tak jak w instrukcjach x86, a nie zespoły .NET.

Dlaczego? Ponieważ znacznie łatwiej jest parsować kod assemblera niż kod C# lub zestawy .NET.

Na przykład, funkcja/deklaracja metoda wygląda mniej więcej tak:

.string "w+" 
    .text 
    .type create_secure_tmpfile, @function 
create_secure_tmpfile: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $24, %esp 
    movl $-1, -8(%ebp) 
    subl $4, %esp 

i funkcja/metoda odniesienia będzie wyglądać mniej więcej tak:

subl $12, %esp 
    pushl 24(%ebp) 
    call create_secure_tmpfile 
    addl $16, %esp 
    movl 20(%ebp), %edx 
    movl %eax, (%edx) 

Kiedy widzisz "create_secure_tmpfile:" Ty wiesz, że masz deklarację funkcji/metody, a gdy zobaczysz "call create_secure_tmpfile", wiesz, że masz odniesienie do funkcji/metody. Może to być wystarczająco dobre dla twoich celów, ale jeśli nie, to jeszcze kilka kroków, zanim będziesz mógł wygenerować bardzo słodkie drzewo wywołań dla całej aplikacji.

+0

Jak to jest "o wiele łatwiejsze" parsować asembler, gdy .net zawiera biblioteki odbić? Nie wspominając o bibliotekach innych firm, takich jak Mono.Cecil. –

+0

Ponieważ istnieje ogromna baza narzędzi do przetwarzania danych liniowych w sposób ad hoc. na przykład grep, sed, awk itd. – mbac32768

1

FXCop ma regułę, która identyfikuje nieużywane metody prywatne. Możesz więc zaznaczyć wszystkie metody jako prywatne i wygenerować listę.

FxCop ma również język, jeśli chciał się hodowcy http://www.binarycoder.net/fxcop/

1

Jeśli nie chcą bulić za NDepend, ponieważ brzmi jak tam jest tylko jedna klasa w jednym zespole - skomentuj metody i kompilacja. Jeśli się kompiluje, usuń je - nie będziesz mieć żadnych problemów związanych z dziedziczeniem, wirtualnych metod ani niczego w tym stylu. Wiem, że to brzmi prymitywnie, ale czasami refaktoryzacja jest po prostu pomrukiem w ten sposób. Jest to przy założeniu, że masz testy jednostkowe, które uruchamiasz po każdej kompilacji, dopóki nie wyczyścisz kodu (Czerwony/Zielony/Refaktor).

4

Aby ukończyć odpowiedź: Romain Verdier, zagłębimy się nieco w to, co może tu przynieść NDepend. (Zastrzeżenie: Jestem twórcą zespołu NDepend)

NDepend pozwala na zapytanie o kod .NET za pomocą zapytań LINQ. Wiedząc, jakie metody zadzwonić i jest nazywany przez których inni, jest tak proste, jak pisanie następujące LINQ kwerendy:

from m in Application.Methods 
select new { m, m.MethodsCalled, m.MethodsCallingMe } 

Rezultatem tego zapytania jest przedstawiony w sposób, który sprawia, że ​​jest łatwy do przeglądania rozmówców i callees (i jego 100 % zintegrowany z Visual Studio).

NDepend methods callers and callees


Istnieje wiele innych możliwości NDepend że może pomóc. Na przykład można prawym przyciskiem sposób w Visual Studio> NDepend> Wybierz metod ...>, który jest używany do mnie (bezpośrednio lub pośrednio) ...

NDepend Visual Studio method right click

Następująca kwerenda kod jest generowany. ..

from m in Methods 
let depth0 = m.DepthOfIsUsing("NUnit.Framework.Constraints.ConstraintExpression.Property(String)") 
where depth0 >= 0 orderby depth0 
select new { m, depth0 } 

... który pasuje bezpośrednie i pośrednie rozmówców, z głębokości połączeń (1 oznacza bezpośredni rozmówcy, 2 oznacza rozmówcę bezpośrednich rozmówców i tak dalej).

NDepend indirect method callers

A następnie klikając przycisk Export do wykresu, otrzymasz wykres połączenia swojego sposobu obrotu (oczywiście może to być na odwrót, czyli metodę zwaną bezpośrednio lub pośrednio przez dany metoda przestawna).

NDepend call graph

Powiązane problemy