Tipps für den Programmieralltag

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Tipps für den Programmieralltag

    Hallo,

    mir war langweilig. Habe mal einige Tipps/Vorschläge zusammengefasst, die ich beim Programmieren beherzige. Diese sind sicherlich nicht der Weisheit letzter Schluss. Daher bitte ich um eure Gedanken dazu. Einige Tipps/Vorschläge sind sicherlich trivial. Aber hier treiben sich ja auch einige Anfänger rum.


    1. Möglichst wenige "Strings" im Quellcode
    Zur Verdeutlichung ein einfaches Negativbeispiel:

    Quellcode

    1. - (void)setName:(NSString *)newName {
    2. [self willChangeValueForKey:@"name"];
    3. name = newName;
    4. [self didChangeValueForKey:@"name"];
    5. }


    Probleme:
    1. Es ist sehr Fehleranfällig den Schlüssel "name" immer wieder als String in der Form @"name" zu schreiben. Ein kleiner

    Tippfehler kann zu schweren Fehlern führen. Das muss nicht sein.

    2. Andere Entwickler, die mittels KVC den "Namen" ermitteln möchten sind gezwungen dies in etwa wie folgt zu tun:

    Quellcode

    1. NSLog(@"Name: %@", [object valueForKey:@"name"]);


    Dies ist für den Entwickler, der die Klasse nutzen möchte unschön, da fehleranfällig.

    Lösung:
    Für jeden Schlüssel, den eine Klasse intern nutzt schafft der Entwickler der Klasse zusätzlich eine Klassenmethode, welche

    den Schlüssel liefert. Muss der Schlüssel auch von außerhalb der Klasse bekannt sein, muss die Klassenmethode in der

    Headerdatei stehen - sonst in einer Kategorie.

    Beispiel eines öffentlichen Schlüssels:

    In der Headerdatei:

    Quellcode

    1. + (NSString *)nameKey;


    In der Implementation:

    Quellcode

    1. + (NSString *)nameKey { return @"name"; }


    Nun kann die "setName:" Methode wie folgt implementiert werden:

    Quellcode

    1. - (void)setName:(NSString *)newName {
    2. [self willChangeValueForKey:[self.cass nameKey]];
    3. name = newName;
    4. [self didChangeValueForKey:[self.cass nameKey]];
    5. }


    Alternativ kann in der Headerdatei auch eine globale Variable definiert werden.

    Quellcode

    1. extern NSString * const MyPrefixNameKey;


    In der Implementation:

    Quellcode

    1. NSString * const MyPrefixNameKey = @"name";


    Der Nachteil dieser Lösung ist, dass viele globale Variablen erzeugt werden, die alle mit einem Präfix versehen werden

    sollten, da dies der Vermeidung von Namenskonflikten hilft. Bei einer Änderung des eigenen Präfix müssen die Namen vieler

    globalen Variablen geändert werden. Bei der Implementierung als Klassenmethode dient die eigene Klasse als "Namensraum". Das

    vorgestellte Prinzip kann auch für Namen von "Bindings" sowie für "Kontexte" beim Observieren genutzt werden. Grundsätzlich

    immer dann, wenn man es mit Keys oder sonstigen statischen Informationen zu tun hat.

    2. Wiederholdende setNeedsDisplay: Aufrufe in NSView Subclass vermeiden.

    Negativbeispiel:

    Aus der Implementierung eines NSView Subclasses:

    Quellcode

    1. ...
    2. - (void)setName:(NSString *)newName {
    3. [self willChangeValueForKey:@"name"];
    4. name = newName;
    5. [self didChangeValueForKey:@"name"];
    6. [self setNeedsDisplay:YES];
    7. }
    8. - (void)setAge:(NSNumber *)newAge {
    9. [self willChangeValueForKey:@"age"];
    10. age = newAge;
    11. [self didChangeValueForKey:@"age"];
    12. [self setNeedsDisplay:YES];
    13. }
    14. ...
    Alles anzeigen


    Wie zu sehen ist geschieht in den Methoden nichts Spannendes. Der einzige Grund, wieso die Methoden selbst implementiert

    werden ist, dasss bei neuem Namen sowie neuem Alter das View neu gezeichnet wird. Dies ist Arbeit, die nicht nötig ist.

    Idee zur Verbesserung:
    Die Accessoren werden nicht selbst implementiert sondern durch @synthesize. Dann wird das View allerdings nicht automatisch

    neu gezeichnet. Allerdings kann das View seine eigenen Attribute observieren.

    Hier nun eine bessere Implementierung:

    In der Headerdatei:


    Quellcode

    1. @interface PersonView : NSView
    2. NSString *name;
    3. NSNumber *age;
    4. @end
    5. + (NSString *)nameKey;
    6. + (NSString *)ageKey;
    7. @property (retain) NSString *name;
    8. @property (retain) NSNumber *age;


    Implementierung (init weggelassen)

    Quellcode

    1. @interface PersonView (Private)
    2. @property (readonly) NSArray *keysAffectingNeedsDisplay;
    3. @end
    4. @implementation PersonView (Private)
    5. - (NSArray *)keysAffectingNeedsDisplay; { return [NSArray arrayWithObjects:[self nameKey], [self ageKey], nil]; }
    6. @end
    7. @implementation PersonView
    8. + (NSString *)nameKey { return @"name"; }
    9. + (NSString *)ageKey { return @"age"; }
    10. @synthesize name;
    11. @synthesize age;
    12. - (void)viewDidMoveToSuperview {
    13. for(NSString *key in self.keysAffectingNeedsDisplay) {
    14. [self addObserver:self forKeyPath:key options:0 context:0];
    15. }
    16. }
    17. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void
    18. *)context {
    19. if(object == self) {
    20. [self setNeedsDisplay:YES];
    21. return;
    22. }
    23. [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    24. }
    25. @end
    Alles anzeigen


    Was geschieht hier? Zunächst wird in der Kategorie "Private" eine "readonly" Eigenschaft erzeugt, die die Keys, deren

    Änderung des Wertes ein Neuzeichnen des Views zur Folge haben muss. Zu dieser Eigenschaft gibt es einiges zu sagen:

    - Sie ist in der Regel "privat" (daher in der Kategorie), da die interne funktionsweise andere Klassen nichts angeht. In

    Ausnahmefällen kann sie auf öffentlich sein. Klar.

    - Sie ist "readonly", da niemand die Schlüssel einfach so ändern können soll.

    - Sie gibt ein Array und kein Set zurück, sodass das Iterieren mittels der neuen Fast Enumeration

    Quellcode

    1. for(NSString *key in self.keysAffectingNeedsDisplay) ...


    möglich ist. Ein Set hat keine Reihenfolge. Eventuell würde sich das View dann zwei mal für den selben Schlüssel als Observer

    anmelden. Alernativ könnte das Iterieren wie folgt geschehen:

    Quellcode

    1. NSSet *keys = self.keysAffectingNeedsDisplay;
    2. for(NSString *key in *keys ) ...


    Dann wäre die Verwendung eines Sets kein Problem. (Hinweis: Ich bin mir nicht sicher, ob NSFastEnumeration intern das Array

    oder das Set über das iteriert wird "speichert". Dem müsste man nachgehen.)

    Statt das Array/Set bei jedem Aufruf von self.keysAffectingNeedsDisplay neu zu erzeugen wäre auch denkbar dies mittels

    "if/static" zu unterbinden.

    - keysAffectingNeedsDisplay ist nicht wie nameKey oder ageKey eine Klassenmethode. Hintergedanke: Momentan gibt

    keysAffectingNeedsDisplay einfach einige Schlüssel zurück, deren Änderung des Wertes ein Neuzeichnen zur Folge haben muss.

    Denkbar wäre, dass diese Schlüssel abhängig davon sind, was das View momentan anzeigt. Man stelle sich ein großes View vor,

    welches nicht all seine Eigenschaften gleichzeitig anzeigen kann. Dann sollten auch nicht alle Änderungen ein Neuzeichnen zur

    Folge haben.

    Hinweise: init sowie das Beenden der Observierung wurden nicht mit in den Code aufgenommen. Auch über den Zeitpunkt des

    Begins der Observierung (in dem Fall geschieht dies bei viewDidMoveToSuperview) kann diskutiert werden. Denkbar:

    awakeFromNib, initWithFrame:, ...


    3. Welcher Controller ist für welches Binding verantwortlich?
    Eine Klasse sollte keine unnötigen Outlets/Membervariablen haben. Oft sehe ich folgenden "Fehler": Der Entwickler erzeugt in

    einer nib ein TableView und bindet dessen "content" an einen ArrayController. Dann möchte er das Verhalten des TableViews

    mittels eines Delegates beeinflussen. Fein. Er erzeugt eine neue Klasse: MyTableViewDelegate. Da er in einer Delegatemethode

    auch auf den ArrayController, der für den "content" des TableViews sorgt benötigt versieht er sein Delegate mit einem Outlet

    zum ArrayController. Das muss nicht sein, denn es ist möglich diesen ArrayController "zur Laufzeit" in Abhängigkeit des

    TableViews zu ermitteln:

    Quellcode

    1. - (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row {
    2. NSArrayController *contentArrayController = [[tableView infoForBinding:NSContentBinding]
    3. valueForKey:NSObservedObjectKey];
    4. NSLog(@"arrayController: %@", contentArrayController);
    5. return YES;
    6. }


    Vorteile: Das eigene Delegate hängt nicht von einem speziellen ArrayController ab sondern ermittelt diesen in Abhängigkeit

    des TableViews. So kann das Delegate von mehreren TableViews genutzt werden.


    4. Die Layoutberechnungen eines NSView Subclasses "lazy" implementieren.
    Angenommen es ist ein View zu implementieren, welches ein blaues Rechteck in die Mitte des Views zeichnet. Das View verfügt

    über das Attribut "inset", welches bestimmt wie viel Abstand zwischen dem äußersten Rand des Views und dem blauen Rechteck

    sein soll. Ein inset von 0 bedeutet, dass das blaue Rechteck das komplette View bedecken soll. Ein inset von 100 soll das

    blaue Rechteck an jeder Seite Einheiten Abstand zum äußersten Rand des Views halten.

    Hier ein Negativbeispiel: (blueRect ist definiert als NSRect)

    Quellcode

    1. @implementation RechteckView
    2. - (CGFloat)inset { return inset; }
    3. - (void)setInset:(CGFloat)newInset {
    4. inset = newInset;
    5. blueRect = NSInsetRect(self.bounds, self.inset, self.inset);
    6. [self setNeedsDisplay:YES];
    7. }
    8. - (void)drawRect:(NSRect) {
    9. [[NSColor blueColor] setFill];
    10. NSRectFill(blueRect);
    11. }
    12. @end
    Alles anzeigen


    Probleme:
    - blueRect ist nicht immer "aktuell", da es nur beim Aufruf von setInset berechnet wird. Wird das View in seiner Größe

    verändert, so wird dies nicht berücksichtigt.

    - Es ist eine zusätzliche "Membervariable" (blueRect) notwendig.

    - Eine Berechnung versuchen zu cachen oder etwas "vorzuberechnen" ist grundsätzlich keine gute Idee.

    Alternative:

    Quellcode

    1. @interface RechteckView(Private)
    2. @property (readonly) NSRect blueRect;
    3. @end
    4. @implementation RechteckView(Private)
    5. - (NSRect)blueRect; { return NSInsetRect(self.bounds, self.inset, self.inset); }
    6. @end
    7. @implementation RechteckView
    8. @synthesize inset; // für setNeedsDisplay: siehe Tipp 2
    9. - (void)drawRect:(NSRect) {
    10. [[NSColor blueColor] setFill];
    11. NSRectFill(self.blueRect);
    12. }
    13. @end
    Alles anzeigen


    Diese Vorgehensweise ist auch gut auf kompliziertere Views anwendbar. Konkretes Beispiel:
    [Blockierte Grafik: http://christian-kienle.de/MediaSnapScreenshots/finishedWindow.png]

    Der Video/Audio Slider verfügt intern über allerhand "readonly" Methoden, die bei jedem Aufruf irgendwas in Abhängigkeit der

    Größe des Views (self.bounds.size) berechnen. Das View erzeugt zum Beispiel bei jedem Aufruf von drawRect: folgende Dinge:

    - borderBezierPath (ein NSBezierPath für den Rand)
    - knobSize (ein NSSize für die Größe des "Schiebereglers")
    - knobRect (ein NSRect, welches neben der Größe auch die Position des "schiebereglers" berechnet.)
    - freeRect (ein NSRect, welches die Dimensionen des "dunklen" Bereiches beschreibt.)

    Usw. Es wird alles "lazy" in diesen Methoden berechnet und das immer wieder. Ohne caching. Die drawRect: Methode wird dadurch

    sehr einfach und logisch sowie gut zu warten. Performanceprobleme gibt es auch keine. Cachen nur da, wo unbedingt nötig.


    5. Möglichst späte Deklaration und Initialisierung von Variablen
    Negativbeispiel:

    Quellcode

    1. - (void)somethingComplicated {
    2. NSPoint point;
    3. NSRect rect;
    4. NSString *a = @"test";
    5. point = [self calculatePoint];
    6. point.x -= 10.0;
    7. rect = NSMakeRect(point.x, 0.0, 100.0, 200.0);
    8. [a drawInRect:rect withAttributes:nil];
    9. }


    Besser:

    Quellcode

    1. - (void)somethingComplicated {
    2. NSPoint point = [self calculatePoint];
    3. point.x -= 10.0;
    4. NSRect rect = NSMakeRect(point.x, 0.0, 100.0, 200.0);
    5. NSString *a = @"test";
    6. [a drawInRect:rect withAttributes:nil];
    7. }


    Noch besser:

    Quellcode

    1. - (void)somethingComplicated {
    2. [@"test" drawInRect:NSMakeRect( [self calculatePoint].x - 10.0, 0.0, 100.0, 200.0) withAttributes:nil];
    3. }


    Sollte klar sein - aber ich sehe das immer wieder.

    6. Komplizierte if-Ausdrücke vereinfachen
    Negativbeispiel:

    Quellcode

    1. if(self.name != nil && self.age != nil && self.sex != nil) { ... }


    Problem: Es ist zwar klar, was überprüft wird - allerdings liest ein Programmierer oftmal mehr Code, als er selbst schreibt.

    Das Lesen sollte also möglichsteinfach sein. Daher kann für komplizierte Ausdrücke wieder eine readonly-Eigenschaft

    geschaffen werden, die in etwa so aussieht:

    Quellcode

    1. - (BOOL)attributesAreReadyToDraw { return (self.name != nil && self.age != nil && self.sex != nil); }


    Dann ergibt dies:

    Quellcode

    1. if(self.attributesAreReadyToDraw) { ... }


    Und jeder weiß, was gemeint ist.
    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: Tipps für den Programmieralltag

    Und wieso mahcst du dann nicht gleicch -name und -setName:? Oder machst du dir hierfür -selectorForSettingTheAttributeWithTheNameName? ;)
    +++
    5:
    self.calculatePoint.x

    Sorry, aber: "Autsch". Die Dotnotation sollte für Accessoren vorbehalten bleiben. Nicht alles, was geht, ist sinnvoll.
    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"?
  • Joar, hast du auch Recht. Geht ja prinzipiell auch in einem Wiki, aber da das nicht oft frequentiert wird...

    Find die Idee jedenfalls gut, ohne dass ich nun konkret was inhaltliches beisteuern könnte. Für Obj-C fehlt mir leider seit meinem letzten Programm (vor 2,5 Jahren) die Zeit :(
    Real programmers confuse Halloween and Christmas because OCT 31 = DEC 25
  • RE: Tipps für den Programmieralltag

    Original von Tom9811
    Und wieso mahcst du dann nicht gleicch -name und -setName:? Oder machst du dir hierfür -selectorForSettingTheAttributeWithTheNameName? ;)


    Nein. Okay - war vielleicht ein dummes Beispiel. Vielleicht wäre es besser gewesen noch zu erwähnen, dass Keys von Dictionaries auch auf diese Weise verfügbar gemacht werden sollten, falls es sich z.b. um ein Dictionary für einen Thread handelt, welches einige "standardkeys" hat.
    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: Tipps für den Programmieralltag

    Original von Tom9811
    Und wieso mahcst du dann nicht gleicch -name und -setName:? Oder machst du dir hierfür -selectorForSettingTheAttributeWithTheNameName? ;)
    +++
    5:
    self.calculatePoint.x

    Sorry, aber: "Autsch". Die Dotnotation sollte für Accessoren vorbehalten bleiben. Nicht alles, was geht, ist sinnvoll.


    Ja okay. Das war so nicht beabsichtigt. Richtig gedacht und falsch hingeschrieben. Das ändere ich noch schnell ab.
    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: Tipps für den Programmieralltag

    Nö, bei Dictionarys machst du dir einfach eine Kategorie.

    Ich sehe immer noch nicht den Vorteil von -keyForName anstelle von @"name". Wenn man das bei Bindings so eingeben könnte, wäre das ja noch irgendwie nachvollziehbar. So sieht das für mich aber eher nach totabstrahiert aus. Irgendwann muss es nun einmal auch eine kleinste Matroschka geben.
    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: Tipps für den Programmieralltag

    Original von Tom9811
    Nö, bei Dictionarys machst du dir einfach eine Kategorie.

    Ich sehe immer noch nicht den Vorteil von -keyForName anstelle von @"name". Wenn man das bei Bindings so eingeben könnte, wäre das ja noch irgendwie nachvollziehbar. So sieht das für mich aber eher nach totabstrahiert aus. Irgendwann muss es nun einmal auch eine kleinste Matroschka geben.


    Was meinst du mit "eingeben könnte"?

    Es soll nicht für jedes Attribut eine entsprechende +<attribut>Key Methode geben. Natürlich nur für die Keys, die man sonst von Hand immer und immer wieder hinschreiben würde.
    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: Tipps für den Programmieralltag

    Original von Objcler
    Original von Tom9811
    Nö, bei Dictionarys machst du dir einfach eine Kategorie.

    Ich sehe immer noch nicht den Vorteil von -keyForName anstelle von @"name". Wenn man das bei Bindings so eingeben könnte, wäre das ja noch irgendwie nachvollziehbar. So sieht das für mich aber eher nach totabstrahiert aus. Irgendwann muss es nun einmal auch eine kleinste Matroschka geben.


    Was meinst du mit "eingeben könnte"?

    Es soll nicht für jedes Attribut eine entsprechense +<attribut>Key Methode geben. Natürlich nur für die Keys, die man sonst von Hand immer und immer wieder hinschreiben würde.

    Na, bei Bindings muss ich ohnehin den Klartext eingeben. Darin kann kein Vorteil liegen.

    Was die Tipparbeit (ohnehin geichgültig) angeht, sind "richtige" Accessoren schneller und kürzer.

    Ich sehe einfach nicht den Vorteil.
    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"?
  • Original von below
    Was hast Du gegen #defines ?

    Alex

    Ich weiß nicht, was der junge Herr gegen Defines hat. Ich weiß aber was ich gegen Defines habe:

    1. Keine Typisierung.
    2. Seiteneffekte.
    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: Tipps für den Programmieralltag

    Original von Tom9811
    Original von Objcler
    Original von Tom9811
    Nö, bei Dictionarys machst du dir einfach eine Kategorie.

    Ich sehe immer noch nicht den Vorteil von -keyForName anstelle von @"name". Wenn man das bei Bindings so eingeben könnte, wäre das ja noch irgendwie nachvollziehbar. So sieht das für mich aber eher nach totabstrahiert aus. Irgendwann muss es nun einmal auch eine kleinste Matroschka geben.


    Was meinst du mit "eingeben könnte"?

    Es soll nicht für jedes Attribut eine entsprechense +<attribut>Key Methode geben. Natürlich nur für die Keys, die man sonst von Hand immer und immer wieder hinschreiben würde.

    Na, bei Bindings muss ich ohnehin den Klartext eingeben. Darin kann kein Vorteil liegen.

    Was die Tipparbeit (ohnehin geichgültig) angeht, sind "richtige" Accessoren schneller und kürzer.

    Ich sehe einfach nicht den Vorteil.


    Klartext? Wenn du im IB bindest? Ja klar. Natürlich. Aber es gibt ja auch Fälle, in denen man im Code binden muss oder oft irgendwelche Dictionaries mit immer gleichen Keys konstruiert werden müssen. Das sind ja keine Tipps, die man stumpfsinnig immer befolgen soll sondern nur da, wo es wirklich Zeit und die Redundanz spart. Du kennst mich doch. Ich bin kein großer Abstahierer.
    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: Tipps für den Programmieralltag

    Selbst wenn es Fälle geben sollte, in denen die Nachteile erträglich sind, sehe ich immer noch nicht den Vorteil gegenüber Accessoren.

    Du führst eine Indirektion ein, ohne Dynamik oder Unabhängigkeit zu benötigen. (Man könnte n so etwas denken, wenn sich der Schlüssel für die Eigenschaft zur Laufzeit ändert. Da gibt es aber wahrlich Besseres.) Das ist sinnlose Indirektion.
    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: Tipps für den Programmieralltag

    Original von Tom9811
    Selbst wenn es Fälle geben sollte, in denen die Nachteile erträglich sind, sehe ich immer noch nicht den Vorteil gegenüber Accessoren.

    Du führst eine Indirektion ein, ohne Dynamik oder Unabhängigkeit zu benötigen. (Man könnte n so etwas denken, wenn sich der Schlüssel für die Eigenschaft zur Laufzeit ändert. Da gibt es aber wahrlich Besseres.) Das ist sinnlose Indirektion.


    Ich glaube du hast mich falsch verstanden. Der erste Punkt hat nicht das Ziel Accessoren zu "ersetzen". Es ging bei dem konkreten Beispiel nur darum die Keys für - zum Beispiel die willChange, DidChange Aufrufe nicht jedes mal im Klartext hinzuschreiben sondern diese durch einen Methodenaufruf zu ersetzen, der den Key liefert. Für die Implementierung eines gewöhnlichen Accessors muss ein und der selbe Key vier mal hingeschrieben werden. Startet man an anderen Stellen im Code für das Attribut noch einige Beobachtungen kommen noch mal einige Nutzungen des Keys hinzu. Genau das ist das Problem.
    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: Tipps für den Programmieralltag

    @synthesize key;
    Das ist nur einmal.

    Und observierbare Eigenschaften kann man allein durch String-Konstanten darstellen. Dazu bedarf es keiner Klassenmethode. Immerhin durchlebt die auch ein Dispatch.

    (BTW: Was du als "lazy" bezeichnest, ist nicht lazy. Es ist einfach dynamisch. Lazy wäre es, wenn du das Ergebnis bei der ersten Berechnung zwischenspeicherst. Genau das geht in deinem Beispiel aber nicht.)
    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: Tipps für den Programmieralltag

    Ja - klar. @synthesize will man aber nicht immer verwenden und genau von diesen Fällen sprach ich ja. Ich dachte das sein klar, da kein vernünftiger Mensch Code schreibt, den er nicht schreiben muss.

    Und genau dann, wenn du die Accessoren selbst schreiben musst und noch einige Male den Key an anderen Stellen benötigst ist es doch Zeit das "irgendwie" zu verbessern. Oder?

    "Und observierbare Eigenschaften kann man allein durch String-Konstanten darstellen. Dazu bedarf es keiner Klassenmethode. Immerhin durchlebt die auch ein Dispatch."

    Ja okay - welche Probleme macht dieser Dispatch denn konkret?

    "(BTW: Was du als "lazy" bezeichnest, ist nicht lazy. Es ist einfach dynamisch. Lazy wäre es, wenn du das Ergebnis bei der ersten Berechnung zwischenspeicherst. Genau das geht in deinem Beispiel aber nicht.) "

    Okay - dann nennen wir es eben "dynamisch".
    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].
  • Übrigens heißt diese "Technik" "Normal Order Evaluation". Es ist ja eigentlich keine Technik sondern nur mehr oder weniger der Verzicht auf das Zwischenspeichern.

    c2.com/cgi/wiki?NormalOrderEvaluation

    Oder sehe ich das falsch? Die Rects und Sizes werden bei jedem Aufruf neu berechnet.
    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].