1) When the domain level uses the IS infrastructure service, then its interface is defined within the domain level, and its implementation is defined at the infrastructure level.
We should not enter IS (for example, repository or email service) directly in the domain entities:
class Foo { IRepository repo; ... public int DoSomething() { var info = repo.Get...; ... } }
Instead, if any Domain Entity method needs a specific IS , then the Application layer can pass that IS as an argument to this method:
class Foo { ... public int DoSomething(IRepository repo) { var info = repo.Get...; ... } }
a) I suggest that IS should also not be entered directly into domain services:
class TransferService { IRepository repo; ... public bool Transfer() { var info = repo.Get...; ... } }
but instead, IS should be passed as an argument to those Domain Service methods that intend to use it:
class TransferService { public bool Transfer(IRepository repo) { var info = repo.Get...; ... } }
b) I assume that if the Domain Entity method needs to use a domain service, it does not need to get it with an argument (although passing the Domain Service as an argument has the advantage of explicitly passing the method dependencies), but can instead call it directly, and the reason is in that both the domain entity and the domain service are domain concepts:
class Foo { ... public int DoSomething() { var info = TransferService.Transfer(...); ... } }
UPDATE:
one)
IS can be entered into the domain service if it is necessary for functionality - i.e. not passed to the method. This is different from and this is due to the fact that the domain service is stateless, and therefore it can be configured with the necessary dependencies once and used where necessary, for example, by other objects.
a) Therefore, the main reason why IS should not be entered into domain objects is due to their statefulf state?
b) But I thought that the main reason not to enter IS in Domain Entities is because it violates the rule of maintaining ignorance?
c) What problems cause the natural character of the object if we insert it using IS ?
d) Does the IS introduce a PI violation into the domain service? If not, why not?
2)
The domain service should be passed to the object as an argument, like you will pass the repository interface as an argument. The same principles apply.
But unlike the Repository, a domain service is a domain concept, so what do you mean by "the same principles"? Namely, entering a domain service into a domain entity will not violate PI , while investing in a repository will!
SECOND UPDATE:
one)
but)
This is one of the reasons. Another is that a useless connection is created. If the repository is necessary for only one behavior on the object, why introduce it into the entity all the time? Also, now you need to think about how you will resolve these dependencies? Make entities part of a dependency injection schedule? This quickly overloads the responsibilities of the facility.
So, if I understand you correctly - Injecting IS into a DS domain service does not violate SRP, because DS uses it to perform its assigned tasks (that is, its assigned responsibility), and injecting IS into a domain entity is a violation of SRP, since the primary responsibility of Domain Entity is focused on its life cycle and identity, and IS in most cases is not an integral part of managing these two tasks (i.e. focuses on the life cycle and identity)?
b)
You can still pass IS to the domain entity method and the problem here would not be a PI violation, since you are passing an interface, not an implementation. The problem is a PSA violation if the domain method used only one method on the IS interface.
I - But in several of your previous posts you noted that it is normal to pass IS as an argument to the Domain Entity method, but here you say that it will violate SRP if this domain method used only one method for an IS instance?
II. If IS implemented a role-based interface containing one method, and instead we pass this role-based interface as an argument to a domain method, would you still consider this an SRP violation? If not, why not?
d)
PI is supported using interfaces.
I read several times that even if a domain method refers to a repository through an interface, it is still considered a violation of the PI. Why do not you agree with this?
2)
It is better, however, to be very explicit. Therefore, instead of a repository and an implicit understanding of what a service is for the subject, declare the provided functions as their own interface and depend on this object.
a) So, the only reason not to enter a domain service into a domain entity due to SRP violation?
b)
declare the provided functionality as your own interface
I assume that you propose to use role interfaces? But not even inserting a role-based interface (implemented, say, by Domain Service) into a domain entity causes an SRP violation, because, as you noted in 1a , injection functionality is most likely needed only for a single domain entity behavior ?!
It looks like you and Aaron Hawkins are on opposite sides with respect to transferring IS methods to domain entities ?!
THIRD UPDATE:
one)
but)
So, if I understand you correctly - Putting IS into the DS domain service does not violate SRP, because DS uses it to perform the assigned tasks (that is, its assigned responsibility), while the injection of IP into the Domain Essence is a violation of the PSA, since the main Domain Entity responsibility focuses on its life cycle and identity, and ISmost time is not an integral part of managing these two tasks (i.e. focusing on the life cycle and personality)?
Yes, this is correct and one of the main reasons.
I - from a distance it seems quite reasonable that, by introducing IS into the DE domain entity, this DE will violate SRP, because IS will not facilitate the management of the two tasks assigned to DE .
But it is a little more complicated when you try to present this scenario in more detail. Namely, if DE methods are focused on managing two assigned tasks (that is, on its life cycle and identity), then if one of these methods needs an IS , is it reasonable to assume that an IS is required to complete the two assigned tasks, and not some other task not related to the DE life cycle. If so, how can we argue that DE violates SRP?
II - It is also difficult for me to imagine what exactly is meant by the management of the DE life cycle. For starters, when an identifier is assigned to DE , that name does not change. So, what about his identity, we would need to manage?
III - And what is meant by DE life cycle management? Perhaps defining invariants on DE that save their data or ...?
IV. Thus, all other tasks (that is, those that are not related to the life cycle and identity of DE) that the real world performs must be accounted for from DE and placed in related objects?
d)
If IS implemented a role-based interface containing one method, and instead we pass this role-based interface as an argument to the domain of the method, would you still consider this a violation of the PSA? If not, why not?
This is not scary, but it can violate SRP or, as guillaume31 - ISP is more clearly stated.
I'm not sure how we can argue that injecting IS into DE can violate ISP , because as far as I know, ISP can only be violated by an object that implements this interface, and not by the object into which the implementation of this interface is injected?
FOURTH UPDATE:
I'm starting to realize that SRP is more confusing than I originally thought
but)
The behavior associated with the object, which usually entails a state of change, should also be placed in the object. If this behavior requires the use of a service, pass on the service, but as a rule, try to put as much behavior as possible into the object.
IV - 1 The following behavioral methods do not include state changes, but I believe that they should also belong to the Dog object:
class Dog { ... void DoBark(); void DoFetch(); void DoGuard(); Breed GetBreed(); Pedigree GetPedigree(); Snack FavSnack(); }
IV - b) Are the GetBreed , GetPedigree and FavSnack behavioral? If so, then the properties Breed , Pedigree and Snack should also be considered as behavior, since they essentially provide the same functionality (provided that GetBreed , GetPedigree and FavSnack do not perform some heavy calculations, but simply return objects):
class Dog { ... void DoBark(); void DoFetch(); void DoGuard(); Breed Breed { get{...} } Pedigree Pedigree { get{...} } Snack Snack { get{...} } }
IV - c) if the above properties also had setters, will we say that they contain changing state behavior?
IV - d)
The behavior associated with the object, which usually entails a state of change, should also be placed in the object.
But if the primary responsibility of Domain Entity is to manage its life cycle, it will not include non-life cycle management behavior that is a violation of SRP (in the example above, methods like Dog.DoBark most likely do not have much in common with Dog life cycle) ?!
d)
I.
Passing IS to the DE behavioral method is better, however, it can violate SRP / ISP if the IS interface has a lot of things unrelated to behavior at hand. This is the basic premise of ISP - dependencies must be made on specific interfaces, in contrast to bloated interfaces, which usually contain the required functionality.
therefore, if IS , passed as an argument to one of the DE-methods of behavior, has some operations that are not related to behavior, but the DE M method does not use any of the IS methods, not related to the behavior of M , should be processed, we still consider Does DE violate SRP / ISP?
II. - I understand what you are saying, but my confusion stems from the fact that according to the following ISP definitions, this term should be used only to mean that the ServObj object that implements the specific interface violates the ISP, and the object into which ServObj is entered , violates SRP (due to receiving ServObj ):
The principle of interface segregation is similar to Single. The principle of responsibility is that they relate to cohesion of duty. In fact, ISP can be understood as applying SRP to a common object interface.
To a certain extent, the ISP can be considered a subset or more specific form of the principle of shared responsibility. The ISP shift perspective, however, considers a public API for a given class or module.
Thank you