2009-06-04 5 views
41

Я использовал ручной инсталлятор DI для немного сейчас. Одна вещь, которую я замечаю, заключается в том, что мои конструкторы начинают довольно долго.Инъекция конструктора: Сколько зависимостей слишком много?

У меня есть класс, который зависит от множества маленьких объектов - иногда между 6 и 10. Поскольку я продолжаю разорвать свое приложение на более мелкие куски, я мог видеть, что это число увеличивается с течением времени. Это общая проблема?

Очевидно, что это сильно зависит от проекта. Однако основной вопрос заключается в следующем:

Когда вы начинаете испытывать дискомфорт по количеству зависимостей, которые имеет класс? Какие стратегии вы используете для сокращения этих зависимостей?

ответ

10

Это может быть признак того, что класс с 6-10 зависимостями должен быть реорганизован.

+1

Что делать, если вы не можете найти логичный способ группировать их в несколько классов, таких как WW. упоминается? Согласны ли вы с тем, что тогда хорошо, чтобы иметь много зависимостей? Я имею в виду, скажем, зависимости - это марки автомобилей: BMW, OPEL, VW и т. Д. Это все автомобили. Может быть, не лучший пример, но я надеюсь, что вы поняли эту идею. –

+1

@ Darius.V - Если у вас есть класс Cars, который имеет 50 зависимостей бренда, то, очевидно, вы нарушили SRP. Вам нужно сгруппировать их в общие характеристики (например, «ElectricCars», «HybridCars», «DieselCars», «GasolineCars»), поэтому ваш класс «Cars» верхнего уровня содержит только несколько зависимостей, каждый из которых имеет общие свойства и методы. Ниже вы можете использовать [шаблон стратегии] (https://stackoverflow.com/a/31971691), чтобы упростить несколько похожих автомобилей в одну зависимость (например, просто иметь только одну «GasolineCarsStrategy», которая вводится в ваши автомобили класс, который управляет всеми газовыми машинами). – NightOwl888

4

Я бы подумал не более трех или четырех. Если вы получите больше, чем это, я бы начал думать о том, насколько хорошо вы абстрагируете свой concerns. Например, один объект repository должен удовлетворять всем потребностям поиска данных в соответствующем классе.

+3

Предположительно, если объект требует доступа к базе данных и каким-то образом может взаимодействовать извне (например, репозиторий и IO), которые уже являются 2 зависимостями из выделенного 4. Кроме того, это не является одним из побочных эффектов, гарантирующих, что каждый у класса есть одна ответственность (единственная проблема), которая приведет к большему количеству классов, а не меньше? В конечном счете, должен быть класс, который может организовывать все эти меньшие фрагменты ... и этот класс будет иметь множество зависимостей, чтобы функционировать. – Runcible

+0

@Runcible, совершенно правильно. И если ваша консолидация, которую вы описываете, имеет место, у вас действительно будет меньше вещей, которые нужно ввести в конструктор. То, что вы описываете BTW, представляет собой контейнер Inversion of Control (например, Windsor). –

+1

@Runcible, я в последнее время боролся с этой проблемой зависимости от инъекций. Я нашел два сообщения, которые были весьма полезными. http://blog.ploeh.dk/2010/01/20/RebuttalConstructorover-injectionanti-pattern/ & http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/ Еще одно замечание, я считаю, что цель SRP не должен иметь класс, который делает одно, но имеет одну из причин для изменения с точки зрения бизнеса. – GetFuzzy

0

Возможно, вам также необходимо увидеть, должен ли какой-либо из параметров вашего конструктора быть объединен в один класс (при условии, что параметры имеют смысл как класс).

Возможно, вы также захотите посмотреть на использование шаблона ServiceLocator для некоторых ваших зависимостей. Это особенно верно, если вам приходится передавать зависимости вниз по длинной цепочке конструкторов.

+4

Паттерн Service Locator не соответствует принципам впрыскивания зависимостей. Service Locator нарушает Закон Деметры: http://www.youtube.com/watch?v=RlfLCWKxHJ0 – Runcible

+0

Очень приятное видео, Runcible. Очень понятное объяснение DI, IOC, Service Locator. – Alexanderius

3

Runcible,

Вот ссылка на проект замка Виндзор. Это контейнер Inversion of Control. Эти контейнеры позволяют фабричным классам собирать ваши зависимости вместе и вставлять их как один объект в ваш конструктор.

http://www.castleproject.org/container/index.html

Я слышал хорошие вещи о Windsor. Spring также делает контейнер IoC и there are others.

9

Я бы не стал беспокоиться об этом.

Вместо этого я буду беспокоиться о том, что класс слишком сложный.

Класс со многими зависимостями, который использует их все, но не имеет циклов или если инструкции в порядке. В некотором коде, в котором я работал, в последнее время в классе было около 14 зависимостей. Однако в коде был только один путь и нет логического способа группировки зависимостей в более качественные классы.

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

1

Класс с 6-10 зависимостями - это запах кода. Это явный признак того, что класс нарушает Single Responsibility Principle.

Каковы некоторые стратегии, которые вы используете для уменьшения этих зависимостей?

Mark Seemann сделал эту задачу ясно в своем посте Refactoring to Aggregate Services и в большей степени, в своей книге Dependency Injection in .NET. Тот факт, что ваш класс имеет столько зависимостей, указывает на то, что в классе есть несколько обязанностей. Часто существует неявная концепция домена, ожидающая 0, явная, идентифицируя ее и превращая ее в свой сервис. Вообще говоря, большинству классов не нужно больше 4-5 зависимостей.

Смежные вопросы