6

Als unsere Codebasis reift, fange ich an, das Muster der Übergabe von Wörterbüchern als eine Möglichkeit, Informationen für Nachrichtenübergabe oder noch schlimmer, Funktionsargumente zu sammeln, nicht mehr zu mögen. Es erfordert die Sende- und Empfangsfunktion, die beide eine undokumentierte API von String-Literalen haben.Besseres Muster als die Weitergabe von NSDictionaries als Parameter?

..in some function.. 
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys: 
         thisObject, @"thisKey", 
         thatObject, @"thatKey", 
         nil]; 

[[NSNotificationCenter defaultCenter] postNotificationName:@"MY_NOTIFICATION" object:nil userInfo:info]; 
.... 

und dann in someClass ‚s Hörer

- (void)someClassListener:(NSNotification *)notification { 
    NSDictionary *info = [notification userInfo]; 

    ThisObject *ob1 = [info objectForKey:@"thisKey"]; 
    ThatObject *ob2 = [info objectForKey:@"thatKey"]; 
} 

Sie müssen bedenken, dass thisKey und thatKey die Schlüssel vom Typ ThisObject und ThatObject für diese Meldung sind, sicher, dass Sie für die, einige Konstanten irgendwo schaffen könnte Schlüssel, aber das löst das Problem nicht wirklich.

Und sagen Sie, Sie haben eine Funktion, die 15 Argumente benötigt, Sie werden keine Funktion mit 15 Parametern machen, es wäre viel einfacher (obwohl weniger lesbar), nur ein Wörterbuch zu übergeben, aber jetzt haben Sie die Das gleiche Problem wie oben.

Ich spielte mit dem Erstellen von "Message Classes" in diesen Header-Dateien der Klasse (dh zwei Schnittstellen in einem Header) und die Message-Klasse war nur eine Liste von Objekten, die Sie definieren und senden an die Methode, die eine stärkere erstellt Vertrag, aber das fühlt sich falsch an.

Es wäre toll, wenn ich so etwas wie typeDef ein Parameterobjekt im Header tun könnte, aber das nicht unterstützt NSObject ‚s nur Dinge wie int oder float usw.

im Wesentlichen Ich versuche, Erstellen Sie einen stärkeren Vertrag zwischen dem Nachrichtensender und dem Nachrichtenempfänger, seien es Funktionen oder Benachrichtigungen.

Antwort

4

Sie könnten Konstanten für die Schlüssel definieren. Ein Beispiel finden Sie in der Dokumentation für UIKeyboardDidShowNotification für ein Beispiel. Es gibt eine Verknüpfung zu allen Schlüsseln, die verwendet werden können, um Informationen über die Benachrichtigung zu erhalten.

Ein besserer Ansatz wäre, Ihre Daten in eine Klasse statt in ein Wörterbuch zu kapseln. Erstellen Sie eine einfache Klasse mit Eigenschaften. Dies wird viel mehr selbst dokumentieren als ein Wörterbuch. Sie können die Eigenschaftsnamen und die Eigenschaftstypen in der H-Datei sehen.

Wenn Sie feststellen, dass Methoden 15 Argumente benötigen, müssen Sie diese Argumente zurücknehmen und in eine geeignete Klasse kapseln. Vielleicht reduziert sich die Methode auf ein paar Argumente und eine Klasse oder etwas Ähnliches.

+0

Ich erwähne Konstanten für Schlüssel als nicht eine gute Lösung, weil Sie immer noch suchen müssen, was der Schlüssel ist, und es nicht einen starken Vertrag für was der Wert (Objekt) sein wird, mehr wie ein Vorschlag. Das Einkapseln der Daten in eine Klasse war eine Richtung, die ich untersuchte, aber es scheint umständlich, eine Klasse für jede Nachricht zu erstellen, die ich weitergeben möchte, sei es 2 Argumente sind 10, würden Sie nicht zustimmen? – Shizam

+0

@Shizam, Wenn diese Nachrichten in verschiedene Wörterbücher geschrieben würden, würden Sie wahrscheinlich mehr als eine Klasse benötigen. Aber wenn Sie über Nachrichten sprechen, die manchmal zwei Schlüssel aus einem Wörterbuch und manchmal 10 übergeben, dann wäre das immer noch nur ein Klassenobjekt. – rdelmar

+0

@rdelmar Was ich während unseres Programms habe, haben wir wahrscheinlich 10-15 eindeutige Benachrichtigungen, jede dieser Benachrichtigungen würde eine eigene Klasse benötigen, um ihre Eigenschaften für die Nachricht usw. zu definieren. – Shizam

2

Was Sie wollen, ist ein Parameter Objekt, ein kleines Objekt, das eine Reihe von Feldern für die bequeme Kommunikation mit einer anderen Klasse kapselt. Intern kann das Parameterobjekt ein Wörterbuch oder einfach eine Reihe von bestimmten Feldern enthalten.

Geben Sie dem Parameterobjekt eine einfache API, mit der beide Klassen bestimmte Felder festlegen und abrufen können - setThisKey: und getThisKey. Dies dokumentiert im Wesentlichen die API zwischen den Methoden und Klassen.

Suchen Sie als Nächstes nach Möglichkeiten zum Verschieben von Funktionen in das Parameterobjekt.wenn Sie so etwas wie dies zum Beispiel haben:

param.fieldSize=[self.data size]; 
param.fieldColor=[self.data color]; 
param.flavor=[self.data lookUpTheRecipe] 

Sie könnten all diese einkapseln mit

[param withField: self.data]; 

Mit Arbeit, können Sie oft das Parameter-Objekt machen tun viele nützliche Arbeit; Dies kann lange Methoden aufbrechen und großen Klassen helfen, überschüssige Verantwortlichkeiten abzubauen.

+0

Ich erwähne dies als eine Lösung, die ich betrachtete, das Problem, das ich sehe, ein Parameterobjekt für jede Nachricht zu erstellen, scheint umständlich. Außerdem scheint es, als ob der Punkt, an dem das Objekt platziert werden soll, in der Kopfzeile der Klasse liegt, die die Nachricht "besitzt", so dass Sie zwei Schnittstellen in einer Kopfzeile haben, die verpönt scheint. – Shizam

+0

Sie können ein Parameterobjekt häufig unter mehreren verwandten Methoden teilen. –

+1

Ich sehe keine Einwände gegen das Hinzufügen von Schnittstellen zu Hilfsobjekten zu einem Klassenheader. Aber Ihr Ziel mit einem Parameter-Objekt besteht darin, diesem Objekt viel nützliches Verhalten hinzuzufügen, nicht nur einige Daten zu umhüllen. Letztendlich kann das Parameterobjekt seinen eigenen Platz in der Welt verdienen. Klassen wie NSURL werden auf diese Weise gestartet. –

0

Zuerst ist es nicht gut, 15 Argumente zu haben, und in diesem Fall sollten Sie darüber nachdenken, solche Rückrufe nicht zu machen oder zu versuchen, die Anzahl zu reduzieren.


Was ist mit der Verwendung des Absenders der Benachrichtigung? Zum Beispiel ist Ihr Objekt Task fertig und sendet eine Benachrichtigung. Der Empfänger verwendet den Absender, um auf sender.result, sender.error, sender.anything zuzugreifen.


Wenn Sie zwischen diesen Objekten stärker Kontakt wollen (Sender/Empfänger) sollten Sie vielleicht eine andere Art der Kommunikation anstelle von NSNotifications.

Einige Alternativen:

  • Delegierten (oder eine andere Art von direkter Aufruf-Methode)
  • Blöcke
  • Ziel + Aktion

Alle von ihnen können als zu viele verwendet werden Callbacks, indem sie in einem Array gespeichert werden und NSDictionaries für die Übergabe von Werten nicht verwendet werden.

+0

Wir verwenden auch Delegaten und Blöcke, ich habe nur NSNotifications als Beispiel verwendet, wo es einfach ist, das Problem zu sehen. Ich habe immer noch dieses Problem mit Blöcken usw., aber ich fange an zu denken, dass das Erstellen von Parameterobjekten, die die Parameter enthalten, so ziemlich die einzige Möglichkeit ist, dies zu tun. – Shizam