Die PDF-Version von PPT-Download-Adresse: http://www.slideshare.net/jibyjohnc/jqquerySummit-largescale-javaScript-anapplication-architecture
Hinweis: Während des Zusammenstellungsprozesses stellte ich fest, dass die Gedanken des Autors wiederholt wurden, und löschte einige von ihnen. Wenn Ihr Englisch gut ist, lesen Sie bitte das englische PPT direkt.
Das Folgende sind die Hauptkapitel dieses Artikels:
1. Was ist "JavaScript Large Program"?
2. Betrachten Sie die aktuelle Programmarchitektur
3.. Langfristige Überlegung
4. Brainstorming
5. Vorgeschlagene Architektur
5.1 Designmuster
5.1.1 Modultheorie
5.1.1.1 Übersicht
5.1.1.2 Modulmodus
5.1.1.3 Objekt Selbstgesichtsgröße
5.1.1.4 CommonJS -Modul
5.1.2 Fassadenmodus
5.1.3 Mediatormodus
5.2 Bewerben Sie sich bei Ihrer Architektur
5.2.1 Fassade - Kernabstraktion
5.2.2 Mediator - Programmkern
5.2.3 eng arbeiten
6. Pub/Sub -Erweiterung veröffentlichen: Automatische Registrierungsereignisse
7. Q & A
8. Anerkennung
Was ist "JavaScript Large Program"?
Lassen Sie uns vor Beginn definieren, was eine große JavaScript -Site ist. Viele erfahrene JS -Entwicklungsexperten wurden ebenfalls in Frage gestellt. Einige Leute sagen, dass mehr als 100.000 Zeilen JavaScript -Code als groß angesehen werden, und einige Leute sagen, dass JavaScript -Code mehr als 1 MB groß sein muss. Tatsächlich ist keiner von ihnen korrekt, da die Codemenge nicht als Anzahl der installierten Codes gemessen werden kann. Viele triviale JS -Code können leicht 100.000 Zeilen überschreiten.
Meine Definition von "groß" ist wie folgt. Obwohl es möglicherweise nicht korrekt ist, sollte es relativ nahe sein:
Ich persönlich denke, dass große JavaScript -Programme sehr wichtig sein sollten und viele herausragende Entwicklerbemühungen zur Verarbeitung von Daten im Schwergewicht und der Anzeige des Browsers einbeziehen sollten.
Überprüfen Sie die aktuelle Programmarchitektur
Ich kann nicht betonen, wie wichtig dieses Problem ist. Viele erfahrene Entwickler sagen oft: "Die vorhandenen kreativen und Designmuster sind bei meinem vorherigen mittelgroßen Projekt sehr gut. Daher sollte es in Ordnung sein, sie in einem etwas größeren Programm erneut zu verwenden, oder?" Ich erkläre kurz, wie es Zeit braucht, die seit lange laufende Programmarchitektur zu überprüfen. In den meisten Fällen sollte die aktuelle JavaScript -Programmarchitektur so aussehen (beachten Sie, dass es sich um eine JS -Architektur handelt, nicht das, was jeder oft ASP.NET MVC bezeichnet):
Benutzerdefinierte Widgets
Modelle
Ansichten
Controller
Vorlagen
Bibliotheken/Toolkits
ein Anwendungskern.
Sie können das Programm auch in mehrere Module einschließen oder andere Designmuster verwenden, was großartig ist. Wenn diese Strukturen jedoch Ihre Architektur vollständig darstellen, kann es einige potenzielle Probleme geben. Schauen wir uns einige wichtige Punkte an:
1. Wie viele Dinge in Ihrer Architektur können sofort herausgenommen und wiederverwendet werden?
Gibt es einige separate Module, die nicht von einem anderen Code abhängen? Ist es in sich geschlossen? Wenn ich zu der Codebasis gehe, die Sie verwenden, und dann einige Modulmodulcodes auswählen und auf eine neue Seite setzen, kann sie sofort verwendet werden? Sie können sagen, dass das Prinzip in Ordnung ist. Ich schlage vor, Sie planen lange. Wenn Ihr Unternehmen bereits viele wichtige Programme entwickelt hat und plötzlich eines Tages jemand sagte, dass das Chat -Modul in diesem Projekt gut ist, nehmen wir es heraus und setzen Sie es in ein anderes Projekt ein. Können Sie es einfach verwenden, ohne den Code zu ändern?
2. Wie viele Module müssen das System auf andere Module verlassen?
Sind alle Module des Systems eng gekoppelt? Bevor ich diese Frage als Sorge nehme, werde ich zuerst erklären. Es ist nicht so, dass alle Module keine Abhängigkeiten haben dürfen. Beispielsweise kann eine feinkörnige Funktion aus der Basisfunktion erweitert werden. Mein Problem unterscheidet sich von dieser Situation. Ich spreche von den Abhängigkeiten vor verschiedenen Funktionsmodulen. Theoretisch sollten alle verschiedenen Funktionsmodule nicht zu viele Abhängigkeiten haben.
3. Wenn mit einem Teil Ihres Programms etwas schief geht, funktionieren die anderen Teile noch?
Wenn Sie ein Programm ähnlich wie Google Mail erstellen, können Sie feststellen, dass viele Module in Google Mail dynamisch geladen werden, z. B. das Chat -Chat -Modul, das bei der Initialisierung der Seite nicht geladen wird, und selbst wenn ein Fehler nach dem Laden auftritt, können andere Teile der Seite normal verwendet werden.
4. Können Sie Ihre Module auf sehr einfache Weise testen?
Jedes Ihrer Module kann an großen Websites mit Millionen von Benutzern oder sogar mehreren Websites verwendet werden, sodass Ihre Module den Test bestehen müssen, dh, ob innerhalb oder außerhalb der Architektur, sollten sehr einfach getestet werden können, einschließlich der meisten Behauptungen, die in verschiedenen Umgebungen übergeben werden können.
Langfristige Überlegung
Bei der Strukturierung großer Programme ist das Wichtigste, vorausschauend zu sein. Sie können die Situation nicht nur einen Monat oder ein Jahr später berücksichtigen. Sie sollten die Möglichkeit von Änderungen in einem längeren Zeitraum in Betracht ziehen? Entwickler binden häufig den DOM -Operations -Code und -programm zu eng, obwohl sie manchmal separate Logik in verschiedene Module eingekapselt haben. Überlegen Sie, warum es auf lange Sicht nicht sehr gut ist.
Ein Kollege von mir sagte einmal, dass eine genaue Architektur möglicherweise nicht für zukünftige Szenarien geeignet ist, und manchmal ist sie richtig, aber wenn Sie es tun müssen, werden Sie viel Geld bezahlen. Zum Beispiel müssen Sie sich möglicherweise dafür entscheiden, Dojo, JQuery, Zepto und Yui für bestimmte Gründe für Leistung, Sicherheit und Design zu ersetzen. Zu diesem Zeitpunkt gibt es ein Problem. Die meisten Module haben Abhängigkeiten, die Geld, Zeit und Menschen erfordern, oder?
Für einige kleine Standorte ist es in Ordnung, aber große Standorte müssen einen flexibleren Mechanismus bieten, ohne sich über verschiedene Probleme zwischen verschiedenen Modulen zu sorgen. Dies spart Geld und Zeit.
Können Sie jetzt sicher sein, dass Sie einige Klassenbibliotheken ersetzen können, ohne das gesamte Programm neu zu schreiben? Wenn nicht, dann ist das, worüber wir unten sprechen werden, für Sie besser geeignet.
Viele erfahrene JavaScript -Entwickler haben einige wichtige Notizen gegeben:
Justin Meyer, Autor von JavaScriptMVC, sagte:
Das größte Geheimnis beim Aufbau großer Programme besteht darin, dass Sie nie große Programme erstellen, die Programme jedoch in kleine Module zerlegen, um jedes kleine Modul testbar, beträchtlich zu machen und sie dann in das Programm zu integrieren.
Hochleistungs-JavaScript-Websites Autor Nicholas, Zakas:
"Der Schlüssel ist, von Anfang an anzuerkennen, dass Sie keine Ahnung haben, wie dies wächst. Wenn Sie akzeptieren, dass Sie nicht alles wissen, beginnen Sie, das System defensiv zu entwerfen. - -
Viele Textprobleme sind zu problematisch. Zusammenfassend kann alles geändert werden, sodass es abstrakt sein muss.
JQuery Fundamentals Autor Rebecca Murphey:
Je näher die Verbindung zwischen jedem Modul ist, desto weniger wiederverwendbar ist es und desto größer ist die Schwierigkeit, sie zu ändern.
Die oben genannten wichtigen Ansichten sind die Kernelemente für den Aufbau der Architektur, und wir müssen sie uns ständig erinnern.
Brainstorming
Lassen Sie uns Brainstorming. Wir brauchen eine locker gekoppelte Architektur ohne Abhängigkeiten zwischen Modulen, jedes Modul- und Programmkommunikat, und dann übernimmt die Zwischenschicht die entsprechenden Nachrichten und verarbeitet sie.
Wenn wir beispielsweise ein JavaScript -Erbau eines Online -Bäckereiprogramms haben, sendet ein Modul eine Nachricht, die möglicherweise "42 Runden zugestellt werden müssen". Wir verwenden verschiedene Ebenenschichten, um Nachrichten zu verarbeiten, die vom Modul gesendet wurden, und machen Folgendes::
Module zugreifen nicht direkt auf den Programmkern zu
Module rufen nicht direkt an oder beeinflussen andere Module nicht
Dies verhindert, dass wir in allen Modulen aufgrund von Fehlern in einem bestimmten Modul Fehler machen.
Ein weiteres Problem ist die Sicherheit. Die reale Situation ist, dass die meisten Menschen nicht der Meinung sind, dass die interne Sicherheit ein Problem ist. Wir sagen in unseren Herzen, dass die Programme von mir selbst gebaut werden. Ich weiß, welche öffentlich und privat sind. Es gibt kein Problem mit der Sicherheit, aber haben Sie die Möglichkeit, auf welches Modul auf den Programmkern zugreifen können? Zum Beispiel gibt es ein Chat -Chat -Modul, mit dem ich nicht das Administratormodul aufruft, oder ich möchte nicht, dass es ein Modul mit DB -Schreibberechtigungen aufruft, da zwischen ihnen eine Zerbrechlichkeit besteht und es einfach ist, XSS -Angriffe zu verursachen. Jedes Modul sollte nicht in der Lage sein, alles zu tun, aber JavaScript -Code in den meisten Architekturen hat derzeit dieses Problem. Geben Sie eine Zwischenschicht zur Steuerung, auf welches Modul auf diesen autorisierten Teil zugreifen kann, dh das Modul kann nur das Beste aus dem von uns autorisierten Teil erreichen.
Vorgeschlagene Architektur
Der Fokus unseres Artikels liegt darin, dass diesmal die von uns vorgeschlagene Architektur Designmuster verwendet, die wir alle bekannt sind: Modul, Fassade und Mediator.
Im Gegensatz zu herkömmlichen Modellen lassen wir das Modul nur einige Ereignisereignisse veröffentlichen. Der Mediatormodus kann für das Abonnieren von Nachrichtennachrichten aus diesen Modulen verantwortlich sein und dann die Benachrichtigungsantwort kontrollieren. Der Fassadenmodus einschränken Benutzer die Berechtigungen jedes Moduls.
Im Folgenden sind die Teile aufgeführt, auf die wir achten müssen:
1 Designmuster
1.1 Modultheorie
1.1.1 Übersicht
1.1.2 Modulmodus
1.1.3 Objekt Selbstgesichtsgröße
1.1.4 CommonJS -Modul
1.2 Fassadenmodus
1.3 Mediatormodus
2 Bewerben Sie sich bei Ihrer Architektur
2.1 Fassade - Kernabstraktion
2.2 Mediator - Programmkern
2.3 eng zusammenarbeiten
Modale Theorie
Jeder hat möglicherweise mehr oder weniger einen modularen Code verwendet. Das Modul ist Teil einer vollständigen und robusten Programmarchitektur. Jedes Modul wird für einen separaten Zweck erstellt. Wenn wir zurück zu Google Mail gehen, nehen wir ein Beispiel. Das Chat -Chat -Modul scheint ein separater Teil zu sein, aber tatsächlich hat es viele separate Submodules. Beispielsweise ist das Ausdrucksmodul in darin tatsächlich ein separates Submodul, das auch im Fenster zum Senden von E -Mails verwendet wird.
Eine andere ist, dass Module geladen, gelöscht und dynamisch ersetzt werden können.
In JavaScript haben wir verschiedene Möglichkeiten, Module zu implementieren. Jeder kennt Modulmuster und Objektliterale. Wenn Sie diese bereits kennen, ignorieren Sie diesen Abschnitt und springen Sie direkt zum CommonJS -Teil.
Modulmodus
Das Modulmuster ist ein relativ beliebtes Designmuster. Es kann private Variablen, Methoden und Zustände durch Zahnspangen zusammenfassen. Durch das Wickeln dieser Inhalte können im Allgemeinen nicht direkt auf globale Objekte zugegriffen werden. In diesem Entwurfsmuster wird nur eine API zurückgegeben und alle anderen Inhalte werden als privat eingekapselt.
Darüber hinaus ähnelt dieses Muster den selbst ausgestellten Funktionsausdrücken. Der einzige Unterschied besteht darin, dass das Modul ein Objekt zurückgibt, während der selbst ausgeführte Funktionsausdruck eine Funktion zurückgibt.
Wie wir alle wissen, möchte JavaScript nicht, dass andere Sprachen Zugriffsmodifikatoren haben und keine privaten und öffentlichen Modifikatoren für jedes Feld oder jede Methode deklarieren können. Wie implementieren wir dieses Muster? Das heißt, ein Objekt zurückzugeben, einschließlich einiger öffentlicher Methoden, die in der Lage sind, interne Objekte aufzurufen.
Schauen Sie sich den Code unten an. Dieser Code ist ein selbstverständlicher Code. Die Erklärung enthält eine globale Objektbatterymodul. Das Korbarray ist privat, daher kann Ihr gesamtes Programm nicht auf dieses private Array zugreifen. Gleichzeitig geben wir ein Objekt zurück, das 3 Methoden enthält (z. B. AddItem, getItemCount, GetTotal). Diese 3 Methoden können auf das private Korbarray zugreifen.
var basketmodule = (function () {var basket = []; // privatereturn {// public addItem: function (values) {basket.push (Werte);}, getItemCount: function () {return basket.Length;}, GetTotal: function () {var q = this.getItemcrt (), p = 0; } return p;}}} ());Beachten Sie auch, dass das von uns zurückgegebene Objekt direkt dem Basketmodul zugeordnet ist, damit wir es wie die folgenden verwenden können:
// Basketmodule ist ein Objekt mit Eigenschaften, das auch MethodsBasketModule.additem ({item: 'bread', Preis: 0,5}) sein kann; baskModule.addItem ({item: 'Butter', Preis: 0,3}); console.log (Basketmodule.getItemCount ()); console.log (baskmodule.gettotal ()); // Folgendes funktioniert jedoch nicht: console.log (Basketmodule.Basket); // (undefiniert als nicht innerhalb der zurückgegebenen Objekt) console.log (Korb); // (existiert nur im Rahmen des Verschlusses)Wie geht es in verschiedenen beliebten Klassenbibliotheken (wie Dojo, JQuery)?
Dojo
Dojo versucht, dojo.declare zu verwenden, um Erklärungsmethoden im Klassenstil bereitzustellen. Wir können es verwenden, um das Modulmuster zu implementieren. Wenn Sie beispielsweise ein Korbobjekt im Store -Namespace deklarieren möchten, können Sie dies tun:
// traditioneller Wayvar Store = Fenster.Store || {}; store.basket = store.basket || {}; // Verwenden Sie dojo.setObjectdojo.setObject ("store.basket.object", (function () {var basket = []; Funktion privatemethod () {console.log (basket);} return {publicMethod: function () {privatemethod ();}};} ());Es ist sehr mächtig, wenn es mit dojo.provide kombiniert wird.
Yui
Der folgende Code ist die ursprüngliche Implementierung von Yui:
Yahoo.store.basket = function () {// "private" variablen: var myprivatevar = "Ich kann nur innerhalb von yahoo.store.Basket zugegriffen werden." // "private" Methode: var myprivatemethod = function () {yahoo.log ("Ich kann nur von innerhalb von Yahoo.store.Basket zugegriffen werden"); } return {MyPublicProperty: "Ich bin eine öffentliche Eigenschaft", mypublicMethod: function () {yahoo.log ("Ich bin eine öffentliche Methode."); // Innerhalb des Korbs kann ich auf "private" Vars und Methoden zugreifen: yahoo.log (MyPrivateVar); Yahoo.log (MyPrivatemethod ()); // Der native Bereich von MyPublicMethod ist ein Geschäft, sodass wir mit "This" zugreifen können, indem wir "This": yahoo.log (this.mypublicProperty); }};} ();JQuery
In JQuery gibt es viele Implementierungen des Modulmusters. Schauen wir uns ein anderes Beispiel an. Eine Bibliotheksfunktion deklariert eine neue Bibliothek. Beim Erstellen der Bibliothek wird die Init -Methode dann automatisch in document.ready ausgeführt.
Funktionsbibliothek (Modul) {$ (function () {if (module.init) {module.init ();}}); Rückgabemodul;} var mylibrary = bibliothek (function () {return {init: function () { /*Implementierung* /}};} ());Objekt Selbstgesichtsgröße
Die Self-Self-Messung des Objekts wird in Zahnspangen deklariert, und das neue Schlüsselwort ist bei der Verwendung nicht erforderlich. Wenn Sie sich in einem Modul nicht viel für öffentliche/private der Attributfelder interessieren, können Sie diese Methode verwenden. Bitte beachten Sie, dass sich diese Methode von JSON unterscheidet. Objekt Self-Face-Größe: var item = {name: "tom", Wert: 123} json: var item = {"name": "tom", "value": 123}.
var MyModule = {MyProperty: 'seltsame', // Objektliterale können Eigenschaften und Methoden enthalten. // Hier ist ein anderes Objekt für die Konfiguration definiert // Zwecke: myconfig: {usecaching: true, Sprache: 'en'}, // Eine sehr grundlegende Methode myMethod: function () {console.log ('I CAN -Funktionalität?'); }, // Ausgabe eines Werts basierend auf der aktuellen Konfiguration myMethod2: function () {console.log ('Caching ist:' + (this.myconfig.USecaching)? 'Enabled': 'Behindert'); }, // Überschreibe die aktuelle Konfiguration myMethod3: function (newConfig) {if (typeof newConfig == 'Objekt') {this.myconfig = newConfig; console.log (this.myconfig.language); }}}; MYMODULE.MYMETHOD (); // Ich kann HAC -FunktionalitätsmarkeModule.mymethod2 (); // Ausgibt enabledMymodule.mymethod3 ({Sprache: 'FR', usecaching: false}); // frCommonjs
Ich werde hier nicht über die Einführung von CommonJs sprechen. Viele Artikel haben es schon einmal vorgestellt. Wir möchten hier erwähnen, dass es zwei wichtige Parameterxporte gibt und im CommonJS -Standard erforderlich ist. Die Exporte stellen das zu ladende Modul dar und erfordern Mittel, dass diese geladenen Module auf andere Module verlassen müssen und auch geladen werden müssen.
/*Beispiel für die Erreichung der Kompatibilität mit AMD und Standard -CommonJs durch Einlegen von Kesselplatten um das Standard -CommonJS -Modulformat:*/(Funktion (Define) {Define (Funktion (erfordern, exportieren) {// Modulinhalt var dep1 = require ("dep1"); exports Define == "Funktion"? Define: function (factory) {factory (erfordern, exportieren)});Es gibt viele CommonJS -Standardmodul -Lade -Implementierungen. Was ich bevorzuge, ist erforderlich. Kann es sehr gut laden Module und verwandte Abhängigkeitsmodule? Nehmen wir ein einfaches Beispiel. Wenn Sie beispielsweise das Bild in den ASCII -Code umwandeln müssen, laden wir zuerst das Encoder -Modul und erhalten dann seine codetoascii -Methode. Theoretisch sollte der Code wie folgt sein:
var codetoascii = required ("codierer"). codetoascii; exporteS.encodesomesource = function () {// nach anderen Operationen, dann nennen Sie CCodetoascii}Der obige Code funktioniert jedoch nicht, da die codetoascii -Funktion nicht zum Anbringen an das Fensterobjekt verwendet wird, sodass sie nicht verwendet werden kann. Dies muss die Verbesserung des Codes tun:
Define (Funktion (Anforderung, Exportieren, Modul) {var codetoascii = Request ("Encoder"). codetoascii; exports.encodesource = function () {// prozess, dann rufen Sie dann codetoascii}});CommonJS hat ein großes Potenzial, aber da der Onkel damit nicht sehr vertraut ist, werde ich es nicht viel vorstellen.
Fassadenmodus
Das Fassadenmodell spielt eine wichtige Rolle in der Architektur dieses Modells. In diesem Modell spiegeln viele Bibliotheken oder Frameworks JavaScript -Klassen oder Frameworks wider. Die größte Funktion besteht darin, die API der hohen Ebene einzubeziehen, um bestimmte Implementierungen zu verbergen. Dies bedeutet, dass wir nur die Schnittstellen aufdecken und die Entscheidungen der internen Implementierungen selbst treffen können, was auch bedeutet, dass der interne Implementierungscode leicht geändert und aktualisiert werden kann. Zum Beispiel verwenden Sie heute JQuery, um es zu implementieren, und morgen möchten Sie Yui ändern, was sehr bequem ist.
Im folgenden Beispiel können wir feststellen, dass wir viele private Methoden bereitstellen und dann eine einfache API enthüllen, damit der Außenwelt interne Methoden ausführen und aufrufen kann:
var module = (function () {var _private = {i: 5, get: function () {console.log ('aktueller Wert:' + this.i);}, set: function (val) {this.i = val;}, run: function () {console.log ('running'; Funktion (args) {_private.set (args.val);Der Unterschied zwischen Fassade und dem, worüber wir unten sprechen, besteht darin, dass Fassade nur vorhandene Funktionen bietet, während Mediatoren neue Funktionen hinzufügen können.
Mediatormodus
Bevor wir über den Modiator sprechen, geben wir ein Beispiel. Das Flughafenflugsteuerungssystem, das der legendäre Turm ist, verfügt über absolute Leistung. Es kann den Start und die Landung und den Ort eines Flugzeugs steuern. Das Flugzeug und das Flugzeug dürfen vorher nicht kommunizieren, was bedeutet, dass der Turm der Kern des Flughafens ist und der Mediator diesem Turm entspricht.
Der Mediator wird verwendet, um mehrere Module in einem Programm zu haben, und Sie möchten nicht, dass jedes Modul Abhängigkeiten hat. Der Mediatormodus kann den Zweck der zentralisierten Kontrolle erreichen. In den tatsächlichen Szenarien fasst Mediator viele Module zusammen, die sie nicht wollen, sodass sie durch Mediatoren miteinander verbunden werden und sie auch locker gekoppelt werden, damit sie durch Mediatoren kommunizieren müssen.
Was sind die Vorteile des Mediatormodus? Das ist Entkopplung. Wenn Sie das Beobachtermuster zuvor ein gutes Verständnis haben, ist es relativ einfach, das folgende Mediatordiagramm zu verstehen. Die folgende Abbildung ist ein Mediator -Musterdiagramm mit hohem Niveau:
Denken Sie darüber nach, jedes Modul ist ein Verlag, und der Mediator ist sowohl ein Verlag als auch ein Abonnent.
Modul 1 überträgt eine tatsächliche Sache an Mediator und sagt, dass etwas getan werden muss
Nachdem der Mediator die Nachricht erfasst hat, starten Sie sofort das Modul 2, mit dem die Nachricht verarbeitet werden muss. Nach Abschluss der Modul 2 -Verarbeitung geben die Informationen an den Mediator zurück.
Gleichzeitig startet Mediator auch Modul 3 und protokolliert automatisch auf Modul 3, wenn Sie die Rückgabenachricht von Modul 2 erhalten.
Es ist ersichtlich, dass es keine Kommunikation zwischen den Modulen gibt. Darüber hinaus kann Mediator auch die Funktion der Überwachung des Status jedes Moduls implementieren. Wenn in Modul 3 beispielsweise ein Fehler vorliegt, kann der Mediator nur vorübergehend andere Module haben, dann Modul 3 neu starten und dann weiter ausführen.
Rückblickend können wir sehen, dass der Vorteil des Mediators darin besteht, dass das locker gekoppelte Modul von demselben Mediator gesteuert wird. Das Modul muss nur Ereignisse übertragen und anhören, und es besteht keine direkte Verbindung zwischen Modulen. Darüber hinaus können mehrere Module gleichzeitig zur Verarbeitung von Informationen verwendet werden, was uns auch ermöglicht, der vorhandenen Steuerlogik in Zukunft neue Module hinzuzufügen.
Es ist sicher, dass, da alle Module nicht direkt kommunizieren können, möglicherweise relativ zu einem leichten Leistungsrückgang kommen, aber ich denke, es lohnt sich.
Verwenden wir eine einfache Demo, die auf der obigen Erklärung basiert:
var mediator = (function () {var subscribe = function (Kanal, fn) {if (! Mediator.Channels [Kanal]) Mediator.Channels [Kanal] = []; Mediator.Channels [Kanal] .push ({Kontext: this this, this Callback: Fn}); Array.prototype.slice.call (Argumente, 1); abonnieren: installto: function (obj) {obj.subscribe = abonnieren;Dann gibt es 2 Module mit dem Namen:
// pub/sub auf einem zentralisierten Mediator mediator.name = "tim"; Mediator.Subscribe ('namechange', function (arg) {console.log (this.name); this.name = arg; console.log (this.name);}); mediator.publish ('namechange', 'David'); // Tim, David // Pub/Sub über Mediator var obj = {name: 'sam'}; mediator.installto (obj); obj.subscribe ('namechange', function (arg) {console.log (this.name); obj.publish ('namechange', 'John'); // Sam, JohnAnwendungsfassade: Die Abstraktion des Kerns der Anwendung
Eine Fassade arbeitet als Zusammenfassung des Anwendungskerns und ist für die Kommunikation zwischen dem Mediator und dem Modul verantwortlich. Jedes Modul kann nur über diese Fassade mit dem Programmkern kommunizieren. Die Verantwortung als Abstract besteht darin, sicherzustellen, dass diese Module jederzeit mit einer konsistenten Schnittstelle versehen werden können, was der Rolle des SENDBOX -Controllers ähnlich ist. Alle Modulkomponenten kommunizieren damit mit Mediatoren, sodass die Fassade zuverlässig und vertrauenswürdig sein muss. Gleichzeitig muss Fassade als Funktion eine Schnittstelle zum Modul zur Verfügung stellen, dh Sicherheitskontrolle, dh zu bestimmen, auf welchen Teil des Programms ein Modul zugegriffen werden kann. Modulkomponenten können nur ihre eigenen Methoden aufrufen und keinen nicht autorisierten Inhalt zugreifen. Beispielsweise kann ein Modul DatavalidationCompletedWritEToDB übertragen, wobei Sicherheitsüberprüfungen sicherstellen müssen, dass das Modul Berechtigungen in die Datenbank hat.
Kurz gesagt, Mediator kann nur die Informationsverarbeitung nach der Erkennung von Fassadenberechtigung durchführen.
Anwendungsmediator: Der Kern der Anwendung
Mediator arbeitet als zentrale Rolle für die Anwendung. Lassen Sie uns kurz über seine Verantwortlichkeiten sprechen. Der zentralste Job ist die Verwaltung des Lebenszyklus des Moduls. Wenn dieser Kern Informationen erfasst, muss er beurteilen, wie das Programm damit umgeht - dh, um zu entscheiden, welches Modul Sie starten oder anhalten sollen. Wenn ein Modul startet, sollte es in der Lage sein, automatisch auszuführen, ohne den Anwendungskern zu entscheiden, ob es ausgeführt werden soll (z. B. ob es ausgeführt werden sollte, wenn DOM bereit ist), damit das Modul selbst bestimmen muss.
Sie können eine Frage haben, unter welchen Umständen wird ein Modul aufhören? Wenn das Programm feststellt, dass ein Modul fehlschlägt oder einen Fehler macht, muss das Programm eine Entscheidung treffen, um zu verhindern, dass die Methode im Modul fortgesetzt wird, damit die Komponente neu gestartet werden kann, um die Benutzererfahrung zu verbessern.
Darüber hinaus sollte der Kern in der Lage sein, Module dynamisch hinzuzufügen oder zu löschen, ohne andere Funktionen zu beeinflussen. Ein häufiges Beispiel ist, dass ein Modul zu Beginn des Seitenladens nicht verfügbar ist. Nach dem Betrieb des Benutzers muss es das Modul dynamisch laden und dann ausführen. Genau wie die Chat -Funktion in Google Mail sollte es aus dem Zweck der Leistungsoptimierung leicht zu verstehen sein.
Auch vom Anwendungskern wird die Handhabung des Ausnahmefehlers behandelt. Wenn jedes Modul Informationen überträgt, sendet es außerdem alle Fehler auf den Kern, sodass der Programmkern diese Module entsprechend der Situation anhalten/neu starten kann. Dies ist auch ein sehr wichtiger Teil der locker gekoppelten Architektur. Wir müssen keine Module manuell ändern. Wir können dies tun, indem wir Veröffentlichung/Abonnieren über den Mediator verwenden.
Montieren
Jedes Modul enthält verschiedene Funktionen im Programm. Wenn sie Informationen verarbeiten müssen, geben sie Informationen aus, die das Programm benachrichtigen (dies ist ihre Hauptverantwortung). Der folgende QA -Abschnitt erwähnte, dass Module auf einige DOM -Werkzeugbetriebmethoden angewiesen sind, aber nicht von anderen Modulen des Systems abhängen sollten. Ein Modul sollte nicht auf den folgenden Inhalt achten:
1. Welches Objekt oder Modul abonniert die von diesem Modul veröffentlichten Informationen
2. sind diese Objekte Client- oder serverseitige Objekte
3. Wie viele Objekte haben Ihre Informationen abonniert?
Der Kern der Abstraktionsanwendung von Fassaden vermeidet eine direkte Kommunikation zwischen Modulen. Es zeichnet Informationen aus jedem Modul ab und ist auch für die Erkennung von Autorisierungsberechtigten verantwortlich, um sicherzustellen, dass jedes Modul eine eigene separate Autorisierung hat.
Mediator (Application Core) verwendet den Mediatormodus, um die Rolle des Veröffentlichung/Abonnement -Managers zu spielen, verantwortlich für die Modulverwaltung und Start-/Stopp -Modulausführung und kann Module mit Fehlern dynamisch laden und neu starten.
Das Ergebnis dieser Architektur ist, dass es keine Abhängigkeit zwischen Modulen gibt. Aufgrund locker gekoppelter Anwendungen können sie leicht getestet und aufrechterhalten werden. Jedes Modul kann in anderen Projekten leicht wiederverwendet werden oder dynamisch hinzugefügt und gelöscht werden, ohne das Programm zu beeinflussen.
Veröffentlichen Sie Pub/Sub -Erweiterung: Automatische Ereignisregistrierung
In Bezug auf die automatische Registrierung von Ereignissen müssen bestimmte Namensschwerpunkte befolgt werden. Wenn beispielsweise ein Modul ein Ereignis namens MessageUpDate veröffentlicht, werden alle Module mit der MessageUpDate -Methode automatisch ausgeführt. Es gibt Vorteile und Vor- und Nachteile. Für bestimmte Implementierungsmethoden sehen Sie einen weiteren Beitrag von mir: Die Magic -Upgrade -Version von JQuery Custom Bindung.
QA
1. Ist es möglich, keine Fassade oder einen ähnlichen Sandbox -Modus zu verwenden?
Obwohl der Umriss der Architektur vorschlägt, dass Fassade Autorisierungsüberprüfungsfunktionen implementieren kann, ist es tatsächlich durchaus möglich, dass Mediatoren dies tun können. Was die Lichtarchitektur tun muss, ist fast gleich, dh zu entkoppeln und sicherzustellen, dass jedes Modul direkt mit dem Kern der Anwendung kommuniziert.
2. Sie haben sich verbessert, dass das Modul nicht direkt abhängig sein kann. Bedeutet es, dass es sich nicht auf eine Bibliothek von Drittanbietern (z. B. JQuery) verlassen kann.
Dies ist eigentlich ein zweiseitiges Problem. Wie oben erwähnt, kann ein Modul einige Submodule oder grundlegende Module haben, z.
3. Ich mag diese Architektur und möchte diese Architektur verwenden. Gibt es Codeproben, auf die sich beziehen können?
Ich habe vor, ein Code -Beispiel für Ihre Referenz zu erstellen, aber davor können Sie sich auf Andrew Burgees 'Post -Schreiben modulare JavaScript beziehen.
4. Ist es machbar, wenn das Modul direkt mit dem Anwendungskern kommunizieren muss?
Technisch gesehen gibt es keinen Grund, warum Module jetzt nicht direkt mit dem Anwendungskern kommunizieren können, aber für die meisten Anwendungserfahrungen ist dies immer noch nicht zulässig. Da Sie diese Architektur ausgewählt haben, müssen Sie die von der Architektur definierten Regeln einhalten.
Anerkennung
Vielen Dank an Nicholas Zakas für den ursprünglichen Beitrag, um die Ideen gemeinsam zusammenzufassen, an Andree Hansson für die technische Überprüfung, an Rebecca Murphey, Justin Meyer, John Hann, Peter Michaux, Paul Irish und Alex Sexton, alle Informationen zu dieser Sitzung.