Let's dive in 😄 .
1️⃣ Service Layer
A common approach in handling domain logic is to split the domain layer in two. A Service Layer (133) is placed over an underlying Domain Model (116) or Table Module (125). Usually you only get this with a Domain Model (116) or Table Module (125) since a domain layer that uses only Transaction Script (110) isn’t complex enough to warrant a separate layer. The presentation logic interacts with the domain purely through the Service Layer (133), which acts as an API for the application.
- 📝 Good Question to ask
When you see a Service Layer (133), a key decision is how much behavior to put in it. The minimal case is to make the Service Layer (133) a facade so that all of the real behavior is in underlying objects and all the Service Layer (133) does is forward calls on the facade to lower-level objects. In that case the Service Layer (133) provides an API that’s easier to use because it’s typically oriented around use cases. It also makes a convenient point for adding transactional wrappers and security checks.
it is the end of that chapter 2, now we go for the third one.
Chapter 3: Mapping to relational databases
1️⃣ The Data Source Layer
The role of the data source layer is to communicate with the various pieces of infrastructure that an application needs to do its job. A dominant part of this problem is talking to a database, which, for the majority of systems built today, means a relational database. Certainly there’s still a lot of data in older data storage formats, such as mainframe ISAM and VSAM files, but most people building systems today worry about working with a relational database.
2️⃣ Architectural Patterns
The first set of patterns comprises the architectural patterns, which drive the way in which the domain logic talks to the database. The choice you make here is far-reaching for your design and thus difficult to refactor, so it’s one that you should pay some attention to. It’s also a choice that’s strongly affected by how you design your domain logic.
- 2.1 - Gateway
A good way of organizing these classes is to base them on the table structure of the database so that you have one class per data base table. These classes then form a Gateway (466) to the table. The rest of the application needs to know nothing about SQL, and all the SQL that accesses the database is easy to find. Developers who specialize in the database have a clear place to go. There are two main ways in which you can use a Gateway
2.1.1 - Row Data Gateway
The most obvious is to have an instance of it for each row that’s returned by a query (Figure 3.1). This Row Data Gateway (152) is an approach that naturally fits an object-oriented way of thinking about the data.
2.1.2 - Table Data Gateway
Many environments provide a Record Set (508)—that is, a generic data structure of tables and rows that mimics the tabular nature of a database. Because a Record Set (508) is a generic data structure, environments can use it in many parts of an application. It’s quite common for GUI tools to have controls that work with a Record Set (508). If you use a Record Set (508), you only need a single class for each table in the database. This Table Data Gateway(144) (see Figure 3.2) provides methods to query the database that return a Record Set (508).
- 2.2 - Active Record > In simple applications the Domain Model (116) is an uncomplicated structure that actually corresponds pretty closely to the database structure, with one domain class per database table. Such domain objects often have only moderately complex business logic. In this case it makes sense to have each domain object be responsible for loading and saving from the database, which is Active Record (160) (see Figure 3.3). Another way to think of the Active Record (160) is that you start with a Row Data Gateway (152) and then add domain logic to the class, particularly when you see repetitive code in multiple Transaction Scripts (110).
- 2.3 - Data Mapper
All of these forces push you to in’direction as your Domain Model (116) gets richer. In this case the Gateway (466) can solve some problems, but it still leaves you with the Domain Model (116) coupled to the schema of the data base. As a result there’s some transformation from the fields of the Gateway (466) to the fields of the domain objects, and this transformation complicates your domain objects. A better route is to isolate the Domain Model (116) from the database completely, by making your indirection layer entirely responsible for the mapping between domain objects and database tables. This Data Mapper (165) (see Figure 3.4) handles all of the loading and storing between the database and the Domain Model (116) and allows both to vary independently. It’s the most complicated of the database mapping architectures, but its benefit is complete isolation of the two layers.
These are the patterns for the data source layer.
That's all for the day ☺️
Top comments (0)