Entities, Services & Resources—Three Categories of Objects

After working with domains for several years I find that there are three major categories of objects I work with: Entities, Services, and Resources. There are clear distinctions between these categories in their purpose, content, dependencies and roles. Understanding these categories clarifies what dependencies I should allow, what purpose the objects serve, and how I should test them.

Purpose / Content

Entities are the domain objects. They model the data that gets persisted to the database. These objects are mostly data, and have little behavior.

Services are the workhorses of the application. They perform the majority of the business logic. These objects have little to no state, and are almost pure behavior.

Resources are the objects that interface with outside dependencies like the file system, database, etc. These objects only have the business logic necessary to interface with these outside dependencies. They are used to decouple the application from the dependency itself. A good example of a resource is a repository—which serves as the source for entities.

Dependencies

Entities only have dependencies on other entities through relationships, such as, an order having line items. An entity should never depend on services or resources.

Services can depend on anything. Services require dependencies on other services or resources to perform complex tasks—per the Single Responsibility Principle.

Resources generally only depend on the underlying subsystems they are encapsulating. Resources don’t depend upon other services, but may depend upon other resources.

Testing

Entities require the least amount of testing. They are mostly data and have simple behavior—there is little to test. But entities are used heavily in testing other objects. The serve as input and expected values when testing services and resources. Because there is so little behavior, it is easiest to use entities directly in the tests rather than mock them. (This is where frameworks like Fluency come into play to help create these objects in a state containing valid anonymous data. What mocking is to Services and Resources, Fluency is to Entities.)

Services require a great deal of testing since they are mostly behavior. Unit testing them requires mocking any other services or resource they depend on. Any entities needed to test them are created and used directly.

Resources cannot be covered in unit tests. Because they interact with underlying systems (disk, database, network, etc), any test against them is, by nature, an integration test. Resources are always mocked when unit testing other objects since they represent dependencies that we want to decouple our tests from.

Architecture

Entities are the core of the Domain Model. They represent the business domain directly.

Services can be part of the domain model or a part of the infrastructure model depending on the behavior they are supporting. For instance, a notification service would be an infrastructure concern while a loan calculation service would be a business domain concern.

Resources are always part of the infrastructure for obvious reasons.

Other

Are there any other observations you can make about these three types of objects that can help us in our thinking? If so, please add your comments. I would love to hear them.

-Chris

This entry was posted in Design, Mocking, Patterns, Principles, Testing and tagged , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*
*