Принцип инверсии зависимостей в JavaScript

кто-нибудь может помочь проиллюстрировать принцип инверсии зависимостей в JavaScript jQuery?

Что бы выделить и объяснить эти 2 пункта:

A. высокоуровневые модули не должны зависеть от низкоуровневых модулей. Оба должны зависеть от абстракций.

Б. абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Что такое абстракции или модули высокого / низкого уровня?

Это очень поможет в моем понимании, спасибо!

4 ответов


я бы сказал, что DIP применяется в JavaScript так же, как и в большинстве языков программирования, но вы должны знать о роли duck typing. Давайте приведем пример, чтобы понять, что я имею в виду...

предположим, я хочу связаться с сервером для получения некоторых данных. Без применения DIP это может выглядеть так:

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

С DIP, я мог бы вместо этого написать код, как

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

где абстракция fillFromServer можете для конкретного случая где мы хотим использовать Ajax jQuery реализовано как

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

и забором view может быть реализована для данного конкретного случая представления на основе элементов с идентификаторами thingy1 и thingy2 as

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

Принцип Такой:

  • fillFromServer принадлежит к низкоуровневому модулю, обрабатывая, как это делает низкоуровневое взаимодействие между сервером и представлением. Что-то вроде, скажем,

EDIT:

это показывает использование DIP в raw JavaScript и A меньше-полное пример jQuery. Однако следующее описание можно легко применить к jQuery. См. пример jQuery внизу.

лучший способ-воспользоваться "шаблоном адаптера", также называемым"оболочкой".

адаптер в основном способ упаковки объекта или модуля таким образом, что он обеспечивает то же самое последовательны интерфейс в своем иждивенцев. Таким образом, зависимый класс (обычно a более высокого уровня class) может легко поменять модули одного и того же типа.

примером этого может быть высокий уровень (или выше) модуль, который зависит от модулей Geo / Mapping.

давайте проанализируем это. Если наш модуль Супра уже с помощью GoogleMaps, но затем руководство решает его дешевле, чтобы пойти с LeafletMaps-мы не хотим, чтобы переписать каждый вызов метода gMap.showMap(user, latLong) to leaflet.render(apiSecret,latLong, user), et al. Это был бы кошмар, чтобы перенести наше приложение из одной структуры в другую таким образом.

что мы хотим: мы хотели бы "обертку", которая обеспечивает то же самое последовательным интерфейсом к модулю supra -- и сделайте это для каждого нижнего уровня модуля (или infra модуль).

вот простой пример:

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');

обратите внимание, что независимо от того, какой тип модуль нижнего уровня "write" мы используем (в данном случае infra1 и infra2), нам не нужно переписывать какую-либо реализацию нашего модуля высокого уровня,Supra. Это связано с тем, что DIP использует два разных принципа проектирования программного обеспечения: "IoC" (инверсия управления) и "DI" (инъекция зависимостей).

лучшая аналогия, с которой я столкнулся, - это изображение, показанное ниже.

enter image description here Каждый электрический источник полагается на интерфейс специфические для типы вещей, которые нужно подключить к нему.

в jQuery описание:

этот шаблон можно легко применить к использованию фреймворков, таких как jQuery. Одним из примеров может быть простой дескриптор DOM-запроса. Мы можем использовать DIP, чтобы разрешить свободную связь, так что, если мы когда-либо решим переключать фреймворки или полагаться на собственные методы DOM-запроса, обслуживание легко:

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');

очевидно, что для этого примера потребуются значения большей функциональности, чтобы быть практично, но я надеюсь, что это дойдет до сути.

в основном, различия между адаптером и фасадом становятся несколько тривиальными. В фасаде вы смотрите, вероятно, на один модуль, который обертывает API или другой модуль; в то время как адаптер создает согласованный API фасада для каждого из своих модулей и использует этот метод, чтобы избежать плотной связи.

большинство книг шаблонов проектирования JavaScript идут по шаблону адаптера; тот, который специально переходит адаптер jQuery - это Изучение Шаблонов Проектирования JavaScript by Адди Османи опубликовано на О'Рейли -- здесь. Тем не менее, я также советую заглянуть в Pro JavaScript Шаблоны Проектирования by Дастин Диас и Росс Хармс опубликовано на Apress -- зацените. Тем не менее, я считаю важным понять контекст, в котором мы планируем реализовать DIP в отношении на jQuery.

надеюсь, это поможет прояснить ситуацию:)


нашел несколько полезных иллюстраций здесь.


принцип инверсии зависимостей в JavaScript jQuery

нет никакой связи между DI и jQuery. DI все о структуре и собирая применении от compoents. jQuery-удобная оболочка вокруг DOM, не более того, она не имеет никакой структуры или компонентов.

вы можете использовать DI для сборки вашего приложения JavaScript, но это будет выглядеть одинаково независимо от того, используете ли вы jQuery или нет.