Kann jemand helfen, Prinzip der Abhängigkeitsinversion in JavaScript jQuery zu illustrieren?
Was würde diese 2 Punkte hervorheben und erklären:
A. High-Level-Module sollten nicht von Low-Level-Modulen abhängig sein. Beide sollten von Abstraktionen abhängen.
B. Abstraktionen sollten nicht von Details abhängen. Details sollten von Abstraktionen abhängen.
Was sind Abstraktionen oder High- / Low-Level-Module?
Dies wird wirklich in meinem Verständnis helfen, danke!
Ich würde sagen, dass der DIP in JavaScript genauso wie in den meisten Programmiersprachen angewendet wird, aber Sie müssen sich der Rolle der Duck-Typisierung bewusst sein. Lassen Sie uns ein Beispiel geben, um zu sehen, was ich meine ...
Nehmen wir an, ich möchte den Server für einige Daten kontaktieren. Ohne DIP könnte dies wie folgt aussehen:
%Vor%Mit DIP könnte ich stattdessen Code wie
schreiben %Vor% wo die Abstraktion fillFromServer
can für den speziellen Fall, in dem wir jQuery's Ajax verwenden wollen, als
und die Abstraktion view
kann für den speziellen Fall einer Ansicht implementiert werden, die auf Elementen mit den IDs thingy1
und thingy2
als
Prinzip A:
fillFromServer
gehört zu einem Low-Level-Modul und behandelt die Interaktion auf niedriger Ebene zwischen dem Server und der Ansicht. Etwas wie, sagen wir mal, wäre ein settingsUpdater
Objekt Teil eines übergeordneten Moduls, und es würde auf die fillFromServer
Abstraktion angewiesen sein - nicht auf die Details, die in diesem Fall über jQuery implementiert werden / li>
fillFromServer
nicht von den Besonderheiten der DOM-Elemente und ihrer IDs ab, um ihre Arbeit auszuführen; stattdessen hängt es von der Abstraktion eines view
ab, das für seine Zwecke ein beliebiger Typ ist, der eine Methode setValues
hat. (Dies ist was mit "Ente tippen" gemeint ist.) Prinzip B:
Dies ist etwas weniger einfach in JavaScript zu sehen, mit der Eingabe von Enten; insbesondere etwas wie view
stammt nicht von einer Art von viewInterface
type ab (d. h. hängt davon ab). Aber wir können sagen, dass unsere spezielle Instanz, thingyView
, ein Detail ist, das von der Abstraktion view
abhängt.
Realistisch ist es "abhängig" von der Tatsache, dass Anrufer verstehen, welche Art von Methoden aufgerufen werden sollten, d. h. dass Anrufer die entsprechende Abstraktion bemerken . In den üblichen objektorientierten Sprachen ist es einfacher, die Abhängigkeit von thingyView
explizit von der Abstraktion selbst zu sehen. In solchen Sprachen wäre die Abstraktion in einer Schnittstelle enthalten (zB IView
in C # oder Viewable
in Java) und die explizite Abhängigkeit ist über Vererbung ( class ThingyView : IView
oder class ThingyView implements Viewable
). Das gleiche Gefühl gilt jedoch.
Warum ist das cool? Nun, eines Tages musste ich die Serverdaten in Textfelder mit den IDs text1
und text2
anstatt <span />
s mit den IDs thingy1
und thingy2
setzen. Nehmen wir weiterhin an, dass dieser Code sehr oft aufgerufen wird, und das Benchmarking ergab, dass kritische Leistung durch die Verwendung von jQuery verloren ging. Ich könnte dann einfach eine neue "Implementation" der view
Abstraktion erstellen, so:
Dann injiziere ich diese bestimmte Instanz der Ansichtsabstraktion in meine fillFromServer
Abstraktion:
Dies erforderte no Änderungen an fillFromServer
code, weil es nur von der Abstraktion von view
mit einer setValues
-Methode abhing, und nicht von den Details des DOM und wie wir darauf zuzugreifen. Das ist nicht nur befriedigend, da wir Code wiederverwenden können, sondern auch, dass wir unsere Bedenken sauber getrennt haben und einen sehr zukunftssicheren Code erstellt haben.
BEARBEITEN:
Dies zeigt die Verwendung von DIP in Raw JavaScript und ein weniger vollständiges jQuery Beispiel. Die folgende Beschreibung kann jedoch leicht auf jQuery angewendet werden. Sehen Sie sich das jQuery-Beispiel unten an.
Am besten nutzen Sie das "Adapter Pattern" - auch "Wrapper" genannt.
Ein Adapter ist im Grunde eine Möglichkeit, ein Objekt oder ein Modul so zu umhüllen, dass es seinen Abhängigen dieselbe konsistente Schnittstelle bietet. Auf diese Weise kann die abhängige Klasse (normalerweise eine höhere -Klasse) einfach Module desselben Typs austauschen.
Ein Beispiel hierfür wäre ein High-Level-Modul (oder supra ), das von Geo / Mapping-Modulen abhängig ist.
Lasst uns das analysieren. Wenn unser Supra-Modul bereits Google Maps verwendet, dann entscheidet das Management, dass es günstiger ist, mit LeafletMaps zu arbeiten - wir wollen nicht jeden Methodenaufruf von gMap.showMap(user, latLong)
auf leaflet.render(apiSecret,latLong, user)
, etc. neu schreiben müssen. Dies wäre ein Albtraum, wenn wir unsere Anwendung auf diese Weise von einem Framework auf ein anderes portieren müssten.
Was wir wollen: Wir hätten gerne einen "Wrapper", der dieselbe konsistente Schnittstelle zum übergeordneten Modul bereitstellt - und dies für jedes untere Modul ( oder infra Modul).
Hier ist ein einfaches Beispiel:
%Vor% Beachten Sie, dass wir, egal welche Art von untergeordneten Modul "schreiben" wir verwenden (in diesem Fall infra1
und infra2
), müssen wir keine der Implementierung unserer High-Level-Modul neu schreiben,% Code%. Dies liegt daran, dass DIP zwei verschiedene Software-Design-Prinzipien nutzt: "IoC" (Inversion of Control) und "DI" (Dependency Injection).
Die beste Analogie, auf die ich gestoßen bin, ist das folgende Bild.
Jede elektrische Quelle beruht auf einer Schnittstelle , die spezifisch für die Arten von Dingen ist, die sich daran anschließen müssen.
jQuery Beschreibung:
Dieses Muster kann leicht auf die Verwendung von Frameworks wie jQuery angewendet werden. Ein Beispiel wäre das einfache DOM-Abfrage-Handle. Wir können DIP verwenden, um lose Kopplung zuzulassen, sodass, wenn wir uns jemals entscheiden, Frameworks zu wechseln oder sich auf native DOM-Query-Methoden zu stützen, die Wartung einfach ist:
%Vor%Offensichtlich würde dieses Beispiel Größen von mehr Funktionalität benötigen, um praktisch zu sein, aber ich hoffe, es bringt den Punkt über.
Grundsätzlich werden die Unterschiede zwischen einem Adapter und einer Fassade etwas trivial. In einer Fassade betrachten Sie wahrscheinlich ein einzelnes Modul, das eine API oder ein anderes Modul umschließt. während ein Adapter eine konsistente Facade-API für jedes seiner Module erstellt und diese Technik nutzt, um eine enge Kopplung zu vermeiden.
Die meisten JavaScript Design Patterns-Bücher gehen über das Adapter Pattern; Eine, die speziell über einen 'jQuery Adapter' geht, ist Lernen von JavaScript Design Patterns von Addy Osmani veröffentlicht von O'Reilly - hier . Ich empfehle aber auch, Pro JavaScript Design Patterns von Dustin Diaz und Ross Harmes zu lesen, die von Apress - überprüfe es . Dennoch denke ich, dass es wichtig ist, den Kontext zu verstehen, in dem wir DIP in Bezug auf jQuery implementieren wollen.
Ich hoffe, dies hilft, die Dinge zu klären:)
Prinzip der Abhängigkeitsinversion in JavaScript jQuery
Es gibt keine Verbindung zwischen DI und jQuery. Bei DI dreht sich alles um den Aufbau und die Montage von Bauteilen. jQuery ist ein praktischer Wrapper um DOM, nicht mehr, es hat keine Struktur oder Komponenten.
Sie können DI verwenden, um Ihre JavaScript-Anwendung zu assemblieren, aber es sieht in etwa gleich aus, egal, ob Sie jQuery verwenden oder nicht.
Tags und Links javascript jquery dependency-injection inversion-of-control dip-principle