Was ist ein Konfigurationsobjekt und warum sollten Sie es verwenden?

Es ist ein Schmerz, die Parameter einer Funktion ändern zu müssen. Sie müssen jeden zweiten Aufruf dieser Funktion ändern, um Fehler zu vermeiden. Sie können dies jedoch umgehen, indem Sie nur einen Parameter verwenden: ein Konfigurationsobjekt.


Wie es aussieht

Hier ist ein dummes Beispiel für eine Funktion zum Erstellen eines Roboters:

 Funktion generateRobot (Arme: int, Persönlichkeit: String): Robot var robot: Roboter = neuer Roboter (); für (var i: int = 0; i < arms; i++)  //create arm and add it to robot  if (personality == "evil")  robot.commands = "Destroy mankind.";  else  robot.commands = "Bake cookies."  return robot;  generateRobot(2, "evil");

Hier ist dasselbe Beispiel, das ein Konfigurationsobjekt verwendet:

 Funktion generateRobot (conf: Object): Roboter var robot: Roboter = neuer Roboter (); für (var i: int = 0; i < conf.arms; i++)  //create arm and add it to robot  if (conf.personality == "evil")  robot.commands = "Destroy mankind.";  else  robot.commands = "Bake cookies."  return robot;  generateRobot(arms:2, personality:"evil");

Ich habe die Zeilen hervorgehoben, die geändert werden müssen. Sie können sehen, dass es keinen großen Unterschied gibt.


Warum die Mühe?

Wenn es kaum einen Unterschied gibt, warum sollten wir es dann auf die zweite Art tun? Schließlich macht es die Funktion tatsächlich etwas schwieriger zu bedienen; Bevor unsere IDE uns diese Informationen über die Parameter geben konnte, erwartete die Funktion:

… Jetzt kann es uns nur folgendes geben:

Angenommen, Sie möchten ein paar weitere Parameter hinzufügen: einen, der das zu verwendende Material angibt, und einen anderen, um die Farbe des Lasers anzugeben. Das ist in beiden Fällen nicht zu schwer:

 Funktion generateRobot (Arme: int, Persönlichkeit: String, Material: String, LaserColor: String): Robot var robot: Roboter = neuer Roboter (); für (var i: int = 0; i < arms; i++)  //create arm and add it to robot  if (personality == "evil")  robot.commands = "Destroy mankind.";  else  robot.commands = "Bake cookies."  switch (material)  case "wood": //wooden robot break; case "steel": default: //steel robot break;  robot.laser = new Laser(); robot.laser.color = laserColor; return robot;  generateRobot(2, "evil", "steel", "red");
 Funktion generateRobot (conf: Object): Roboter var robot: Roboter = neuer Roboter (); für (var i: int = 0; i < conf.arms; i++)  //create arm and add it to robot  if (conf.personality == "evil")  robot.commands = "Destroy mankind.";  else  robot.commands = "Bake cookies."  switch (conf.material)  case "wood": //wooden robot break; case "steel": default: //steel robot break;  robot.laser = new Laser(); robot.laser.color = conf.laserColor; return robot;  generateRobot(arms:2, personality:"evil", material:"steel", laserColor:"red");

Bis jetzt kein großer Unterschied. Was ist, wenn Sie möchten, dass Ihre Roboter standardmäßig über einen roten Laser verfügen? Wieder einfach Ohne ein Konfigurationsobjekt müssen Sie nur die Methodensignatur ändern (die Funktion Zeile), und Sie können das letzte Argument aus dem Funktionsaufruf entfernen:

 function generateRobot (Arme: int, Persönlichkeit: String, Material: String, laserColor: String = "red"): Robot // das ist alles gleich generateRobot (2, true, "steel"); // Ich habe das letzte Argument entfernt

Mit einem Konfigurationsobjekt ist es etwas schwieriger - wenn auch nicht viel:

 function generateRobot (conf: Object): Roboter if (! conf.laserColor) conf.laserColor = "rot";  var robot: Roboter = neuer Roboter (); für (var i: int = 0; i < conf.arms; i++)  //create arm and add it to robot  if (conf.personality == "evil")  robot.commands = "Destroy mankind.";  else  robot.commands = "Bake cookies."  switch (conf.material)  case "wood": //wooden robot break; case "steel": default: //steel robot break;  robot.laser = new Laser(); robot.laser.color = conf.laserColor; return robot;  generateRobot(arms:2, personality:"evil", material:"steel"); //I removed the last argument

Okay. Stellen Sie sich nun vor, Sie stellen fast alle Roboter als böse ein (ich meine, warum nicht?). Es ist also ziemlich schmerzhaft, jedes Mal "böse" als Parameter zu schreiben. Natürlich möchten Sie "Übel" als Standard festlegen - aber Sie nicht möchte ein Standardmaterial festlegen.

Die einzige Möglichkeit, dies mit einem regulären Satz von Funktionsparametern zu tun, besteht darin, die Reihenfolge der Parameter zu ändern Persönlichkeit und Material Parameter:

 Funktion generateRobot (Arme: int, Material: String, Persönlichkeit: String = "Evil", LaserColor: String = "Red"): Robot 

Ah, aber jetzt müssen Sie die Reihenfolge der Argumente bei jedem einzelnen Funktionsaufruf ändern!

 generateRobot (2, "Übel", "Stahl"); //funktioniert nicht mehr

Ein Konfigurationsobjekt gibt dieses Problem nicht an. Hör zu:

 function generateRobot (conf: Object): Roboter if (! conf.laserColor) conf.laserColor = "rot";  if (! conf.personality) conf.personality = "böse" // das ist alles das selbe generateRobot (arms: 2, Material: "steel"); // kein Parameter "Persönlichkeit"? kein Problem!

Ordentlich! Alle deine alten generateRobot () Funktionsaufrufe funktionieren weiterhin, aber Sie können neue Aufrufe erstellen, die die Spezifikation nicht stören Persönlichkeit.

Sie können sich sogar dafür entscheiden, das loszuwerden Persönlichkeit Parameter insgesamt:

 function generateRobot (conf: Object): Roboter if (! conf.laserColor) conf.laserColor = "rot";  if (! conf.personality) conf.personality = "böse" var robot: Roboter = neuer Roboter (); für (var i: int = 0; i < conf.arms; i++)  //create arm and add it to robot  robot.commands = "Destroy mankind."; switch (conf.material)  case "wood": //wooden robot break; case "steel": default: //steel robot break;  robot.laser = new Laser(); robot.laser.color = conf.laserColor; return robot; 

Die obige Version der Funktion bezieht sich nicht auf conf.personality Überhaupt - aber Sie erhalten keine Fehlermeldung, wenn Sie noch solche Anrufe haben:

 generateRobot (Arme: 2, Persönlichkeit: "Böse", Material: "Stahl");

Natürlich können Sie einige verwirrte Benutzer erhalten, wenn Sie wie folgt telefonieren:

 generateRobot (Arme: 2, Persönlichkeit: "gut", Material: "Stahl");

… Da alle Roboter jetzt böse sind. Aber zumindest wird der Code kompiliert.

Aus demselben Grund können Sie die Reihenfolge der Argumente ändern, ohne dass dies eine Rolle spielt, und Sie können sogar neue Parameter hinzufügen, die noch nichts bewirken:

 generateRobot (Material: "Stahl", LaserColor: "Grün", Arme: 2, Stimme: "Mr T");

Das Einstellen der Standardeinstellungen wird einfacher

Der Code zum Einstellen der Standardwerte ist bisher leicht zu verstehen, wird jedoch sehr lästig sein, wenn viele Parameter benötigt werden:

 if (! conf.laserColor) conf.laserColor = "rot";  if (! conf.personality) conf.personality = "böse"

Lassen Sie uns etwas allgemeineren Code schreiben, um damit umzugehen:

 var default: Object = laserColor: red, persönlichkeit: "evil" for (var key: String in default) if (! conf [key]) conf [key] = default [key]; 

Das zum Schleife kann ein wenig verwirrend sein, also werde ich es brechen. Zuerst schau dir das an:

 for (var key: String in default) trace (key); 

Das ist ein für in Schleife, in der die Namen der Tasten ausgegeben werden Standard Objekt:

 laserColor persönlichkeit

Sehen Sie sich als Nächstes diese Zeile an:

 trace (Standardwerte ["laserColor"]);

Dies wird ausgegeben rot - es ist das gleiche wie schreiben trace (defaults.laserColor).

Schauen Sie sich dieses Beispiel an:

 var Beispiel: Object = Demo: "Test"; Trace (Beispiel ["Demo"]); trace (Beispiel ["foo"]);

Was denkst du wird dies ausgeben?

Gut, Beispiel ["Demo"] ist das gleiche wie beispiel.demo, was gleich ist "Prüfung". Aber beispiel.foo existiert nicht so Beispiel ["Foo"] wird zurückkehren Null. Das bedeutet, dass !Beispiel ["Foo"] (Beachten Sie das Ausrufezeichen) entspricht wahr.

Wenn Sie das alles zusammenfassen, sollten Sie verstehen, warum dieser Code funktioniert:

 var default: Object = laserColor: red, persönlichkeit: "evil" for (var key: String in default) if (! conf [key]) conf [key] = default [key]; 

Gib mir einen Kommentar in den Kommentaren, wenn du eine Hand brauchst!

Ich will mehr!

Für eine noch schnellere Version versuchen Sie Folgendes:

 Funktion generateRobot (conf: Object = null): Robot var conf: Object = conf || ; var default: Object = laserColor: rot, persönlichkeit: "evil" für (var key: String in default) conf [key] = conf [key] || Standardwerte [Schlüssel]; 

Die Änderung in Zeile 1 (und neuer Zeile 2) bedeutet, dass auch die conf Objekt selbst ist optional, Sie können also einfach anrufen generateRobot (). (Natürlich müssen Sie den Code ändern, um die Werte zu berücksichtigen, für die derzeit keine Standardwerte festgelegt sind.)


Helfen Sie der IDE, Ihnen zu helfen

Wie bereits erwähnt, kann Ihnen die IDE keine Tipps geben, welche Parameter eine Funktion erwartet, wenn diese Funktion ein Konfigurationsobjekt verwendet. Dies ist ein großer Nachteil, da der Code sehr schwer zu verwenden ist. Sie müssen sich daran erinnern, welche Parameter in der conf Objekt sowie alle ihre Namen und Typen.

Diese Informationen können wir dem Codierer jedoch immer noch anzeigen, wenn sie benötigt werden. Wir müssen das nur manuell tun, so:

 / ** * Generiere einen Roboter basierend auf den angegebenen Parametern. * @param conf Konfigurationsobjekt. Erwartet: * arms (int) Anzahl der Roboter, die der Roboter haben sollte. * Persönlichkeit (String) Persönlichkeit des Roboters. Kann "böse" oder "gut" sein. Standardmäßig "böse". * Material (String) Woraus der Roboter bestehen soll. Kann zu dieser Zeit "Stahl" oder "Holz" sein. * laserColor (String) Farbe des Laserlasers. Standardeinstellung "rot". * voice (String) Gesangsstyling des Roboters. Derzeit nicht implementiert. * @return Der fertige Roboter. * / function generateRobot (conf: Object): Roboter //

Wenn ich jetzt anfange, einen Aufruf dieser Funktion in FlashDevelop (meiner bevorzugten IDE) zu schreiben, sehe ich Folgendes:

Sicher, es ist ein bisschen schmerzlich, dieses Handbuch manuell zu aktualisieren, aber in vielen Fällen lohnt es sich.


Fazit

Ich behaupte nicht, dass Sie ein Konfigurationsobjekt für verwenden sollten jede einzelne Funktion du erschaffst von jetzt an; Betrachten Sie es einfach als ein weiteres nützliches Werkzeug in Ihrem Arsenal.

Ich persönlich finde es besonders nützlich, wenn ich den ersten Entwurf einer Gruppe von Klassen baue, die alle zusammenarbeiten müssen. Die zusätzliche Flexibilität von a conf gibt mir so viel mehr Flexibilität, ich habe die Freiheit, mich um alle Funktionen zu kümmern und die Art und Weise zu ändern, wie sie sich gegenseitig anrufen, ohne mir Sorgen zu machen, dass der Code durch Einfügen oder Entfernen eines Parameters beschädigt wird.

Erinnern Sie sich an die Vorteile:

  • Das Hinzufügen und Entfernen von Parametern ist an jedem Ende einfach..
  • Es ist einfach, Standardwerte festzulegen.
  • Sie müssen sich nicht um die Reihenfolge der Parameter kümmern.

Die Verwendung einfacher Objekte wie ich hat jedoch Nachteile - vor allem, wenn Sie dies in einem Projekt tun, das die Prototypenphase überstanden hat. Überprüfen Sie die großartigen Kommentare unten für weitere Details!