Ich habe die TypeScript-Codierungsrichtlinien gelesen
Und ich fand diese Aussage ziemlich rätselhaft:
Verwenden Sie "I" nicht als Präfix für Schnittstellennamen
Ich meine, so etwas würde ohne das Präfix "I" nicht viel Sinn machen
class Engine implements IEngine
Vermisse ich etwas Offensichtliches?
Eine andere Sache, die ich nicht ganz verstand, war folgende:
Klassen
Verwenden Sie aus Gründen der Konsistenz keine Klassen in der Core-Compiler-Pipeline. Verwenden Sie stattdessen Funktionsabschlüsse.
Bedeutet das, dass ich überhaupt keine Klassen verwenden sollte?
Hoffe jemand kann es für mich klären :)
coding-style
typescript
Snæbjørn
quelle
quelle
I
Präfixes für Sie und Ihr Team sinnvoll ist, verwenden Sie es. Wenn nicht, vielleicht den Java-Stil vonSomeThing
(Schnittstelle) mitSomeThingImpl
(Implementierung), dann verwenden Sie das auf jeden Fall.I
eine Schnittstelle, weil es das ist, was ich gewohnt bin und es für die Leute in meinem Team sinnvoll ist.Antworten:
Wenn ein Team / Unternehmen ein Framework / Compiler / Tool-Set ausliefert, verfügt es bereits über einige Erfahrungen und Best Practices. Sie teilen es als Richtlinien. Richtlinien sind Empfehlungen . Wenn Sie keine mögen, können Sie sie ignorieren. Der Compiler kompiliert weiterhin Ihren Code. Aber wenn in Rom ...
Dies ist meine Vision, warum das TypeScript-Team empfiehlt,
I
Schnittstellen nicht zu fixieren.Grund Nr. 1 Die Zeiten der ungarischen Notation sind vorbei
Das Hauptargument von
I
Unterstützern von -prefix-for-interface ist, dass das Präfix hilfreich ist, um sofort zu prüfen, ob der Typ eine Schnittstelle ist. Die Aussage, dass das Präfix hilfreich ist, um sofort zu grokken (spähen), ist ein Appell an die ungarische Notation .I
Präfix für Schnittstellenname,C
Klasse,A
abstrakte Klasse,s
Zeichenfolgenvariable,c
Konstantenvariable,i
Ganzzahlvariable. Ich bin damit einverstanden, dass eine solche Namensdekoration Ihnen Typinformationen liefern kann, ohne mit der Maus über die Kennung zu fahren oder über einen Hotkey zur Typdefinition zu navigieren. Dieser winzige Vorteil wird durch die nachstehend genannten ungarischen Notationsnachteile und andere Gründe aufgewogen. Die ungarische Notation wird in zeitgenössischen Rahmenbedingungen nicht verwendet. C # hatI
Präfix (und dies ist das einzige Präfix in C #) für Schnittstellen aus historischen Gründen (COM). Rückblickend ist einer der .NET-Architekten (Brad Abrams) der Meinung, dass es besser gewesen wäre, keinI
Präfix zu verwenden . TypeScript ist COM-Legacy-frei, daher gibt es keineI
Präfix-für-Schnittstelle-Regel.Grund # 2-
I
Präfix verstößt gegen das KapselungsprinzipNehmen wir an, Sie bekommen eine Blackbox. Sie erhalten eine Typreferenz, mit der Sie mit diesem Feld interagieren können. Es sollte Ihnen egal sein, ob es sich um eine Schnittstelle oder eine Klasse handelt. Sie verwenden nur den Schnittstellenteil. Die Forderung zu wissen, was es ist (Schnittstelle, spezifische Implementierung oder abstrakte Klasse), ist eine Verletzung der Kapselung.
Beispiel: Nehmen wir an, Sie müssen API Design Mythos: Schnittstelle als Vertrag in Ihrem Code korrigieren, z. B.
ICar
Schnittstelle löschen undCar
stattdessen Basisklasse verwenden. Dann müssen Sie einen solchen Austausch bei allen Verbrauchern durchführen.I
-prefix führt zu einer impliziten Abhängigkeit der Verbraucher von Black-Box-Implementierungsdetails.Grund Nr. 3 Schutz vor schlechten Namen
Entwickler sind faul, über Namen richtig nachzudenken. Das Benennen ist eines der beiden schwierigen Dinge in der Informatik . Wenn ein Entwickler eine Schnittstelle extrahieren muss, ist es einfach, den Buchstaben
I
zum Klassennamen hinzuzufügen, und Sie erhalten einen Schnittstellennamen. Wenn Sie dasI
Präfix für Schnittstellen nicht zulassen , müssen Entwickler ihr Gehirn belasten, um geeignete Namen für Schnittstellen auszuwählen. Ausgewählte Namen sollten sich nicht nur im Präfix unterscheiden, sondern auch den Unterschied zwischen den Absichten betonen.Abstraction Fall: Sie sollten nicht keine definieren
ICar
Schnittstelle und eine zugehörigeCar
Klasse.Car
ist eine Abstraktion und sollte für den Vertrag verwendet werden. Implementierungen sollten beschreibende, eindeutige Namen haben, zSportsCar, SuvCar, HollowCar
.Gutes Beispiel:
WpfeServerAutosuggestManager implements AutosuggestManager
,FileBasedAutosuggestManager implements AutosuggestManager
.Schlechtes Beispiel :
AutosuggestManager implements IAutosuggestManager
.Grund Nr. 4 Richtig ausgewählte Namen impfen Sie gegen API Design Mythos: Schnittstelle als Vertrag .
In meiner Praxis habe ich viele Leute getroffen, die gedankenlos einen Schnittstellenteil einer Klasse in einer separaten Schnittstelle mit
Car implements ICar
Namensschema dupliziert haben . Das Duplizieren eines Schnittstellenteils einer Klasse in einem separaten Schnittstellentyp konvertiert sie nicht auf magische Weise in eine Abstraktion. Sie erhalten weiterhin eine konkrete Implementierung, jedoch mit einem doppelten Schnittstellenteil. Wenn Ihre Abstraktion nicht so gut ist, wird sie durch das Duplizieren des Schnittstellenteils ohnehin nicht verbessert. Abstraktion zu extrahieren ist harte Arbeit.HINWEIS: In TS benötigen Sie keine separate Schnittstelle zum Verspotten von Klassen oder zum Überladen von Funktionen. Anstatt eine separate Schnittstelle zu erstellen, die öffentliche Mitglieder einer Klasse beschreibt, können Sie TypeScript-Dienstprogrammtypen verwenden .
Required<T>
Konstruiert zB einen Typ, der aus allen öffentlichen Mitgliedern des Typs bestehtT
.export class SecurityPrincipalStub implements Required<SecurityPrincipal> { public isFeatureEnabled(entitlement: Entitlement): boolean { return true; } public isWidgetEnabled(kind: string): boolean { return true; } public areAdminToolsEnabled(): boolean { return true; } }
Wenn Sie einen Typ ohne einige öffentliche Mitglieder erstellen möchten, können Sie die Kombination aus Auslassen und Ausschließen verwenden .
quelle
I
Präfix ist hilfreich, um sofort zu prüfen, ob der Typ eine Implementierung hat oder nicht. Der Hauptvorteil bei der Verwendung von Schnittstellen besteht darin, dass die Implementierungsdetails von externem Code nicht an eine bestimmte Implementierung gekoppelt werden.I
undImpl
ist schwierig ("Es gibt nur zwei schwierige Dinge in der Informatik: Cache-Ungültigmachung und Benennung von Dingen" - Phil Karlton), aber es ist machbar.Klarstellung bezüglich des Links, auf den Sie verweisen:
Wenn die Verwendung des
I
Präfixes für Sie und Ihr Team sinnvoll ist, verwenden Sie es (das tue ich).Wenn nicht, vielleicht den Java-Stil von
SomeThing
(Schnittstelle) mitSomeThingImpl
(Implementierung), dann verwenden Sie das auf jeden Fall.quelle
In general, do not prefix interfaces with I (e.g. IColor). Because the concept of an interface in TypeScript is much more broad than in C# or Java, the IFoo naming convention is not broadly useful.
Es ist nicht streng, sieht aber nach einer starken Empfehlung aus.I
. In einem React-ProjektCard
heißt das eine Schnittstelle und eine KomponenteCard
. In den Requisiten brauche ich ein Array vonCard
, aber der Typ nicht die Komponente. Ich muss wählen, um zu benennenICard
oderCardComponent
...SomeThingImpl implements SomeThing
ist so gut wieSomeThing implements ISomeThing
. WennSomeThing
es sich um eine Abstraktion handelt, sollte die Benennung erfolgenConcrete[Some]Thing implements SomeThing
.Der Typ, der eine Schnittstelle ist, ist ein Implementierungsdetail. Implementierungsdetails sollten in der API ausgeblendet werden: s. Deshalb sollten Sie vermeiden
I
.Sie sollten beide
prefix
und vermeidensuffix
. Beides ist falsch:ICar
CarInterface
Was Sie tun sollten, ist, einen hübschen Namen in der API sichtbar zu machen und das Implementierungsdetail in der Implementierung auszublenden. Deshalb schlage ich vor:
Car
- Eine Schnittstelle, die in der API verfügbar gemacht wird.CarImpl
- Eine Implementierung dieser API, die dem Verbraucher verborgen bleibt.quelle
Impl
Suffixes hat den Nebeneffekt, dass Sie den Besserwisser ersetzen, der Sie für dasI
Präfix mit Onkel Bob beschimpft .