Frage

Ich höre oft hier in der Nähe von Testentwicklung Menschen angetrieben, dass eine Funktion große Mengen an Informationen implizit erhalten, die eine schlechte Sache ist. Ich kann sehen, um dieses aus der Perspektive des Testens schlecht wäre, aber ist es nicht manchmal von einer Verkapselung Perspektive notwendig? Die folgende Frage in den Sinn kommt:

Nutzt Zufall und SortiertNach ein guter Shuffle-Algorithmus ?

Im Grunde jemand wollte eine Funktion in C # erstellen, um zufällig ein Array zu mischen. Mehrere Leute sagten ihm, dass der Zufallszahlengenerator als Parameter übergeben werden soll. Dies scheint wie eine ungeheuerliche Verletzung der Einkapselung zu mir, auch wenn es einfacher Prüfung macht. Ist das nicht die Tatsache, dass ein Array schlurfenden Algorithmus bei allen anderen beliebigen Zustand erfordert als das Array es eine Implementierung Detail ist schlurfend, dass der Anrufer sollte etwa müssen kümmern sich nicht? Wäre das nicht der richtige Ort, um diese Informationen zu erhalten implizit, möglicherweise von einem lokalen Thread-Singletons?

War es hilfreich?

Lösung

Ja, das nicht bricht Verkapselung . Wie bei den meisten Software-Design-Entscheidungen, das ist ein Kompromiss zwischen zwei entgegengesetzten Kräften. Wenn Sie die RNG kapseln dann machen Sie es schwierig, für eine Unit-Test zu ändern. Wenn Sie es ein Parameter machen dann machen Sie es einfach für einen Benutzer die RNG zu ändern (und möglicherweise etwas falsch gemacht).

Meine persönliche Präferenz ist es einfach zu testen, um dann eine Standardimplementierung zur Verfügung stellt (einen Standard-Konstruktor, der seine eigenen RNG erzeugt, in diesem speziellen Fall) und ein gute Dokumentation für den Endverbraucher. Hinzufügen einer Methode mit der Signatur

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)

das schafft eine Random die aktuelle Systemzeit als Saatgut kümmern würde die meisten normalen Anwendungsfälle dieser Methode. Die ursprüngliche Methode

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)

könnte zum Testen verwendet werden (mit der in einem Random Objekt mit einem bekannten Samen) und auch in den seltenen Fällen, in denen ein Benutzer sie brauchen eine kryptografisch sichere RNG entscheidet. Die Ein-Parameter-Implementierung sollte diese Methode aufrufen.

Andere Tipps

Ich glaube nicht, es bricht Kapselung. Der einzige Zustand, in dem Array ist, die Daten selbst - und „eine Quelle der Zufälligkeit“ ist im Wesentlichen ein Service. Warum sollte ein Array natürlich eine zugehörige Zufallsquelle haben? Warum sollte das eine Singleton sein? Was über die verschiedenen Situationen, die unterschiedliche Anforderungen haben - zum Beispiel Geschwindigkeit vs kryptografisch sicheren Zufall? Es gibt einen Grund, warum java.util.Random eine SecureRandom Unterklasse hat :) Vielleicht spielt es keine Rolle, ob die shuffle Ergebnisse vorhersehbar sind mit viel Aufwand und Beobachtung - oder vielleicht tut es. Das wird von dem Kontext abhängen, und das ist Information, dass der Shuffle-Algorithmus sollte etwa nicht.

Wenn Sie denken, es als Dienst starten, macht es Sinn, dass sie als Abhängigkeit übergeben wird.

Ja, Sie könnte es von einem lokalen Thread-Singleton bekommen (und in der Tat werde ich über genau das in den nächsten Tagen zum Blog), aber ich würde es in der Regel Code, so dass die < em> Anrufer bekommt, um diese Entscheidung zu treffen.

Ein Vorteil der „Zufälligkeit als Service“ -Konzept ist, dass es für die Wiederholbarkeit macht - wenn Sie einen Test haben, die ausfällt, können Sie in einem Random mit einem bestimmten Samen passieren und wissen, dass Sie immer das gleiche bekommen Ergebnisse, die einfacher macht das Debuggen.

Natürlich gibt es immer die Möglichkeit, die Random optional machen -. Verwenden, um einen lokalen Thread-Singletons als Standard, wenn der Anrufer nicht ihre eigenen bereitstellt

Ich glaube nicht, das gegen Kapselung.

Ihr Beispiel

Ich würde sagen, dass ein RNG zu schaffen in der Lage, ein Merkmal der Klasse ist. Ich würde offensichtlich ein Verfahren bereitzustellen, das es nicht erforderlich ist, aber ich kann mal sehen, wo es sinnvoll sein kann in der Lage sein, die Randomisierung zu duplizieren.

Was passiert, wenn das Array shuffler Teil eines Spiels war, das die RNG für Ebene genutzt wird. Wenn ein Benutzer das Niveau und spielen Sie es später noch einmal retten wollte, kann es effizienter sein, die RNG Samen zu speichern.

Allgemeiner Fall

Einfache Klassen, die eine einzige Aufgabe wie diese hat in der Regel müssen nicht über die Preisgabe ihre Innenleben kümmern. Was sie kapseln ist die Logik der Aufgabe, nicht die von dieser Logik erforderlichen Elemente.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top