Ich arbeite derzeit an einer Set-Implementierung in JavaScript. Dies sollte Generika simulieren, wie sie aus Java oder C # bekannt sind. Ich benötige eine veränderbare Version davon (ermöglicht das Hinzufügen / Entfernen von festgelegten Werten) und eine unveränderliche.
Meine Konstruktorsignatur sieht folgendermaßen aus:
new GenericSet( 'number', [ 10, 20, 30 ] );
,
// mutable set of mixed values (allows to add further values via "add")
new MutableGenericSet( '*', [ 'foo', 42, {}, /./ ] );
oder
// DataValues.prototype.equals will be used by the set for determining equality.
new GenericSet( { type: DataValue, valueComparison: 'equals' }, [ dv1, dv2, dv3 ] );
Nur GenericSet oder eine Set-Implementierung pro Typ?
Anfangs bestand mein Hauptzweck darin, Wertesätze eines Typs zu haben. ZB ein DataValuesSet, das nur Datenwerte akzeptiert. Ich könnte dann Schnittstellen mit Funktionen definieren, die eine DataValuesSet- Instanz erfordern . Ich konnte keine Vererbung verwenden (und denke, das wäre sowieso schlecht), also würde ich Komposition verwenden und intern eine GenericSet / MutableGenericSet- Instanz haben.
Ein alternativer Ansatz wäre, immer GenericSet zu nehmen und zu implementieren und zu verwenden, GenericSet.requireSetOfType( type )
was einen Fehler auslösen würde, wenn der Typ des Sets nicht der erforderliche wäre. Mein Anliegen dabei ist, dass meine Schnittstellendefinitionen weniger explizit aussehen.
Nehmen
/**
* @param DataValuesSet dataValues
*/
function printDataValues( dataValues ) {
if( !( dataValues instanceof DataValuesSet ) ) {
throw Error( '...' );
}
// ...
}
vs.
/**
* @param GenericSet<DataValue>
*/
function printDataValues( dataValues ) {
// Throws error if dataValues is not a set or it it is a set with values of wrong type.
GenericSet.requireSetOfType( dataValues, DataValue );
// ...
}
Vielleicht @param GenericSet(DataValues) dataValues
wäre es in Ordnung, die zweite Wahl zu dokumentieren. Hat jemand weitere Auswirkungen auf den zweiten Ansatz oder gibt es alternative Vorschläge? Für mich sieht der zweite intuitiver aus und mein Anliegen beim ersten ist, dass ich mit Konstruktoren nur mehr Overhead schaffen würde, während ich momentan keinen klaren Vorteil sehe.
quelle
Antworten:
Ich habe versucht, diese Art von Problemen mit JavaScript zu lösen, was nur dazu diente, die Implementierung von ... Nun ... irgendetwas zu erschweren. Wenn Sie so etwas wie Typescript nicht verwenden möchten, dokumentieren Sie, was Sie erwarten. Wenn Leute Ihre Dokumentation ignorieren, betreten sie Neuland.
Versuchen Sie nicht, einen runden Stift in ein quadratisches Loch zu zwingen, das jeder in ein rundes Loch formen kann. Das ist JavaScript. Umarme es. Kämpfe nicht dagegen an, Baby. Dokumentieren Sie es und schreiben Sie einfach wieder Code.
quelle
Ich würde sagen, dass das erste Beispiel besser lesbar ist. Dies bedeutet nicht, dass für den falsch eingegebenen Satz ein Fehler ausgegeben wird. Es heißt, dass diese Funktion a benötigt
DataValueSet
. Die explizite Darstellung in Ihrem Code erhöht die Klarheit.GenericSet.requireSetOfType
verschleiert die Absicht der Typprüfung in der Druckfunktion. Es sieht so aus, als würde nach Artikeln mit Typ gesuchtDataValue
.quelle
DataValuesSet
gegenGenericSet<DataValue>
. Vielleicht wäre es in der Tat klarer, anstattGenericSet.requireSetOfType
die FunktionGenericSet.assertSetOfType
oder ähnliches zu benennen .Angesichts der von Ihnen vorgestellten Optionen würde ich die erste Lösung vorziehen, da sie besser lesbar ist als die zweite. Wenn Sie jedoch wirklich eine Lösung im JS-Stil erstellen möchten, erstellen Sie eine Builder-Funktion, unabhängig davon, ob die Objekte vom selben Typ sind oder vom gemischten Typ (
MakeStrictCollection
vsMakeMixedCollection
) sein sollten. In der Builder - Funktion, können Sie testen, ob die Art der jedes Mitglied Ihrer gegebenen Sammlung vom gleichen Typ ist oder nicht , und werfen einen Fehler oder ein Objekt von jedem Konstruktor zurückgeben, was einen zusätzlichen Typ Attribut"type":"strict"
vs"type":"mixed"
.Außerdem:
Sie sollten sich Typescript ansehen , das möglicherweise das ist, wonach Sie suchen. Und es gibt ein Paket, das Ihren Anforderungen mit generischen Sammlungen zu entsprechen scheint .
quelle
MakeStrictCollection
vsMakeMixedCollection
. In Bezug auf die obigen CodebeispieleprintDataValues
würde sich die Funktion ändern, um zu überprüfen, ob das angegebene Objektinstanceof StrictCollection
und sein Typ warenDataValues
.GenericSet.requireSetOfType
könnte genau das sein - daher scheint Ihr Vorschlag lediglich ein Implementierungsdetail für denGenericSet
Ansatz zu sein.