1 Introduction
Martin Fowler's Patterns of Enterprise Application Architecture (PEAA) book is not setup like a normal technical book. Instead, the first 106 pages cover a high level of some of the most common patterns used in enterprise application design that have been used in the past, present and future. The remaining 500+ pages are split into 10 chapters covering the specifics of 51 different design patterns.
Due to the format of PEAA, doing a standard book review on this book would not do it justice. Instead, my intent is to provide some feedback on a few of the patterns I have worked with and used from this book. Over the course of this and my next two articles, I hope to provide you with a real world example of how some of the patterns found in Martin's book can be used, things to consider, and things to avoid. Some of the patterns I will be covering were introduced to me before I read the book, and others were directly taken from the pages of PEAA.
All of the patterns I will be covering here were/are being used in a web framework that has been deployed in over 30 different instances. This web framework consists of a data access layer, some inherited controls, and a few page handlers. It is also very modular. For this particular framework I was not involved with the initial design, so I may not be able to provide insight as to why a particular pattern was chosen at that time. Instead, I will try and provide a look into why it is or is not working well in today's environment. No part of this book review is intended to be a sales pitch for the product. I mention it only because I feel it will give you, the reader a good background of the environment these patterns are being used in.
As a last point of clarification, I am not trying to portray myself as some advanced application designer whose words you should take as gold. In fact, I would say quite the opposite. My experience in using predetermined design patterns is limited to a handful of projects, only a handful of which I was the initial or ongoing 'architect'.
Oh, the numbers inside of () throughout this article refer to pages within the book. You will see this same mechanism throughout the book when you go purchase it. Here we go!
2.1 Domain Model(116)
"An object model of the domain that incorporates both behavior and data."
In our framework, the initial goal was to create a code base that would allow us to quickly build a new website with all of the core functionality (page management, security, etc) out of the box, while also providing us with the ability to easily extend the core objects to meet a specific client's needs. This was accomplished by implementing Fowler's definition of a "rich Domain Model", using Data Mapper(165).
If you were to take a look at our domain layer, you would see absolutely no database code. Instead you will find a model of the base objects, caching mechanisms, and a few other pieces of functionality need to live at the highest level of our framework. The reason for the lack of data manipulation code is due to our implementation of the Data Mapper(165) pattern. I will talk more about this later in this article.
Our initial implementation of the Domain Model(116) was not quite perfect. As Fowler mentions, it is very important to keep the Domain Layer separate from all other layers. Our first few projects we less than perfect to say the least. Before we realized the importance of a Service Layer(133), our UI layer was tied to the Domain Layer at the hip. Changes were very difficult to say the least, and regression testing on existing applications frequently failed due to breaking changes throughout the Domain Layer. Because of this it became very clear that some sort of business layer was needed for each project. We quickly realized that although this Domain Model(116) provided us with the ability to add new objects specific to a client; it was not very useful for extending existing objects without impacting every application that had utilized our framework.
2.2 Service Layer(133)
"Defines an application's boundary with a layer of services that establishes a set of available operation and coordinates the application's response in each operation."
As I mentioned before, early on we realized that our framework would not live, or serve its intended purpose for very long if we did not find a way to implement some sort of business layer. It was at this time that I was reading the PEAA book and realized that the Service Layer(133) pattern was exactly what we needed. Specifically the "domain facade" that Fowler describes. This is a Service Layer(133) that implements a set of thin facades over the Domain Model(116).
In its simplest form, a Service Layer(133) is a business logic layer. By implementing the Service Layer(133) pattern, we were now able to keep 100% of our client specific code out of the Domain Model(116), giving us greater flexibility, and also reducing the amount of regression testing we needed to do for every change dramatically.
The first couple of projects where we implemented the Service Layer(133) were a bit time consuming. This was not due to the patterns complexity, but more so because we had to go back and create Service Layers(133) for the existing projects, strip out client specific code from the Domain Model(116), and then retest. Even though this bit of refactoring was time consuming, it was also very valuable for the team. It gave us a lot of insight as to how we should plan future enhancements and also helped the team as a whole to better understand the Domain Model(116) since not all developers were involved in its initial creation.
Our first couple of Service Layer(133) designs were less than perfect. Initially our UI was making direct calls to methods in both the Domain Model(116) and the Service Layer(133), sometimes even in the same method. This quickly proved to be an issue and we made the decision that all object iterations must go through the Service Layer(133) only. This helped to reduce a number of issues we ran in to during testing, especially the casting issues we were having.
3.1 Data Mapper(165)
"A layer of Mappers(473) that moves data between objects and a database while keeping them independent of each other and the mapper itself."
The Data Mapper(165) pattern is where a lot of the magic happens. Fowler does an excellent job of defining exactly what a Data Mapper(165) should consist of, and what it should not. Although I was not involved with the initial design of our framework, I am able to look back and clearly see why the Data Mapper(165) pattern was implemented. Because of the Data Mapper(165) pattern, our Domain Model(116) and Service Layers(133) are completely unaware of the data source. This gives us the flexibility to use any data source we want. We currently have support for MSSQL and Oracle, but if we were to need to use, say MySQL, we would not be rewriting our entire Domain Model(116). Instead we would simply need to create a new set of Data Mappers(165) and be on our way.
Martin also describes a couple different ways to implement the Data Mapper(165) pattern. One way is the single mapper approach. As he describes, this is only ideal if your code base also implements the Metadata Mapper(306). Since ours does not, we chose to implement one Data Mapper(165) per object in our Domain Model(116) and Service Layers(133).
Closing
And that concludes my first ever CodeProject article. I will be following this article up with 2 more articles. The next one will be focused on Object-Relational Behavioral Patterns and Object-Relational Structural Patterns and the final article will cover Web Presentation Patterns.
I expect feedback from you. I don't care if you think I did an outstanding job with this review, or if you feel I should delete it. Please provide me with feedback! Thank you for your time and I hope you have enjoyed this article.