Jak wykryć nieużywane metody i #import w Objective-C

100

Po długiej pracy nad aplikacją na iPhone'a zdałem sobie sprawę, że mój kod jest dość brudny i zawiera kilka #import i metod, które nie są wywoływane lub w ogóle nie są przydatne.

Chciałbym wiedzieć, czy istnieje jakakolwiek dyrektywa kompilatora lub sposób na wykrycie tych bezużytecznych linii kodu. Czy Xcode ma jakieś narzędzie do wykrywania tego?

Hectoret
źródło

Odpowiedzi:

66

Xcode umożliwia (anulowanie) sprawdzania ustawień określonych ostrzeżeń kompilatora, które mogą ostrzegać o niektórych typach nieużywanego kodu. (Wybierz projekt z listy źródeł i Plik> Uzyskaj informacje, a następnie wybierz kartę Kompilacja). Oto kilka (które pojawiają się w Clang i GCC 4.2 dla mnie), które mogą być interesujące:

  • Nieużywane funkcje
  • Nieużywane parametry
  • Niewykorzystane wartości

Nie widzę żadnych opcji wykrywania nieużywanych importów, ale jest to nieco prostsze - mało zaawansowane technologicznie podejście polega po prostu na komentowaniu instrukcji importu, dopóki nie pojawi się błąd / ostrzeżenie kompilacji.

Nieużywane metody Objective-C są znacznie trudniejsze do wykrycia niż nieużywane funkcje C, ponieważ komunikaty są wysyłane dynamicznie. Ostrzeżenie lub błąd może powiedzieć, że masz potencjalny problem, ale jego brak nie gwarantuje, że nie wystąpią błędy w czasie wykonywania.


Edycja: Innym dobrym sposobem na wykrycie (potencjalnie) nieużywanych metod jest zbadanie pokrycia kodu z rzeczywistych wykonań. Zwykle odbywa się to w połączeniu z automatycznymi testami jednostkowymi, ale nie musi.

Ten post na blogu to przyzwoite wprowadzenie do testów jednostkowych i pokrycia kodu przy użyciu Xcode. Sekcja on gcov(która, nawiasem mówiąc, działa tylko z kodem wygenerowanym przez GCC) wyjaśnia, jak zmusić Xcode do zbudowania oprzyrządowanego kodu, który może rejestrować, jak często był wykonywany. Jeśli weźmiesz oprzyrządowaną kompilację swojej aplikacji do obrócenia w symulatorze, a następnie uruchomisz na niej gcov, możesz zobaczyć, jaki kod został wykonany za pomocą narzędzia takiego jak CoverStory (dość uproszczony interfejs GUI) lub lcov(skrypty Perla do tworzenia raportów HTML) .

Używam gcovi lcovdla CHDataStructures.framework i automatycznie generuję raporty pokrycia po każdym zatwierdzeniu SVN. Pamiętaj, że nierozsądne jest traktowanie wykonanego pokrycia jako ostatecznej miary tego, który kod jest „martwy”, ale z pewnością może pomóc w zidentyfikowaniu metod, które możesz zbadać dalej.

Na koniec, skoro próbujesz usunąć martwy kod, myślę, że to pytanie również okaże się interesujące:

Quinn Taylor
źródło
4
Nie jestem pewien, o co ci chodzi ... Analizator statyczny może znaleźć wiele problemów, ale jeśli wyślesz wiadomość do zmiennej wpisanej jako idlub utworzysz selektor do wywołania w czasie wykonywania, analizator statyczny nie może zagwarantować że kod jest naprawdę nieużywany. Jeśli kod, który nadal jest potrzebny, zostanie usunięty, pojawią się błędy w czasie wykonywania. Czy coś mi brakuje?
Quinn Taylor
1
Ponadto selektory, które są tworzone na podstawie ciągów w czasie wykonywania, są dość powszechne.
dreamlax
1
Oczywiście są przypadki, w których kod dynamiczny może być lepiej obsługiwany przez silniejsze rzutowanie typu (tj. Zwraca coś zamiast identyfikatora). Pisanie w czasie wykonywania jest mocną stroną programowania w języku Cocoa / Objective-C, ale czasami konserwacja i czytelność byłyby lepsze, gdybyśmy więcej myśleli o silnym pisaniu.
alesplin
3
Och, zdecydowanie się zgadzam. Moją zasadą jest statyczne wpisywanie (tak jak w Javie), chyba że naprawdę potrzebuję dynamicznego pisania, co jest rzadkie, ale zdarza się czasami. Jednak samo połączenie z klasami Cocoa (na przykład określenie delegata) może spowodować trudną do prześledzenia dynamikę i ścieżki wykonywania. Do licha, każdy program z pętlą uruchamiania i wieloma wątkami może być nietrywialny ...
Quinn Taylor
40

Appcode ma funkcję inspekcji kodu, która znajduje nieużywane importy i kod.

patrick-fitzgerald
źródło
18
Więc masz na myśli, że powinniśmy zainstalować Appcode tylko dla tej funkcji?
majqiyue
Jeśli to ci się przyda, tak!
rmp251
5

Niedawno napisałem skrypt, aby znaleźć nieużywane (lub zduplikowane) #importstwierdzenia: https://gist.github.com/Orangenhain/7691314

Skrypt pobiera plik ObjC .m i zaczyna komentować każdy #importwiersz po kolei i sprawdza, czy projekt nadal się kompiluje. Będziesz musiał zmienić BUILD_DIR i BUILD_CMD.

Jeśli używasz findpolecenia, aby pozwolić skryptowi działać na wielu plikach, upewnij się, że używasz BUILD_CMD, który faktycznie używa wszystkich tych plików (lub zobaczysz plik z wieloma nieużywanymi instrukcjami importu).

Napisałem to nie wiedząc, że AppCode ma podobną funkcję, jednak kiedy testowałem AppCode, nie był tak dokładny jak ten skrypt (ale znacznie szybszy [dla całego projektu]).

Orangenhain
źródło
Działa tylko dla duplikatów, nieużywane importy nie są usuwane.
Rahul
1

Ostatnio zmieniłem duży projekt z Carbon na Cocoa. Na końcu było sporo osieroconych plików, które nie były już używane. Napisałem skrypt, aby znaleźć je, które zasadniczo zrobiły to:

Upewnij się, że całe źródło jest wpisane do subversion (tj. Czyste) Upewnij się, że obecnie kompiluje się bez błędów (tj. Xcodebuild zwraca stan 0). Następnie dla każdego pliku źródłowego w katalogu pusty (tj. Usuń zawartość, skróć długość) source i plik nagłówkowy, spróbuj kompilacji, jeśli się nie powiedzie, przywróć pliki, w przeciwnym razie pozostaw je puste.

Po uruchomieniu przywróć, a następnie usuń wszystkie opróżnione pliki, skompiluj, a następnie usuń wszystkie błędne #importy.

Powinienem również dodać, że musisz unikać plików, do których istnieją odniesienia z plików .xib lub .sdef, i mogą istnieć inne przypadki dynamicznego łączenia, ale nadal może to dać ci dobrą wskazówkę co do tego, co można usunąć.

Tej samej techniki można użyć, aby sprawdzić, które #importy mogą zostać usunięte - zamiast obcinania pliku, usuń po kolei każdy #import w pliku i sprawdź, czy kompilacja się nie powiedzie.

Peter N Lewis
źródło