Chapter 2. Creating services

 

This chapter covers

  • Instantiating service objects
  • Injecting and validating dependencies and configuration values
  • Promoting optional constructor arguments to required ones
  • Making implicit dependencies explicit
  • Designing services to be immutable

In the following two chapters, we’ll discuss different types of objects and the guidelines for instantiating them. Roughly speaking, there are two types of objects, and they both come with different rules. In this chapter we’ll consider the first type of objects: services. The creation of other objects will be the topic of chapter 3.

2.1. Two types of objects

In an application there will typically be two types of objects:

  • Service objects that either perform a task or return a piece of information
  • Objects that will hold some data, and optionally expose some behavior for manipulating or retrieving that data

Objects of the first type will be created once, and then be used any number of times, but nothing can be changed about them. They have a very simple lifecycle. Once they’ve been created, they can run forever, like little machines with specific tasks. These objects are called services.

2.2. Inject dependencies and configuration values as constructor arguments

2.3. Inject what you need, not where you can get it from

2.4. All constructor arguments should be required

2.5. Only use constructor injection

2.6. There’s no such thing as an optional dependency

2.7. Make all dependencies explicit

2.8. Task-relevant data should be passed as method arguments instead o- of constructor arguments

2.9. Don’t allow the behavior of a service to change after it has been instantiated

2.10. Do nothing inside a constructor, only assign properties

2.11. Throw an exception when an argument is invalid

2.12. Define services as an immutable object graph with only a few entry points

Summary

Answers to the exercises