Если класс School
зависит от класса EmailSender
, вам, возможно, придется внедрить этот EmailSender
через его конструктор с универсальным интерфейсом, таким как IMessagable
, IMessageSender
или даже IEmailSender
, чтобы в будущем его можно было заменить чем-то другим.
Для этого вы должны создать закрытое поле только для чтения в классе School
.
Но тогда вы говорите, что School
HAS-A MessageSender
, но, конечно же, он просто ИСПОЛЬЗУЕТ его в нескольких своих методах ??
как определить зависимость. Это то, что класс имеет или использует? Или и то, и другое, и, следовательно, как вы различаете, чем владеет класс, и тем, что он использует?
с точки зрения класса нет никакой разницы между отношением «имеет» и отношением «использует». На самом деле вы наверняка можете использовать то, что у вас есть, не так ли? Так что совершенно нормально использовать зависимости, предоставляемые полем.
это не то же самое, что школа, имеющая зависимость от IStudentCollection, не так ли? В этих отношениях есть более четкая связь. Конечно, EmailSender следует передавать только в методы, в которых он используется, а не быть атрибутом класса? Я надеюсь, что вы можете развеять мою путаницу. Спасибо!
У класса должно быть что-то, чтобы его использовать. Даже если это интерфейс, он все равно сводится к необходимости конкретного типа, который выполняет контракт, определенный IStudentCollection
.
в «Школе» есть «студенты: IStudentCollection», но в школе нет «emailSender: EmailSender». Имеет больше смысла передавать его только в методы, в которых он используется; вот почему инъекция зависимостей сбивает меня с толку.
Школа - нет, но тогда школа звучит как модель, а не служба. SchoolControllerService
будет иметь и использовать emailSender
на основе данных в SchoolModel
.
Для меня это больше похоже на проблему моделирования, чем на проблему DI. Игнорируя какие-либо/все концепции DI, вы думаете, что School
отвечает за отправку электронных писем? Кажется, вы согласны с тем, что ответ отрицательный. Вероятно, будет введена какая-то другая абстракция, которая будет более ответственной за отправку электронных писем/уведомлений в этих случаях (например, отдел зачисления). При правильных абстракциях зависимости должны быть ясны.
зачем тебе иметь отношения, если ты не сможешь их использовать никоим образом? Весь смысл зависимости в том, чтобы что-то с ней делать — это использовать ее. Если вы им не пользуетесь, в первую очередь нет причин его иметь.
У Shool
есть Sender
, чтобы его использовать, не так ли?
но отправитель не принадлежит к школе не так ли?
ну, человек, наверное, работает в школе, так что в каком-то смысле школа есть, если хотите.
но мы говорим об отправителе электронной почты. Это может быть регистратор, который ведет журнал. Это может быть что угодно, что School или SchoolService использует, но не владеет.
Даже если класс использует только один из многих методов переданного объекта, весь объект по-прежнему считается зависимостью класса.
Это становится очевидным, когда вы меняете API (сигнатуры методов) объекта. Передавая этот объект классу, вы, по сути, гарантируете «контракт» этого объекта. Если вы измените API этого объекта, вы рискуете сломать классы, которые от него зависят.
Вот почему мы часто используем интерфейсы для передачи зависимостей классам. Интерфейс обеспечивает соблюдение контракта между классом и его зависимостью и поощряет разделение, поскольку передаваемый объект должен соответствовать только методам интерфейса.
Номенклатура IS-A и HAS-A используется в основном для того, чтобы отличить наследование от состава.
Любое свойство/член, объявленное классом, является чем-то, что есть у класса.
Has-A здесь для того, чтобы отличаться от Is-A наследственности.
Свойство «использует» больше связано с классовой сплоченностью, чем с составом. Если у класса есть свойство-A, но он его не использует или использует в небольшом проценте функций, у него низкая связность.
И HAS-A, и IS-A являются зависимостями класса. Вот почему мы стремимся, чтобы они оба были абстракциями, чтобы слабо связать их.
Любое определение класса/интерфейса, без которого ваш класс не будет компилироваться, является зависимостью. Даже если он не имеет отношения HAS-A и просто передается как параметр функции.
а в чем вопрос?