it-swarm.dev

Sollten Schnittstellennamen mit einem "I" -Präfix beginnen?

Ich habe " Clean Code " von Robert Martin gelesen, um hoffentlich ein besserer Programmierer zu werden. Obwohl bisher nichts davon wirklich bahnbrechend war, habe ich anders darüber nachgedacht, wie ich Anwendungen entwerfe und Code schreibe.

Es gibt einen Teil des Buches, dem ich nicht nur nicht zustimme, der für mich auch keinen Sinn ergibt, insbesondere in Bezug auf die Namenskonventionen für Schnittstellen. Hier ist der Text, der direkt aus dem Buch stammt. Ich habe den Aspekt, den ich verwirrend finde, kühn gemacht und möchte dies näher erläutern.

Ich ziehe es vor, Schnittstellen schmucklos zu lassen. Das vorhergehende Ich, das in den heutigen Legacy-Wads so häufig vorkommt, ist bestenfalls eine Ablenkung und im schlimmsten Fall zu viele Informationen. Ich möchte nicht, dass meine Benutzer wissen, dass ich ihnen eine Benutzeroberfläche übergebe .

Vielleicht liegt es daran, dass ich nur ein Student bin, oder vielleicht daran, dass ich noch nie professionell oder teambasiert programmiert habe, aber Ich möchte, dass der Benutzer weiß, dass es sich um eine Schnittstelle handelt. Es gibt einen großen Unterschied zwischen der Implementierung einer Schnittstelle und der Erweiterung einer Klasse.

Meine Frage lautet also: "Warum sollten wir die Tatsache verbergen, dass ein Teil des Codes eine Schnittstelle erwartet?"

Bearbeiten

Als Antwort auf eine Antwort:

Wenn Ihr Typ eine Schnittstelle ist oder eine Klasse Ihr Geschäft ist, nicht das Geschäft von jemandem, der Ihren Code verwendet. Sie sollten also keine Details Ihres Codes in diesem Drittanbieter-Code veröffentlichen.

Warum sollte ich nicht die Details "verlieren", ob ein bestimmter Typ eine Schnittstelle oder eine Klasse für Code von Drittanbietern ist? Ist es für Entwickler von Drittanbietern, die meinen Code verwenden, nicht wichtig zu wissen, ob sie eine Schnittstelle implementieren oder eine Klasse erweitern? Sind die Unterschiede einfach nicht so wichtig, wie ich sie mir vorstelle?

78

Wenn Sie aufhören, darüber nachzudenken, werden Sie feststellen, dass sich eine Schnittstelle semantisch nicht wesentlich von einer abstrakten Klasse unterscheidet:

  • Beide haben Methoden und/oder Eigenschaften (Verhalten);
  • Weder sollten nicht private Felder (Daten) haben;
  • Beides kann nicht direkt instanziiert werden;
  • Von einem abzuleiten bedeutet, alle abstrakten Methoden zu implementieren, es sei denn, der abgeleitete Typ ist ebenfalls abstrakt.

Tatsächlich sind die wichtigsten Unterscheidungen zwischen Klassen und Schnittstellen:

  • Schnittstellen können keine privaten Daten enthalten.
  • Schnittstellenmitglieder können keine Zugriffsmodifikatoren haben (alle Mitglieder sind "öffentlich").
  • Eine Klasse kann mehrere Schnittstellen implementieren (im Gegensatz dazu, dass sie im Allgemeinen nur von einer Basisklasse erben kann).

Da sich die einzigen besonders aussagekräftigen Unterscheidungen zwischen Klassen und Schnittstellen auf (a) private Daten und (b) Typhierarchie beziehen - von denen keiner für einen Anrufer den geringsten Unterschied macht - ist es im Allgemeinen nicht erforderlich zu wissen, ob ein Typ eine Schnittstelle ist oder eine Klasse. Sie brauchen auf keinen Fall die Anzeige visual.

jedoch Es gibt bestimmte Eckfälle, die beachtet werden müssen. Insbesondere wenn Sie Reflektion, Abfangen, dynamische Proxys/Mixins, Bytecode-Weberei, Codegenerierung oder alles verwenden, was direkt mit dem Typisierungssystem oder dem Code der Umgebung selbst zu tun hat, dann ist es sehr hilfreich und manchmal notwendig, um sofort zu wissen, ob es sich um eine Schnittstelle oder eine Klasse handelt. Sie möchten eindeutig nicht, dass Ihr Code auf mysteriöse Weise fehlschlägt, weil Sie versucht haben, eine Klasse anstelle einer Schnittstelle als Mixin hinzuzufügen.

Für typischen, gewöhnlichen Geschäftslogikcode von Vanilla müssen die Unterscheidungen zwischen abstrakten Klassen und Schnittstellen jedoch nicht angekündigt werden, da sie niemals ins Spiel kommen.

Abgesehen davon neige ich dazu, meinen C # -Schnittstellen ohnehin I voranzustellen, da dies die von Microsoft verwendete und befürwortete .NET-Konvention ist. Und wenn ich einem neuen Entwickler Codierungskonventionen erkläre, ist es weitaus weniger mühsam, nur die Regeln von Microsoft zu verwenden, als zu erklären, warum wir unsere eigenen "speziellen" Regeln haben.

70
Aaronaught

In vielerlei Hinsicht ist Konsistenz wichtiger als Konvention. Solange Sie in Ihren Namensschemata konsistent sind, wird es nicht schwierig sein, mit ihnen zu arbeiten. Präfix-Schnittstellen mit einem I, wenn Sie möchten, oder lassen Sie den Namen einfach schmucklos, es ist mir egal, solange Sie einen Stil auswählen und dabei bleiben!

14
Jim Nutt

Das Buch ist voller guter Sachen, aber ich würde trotzdem "I" zum Namen der Benutzeroberfläche hinzufügen.

Stellen Sie sich vor, Sie haben public interface ILog Mit einer Standardimplementierung public class Log.

Wenn Sie sich für public interface Log Entscheiden, müssen Sie plötzlich die Log-Klasse in public class LogDefault Oder etwas in diesen Zeilen ändern. Du bist von einem zusätzlichen Charakter auf sieben übergegangen - das ist sicherlich verschwenderisch.

Es gibt oft eine feine Linie zwischen Theorie und Praxis. Theoretisch ist das eine wirklich gute Idee, aber in der Praxis ist es nicht so gut.

13
CodeART

Nun, es geht nicht darum, die Schnittstelle zu implementieren oder eine Klasse zu erweitern. In diesen Fällen wissen Sie sowieso, was Sie tun.

Wenn jedoch Code von Drittanbietern (z. B. ein anderes Modul der Anwendung) Ihre Daten manipuliert, sollte es diesem Code egal sein, ob Sie eine Schnittstelle oder eine Klasse präsentieren.

Dies ist der springende Punkt der Abstraktion. Sie präsentieren diesem Code eines Drittanbieters ein Objekt eines bestimmten Typs. Dieser angegebene Typ verfügt über eine Elementfunktion, die Sie aufrufen können. Das ist genug.

Wenn Ihr Typ eine Schnittstelle ist oder eine Klasse Ihr Geschäft ist, nicht das Geschäft von jemandem, der Ihren Code verwendet. Sie sollten also keine Details Ihres Codes an diesen Code eines Drittanbieters weitergeben.

Schnittstellen und Klassen sind übrigens am Ende Referenztypen. Und darauf kommt es an. Das muss also Ihre Namenskonvention hervorheben.

8
deadalnix

Die meisten Antworten scheinen davon auszugehen, dass die Programmiersprache entweder Java oder C #) ist, wobei es ein Konzept (oder Schlüsselwort) für Schnittstellen/abstrakte Klassen gibt. In diesen Fällen ist dies in einer anständigen IDE sofort der Fall sichtbar, mit welcher Art von Klasse man sich befasst und schreibt public interface IMyClass ist unnötige Vervielfältigung. Es ist, als würdest du nicht schreiben public final FinalMyClass - Stellen Sie sich vor, Sie fügen jedes Schlüsselwort in den Klassennamen ein.

Meiner Meinung nach ist die Situation in C++ jedoch etwas anders, da man in die Header-Datei eintauchen und prüfen muss, ob die Klasse über virtuelle Methoden verfügt, um herauszufinden, ob es sich um eine abstrakte Klasse handelt. In diesem Fall sehe ich deutlich ein Argument für das Schreiben von class AbstractMyClass.

Meine Antwort wäre also: Es kommt auf die Programmiersprache an.

Aktualisiert 2016 : 2 Jahre C++ - Erfahrung später würde ich es jetzt wahrscheinlich als schlechte Praxis betrachten, Klassennamen Abstract voranzustellen, obwohl ich sagen würde, dass es wahrscheinlich Codebasen gibt, die so komplex sind dass es Sinn machen könnte.

6
Ela782

Folgen Sie den Redewendungen der Sprache, die Sie verwenden.

Jede Sprache hat ihre eigenen Redewendungen und Kodierungsrichtlinien. In C # ist es beispielsweise idiomatisch, Schnittstellen mit I voranzustellen. In Go ist dies nicht der Fall.

4
Pete

In meinem (Java-) Code habe ich diese Konvention in den APIs, die ich Anrufern zur Verfügung stelle:

  • Die Funktionalität wird über Schnittstellen und nie durch Klassen bereitgestellt.
  • Nicht funktionierende Teile sind Klassen.

Mit nicht funktionsfähig meine ich Dinge wie reine Datenstrukturen (wie Klassen, die als Brücken zur XML-Serialisierung oder zum ORM fungieren), Aufzählungen und Ausnahmen, die alle können nicht Schnittstellen sein (na ja, Sie können für die reinen Datenklassen, aber es ist viel Arbeit für sehr wenig Gewinn, da es nichts gibt, was diese Klassen tun außer Daten halten).

In Bezug auf Namenskonventionen tendieren Schnittstellen dazu, entweder Akteursnomen (z. B. FooBarWatcher) oder Adjektiven (z. B. FooBarWatchable) zuzuordnen, und sowohl reine Datenklassen als auch Aufzählungen werden nicht aktiven Nomen zugeordnet (z. zB FooBarStatus); Die IDE kann den API-Konsumenten ohne spezielle Namenskonventionen führen. Ausnahmen folgen den üblichen Java Konventionen (FooBarException, FooBarError, FooBarFault) natürlich.

Ich werde die Schnittstellen auch oft in ein eigenes Paket oder sogar in eine eigene Bibliothek stellen, um sicherzustellen, dass ich nicht versucht bin, meine eigenen Regeln zu brechen. (Dies hilft mir auch bei der Verwaltung des Builds, wenn ich den Code aus externen Quellen wie WSDL-Dokumenten ableite.)

0
Donal Fellows