Я использую Dependency Injection: какие типы я должен связывать как одиночные? - PullRequest
9 голосов
/ 14 августа 2010

Есть много вопросов о том, являются ли синглеты "плохими", и какие шаблоны использовать вместо них.Как правило, они ориентированы на шаблон проектирования синглтона, который включает извлечение экземпляра синглтона из статического метода класса.Это не один из этих вопросов.

С тех пор, как я действительно "обнаружил" внедрение зависимостей несколько месяцев назад, я управлял его внедрением в нашей команде, со временем удаляя статические и одноэлементные шаблоны из нашего кода, ииспользуя конструктор на основе инъекций везде, где это возможно.Мы приняли соглашения, чтобы нам не нужно было добавлять явные привязки к нашим модулям DI.Мы даже используем инфраструктуру DI для предоставления экземпляров регистратора, чтобы мы могли автоматически сообщать каждому регистратору, в каком классе он находится, без дополнительного кода.Теперь, когда у меня есть единственное место, где я могу контролировать, как связаны различные типы, действительно легко определить, каким должен быть жизненный цикл конкретной категории классов (служебные классы, репозитории и т. Д.).

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

Затем я читаю «Синглтон».Я люблю тебя, но ты меня опускаешь »на www.codingwithoutcomments.com, и это заставило меня задуматься, была ли у меня правильная идея.В конце концов, Ninject компилирует функции создания объектов по умолчанию, поэтому при создании дополнительных экземпляров этих объектов очень мало затрат на отражение.Поскольку мы скрываем бизнес-логику от конструктора, создание новых экземпляров - это действительно легкая операция.И у объектов нет группы нестатических полей, поэтому при создании новых экземпляров также не требуется много дополнительной памяти.

Итак, сейчас я начинаю думатьчто это, вероятно, не будет иметь большого значения в любом случае.Есть ли дополнительные соображения, которые я не учел?Кто-нибудь действительно испытал значительное улучшение производительности, изменив жизненные циклы определенных типов объектов?Является ли следование паттерну DI единственно важной вещью, или есть другие причины, по которым использование одного экземпляра объекта может быть по сути «плохим»?

Ответы [ 4 ]

5 голосов
/ 17 августа 2010

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

Если в условиях неопределенности я бы предпочел, чтобы объект создавался заново каждый раз, когда он используется, и помечал его как синглтон или "на поток" / "на запрос" / "на что угодно", только если вам действительно это нужно.

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

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

1 голос
/ 14 августа 2010

Я не уверен, является ли управление памятью большой проблемой, если вы не создаете МНОГО объектов.Я обнаружил, что использование синглтона из моего контейнера IoC полезно при работе с чем-то вроде кэширования, когда создание объекта кэширования и подключение к серверам кэширования является дорогостоящим процессом, поэтому мы создаем объект кэширования один раз и используем его повторно.

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

0 голосов
/ 16 августа 2010

Как отмечается в ответе Гэри , весь смысл DI - это тестируемость (вы можете легко смоделировать все ссылки на класс, поскольку все они перечислены в конструкторе), а не производительность во время выполнения.

Вы хотите сделать TDD (тест-драйв), верно?

0 голосов
/ 14 августа 2010

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

...