Was ist der beste Ansatz, um Klassen zu benennen?

92

Es ist bekanntermaßen schwierig, gute und genaue Namen für Klassen zu finden. Richtig gemacht, macht es den Code selbstdokumentierender und bietet ein Vokabular, um über Code auf einer höheren Abstraktionsebene nachzudenken.

Klassen, die ein bestimmtes Entwurfsmuster implementieren, können einen Namen erhalten, der auf dem bekannten Musternamen basiert (z. B. FooFactory, FooFacade), und Klassen, die Domänenkonzepte direkt modellieren, können ihre Namen aus der Problemdomäne übernehmen, aber was ist mit anderen Klassen? Gibt es so etwas wie einen Thesaurus eines Programmierers, an den ich mich wenden kann, wenn mir die Inspiration fehlt und ich generische Klassennamen (wie FooHandler, FooProcessor, FooUtils und FooManager) vermeiden möchte?

Henry
quelle
6
Das ist eine ausgezeichnete Frage! Das Schließen ist meiner Meinung nach ungerechtfertigt, besser wäre es, die Website des Programmierers zu migrieren.
Timofey
1
Ich bin damit einverstanden, sollte wieder geöffnet oder verschoben werden
ftl
Ich habe viele dieser hervorragenden Fragen gesehen, die "von casperOne geschlossen" wurden. Vielleicht könnte er als Deletionist bei Wikipedia arbeiten?
Perlator

Antworten:

58

Ich zitiere einige Passagen aus Implementation Patterns von Kent Beck:

Einfacher Name der Oberklasse

"[...] Die Namen sollten kurz und druckvoll sein. Um die Namen präzise zu machen, sind jedoch manchmal mehrere Wörter erforderlich. Ein Ausweg aus diesem Dilemma besteht darin, eine starke Metapher für die Berechnung auszuwählen. Selbst mit Blick auf eine Metapher Einzelne Wörter bringen ein reiches Netz von Assoziationen, Verbindungen und Implikationen mit sich. Im HotDraw-Zeichnungsframework war mein Vorname für ein Objekt in einer Zeichnung beispielsweise DrawingObject . Ward Cunningham kam mit der Typografie-Metapher: Eine Zeichnung ist wie Eine gedruckte, übersichtliche Seite. Grafische Elemente auf einer Seite sind Figuren, daher wurde die Klasse zu Figur . Im Kontext der Metapher ist Figur gleichzeitig kürzer, reicher und präziser als DrawingObject . "

Qualifizierter Name der Unterklasse

"Die Namen von Unterklassen haben zwei Aufgaben. Sie müssen mitteilen, wie sie aussehen und wie sie sich unterscheiden. [...] Im Gegensatz zu den Namen an den Wurzeln von Hierarchien werden Unterklassennamen in Konversationen nicht annähernd so häufig verwendet. so können sie auf Kosten der Prägnanz ausdrucksstark sein. [...]

Geben Sie Unterklassen, die als Wurzeln von Hierarchien dienen, ihre eigenen einfachen Namen. Zum Beispiel HotDraw hat eine Klasse Handle , die Geschenke figuren- Bearbeitungsoperationen , wenn eine Figur ausgewählt wird. Es wird einfach Handle genannt, obwohl die Figur erweitert wurde . Es gibt eine ganze Familie von Griffen, die am besten Namen wie StretchyHandle und TransparencyHandle haben . Da Handle die Wurzel seiner eigenen Hierarchie ist, verdient es einen einfachen Oberklassennamen mehr als einen qualifizierten Unterklassennamen.

Eine weitere Falte bei der Benennung von Unterklassen sind mehrstufige Hierarchien. [...] Anstatt die Modifikatoren blind der unmittelbaren Oberklasse voranzustellen, sollten Sie den Namen aus der Sicht des Lesers betrachten. Welche Klasse braucht er, um zu wissen, wie diese Klasse ist? Verwenden Sie diese Oberklasse als Grundlage für den Namen der Unterklasse. "

Schnittstelle

Zwei Arten der Benennung von Schnittstellen hängen davon ab, wie Sie die Schnittstellen betrachten. Schnittstellen als Klassen ohne Implementierungen sollten so benannt werden, als wären sie Klassen ( einfacher Oberklassenname , qualifizierter Unterklassenname ). Ein Problem bei dieser Art der Benennung besteht darin, dass die guten Namen aufgebraucht sind, bevor Sie mit der Benennung von Klassen beginnen. Eine Schnittstelle namens File benötigt eine Implementierungsklasse namens ActualFile , ConcreteFile oder (yuck!) FileImpl(sowohl ein Suffix als auch eine Abkürzung). Im Allgemeinen ist es weniger wichtig zu kommunizieren, ob es sich um ein konkretes oder abstraktes Objekt handelt, ob das abstrakte Objekt als Schnittstelle oder als Oberklasse implementiert ist. Das Aufschieben der Unterscheidung zwischen Schnittstellen und Oberklassen wird durch diese Art der Benennung gut unterstützt, sodass Sie später Ihre Meinung ändern können, wenn dies erforderlich wird.

Manchmal ist es für die Kommunikation wichtiger, konkrete Klassen zu benennen, als die Verwendung von Schnittstellen zu verbergen. Stellen Sie in diesem Fall den Schnittstellennamen "I" voran. Wenn die Schnittstelle IFile heißt , kann die Klasse einfach File genannt werden .

Kaufen Sie das Buch für eine ausführlichere Diskussion! Das ist es wert! :) :)

Marcio Aguiar
quelle
1
"Manchmal ist es für die Kommunikation wichtiger, konkrete Klassen zu benennen, als die Verwendung von Schnittstellen zu verbergen. In diesem Fall wird den Schnittstellennamen" I "vorangestellt. Wenn die Schnittstelle IFile heißt, kann die Klasse einfach File genannt werden." Es ist so lustig, weil ich in dem Buch Clean Code von Robert C. Martin herausgefunden habe, dass wir Implementierungen lieber als FileImpl benennen würden, als die Schnittstelle wie IFile zu benennen, weil wir nicht möchten, dass der Client weiß, dass wir sie bedienen Schnittstelle. Und in dem Buch ^ gibt es Zitate aus dem Buch, auf das Sie sich beziehen :)
Cristian Ciobotea
38

Entscheide dich immer für MyClassA, MyClassB - Es ermöglicht eine schöne Alpha-Sortierung.

Ich scherze nur!

Dies ist eine gute Frage und etwas, das ich vor nicht allzu langer Zeit erlebt habe. Ich habe meine Codebasis bei der Arbeit neu organisiert und hatte Probleme, wo ich was ablegen und wie ich es nennen soll.

Das eigentliche Problem?

Ich hatte zu viel Unterricht. Wenn Sie versuchen, sich an das Prinzip der Einzelverantwortung zu halten, wird alles viel besser zusammenpassen. Statt einer monolithischen PrintHandler- Klasse können Sie es in PageHandler , PageFormatter (usw.) aufteilen und dann eine Master- Druckerklasse haben , die bringt alles zusammen.

In meiner Neuorganisation habe ich einige Zeit gebraucht, aber am Ende habe ich viel doppelten Code gebündelt, meine Codebasis viel logischer gemacht und verdammt viel gelernt, bevor ich eine zusätzliche Methode in eine Klasse geworfen habe: D.

Ich würde jedoch nicht empfehlen, Dinge wie Musternamen in den Klassennamen einzufügen. Die Klassenschnittstelle sollte dies deutlich machen (wie das Ausblenden des Konstruktors für einen Singleton). An dem generischen Namen ist nichts auszusetzen, wenn die Klasse einem generischen Zweck dient.

Viel Glück!

Rob Cooper
quelle
Stimmen Sie zu, keine Musternamen in den Klassennamen einzufügen. Was ist, wenn sich das Muster später ändert, wenn sich die Implementierung ändert?
Thegreendroid
2
Ich würde lieber einen Musternamen in einen Namen einfügen. Warum? Denn wenn ich mir die Implementierungsdetails (wie den privaten Konstruktor) ansehen muss, um herauszufinden, dass es sich um einen Singleton handelt, verlangsamt mich das als Leser und je nach meinem Kenntnisstand kann ich möglicherweise nicht herausfinden, dass es sich tatsächlich um einen Klassenteil handelt des allgemeinen Musters. Singleton und privater Konstruktor sind ein fragwürdiges Beispiel, aber für kompliziertere Muster (Besucher, Adapter usw.) wird es ziemlich kompliziert. Wenn sich das Muster ändert, besteht die Möglichkeit, dass diese Klassen nicht mehr existieren ...
dragan.stepanovic
28

Josh Blochs ausgezeichnetes Gespräch über gutes API-Design enthält einige gute Ratschläge:

  • Der Unterricht sollte eines tun und es gut machen.
  • Wenn eine Klasse schwer zu benennen oder zu erklären ist, folgt sie wahrscheinlich nicht den Ratschlägen im vorherigen Aufzählungspunkt.
  • Ein Klassenname sollte sofort mitteilen, was die Klasse ist.
  • Gute Namen treiben gute Designs an.

Wenn Ihr Problem darin besteht, exponierte interne Klassen zu benennen, sollten Sie sie möglicherweise zu einer größeren Klasse zusammenfassen.

Wenn Ihr Problem darin besteht, eine Klasse zu benennen, die viele verschiedene Aufgaben ausführt, sollten Sie in Betracht ziehen, sie in mehrere Klassen aufzuteilen.

Wenn das ein guter Rat für eine öffentliche API ist, kann es für keine andere Klasse schaden.

Josh Segall
quelle
1
Videolink auf youtube youtube.com/watch?v=aAb7hSCtvGw
Andrew Harry
12

Wenn Sie an einem Namen festhalten, ist es manchmal eine gute Strategie , ihm nur einen halbwegs vernünftigen Namen zu geben, um ihn später zu überarbeiten.

Keine Namenslähmung. Ja, Namen sind sehr wichtig, aber sie sind nicht wichtig genug, um viel Zeit damit zu verschwenden. Wenn Sie sich in 10 Minuten keinen guten Namen ausdenken können, fahren Sie fort.

Simon Johnson
quelle
9

Wenn mir ein guter Name nicht in den Sinn kommt, würde ich mich wahrscheinlich fragen, ob es ein tieferes Problem gibt - erfüllt die Klasse einen guten Zweck? Wenn ja, sollte die Benennung ziemlich einfach sein.

Luke Halliwell
quelle
3

Wenn Ihr "FooProcessor" wirklich Foos verarbeitet, zögern Sie nicht, ihm diesen Namen zu geben, nur weil Sie bereits einen BarProcessor, BazProcessor usw. haben. Im Zweifelsfall ist offensichtlich am besten. Die anderen Entwickler, die Ihren Code lesen müssen, verwenden möglicherweise nicht denselben Thesaurus wie Sie.

Eine genauere Darstellung würde diesem Beispiel jedoch nicht schaden. "Prozess" ist ein ziemlich weites Wort. Ist es zum Beispiel wirklich ein "FooUpdateProcessor" (der zu "FooUpdater" werden könnte)? Sie müssen nicht zu "kreativ" in Bezug auf die Benennung werden, aber wenn Sie den Code geschrieben haben, haben Sie wahrscheinlich eine ziemlich gute Vorstellung davon, was er tut und was nicht.

Denken Sie schließlich daran, dass der bloße Klassenname nicht alles ist, was Sie und die Leser Ihres Codes weiter machen müssen - normalerweise sind auch Namespaces im Spiel. Diese können den Lesern oft genug Kontext geben, um klar zu sehen, wofür Ihre Klasse wirklich ist, auch wenn ihr bloßer Name ziemlich allgemein ist.

McKenzieG1
quelle