DIP in the Wild

192 阅读1分钟
原文链接: martinfowler.com

Hide DB Behind Something Domain-related

Confusing a solution with the problem is a common mistake. Luckily, this is a well understood problem and you might already know a solution to it. A common one is to use a Repository:

Figure 8: Give Domain what it wants to see

A repository is a gateway to a conceptual (maybe actual) potentially large collection of durable objects. The interface should comprise methods that make sense to goals of a user in a domain, not to a database. If it just so happens that behind the repository sits a database, then the Repository will deal with mapping from the requests that make sense to the domain into something that makes sense to the database. Make the implementation of the abstraction do the work once rather than all consumers of a lower-level abstraction duplicating the effort.

The typical interface might include basic CRUD operations (assuming the domain calls for them) but then we'll add methods that make sense for the needs of the system. That is, as we grow the system by adding new use cases, scenarios, user stories or backlog items, we'll extend the interface so that it supports the current needs of the system. No more, no less.

Consider a system that works with travel schedules for trains. There are a number of scheduled journeys between stations. Over time new stations get built, others are closed for maintenance, and the schedule of trains between stations changes due to changes in capacity, to match seasonal demand, or to introduce specials in an attempt to lure new business. Train schedules are planned well in advance and then added to the system for future activation. The system needs to periodically find schedules that are no longer relevant, ones that are about to become active, and potential conflicts such as overlapping schedules or gaps in schedules.

Figure 9: Operations that match what my domain needs

Does this mean for a given system we will only have one Repository for a given domain concept? Maybe. Maybe we'll have multiple based on considerations like the use of Bounded Contexts, or we might split a single Repository interface based on the Interface Segregation Principle. The important consideration from the DIP perspective is that the interface exists at an appropriate abstraction level for the current needs of the system. What drives the current needs of the system? The use cases, user stories, scenarios, backlog items. That is, who are your actors, and what do they need to do?