Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why must Domain services use domain objects as parameters and return values?

When operation doesn't conceptually belong to any Entity or Value Object, then rather than forcing the behavior into an object, we should create a Domain Service.

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

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

b) Why doesn't DDD also require methods of Entities and Value Objects to use domain objects as parameters and return values? Why instead is this constraint placed only on Services?

Thank you

EULERFX:

1)

Both of these constraints promote immutability and a functional style

a) How do the two constraints promote immutability?

b) What is functional style?

c) So we should try ( since it may not always be possible to use force ) to force the Service to use domain objects as parameters and return values, even though it may be more natural for that service ( ie behavior ) to accept/return non-domain objects?

2)

Entities and value objects compose more primitive types to form complex types and some behaviors may depend on a primitive parameter.

So is it due to some sort of intrinsic characteristic of Domain Entities/Value objects that in most cases their behaviors ( ie their operations ) operate on primitive types ( ie use primitive types as parameters )? If yes, then is in majority of cases this intrinsic characteristic found in domain objects, but rarely in domain services?

SECOND UPDATE:

How do the two constraints promote immutability?

The idea is that a domain service does not mutate state and all state changes are made explicit through parameters.

a) Not mutate its own state or some domain object's state? Since domain service should be stateless, I assume you mean it shouldn't mutate DO's state? In other words, service promotes immutability by making sure that any DO which it intends to modify is passed to it ( ie passed to its operation ) as an argument?

b) But if instead DO to be modified by service isn't passed as an argument, then we say that domain service mutated the state of this DO?

c) Is reason why mutating the state of a DO is considered a bad thing, is because it doesn't promote clarity ( ie it's not immediately obvious when looking at the signature of a service operation, which DOs will get their state changed by the operation )?

d) If domain service is going to modify the state of a DO passed to it as an argument, would it be ideal if values it'll use to change the state of this DO would also be passed as an argument to the service. If yes, is it because it promotes clarity or...?

2) I still don't understand how return value being of same type as argument also promotes immutability?

EULERFX 3

a)

A domain service can avoid state mutation by returning new instances of objects instead of modifying the objects that were passed in.

Not a question per say, more of an observation, but some difficulties understanding why would such services behavior be common in most domain models or even whether such behavior comes naturally about when modeling the domain or we must force it into the concept a bit?!

b)

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

And major reason why DO should mutate itself is because that way code performing the mutation on a particular DO is concentrated in one place and so if we need to inspect this code, we know where to look for it?

like image 657
user437291 Avatar asked Jan 14 '13 20:01

user437291


People also ask

Why do we need value objects?

Value Objects can be especially useful as a means for describing concepts in an application that have intrinsic rules but which are not themselves entities. In many applications, some concepts that are described as entities would be better off implemented as value objects.

When should I use domain services?

We use Domain Services when putting the logic on a particular entity would break encapsulation and require the entity to know about things it really shouldn't be concerned with.

What is the difference between entity and Value Object?

The main difference between entities and value objects lies in the way we compare their instances to each other. The concept of identifier equality refers to entities, whereas the concept of structural equality - to value objects. In other words, entities possess inherent identity while value objects don't.

What is an object domain?

Domain objects are the basic building blocks of an application. Domain objects are the basic building blocks of an application. They are the objects that represent the data in the application. Domain objects are the objects that the user interacts with. They are the objects that the user manipulates.


1 Answers

a) This is not a strict constraint, but offers certain advantages. The idea behind the rule is that domain services contain functionality that supplements existing entities and value objects. Another non-strict constraint is closure of operations where both the argument and the return value of domain service methods are of the same type. Both of these constraints promote immutability and a functional style thereby reducing side-effects and making it easier to reason about the code, refactor the code, etc.

It is possible to have a domain service method that accepts a primitive type which is neither an entity or value object. However, extensive use of primitive types can result in primitive obsession.

b) This constraint can be applied at the entity and value object level to an extent. Entities and value objects compose more primitive types to form complex types and some behaviors may depend on a primitive parameter. This primitive parameter can itself be turned into a value object.

UPDATE

Just returned from DDD meetup where I had a chance to talk this over with Vaughn Vernon author of Implementing Domain-Driven Design. He agrees that the specified constraint is not strict. In other words, there are scenarios where it is perfectly acceptable for a domain service method to be parameterized by primitive types.

How do the two constraints promote immutability?

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

What is functional style?

I'm referring to functional programming. Programming in a functional style usually entails immutability and pure functions. Another trait of a functional approach is a declarative style contrasted with imperative.

So we should try ( since it may not always be possible to use force ) to force the Service to use domain objects as parameters and return values

No. If a primitive type suffices for an operation there is no reason to coerce it into something else. The use of entities and value objects is only a guideline and some prefer to be more strict than others. Some, for instance, use an explicit type to represent identities for each entity. So instead of using int you'd create a value object called OrderId to represent an identity of an order.

So is it due to some sort of intrinsic characteristic of Domain Entities/Value objects that in most cases their behaviors ( ie their operations ) operate on primitive types ( ie use primitive types as parameters )?

I wouldn't say it is intrinsic to DDD. I was referring to the more general idea of composition - complex entities (non-DDD) are composed out of simpler ones. By this token, it makes sense that operations on complex entities would be expressed in terms of constituent parts.

UPDATE 2

a) A domain service can avoid state mutation by returning new instances of objects instead of modifying the objects that were passed in. In this way, the signature of the method fully describes what it does because there are no side-effects.

b) A domain service can mutate state of an object passed to it, in which case the return type would likely be full. This however is less desirable - it would be better for a DO to mutate its own state.

c) Yes that is part of it. Immutability and purity allow you to refactor code much like you would factor an algebraic equation with substitution. Another reason is that it makes reasoning about the code easier since if you look at a piece of immutable data you can be certain it doesn't change for the remainder of its scope.

d) Yes, although in that case it would be better for the domain object to mutate itself. This mutation would be invoked by a surrounding application service. A lot of times I pass domain services to entity behavior methods to provide them functionality they don't have access to directly.

e) The notion of closure of operations does not in and of itself promote immutability but it is a characteristic of immutable code. The reason is that a if a domain service method accepts a value of type T and returns a value of type T it can indicate that it returns a new value of T resulting from the encapsulated operation. This is a characteristic of immutability because the change resulting from the operation is made explicit as a new object.

UPDATE 3

a) This has more to do with traditional OOP than it does with DDD. OOP tries to hide the moving parts behind objects - encapsulation. FP tries to minimize the moving parts - immutability. Immutability can be seen as more "natural" in some scenarios. For example, in event-centric scenarios, events are immutable because they are a record of what has happened. You don't change what has happened, but you can create compensating actions.

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

like image 112
eulerfx Avatar answered Oct 11 '22 16:10

eulerfx