Мое наблюдение состоит в том, что в большинстве случаев классы, имеющие конструктор, который принимает как зависимости, так и примитивы, нарушают Принцип единой ответственности или, по крайней мере, приводят к менее чистому проекту, что приводит к контейнеру конфигурации, которые являются более хрупкими и трудными для понимания.
В большинстве (если не во всех) случаях эти примитивы являются значениями конфигурации, такими как строки подключения, параметры отладки и тому подобное.
Есть несколько способов изменить дизайн, чтобы решить эту проблему:
- В случае, если вы нарушаете SRP, извлеките код в его собственный тип. Возьмем, к примеру, этот пример , где
NotifyCustomerHandler
принимает string notificationServiceUrl
, тогда как этот string
должен был быть заключен в некоторый тип NotificationService
.
- Другой вариант - извлечь значения конфигурации типа в его собственный тип. В случае
NotifyCustomerHandler
он может зависеть от INotifyCustomerHandlerConfiguration
. Раньше у меня был один интерфейс IMyApplicationConfiguration
со всеми значениями конфигурации, которые требовались приложению, но я пришел к выводу, что это плохая идея. Это нарушает принцип разделения интерфейсов , и ваши модульные тесты начнут страдать с точки зрения читабельности и удобства обслуживания.
- Когда вы не нарушаете SRP и вставляете объект конфигурации нецелесообразно (когда у вас есть один примитив или у вас слишком много конфигурационных интерфейсов, или вам просто не нравится эта опция), вы можете изменить этот конструктор аргументы в пользу публичной собственности. Это позволит вам (с большинством контейнеров) зарегистрировать делегата, который будет настраивать экземпляр после создания, таким образом, чтобы компилятор мог проверить это для вас.