This question about unit testing best practices упоминает классы проектирования для инъекций зависимости. Это заставило меня задуматься о том, что именно это может означать.Рекомендации по проектированию классов для инъекций зависимостей
Только что начал работать с инверсией контрольных контейнеров. У меня есть некоторые идеи по этому вопросу, поэтому позвольте мне бросить их к стене и посмотреть, какие палки.
Как я вижу это, существуют три основных типа зависимостей, которые может иметь объект.
- Зависимость от объекта - Реальный объект, который будет использоваться данным классом. Например, LogInVerifier в LogInFormController. Они должны вводиться через конструктор. Если класс достаточно высокий, что требует более 4 из этих объектов в конструкторе, подумайте о его разломе или, по крайней мере, с использованием заводского шаблона. Вы также должны рассмотреть возможность обеспечения зависимости интерфейса и кодирования с интерфейсом.
- Простая настройка - Например, пороговое значение или период ожидания. Как правило, они должны иметь значение по умолчанию и устанавливаться через построитель фабричного шаблона. Вы также можете предоставить перегрузки конструктора, которые их устанавливают. Однако в большинстве случаев вы, вероятно, не должны заставлять клиента настраивать его явно.
- Объект сообщения - Объект, передаваемый из одного класса в другой, который, по-видимому, использует принимающий класс для бизнес-логики. Примером может служить объект User для класса LogInCompleRouter. Здесь я нахожу, что часто бывает лучше, чтобы сообщение не указывалось в конструкторе, так как вам пришлось бы либо зарегистрировать экземпляр пользователя с контейнером IoC (делая его глобальным), либо не создавать экземпляр LogInCompleteRouter до тех пор, пока у вас не появится экземпляр пользователя (для которых вы не могли использовать DI или, по крайней мере, нуждались бы в явной зависимости от контейнера). В этом случае было бы лучше передать объект сообщения только тогда, когда вам это нужно для вызова метода (например, LoginInCompleteRouter.Route (User u);).
Кроме того, я должен отметить, что не все должно быть DI'ed, если у вас есть простой немного функциональности, которая была просто удобно факторизовать к классу одноразовая, это, вероятно, хорошо, чтобы создать экземпляр на месте. Очевидно, это призыв к суду; если я счел целесообразным написать класс, такой как
class PasswordEqualsVerifier {
public bool Check(string input, string actual) { return input===actual;}
}
я, вероятно, не буду беспокоить зависимость впрыскивания и буду просто объект его экземпляр непосредственно внутри с помощью блока. Следствием является то, что, если стоит писать модульные тесты, то, вероятно, стоит впрыскивать.
Так что вы, ребята, думаете? Любые дополнительные рекомендации или противоположные мнения приветствуются.