2009-02-20 2 views
9

Я пишу программу анализа среднего размера (5-10kloc) в MATLAB (не мое решение), и я пытаюсь использовать инъекцию зависимостей, чтобы сделать мой код более проверяемым. Я думаю, что я понимаю базовую модель внедрения объекта/конструктора, но я смущен тем, как это масштабирует граф зависимостей.Зависимость впрыска без рамки

Например, если у меня есть объект A, у которого есть объект B, у которого есть объект C, а объект C имеет зависимость, которая должна быть введена, нужно ли передавать его по всей цепочке? В конце концов, поскольку это программа анализа данных, все в основном возвращается к одному объекту/методу AnalyzeData, означает ли это, что у этого объекта должны быть все зависимости всей программы?

Возможно, ответ заключается в просто использовании ServiceFactory/ServiceProvider в этом случае, но я хотел бы знать, можно ли масштабировать многие зависимости до большого графа объектов без рамки.

Кроме того, исправления в отношении моего мышления/формулировки/основы поощряются - я в основном изучал большую часть этого через Google/HN/SO.

+0

Что означает HN? – iddober

+0

Это отнюдь не ответ, но из всех тех, кто может ответить на этот вопрос, взгляните на (довольно приятный) [рамки DI для Matlab] (https://github.com/mattmcd/mdepin), написанный Мэттом Макдоннеллом. Это должно заставить вас идти .... – Kris

+0

Следуйте за комментарием Криса, вот блог на тему, посвященный MATLAB (и с использованием рамки DI Matt MCDonnell): http://blogs.mathworks.com/developer/2016/02/24/dependency-injection/ –

ответ

2

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

Я нашел это видео очень полезное введение к этим темам - http://www.dnrtv.com/default.aspx?showNum=126

2

Если вы делаете инъекции зависимостей вручную вы лучше не проходя через зависимость. Вы просто создаете C с его зависимостью, создавайте B с C, создавайте A с B. Нет необходимости, чтобы A знал что-либо о C или его зависимости. Он просто знает об интерфейсе B, и обычно зависимости не являются частью интерфейса для объекта.

5

Matlab-агностик ответ:

Если (А требуется B) и (требуется B C), то вы сначала создать C, а затем создать B и передать C до B. Тогда вы создаете и передать (B есть C) до A.

Теперь, если для C требуется зависимость для инъекции, назовите ее D, вы все равно можете сделать это после этой последовательности событий, используя инъекцию установщика. Это будет иметь место, если зависимость является необязательной для C. В противном случае, вероятно, недостаток в вашей инициализации программы состоит в том, что C не был введен с D до, он был передан B.

Если вы хотите использовать конструктор инъекция для инъекции D в C после того, как вы уже имеете (у A есть (B есть C)), тогда вам придется использовать инъекцию сеттера для передачи нового (C имеет D) в B, но эта последовательность событий обычно не является допустимый сценарий для DI.

0

Не знаю ничего о Matlab, но я предполагаю (из ваших слов), что есть объекты. Если да, перейдите на Service Locator вместо Injection Dependency. Сервис-локаторы очень просты в реализации, поэтому никаких фреймворков не требуется.

+0

Утилита локатора обслуживания (анти) широко устарела. Он создает огромную глобальную область видимости и не имеет видимости того, где используются ваши объекты. – time4tea

2

Отказ от ответственности: OO язык агностик ответ

Нет, вам не нужно проходить зависимости через весь граф объектов. Не обязательно создавать конкретные типы или передавать их в качестве параметров - это точка DI. Как правило, у вас будет другой объект, например Assembler, который будет вводить эти зависимости. Ассемблер может быть ad-hock, рукописным или может быть некоторой картой DI.

Например:

  • Класс CLSA имеет свойство типа интерфейса IB.
  • Класс ClsB реализует IB и обладает свойством типа Интерфейс IC.
  • Класс ClsC реализует IC.

Ваш Ассемблер будет грузиться приложение и:

  1. создать экземпляр с именем оС класса CLSC
  2. создать экземпляр с именем оВ из CLSB и впрыснуть его РЯ
  3. создать экземпляр с именем оА и введите его oB

Весь ваш домен o bject знают только интерфейсы. Ассемблер знает весь объект, но его цель - просто создать граф объектов и привести все в движение. Рукописный ассемблер идеально подходит; некоторые люди предпочитают писать код проводки, чем использовать файлы конфигурации. Не думайте, что стоит писать ассемблер (рамки DI), если вы не планируете использовать его более одного раза. Дело в том, что ваши классы написаны на моделях DI.

Посмотрите на эту статью: http://books.google.com/books?id=vRxAnRb3mb4C&pg=PP1&dq=Danijel+Arsenovski#PPA428,M1

2

Если я правильно понимаю ваш вопрос, ответ может зависеть от того, как вы создаете классы, из которых инстанцировании объекты. В новейших версиях MATLAB классы могут быть определены двумя способами: классом «значение» или классом «дескриптор» (документация MATLAB here). Цитирование из документации:

  • класса Value:. «Объекты классов значений постоянно связанных с переменными, к которым они приписаны Когда значение объекта копируется, данные объекта также копируются и новый объект не зависит от изменений исходного объекта. Экземпляры ведут себя как стандартные числовые и структурные классы MATLAB ».

  • Ручка Класс:.. «Объекты классов ручки использовать дескриптор для ссылки на объекты класса А ручка является переменной, которая идентифицирует конкретный экземпляр класса Когда дескриптор объект копируется, ручка копируется , но не данные, хранящиеся в свойствах объекта. Копия относится к тем же данным, что и оригинал - если вы изменяете значение свойства на исходном объекте, скопированный объект отражает одно и то же изменение."

В примере ниже приведены некоторые примеры того, как взаимодействовать с„вложенными“объектами, как вы описали выше, как для значения класса вложенных объектов и ручки класса вложенных объектов:

% For value classes: 

objC = C(...); % Make an object of class C, where "..." stands 
       % for any input arguments 
objB = B(...,objC); % Make an object of class B, passing it objC 
        % and placing objC in field 'objC' 
objA = A(...,objB); % Make an object of class A, passing it objB 
        % and placing objB in field 'objB' 

% If the '.' operator (field access) is defined for the objects: 

objA.objB.objC.D = 1; % Set field 'D' in objC to 1 
objA.objB.objC = foo(objA.objB.objC,...); % Apply a method that 
              % modifies objC and 
              % returns the new 
              % object 

% For handle classes: 

hC = C(...); % Get a handle (reference) for a new object of class C 
hB = B(...,hC); % Get a handle for a new object of class B, 
       % passing it handle hC and placing it in field 'hC' 
hA = A(...,hB); % Get a handle for a new object of class A, 
       % passing it handle hB and placing it in field 'hB' 

% If the '.' operator (field access) is defined for the objects: 

hC.D = 1; % Set field 'D' to 1 for object referenced by hC; Note 
      % that hC and hA.hB.hC both point to same object, and 
      % can thus be used interchangably 
foo(hC); % Apply a method that modifies the object referenced by hC 

% If instead using get/set methods for the handle object: 

set(hC,'D',1); 
set(get(get(hA,'hB'),'hC'),'D',1); % If variable hC wasn't made, get 
            % reference from nested objects 
foo(hC); 
foo(get(get(hA,'hB'),'hC')); 

Как вы можете видеть, используя класс ручки может помочь вам избежать вызовов функций цепи и ссылки на местах, сохраняя копию ручки (по существу указатель) в другой переменной. Обрабатывать классы также Tak e) необходимость перезаписывать старые копии объектов новыми, возвращаемыми методами, которые работают с этими объектами.

Надеюсь, это поможет в том, что вы просили.