[Hinweis: Das Folgende ist in seiner Syntax und Konventionen etwas C # -lastig, z. B. das Zitieren von FxCop-Regeln, da dies mein Hintergrund ist. Die Absicht dieser Diskussion ist jedoch, sprachunabhängig zu sein, und die verwendeten Codebeispiele sollten allgemein als solche angesehen werden Pseudocode. - Mike]
Ich denke, wir sind uns alle einig, dass Klassen im Allgemeinen so gestaltet werden sollten, dass ihre Objektinstanzen unveränderlich sind, wo immer dies praktikabel ist, und dass die Ergebnisse des Aufrufs von Klassenmitgliedern so weit wie möglich frei von Nebenwirkungen sein sollten.
Historische Namenskonventionen verwenden jedoch in der Regel die aktive Stimme: "GetSomething", "DoSomehing" usw. Dies ist gut, da darin klar angegeben ist, welche Maßnahmen das Klassenmitglied ergreifen wird.
Ich fange jetzt jedoch an zu denken, dass Mitglieder manchmal (oder möglicherweise oft) davon profitieren könnten, wenn sie in der Vergangenheitsform benannt werden, um zu kennzeichnen, dass ein Wert zurückgegeben wird, ohne das referenzierte Objekt zu beeinflussen.
Für eine Methode, die ein Array transponiert, wird es in aktuellen Namensstilen wahrscheinlich als "Array.Transpose" bezeichnet. Wenn dieses Mitglied jedoch ein neues Array zurückgibt , ohne das referenzierte Objekt zu transponieren, wird es meiner Meinung nach als "Array.Transposed" bezeichnet 'wäre genauer und macht es dem Programmierer klarer.
Wenn Sie mit einer 'Array.Transpose ()' - Methode arbeiten, wird möglicherweise versehentlich versucht, Code wie den folgenden zu verwenden:
Array myArray = new Array();
myArray.Transpose();
Wenn die 'Transpose'-Methode jedoch ein neues Array zurückgibt, ohne das referenzierte Objekt zu beeinflussen, führt dieser Code nichts aus - das heißt,' myArray 'wird stillschweigend nicht transponiert. (Ich nehme an, wenn 'Transponieren' eine Eigenschaft wäre, würde der Compiler feststellen, dass das oben Genannte nicht legal ist, aber die FxCop-Richtlinien besagen, dass ein Mitglied, das eine Konvertierung durchführt, eine Methode sein sollte.)
Wenn die Methode jedoch in der Vergangenheitsform als "Array.Transposed" bezeichnet würde, wäre für den Benutzer klarer, dass die folgende Syntax erforderlich ist:
Array myArray = new Array();
Array transposedArray = myArray.Transposed();
Andere Namen, von denen ich denke, dass sie in diese Kategorie passen, sind Mitglieder mit den Namen "Größe geändert" vs. "Größe ändern", "Verschoben" vs. "Verschiebung" usw. Die Gegenwart wird für Mitglieder verwendet, die das referenzierte Objekt betreffen, während die Vergangenheitsform wird für Mitglieder verwendet, die einen neuen Wert zurückgegeben haben, ohne das referenzierte Objekt zu beeinflussen.
Ein anderer Ansatz, der derzeit üblicher ist, besteht darin, jedem Namen "Get" oder "To" voranzustellen, aber ich denke, dass dies unnötiges Gewicht hinzufügt, während der Wechsel in die Vergangenheitsform die Bedeutung effektiv kommuniziert.
Ist dies für andere Programmierer hier sinnvoll, oder klingt diese Vergangenheitsform beim Lesen zu umständlich?
Bearbeiten:
Tolle Diskussionen unten, ich danke allen vielmals. Einige Punkte, die ich basierend auf Ihren Kommentaren und meinen eigenen überarbeiteten Überlegungen dazu zusammenfassen möchte, folgen unten.
Methode zur Verkettung "fließender" Syntaxen
Basierend auf den folgenden Diskussionen ist die Verwendung der Vergangenheitsform wahrscheinlich von Wert, wenn sie für eine veränderbare Klasse verwendet wird, um zu verdeutlichen, welche Mitglieder den internen Status des referenzierten Objekts beeinflussen oder nicht.
Für unveränderliche Klassen, die die Mehrheit der Fälle sein sollten (man würde hoffen), denke ich jedoch, dass die Verwendung der Vergangenheitsform die Syntax unnötig umständlich machen kann.
Bei "fließenden Syntaxen", wie sie beispielsweise durch Methodenverkettung erstellt werden, würde die Verwendung der Vergangenheitsform den Code weniger lesbar machen. Wenn Sie beispielsweise LINQ über C # verwenden, kann eine typische Methodenkette wie folgt aussehen:
dataSource.Sort().Take(10).Select(x => x.ToString);
Wenn in die Vergangenheitsform geändert würde, würde dies unangenehm werden:
dataSource.Sorted().Taken(10).Selected(x => x.ToString);
Allerdings hat dataSource.Sorted () eine klarere Bedeutung als dataSource.Sort (), da LINQ-Ausdrücke immer eine neue Aufzählung erstellen, ohne die Quelle zu beeinflussen. Da wir uns dessen jedoch bei der Verwendung dieses Paradigmas voll bewusst sind, ist die Verwendung der Vergangenheitsform überflüssig und macht die "Fließfähigkeit" des Lesens umständlich, ohne dass ein wirklicher Gewinn erzielt wird.
Verwendung von Eigenschaften vs. Methoden
Ein zentrales Thema, das im Folgenden angesprochen wurde, betrifft die FxCop-Richtlinien für die Verwendung von "Get" -Methoden im Vergleich zu schreibgeschützten Eigenschaften. Beispiel: FxCop-Regel CA1024 .
Obwohl in dieser FxCop-Regel nicht explizit erwähnt, scheint die Verwendung von "To" -Methoden auch für diese Begründung zu gelten, da ToXXXXXX () -Methoden Konvertierungsmethoden sind. Im Fall von ToArray () ist die Methode sowohl eine Konvertierungsmethode als auch eine Methode, die ein Array zurückgibt.
Verwendung der Vergangenheitsform für boolesche Eigenschaften
Einige schlugen vor, dass die Vergangenheitsform einen booleschen Wert bedeuten kann, z. B. eine Eigenschaft 'Erfolgreich' oder 'Verbunden'. Ich glaube, dass die folgenden Retorten, in denen die Verwendung von 'Is', 'Has' oder 'Are' für boolesche Eigenschaften und Felder hervorgehoben wird, korrekt sind. Vergangenheitsform kann auch in dieser Hinsicht hilfreich sein, aber bei weitem nicht so viel wie die Verwendung eines 'Is'-Präfixes. Fühlen Sie sich frei, die Vergangenheitsform für boolesche Eigenschaften und Felder zu verwenden, es hilft, aber ich denke, dass es noch wichtiger ist, dem Namen 'Is', 'Has' oder 'Are' voranzustellen.
Allgemeine Schlussfolgerungen?
Für das Problem von Tranpose () vs. Transposed () denke ich, dass 'skizzy' es richtig gemacht hat, was darauf hindeutet, dass es Transpose () für eine mutierende Aktion vs. GetTransposed () für ein nicht mutierendes Ergebnis sein sollte. Dies macht es 100% klar. Aber ich denke auch hier, dass dies möglicherweise nur für eine veränderbare Klasse wie ein Array gilt.
Für unveränderliche Klassen, insbesondere wenn eine fließende Syntax zur Verkettung von Methoden verwendet werden könnte, würde diese Syntax meiner Meinung nach unnötig umständlich werden. Vergleichen Sie zum Beispiel:
var v = myObject.Transpose().Resize(3,5).Shift(2);
zu:
var v = myObject.GetTransposed().GetResized(3,5).GetShifted(2);
Hmmm ... eigentlich scheint es auch hier 100% klar zu sein, dass das Ergebnis die Quelle nicht beeinflusst, aber ich bin mir nicht sicher.
Ich denke, für ein Paradigma wie LINQ, bei dem es bekannt ist, ist die Verwendung von "Get" und / oder der Vergangenheitsform nicht erforderlich, aber für eine neue API könnte es einen gewissen Wert haben - zunächst! Wenn die API nur unveränderliche Objekte enthält, verringert die Verwendung von "Get" und / oder der Vergangenheitsform nur die Lesbarkeit, sobald der Benutzer dies versteht.
Ich denke, hier gibt es keine einfachen Antworten. Ich denke, man muss über die Gesamtheit Ihrer API nachdenken und sorgfältig auswählen!
-- Mike