Why should domain services use domain objects as parameters and return values?

When an operation does not conceptually belong to any object or object value, instead of forcing behavior on the object, we must create a domain service.

The Service interface should be defined in terms of other elements of the domain model. In other words, the parameters and return value of the shold service are domain objects

a) Why / should domain services use domain objects as parameters and return values?

b) Why does DDD also not require Entities and Value Objects to use domain objects as parameters and return values? Why is the restriction instead limited only to services?

thanks

EULERFX:

1)

Both of these limitations contribute to immutability and functional style.

a) How do these two constraints contribute to immutability?

b) What is a functional style?

c) Therefore, we should try (since it is not always possible to use force) to force the Service to use domain objects as parameters and return values, even if it may be more natural for this service (i.e., accept / return non-domain objects?

2)

Objects and value objects make up more primitive types for the formation of complex types and some types of behavior may depend on a primitive parameter.

This is due to some internal characteristic of Domain Entities / Value objects, which in most cases their behavior (i.e., their operations) work on primitive types (i.e. use primitive types as parameters)? If so, then in most cases is this internal characteristic found in domain objects, but rarely in domain services?

SECOND UPDATE:

How do these two limitations contribute to immutability?

The idea is that the domain service does not change state and all change states become clear through the parameters.

a) Do not mutate his own state or the state of any domain? Since the domain service should be inactive, I assume that you mean that it should not mutate the DO state? In other words, does the service contribute to immutability by ensuring that any DO that it intends to modify is passed to it (i.e., passed to its operation) as an argument?

b) But if instead the DO, which should be changed by the service, is not passed as an argument, then we say that the domain service changed the state of this DO?

c) Is the reason why the DO state mutation is considered bad is because it does not contribute to clarity (i.e., it is not immediately obvious when considering the signature of a service operation that DOs get their state changed by operation)?

d) If the domain service changes the state of the DO passed to it as an argument, it would be ideal if the values ​​that it will use to change the state of this DO are also passed as an argument for the provision of services. If so, is it because it promotes clarity or ...?

2) I still don't understand how the return value of the same type as the argument also contributes to immutability?

EULERFX 3

a)

A domain service can avoid state mutations by returning new instances of objects instead of modifying the objects that were transferred.

Not a question, say, more about observation, but some difficulties in understanding why the behavior of such services would be common in most domain models, or even regardless of whether such behavior occurs when modeling a domain, or should we force it to understand a bit? !

b)

Yes, although in this case it would be better for the domain object to mutate itself.

And the main reason why DO must mutate itself is because this code that mutates on a particular DO is concentrated in one place, so if we need to check this code, we know where to look for it?

+4
source share
1 answer

a) This is not a strict restriction, but it offers certain advantages. The idea behind this rule is that domain services contain functionality that complements existing and value objects. Another lax restriction is to close operations in which both the argument and the return value of the domain service methods are of the same type. Both of these limitations contribute to immutability and functional style, which reduces side effects and facilitates code explanation, code refactoring, etc.

Perhaps there is a domain service method that accepts a primitive type that is not an object of an object or value. However, the widespread use of primitive types can lead to a primitive obsession .

b) This restriction may apply at the level of the object and the object of value to the extent. Objects and value objects make up more primitive types for the formation of complex types, and some types of behavior may depend on a primitive parameter. This primitive parameter itself can be turned into an object of value.

UPDATE

Just returned from a DDD meetup, where I had the opportunity to talk about it with Vaughn Vernon author of Domain Management Implementation . He agreed that the limitation was not strict. In other words, there are scenarios where it is acceptable for a domain service method to be parameterized with primitive types.

How do these two limitations contribute to immutability?

The idea is that the domain service does not mutate the state, and all state changes become explicit through the parameters. This is the essence of pure function . Given that domain services complement entities, their methods must be expressed in these terms.

What is a functional style?

I mean functional programming . Functional style programming usually entails immutability and pure functions. Another sign of a functional approach is the declarative style , which is the opposite of the imperative.

Therefore, we should try (since it is not always possible to use force) to force the service to use domain objects as parameters and return Values

No. If the operation is of a primitive type, there is no reason to force it to do something else. The use of objects and objects of value is only a guideline, and some prefer to be more strict than others. Some, for example, use an explicit type to represent identities for each object. So instead of using int you will create a value object named OrderId to represent the order ID.

So this is due to some internal characteristic of the domain. Objects / values, in most cases, their behavior (i.e. their operations) work on primitive types (i.e. use primitive types as parameters)?

I would not say that this is an integral part of DDD. I had in mind a more general idea of ​​composition - complex objects (non-DDD) consist of simpler ones. Thus, it makes sense that operations on complex objects will be expressed through their constituent parts.

UPDATE 2

a) A domain service can avoid state mutations by returning new instances of objects instead of modifying transferred objects. Thus, the method signature fully describes what it does, because there are no side effects.

b) The domain service can change the state of the object it passed, in which case the return type is likely to be populated. This, however, is less desirable - it would be better if the DO changed its own state.

c) Yes, that is part of it. Consistency and purity allow you to reorganize code in the same way as the factor of an algebraic equation with substitution. Another reason is that it simplifies the discussion about code, because if you look at a piece of immutable data, you can be sure that it will not change for the rest of its area.

d) Yes, although it would be better for the domain object to mutate itself. This mutation will be caused by the surrounding application service. Many times I pass domain services to entity behavior methods to provide them with functionality that they do not have direct access to.

e) The concept of closing operations does not in itself contribute to immutability, but is a characteristic of immutable code. The reason is that if the domain service method accepts a value of type T and returns a value of type T, it may indicate that it returns a new value of T obtained as a result of the encapsulated operation. This is a property of immutability, since the change caused by the operation becomes explicit as a new object.

UPDATE 3

a) This is more related to traditional OOP than to DDD. OOP tries to hide the moving parts of objects - encapsulation. FP tries to minimize moving parts - immutability. In some scenarios, immutability can be seen as more “natural." For example, in event-oriented scenarios, events are unchanged because they are a record of what happened. You do not change what happened, but you can create compensatory actions.

b) Again, this has more to do with OOP than with DDD and is based on an expert information template that essentially states that data behavior should be as close as possible to that data. In DDD, this means that the object must encapsulate the contained data as much as possible so that it can provide its own integrity.

+6
source

All Articles