1unitedpower: Private Klassen-Eigenschaften

Beitrag lesen

was ist denn am revealing pattern so schlecht, dass man es dafür nicht benutzen sollte?

Nichts ist daran schlecht, es ist vielleicht etwas verbose, aber das kriegt man mit Blockscope auch irgendwie gelöst. Man darf sich nur von dem Namen nicht in die Irre führen lassen, es ist ein Muster für Datenkapselung, nicht für Modularisierung. Modulsysteme, wie CommonJS oder ASM, lösen wesentlich komplexere Aufgaben. Sie ermöglichen es dem Entwickler zum Beispiel den Code über mehrere Dateien zu verteilen und die Ladereihenfolge automatisch herauszufinden zu lassen. Man kann damit Module von Drittanbietern (zum Beispiel aus dem npm-Repository oder von GitHub) installieren. Sie helfen sowohl bei der Verwaltung von Versionsabhängigkeiten als auch bei Platform-Unterschieden. Sie bieten sogar Werkzeuge an, um den Code zu optimieren, bspw. hinsichtlich Datenübertragungs-Volumen. Datenkapselung lösen diese Modulsysteme nur beiläufig. Und dennoch machen sie das Revealing-Module-Pattern nicht hinfällig, ich nutze es immer noch in überschaubaren, eingebetteten Szenarien. D.h. wenn ich empfinde, dass ein eigenständiges Modul die Sache unnötig aufblähen würde.

Ich nutze ja das Revealing Module Pattern, aber ich frage mich, inwiefern die besagte reverse Methode sinnvoll ist. Auf der einen Seite gehört sie insofern zur Klasse, als dass sie eine solche Klasse als Parameter (oder this-Kontext) erwartet, auf der anderen Seite ist es eine Helferfunktion und damit nicht als API-Methode gedacht.

Unsichtbare Helferfunktionen sind immer gut, um Code-Duplikation zu vermeiden, und gleichzeitig die öffentliche Schnittstelle schmal zu halten. Sie hat also definitiv ihre Existenzberechtigung. Wie genau die Datenkapselung am besten umzusetzen ist, ist dann von Anwendungsfall zu Anwendungsfall zu entscheiden. Da lässt sich keine Regel an einem abstrakten Beispiel ausmachen.

Symbol() würde, wie @1unitedpower angemerkt hat, die Helferfunktion als pseudo-private Methode in der API verfügbar machen, aber hätte einen engeren Kontext zur Klasse als wenn auf eine private Variable referenziert werden würde.

Die Symbol-Lösung macht vor allem Sinn, wenn du damit Daten verwalten möchtest, die sich pro Instanz unterscheiden können. Deine Helferfunktion "reverse" fällt nicht in diese Kategorie. Sie arbeitet zwar mit Objekt-Instanzen, aber sie bleibt dennoch immer gleich. Die Lösung habe ich vorgeschlagen, weil sie der Datenkapselung aus klassischen Programmiersprachen sehr nahe kommt und ich vermutete, dass du nach solch einem Muster suchst.

Eine weitere Alternative, um pro Instanz Daten zu verwalten, wäre übrigens eine Map:

const privates = new Map();
export class Person {
   constructor (age) {
      privates.set(this,{age});
   },
   get age () {
      return privates.get(this).age;
   }
}

Nichtsdestotrotz, wenn die Verfügbarkeit von Symbol() nicht sicher ist, wären wir doch wieder bei meinem Ausgangsposting.

Der native Browsersupport für EcmaScritp2015 ist heute schon ganz gut. Chrome 98%, FF 90%, Edge 90%. Bis man sie aber guten Gewissens produktiv einsetzen kann, dauert es noch eine ganze Weile, weil man meistens auch ältere Browserversionen unterstützen möchte. Dafür gibt es heute schon Compiler, die EcmaScript2015 Code lesen und in eine niedrigere Version übersetzen. Ich habe dafür früher Babel benutzt und bin jetzt auf TypeScript umgestiegen, weil mir das extrem starke Typsystem einfach zusagt. Mit TypeScript kannst du sogar bis herunter zu EcmaScript 3 kompilieren. Es gibt heute aus meiner Sicht keine guten Gründe mehr dafür noch länger zu warten und sich mit dem vergleichsweise schmalen Sprachkern von EcmaScript 5.1 abzumühen.