Objective-C: Tool zum "Aufräumen" gesucht

  • Objective-C: Tool zum "Aufräumen" gesucht

    Hallo,

    ich bin wie so oft am Optimieren meines Codes. Habe hier u.a eine recht umfangreiche eigene Klasse, die ich gerne möglichst "säubern" möchte. Gäbe es ein Tool, welches folgendes leisten könnte wäre mir sehr geholfen:

    1. Finde alle privaten Methoden, die (intern) nie aufgerufen werden. Bei mir sind - wie bei vielen anderen wohl auch die privaten Methoden in einer oder mehreren Categories untergebracht. Man müsste diesem Tool mitteilen können, welche Categories es als privat ansehen soll (gibt ja auch Delegatecategories) welche dann wiederum auf ihren Inhalt hin untersucht wird.

    2. Finde alle Methoden einer Klasse, die im Projekt nicht genutzt werden. Die eigenen Klassen (die, die in der Regel am fehleranfälligsten/wenigsten optimierten) sind aber auch gleichzeitig die konkretesten. Daher macht es wohl schon Sinn projektweit ungenutzte Methoden zu entfernen bzw. sich darüber im Klaren zu sein, was ungenutzte Methoden bedeuten.

    3. Finde alle "nicht richtig nutzbaren" Instanzvariablen. Sobald ich in einer Klasse in der @interface Sektion eine Instanzvariable definiere sollten dazu auch die entsprechenden KVC konformen Accessors existieren - alles andere will man als KVO/KVC Abhängiger ja nicht haben. :) Ausnahmen sollten irgendwie explizit als solche markiert werden. Mit Objective-C 2.0 wird sich das wohl gelöst haben - aber bis dahin...

    Das sind mal die 3 Dinge, die mich am meisten von "wichtigeren" Dingen abhalten. Man könnte sie aber doch so schön teilweise optimieren. Bestimmt gibt es dazu doch schon was fertiges - oder? :)

    Gruß
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Original von Objcler
    Daher macht es wohl schon Sinn projektweit ungenutzte Methoden zu entfernen bzw. sich darüber im Klaren zu sein, was ungenutzte Methoden bedeuten.

    ...

    Bestimmt gibt es dazu doch schon was fertiges - oder? :)
    Hm. Ein fertiges Tool das auf dem Mac läuft kenne ich nicht. Aber eines ist - zumindest bei mir - fest angewachsen, hat zwei Augen, zwei Ohren usw...

    D.h. warum schreibst Du überhaupt Methoden, die nicht genutzt werden? Ist das nicht gleich von Anfang an unnötig aufw(e)ändig? Mir scheint das Problem nur dann aufzutauchen, wenn man sich nicht ordentlich überlegt, welche Objekte oder Methoden man braucht bevor man mit dem Programmieren anfängt...

    Noch ein Gedanke: Eventuell ist der Compiler in der Stufe -O3 so schlau die Methoden zumindest aus dem Binary zu entfernen. Dann kannst Du sie - für das Binary so bedeutungslos wie Kommentare - im Sourcecode einfach drin lassen.

    -- hns
  • Ja - in der Praxis sieht es halt doch so aus, dass bei Bedarf eine neue Methode implementiert wird und nach ein paar Monaten und vielen weiteren Änderungen am Quellcode diese Methode eigentlich überflüssig ist, da sie nicht genutzt wird.

    Es geht mir nur darum jeden überflüssigen Code ausfindig zu machen. Dies ist bei eigenem Quellcode, der noch dazu für eine konkrete Anwendung und nicht für eine eher abstrake Library geschrieben wird eigentlich viel leichter zu entscheiden: ob überflüssig oder nicht. Bei einer Library können ja auch ungenutzte Methoden für die Anwender der Library wichtig sein. Bei Code für Anwendungsprogramme ist das je eher nicht der Fall. Da plant entweder einer ganz weit in die Zukunft oder er hat die überflüssig gewordene Methode einfach "übersehen".
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Original von hnsNoch ein Gedanke: Eventuell ist der Compiler in der Stufe -O3 so schlau die Methoden zumindest aus dem Binary zu entfernen. Dann kannst Du sie - für das Binary so bedeutungslos wie Kommentare - im Sourcecode einfach drin lassen.


    Bei Objective-C werden keine Methoden "wegoptimiert", nicht mal inlining wird betrieben. ;)
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Wegoptimieren geht kaum, da der Compiler nicht wissen kann, welche Action in einem Nib steht.

    Das mit dem Inlining verstehe ich indessen nicht:
    FOUNDATION_STATIC_INLINE NSRect NSMakeRect(float x, float y, float w, float h) {
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Original von Tom9811Das mit dem Inlining verstehe ich indessen nicht:
    FOUNDATION_STATIC_INLINE NSRect NSMakeRect(float x, float y, float w, float h) {


    NSMakeRect ist auch keine Objective-C Methode sondern eine C-Funktion. ;)
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Von Methode war nicht die Rede. Es ist eine Objective-C-Funktion, keine C-Funktion. Mein Objective-C-Compiler verdaut sie auch ohne Weiteres. Kurze frage: Ist "=" ein C-= oder ein Objective-C-=?

    Aber wieso braucht man Inline-Methoden? Sind die polymorph?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Original von Tom9811
    Wegoptimieren geht kaum, da der Compiler nicht wissen kann, welche Action in einem Nib steht.

    Genau. Und, m.E. noch viel schlimmer, weil es Dinge wie NSSelectorFromString() gibt - da kann Beliebiges drin stehen. Das kann keine maschinelle Codeanalyse allgemein lösen.

    Man könnte per poseAsClass: o.ä. NSObject patchen, dass es respondsToSelector: und/oder performSelector: loggt und das Ergebnis dann mit vollständigen Classdumps vergleichen - das gäbe zumindest eine Annäherung...

    Das mit den Membervariablen ohne Accessoren verstehe ich nicht. Zumindest bei mir haben einige Objekte jede Menge privater Eigenschaften - ist das nicht einer der Hauptvorteile von Objektorientierung? Ich glaube nicht, dass es dafür ein Tool gibt, aber das sollte sich doch recht schnell selbst zusammenbasteln lassen, oder?
    Multigrad - 360°-Produktfotografie für den Mac
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Original von mattik
    Original von Tom9811
    Wegoptimieren geht kaum, da der Compiler nicht wissen kann, welche Action in einem Nib steht.

    Genau. Und, m.E. noch viel schlimmer, weil es Dinge wie NSSelectorFromString() gibt - da kann Beliebiges drin stehen. Das kann keine maschinelle Codeanalyse allgemein lösen.

    Wobei ich das für gleich schlimm halten würde, weil ich nicht weiß, wie sonst der Nib-Loader aus der Information im Nib einen Call machen sollte. ;)

    Original von mattik
    Man könnte per poseAsClass: o.ä. NSObject patchen, dass es respondsToSelector: und/oder performSelector: loggt und das Ergebnis dann mit vollständigen Classdumps vergleichen - das gäbe zumindest eine Annäherung...

    Uiuiuiuiui, das ist eher Schätztechnik.

    Original von mattik
    Das mit den Membervariablen ohne Accessoren verstehe ich nicht. Zumindest bei mir haben einige Objekte jede Menge privater Eigenschaften - ist das nicht einer der Hauptvorteile von Objektorientierung?

    Du solltest auch für private Eigenschaften Accessoren benutzen.

    Original von mattik
    Ich glaube nicht, dass es dafür ein Tool gibt, aber das sollte sich doch recht schnell selbst zusammenbasteln lassen, oder?

    Jedenfalls, wenn man die Analyse einem der dafür vorgesehenen Tools überlässt.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Original von Tom9811
    Uiuiuiuiui, das ist eher Schätztechnik.

    Naja, ich würde es dynamische Softwareanalyse nennen - das klingt nicht so böse. Was willst Du sonst machen? Statisch geht's aus o.g. Gründen nicht.
    Original von Tom9811
    Du solltest auch für private Eigenschaften Accessoren benutzen.

    Jaja, ich weiß, dass Du diese Meinung energisch vertrittst. Ich habe da eine andere.
    Multigrad - 360°-Produktfotografie für den Mac
  • Naja - Dynamik (NSSelectorFromString, ...) hin oder her. Eine gewisse (große) Erleichterung wären solche Tools doch. Die sollen ja nicht automatisch im Code rumpfuschen sondern lediglich mögliche unnütze Dinge auflisten. Außerdem wird man innerhalb einer eigenen Implementation einer Klasse wohl kaum auf eigene Methoden mit NSSelectorFromString zugreifen. So ab 10.000 Zeilen Quellcode und annähernd 50 .m Dateien wird es halt ein wenig unübersichtlich und man freut sich über jede unnütze Methode, die man killen kann.
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Na ja, Actions kann man erkennen, sind sie ja markiert. Accessoren kann man eigentlich auch erkennen. Der Scanner soll ja auch erst einmal einen Vorschlag machen. Und in der Tat geht es zumindest bei mir um echte "Operationen", die ich nicht mehr benötige, weil ich nunmehr etwas anders löse.

    Klar, bei einem richtigen Refaktorierungspfad fällt das auf. Aber die Realität …

    Accessoren halte ich einfach für praktisch:
    - Keine Probleme mit nachträglicher Implementierung von Lazyness
    - Keine Probleme bei errechneten Eigenschaften
    - Keine Probleme mit Speicherverwaltung
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Original von Tom9811
    Von Methode war nicht die Rede.


    Ich zitiere mich noch mal:
    "Bei Objective-C werden keine Methoden "wegoptimiert", nicht mal inlining wird betrieben."

    Es ist eine Objective-C-Funktion, keine C-Funktion. Mein Objective-C-Compiler verdaut sie auch ohne Weiteres. Kurze frage: Ist "=" ein C-= oder ein Objective-C-=?


    C ist nunmal zu 100% in ObjC enthalten. Klar das sie dein ObjC-Compiler verdaut ;)
    Und alles was nicht zwischen [ und ] (jetzt komm mir nicht mit C-Arrays ;)) steht ist nunmal stink normales C.

    Aber wieso braucht man Inline-Methoden?


    Wenn man Mini-Methoden nur zur Übersichlichkeit erstellt, dann könnte es durch inlining einen guten Geschwindigkeitsvorteil bringen. Klar, klappt bei ObjC eben nicht. Ist ja auch nicht weiter fatal ;)
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Ich zitiere mich noch mal:
    "Bei Objective-C werden keine Methoden "wegoptimiert", nicht mal inlining wird betrieben."

    Sorry, wegen des Kommas verstand ich das so, dass der zweite Teil allgemein gelten sollte. Mea culpa.

    C ist nunmal zu 100% in ObjC enthalten. Klar das sie dein ObjC-Compiler verdaut
    Und alles was nicht zwischen [ und ] (jetzt komm mir nicht mit C-Arrays ) steht ist nunmal stink normales C.

    Du erklärst hier, warum es so ist. Das ändert nichts daran das es so ist.
    Halten wir also fest: In Objective-C gibt es Function-Inlining.

    Wenn man Mini-Methoden nur zur Übersichlichkeit erstellt, dann könnte es durch inlining einen guten Geschwindigkeitsvorteil bringen. Klar, klappt bei ObjC eben nicht. Ist ja auch nicht weiter fatal

    Die Frage lautete:
    Wozu braucht man Inline-Methoden? Verhalten die sich polymorph?
    +++
    Der Punkt, die Frage war rhethorisch:
    Polymorphie und Inlining widersprechen sich. Die Vorhersage, wann eine Inline-Funktion sich polymorph verhält, st die Frage, ob Inlinng und virtual sich beißen. Grundsätzlich ja. Du kannst jetzt im Stoßtrupp nachlesen, was die Kombination bedeutet. Nach langamtmigen Fallunterscheidungen kommst du zum Ergebnis: Kann man nicht sagen, hängt von den Umständen und dem Optimierungsverhalten des Compilers ab. Na, super!
    [+++
    Ich schaue einfach mal nach. Ich habe hier doch ein Internet.
    Nur mal kurz Microsofts Antwort:
    Q
    How does C++ handle inline virtual functions? When a function is inline and virtual, will code substitution take place or is the call resolved using the vtable?
    G.N. Rajagopal

    A
    The answer is, it depends. To see why, let's consider each case—inline and virtual—separately. Normally, an inline function is expanded, well, inline.
    class CFoo {
    private:
    int val;
    public:
    int GetVal() { return val; }
    int SetVal(int v) { return val=v; }
    };
    In this situation, if you write
    CFoo x;
    x.SetVal(17);
    int y = x.GetVal();
    then the compiler generates the code as if you'd written:
    CFoo x;
    x.val = 17;
    int y = x.val;
    Of course you can't do this because val is private. Inline functions give you the advantage of data hiding without paying the price of a function call. So much for inline functions.
    Virtual functions give you polymorphism, which means derived classes can implement the same function differently. Suppose GetVal is now declared virtual and you have a second class, CFoo2, with a different implementation:
    class CFoo2 : public CFoo {
    public:
    // virtual in base class too!
    virtual int CFoo2::GetVal() {
    return someOtherVal;
    }
    };
    If pFoo is a pointer to a CFoo or CFoo2, then pFoo->GetVal will call the member function for whichever class pFoo really points to—CFoo or CFoo2. This is C++ 101, and you should know it like the back of your hand.
    But what happens if a function is both virtual and inline? Remember, there are two ways to make a function inline: by using the inline keyword in the function definition, as in
    inline CFoo::GetVal() { return val; }
    or by coding the function body inline within the class declaration, as in the previous CFoo2::GetVal example. So if you include the body of your virtual function within the class declaration
    class CFoo {
    public:
    virtual int GetVal() { return val; }
    };
    then you are telling the compiler you want GetVal to be both inline and virtual. This doesn't seem to make sense, for how can polymorphism work if the function is expanded inline? The answer, of course, is that it can't. Or can it?
    The first rule the compiler follows when it encounters such a beast is this: whatever happens, polymorphism must work. If you have a pointer to a CFoo object, then pFoo->GetVal is guaranteed to call the right function. In general, this means the GetVal functions will be instantiated as real (noninline) functions, with vtable entries pointing to them. But that doesn't mean the function can't ever be expanded! Consider this code again:
    CFoo x;
    x.SetVal(17);
    int y = x.GetVal();
    The compiler knows that x is really a CFoo, not a CFoo2, since the stack object is explicitly declared. There's no way x could really be a CFoo2. So it's safe to expand SetVal/GetVal inline. If you write this more complex code
    CFoo x;
    CFoo* pfoo=&x;
    pfoo->SetVal(17);
    int y = pfoo->GetVal();
    •••
    CFoo2 x2;
    pfoo = &x2;
    pfoo->SetVal(17); //etc.
    the compiler knows that pfoo points to x the first time and x2 the second time, so again it's safe to expand the virtual functions. You can dream up ever more complex examples, where the type of object pfoo points to is always known, but most compilers won't do any heavy analysis. Even in the preceding example, some compilers will do the safe thing, which is to instantiate the function and call through a vtable. Indeed, the compiler is free to ignore the inline requirement and always use the vtable. The only absolute rule is that the code must work; that is, virtual functions must behave polymorphically.
    In general, inline—whether explicit or implicit—is a hint, not a mandate, just like register. (Does anyone remember register? It asks the compiler to use a machine register for a variable if it can.) The compiler can refuse to expand even a nonvirtual inline function if it wants to, and the first C++ compilers often complained, "inline aborted—function too big." Certainly if an inline function calls itself, or if you pass its address somewhere, the compiler must generate a normal (outline?) function. And, of course, inline functions are not expanded in debug builds, or if you set a compiler option preventing it.
    The only way to really know what your compiler is doing is to look at the code it generates. For the Microsoft® compiler, you can compile with -FA to generate an assembly listing. You don't need to be an assembler jock to know what's going on. I encourage you to perform this experiment; it's good for the soul to see what the machine is actually doing, and you can learn a lot poking around assembly listings. For now, I'll spare you that agony.
    The topic of inline functions is more complex than you might think at first. There are many circumstances that force the compiler to generate a normal function: recursion, taking the address of your function, functions that are too big, and virtual functions. Here's another consideration: if the compiler decides to instantiate your inline function, where does it put the function? Which module does it go into?
    Usually, classes are declared in header (.h) files. So if mumble.cpp includes foo.h and the compiler decides it has to instantiate CFoo:: GetVal, it will instantiate it as a static function in mumble.cpp. If 10 modules include foo.h, the compiler could generate up to 10 copies of your virtual function. In fact, you could end up with objects of the same type with vtables pointing to different copies of GetVal. Yuk! Some linkers are smart enough to eliminate the redundancies at link time, but in general you can't be sure.
    So the bottom line is: it's best not to use inline virtual functions, since they're almost never expanded anyway. Even if your function is just one line, you're better off putting it in the module (.cpp file) along with the other class functions. Of course, programmers often put short virtual functions in the class declaration—not because they expect the function to be expanded inline, but because it's more convenient and readable.

    Danke, so etwas brauche ich nicht.]

    De facto läuft es darauf hinaus, dass sich virtual und inline beißen. Du hast also bei Inlining keine Polymorphie.

    Und wozu willst du dann eine Methode haben?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Original von Tom9811
    Und wozu willst du dann eine Methode haben?

    Da fügen wir mal gleich ein Zitat von Dir an:
    Original von Tom9811
    Du solltest auch für private Eigenschaften Accessoren benutzen.

    Es soll Personen geben, die deren Preis nicht bezahlen wollen und dann lieber direkt die Attribute nutzen wollen. Inlined Accessoren würden das Problem lösen.
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Huch, hatte ich nicht den Grund dafür genannt? Echt nicht? Stand da nicht zum Beispiel etwas von ausgerechneten Eigenschaften? Doch, stand da. Oder etwas von Lazyness? Doch stand da.

    Und das gilt in beide Richtungen: Sehr gerne überschreibe ich Accessoren, um mein Model konstant zu halten, abhängig von den Werten andere Eigenschaften zu setzen usw. Die müssen also virtual sein.

    Womit ich wieder weg bin von den Inlines …
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RE: Objective-C: Tool zum "Aufräumen" gesucht

    Ja, das hattest Du so geschrieben.
    Nein, sie müssen nicht virtuell sein, ein Recompile wäre notwendig. Ob man das so haben will oder nicht ist eine Frage der Philosophie des Sprachdesigns. Da Du es überdeutlich gemacht hast, daß Du ein dynamisches Sprachdesign bevorzugst, brauchen wir diesen Punkt nicht zu vertiefen. Die jeweiligen Standpunkte sind bekannt.