Question

Quelqu'un est-il capable d'aider à illustrer principe de dépendance inversion en JavaScript jQuery?

Ce qui mettrait en évidence et expliquer ces 2 points:

A. Les modules de haut niveau ne doivent pas dépendre de modules de bas niveau. Les deux devraient dépendre des abstractions.

B. Abstractions ne doivent pas dépendre de détails. Les détails devraient dépendre des abstractions.

Quels sont des abstractions ou des modules haut / bas niveau?

Cela va vraiment aider dans ma compréhension, merci!

Était-ce utile?

La solution

Je dirais que le DIP applique en JavaScript de la même manière qu'il applique dans la plupart des langages de programmation, mais vous devez être conscient du rôle de frappe de canard. Faisons un exemple pour voir ce que je veux dire ...

Le mot Let je veux contacter le serveur pour certaines données. Sans l'application de DIP, cela pourrait ressembler à:

$.get("/address/to/data", function (data) {
    $("#thingy1").text(data.property1);
    $("#thingy2").text(data.property2);
});

Avec DIP, je pourrais écrire le code à la place comme

fillFromServer("/address/to/data", thingyView);

où le fillFromServer d'abstraction peut pour le cas particulier où l'on veut utiliser Ajax jQuery être mis en œuvre comme

function fillFromServer(url, view) {
    $.get(url, function (data) {
        view.setValues(data);
    });
}

et la view d'abstraction peut être mis en œuvre pour le cas particulier d'une vue basée sur des éléments avec des ID thingy1 et thingy2

var thingyView = {
    setValues: function (data) {
        $("#thingy1").text(data.property1);
        $("#thingy2").text(data.property2);
    }
};

Principe A:

  • fillFromServer appartient à un module de bas niveau, la manipulation comme il le fait de l'interaction faible niveau entre le serveur et la vue. Quelque chose comme, par exemple, un objet settingsUpdater ferait partie d'un module de niveau supérieur, et il se fonderait sur l'abstraction fillFromServer --- pas sur les détails de celui-ci, qui sont dans ce cas, mis en œuvre par jQuery.
  • De même, fillFromServer ne dépend pas de spécificités des éléments DOM et leurs papiers d'identité pour effectuer ses travaux; à la place, elle dépend de l'abstraction d'un view, qui à ses fins est un type qui a une méthode de setValues. (C'est ce que l'on entend par « taper le canard. »)

Principe B:

Ceci est un peu moins facile de voir en JavaScript, avec son canard frappe; en particulier, quelque chose comme view ne dérive pas de (à savoir dépendent) une sorte de type viewInterface. Mais nous pouvons dire que notre cas particulier, l'thingyView, est voir qui "dépend" de la view d'abstraction.

De façon réaliste, il est « en fonction » sur le fait que devrait appeler les appelants comprennent ce genre de méthodes, à savoir que les appelants sont conscients de l'abstraction appropriée. Dans les langues habituelles orientées objet, il est plus facile de voir la dépendance des thingyView explicitement sur l'abstraction elle-même. Dans ces langues, l'abstraction serait incorporée dans une interface (par exemple, IView en C # ou en Java Viewable), et la dépendance explicite par héritage (class ThingyView : IView ou class ThingyView implements Viewable). Le même sentiment s'applique cependant.


Pourquoi est-ce cool? Eh bien, disons qu'un jour je besoin de mettre les données du serveur dans les zones de texte avec ID text1 et text2 au lieu de <span />s avec ID thingy1 et thingy2. De plus, disons que ce code a été appelé très souvent et l'analyse comparative a révélé que la performance critique était perdu par l'utilisation de jQuery. Je pourrais alors simplement créer une nouvelle « mise en œuvre » de l'abstraction view, comme suit:

var textViewNoJQuery = {
   setValues: function (data) {
        document.getElementById("text1").value = data.property1;
        document.getElementById("text2").value = data.property2;
   }
};

Alors j'injectent ce cas particulier de l'abstraction de vue dans mon abstraction fillFromServer:

fillFromServer("/address/to/data", textViewNoJQuery);

requis pas modifications de code fillFromServer, car il ne dépend que de l'abstraction d'un view avec une méthode setValues, et non sur les détails du DOM et la façon dont nous accédons. Non seulement cela est satisfaisant en ce que nous pouvons réutiliser le code, il indique aussi que nous avons nos préoccupations proprement séparés et créé un code très à l'épreuve.

Autres conseils

EDIT:

Cela montre l'utilisation des DIP en JavaScript brut et moins complet exemple jQuery. Cependant, la description suivante peut être facilement appliquée à jQuery. Voir par exemple jQuery en bas.

La meilleure façon est de tirer parti du « modèle adaptateur » - aussi appelé un « emballage »

.

Adaptateur An est essentiellement un moyen d'enveloppement d'un objet ou d'un module de telle sorte qu'il fournit la même interface compatible sa charge . De cette façon, la classe dépendante (généralement un niveau plus élevé classe) peut facilement échanger des modules du même type.

Un exemple de ceci serait un haut niveau (ou supra ) Module qui dépend de Geo / modules de mappage.

permet d'analyser cela. Si notre module ci-dessus utilise déjà GoogleMaps mais la direction décide de son moins cher d'aller avec LeafletMaps - nous ne voulons pas avoir à réécrire chaque appel de méthode de gMap.showMap(user, latLong) à leaflet.render(apiSecret,latLong, user), et al. Ce serait un cauchemar d'avoir au port notre application d'un cadre à un autre de cette façon.

Ce que nous voulons: Nous aimerions un "wrapper" qui fournit la même cohérente Interface au module ci-dessus - et faire cela pour tous les module de niveau inférieur ( ou infra module).

Voici un exemple simple varie:

var infra1 = (function(){
    function alertMessage(message){
        alert(message);
    }

    return {
        notify: alertMessage
    };
})();

var infra2 = (function(){
    function logMessage(message){
        console.log(message);
    }

    return {
        notify: logMessage
    };
})();


var Supra = function(writer){
    var notifier = writer;
    function writeMessage(msg){
        notifier.notify(msg);
    }

    this.writeNotification = writeMessage;
};


var supra;

supra = new Supra(infra1);
supra.writeNotification('This is a message');

supra = new Supra(infra2);
supra.writeNotification('This is a message');

Notez que quel que soit le type de « écriture » module de niveau inférieur, nous utilisons (dans ce cas infra1 et infra2), nous n'avons pas de réécrire toute la mise en œuvre de notre module de haut niveau, Supra. En effet, DIP profite de deux différents principes de conception de logiciels: "IoC" (Inversion of Control) et "DI" (Dependency Injection)

.

La meilleure analogie que je suis venu à travers est l'image ci-dessous.

entrer dans la description d'image ici Chaque source électrique repose sur une Interface spécifique pour les types de choses qui ont besoin de se brancher sur elle.

jQuery Description:

Ce modèle peut être facilement appliquée à l'utilisation de cadres tels que jQuery. Un exemple serait simple poignée DOM-requête. Nous pouvons utiliser DIP pour permettre couplage lâche de sorte que si nous décidons jamais à des cadres de commutation ou se fonder sur les méthodes DOM-requête native, l'entretien est facile:

var jQ = (function($){

    return {
        getElement: $
    };
})(jQuery);

var nativeModule = (function(){

    return {
        getElement: document.querySelector
    };
})();


var SupraDOMQuery = function(api){
    var helper = api, thus = this;

    function queryDOM(selector){
        el = helper.getElement(selector);
        return thus;
    }

    this.get = queryDOM;
};


var DOM;

DOM = new SupraDOMQuery(jQ);
DOM.get('#id.class');

DOM = new SupraDOMQuery(nativeModule);
DOM.get('#id.class');

De toute évidence, cet exemple aurait besoin magnitudes de plus de fonctionnalités pour être pratique, mais j'espère qu'il obtient le point à travers.

En fait, les différences entre un adaptateur et une façade devient un peu trivial. Dans une façade, vous cherchez à probablement un seul module qui enveloppe une API ou un autre module; tandis qu'un adaptateur crée une API de façade cohérente pour chacun de ses modules, et exploite cette technique pour éviter le couplage de serré.

La plupart des livres Design Patterns JavaScript vont sur le motif adaptateur; qui va spécifiquement sur un 'adaptateur jQuery' est Patterns Learning Design JavaScript par Addy Osmani publié par O'Reilly - ici . Cependant, je vous conseille également la recherche dans JavaScript Pro Design Patterns par Dustin Diaz et Ross Harmes publié par Apress - vérifier . Néanmoins, je pense qu'il est important de comprendre le contexte dans lequel nous envisageons de mettre en œuvre DIP par rapport à jQuery.

J'espère que cela aide à clarifier les choses:)

trouvé quelques illustrations utiles .

Dépendance principe d'inversion en JavaScript jQuery

Il n'y a pas de lien entre DI et jQuery. DI est tout au sujet de la structure et de l'application de l'assemblage compoents. jQuery est un emballage pratique autour DOM, rien de plus, il n'a pas une structure ou des composants.

Vous pouvez utiliser DI à l'assemblage Votre JavaScript application, mais il ressemble beaucoup même, peu importe utilisez-vous jQuery ou non.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top