Prinzip der Abhängigkeitsinversion in JavaScript

7

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!

    
bcm 18.03.2011, 07:02
quelle

4 Antworten

25

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

implementiert wird %Vor%

und die Abstraktion view kann für den speziellen Fall einer Ansicht implementiert werden, die auf Elementen mit den IDs thingy1 und thingy2 als

basiert %Vor%

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>
  • Ebenso hängt 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:

%Vor%

Dann injiziere ich diese bestimmte Instanz der Ansichtsabstraktion in meine fillFromServer Abstraktion:

%Vor%

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.

    
Domenic 18.03.2011, 08:12
quelle
4

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:)

    
Cody 17.04.2014 19:03
quelle
2

Hier finden Sie einige nützliche .

    
bcm 18.03.2011 07:42
quelle
0
  

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.

    
Alexey Petrushin 22.11.2011 19:48
quelle