Apex Enterprise Patterns - Separation of Concerns
Software is often referred to as a living thing that changes and evolves over time. From the single-celled amoeba of a "Hello World" program, to the complexity of enterprise-level software, the range and variety in life occurs in software as well.
Complex organisms evolve systems for specialized purposes. Skeletons, muscles, and organs work as a discrete unit, but also interface with other systems to benefit the whole. The same is true of complex enterprise applications. By separating the various concerns into different systems, a healthier and more adaptable program evolves.
Separation of Concerns
Complex code gets out of hand when you don't partition it properly. Code becomes heavily intermixed, making it error prone, difficult to maintain, and hard to learn, only serving to worsen the problem as you bring new developers into the party! Creating modules or libraries to share common calculations or processes among different parts of your application is often the first step in 'code re-use'. Which is of course, a very good thing!
Is SOC just a fancy word for 'code re-use' then?
If you're considering SOC properly, you're doing some upfront thinking about the internal plumbing of your application (down to class naming conventions and coding guidelines) that you feel will endure and hopefully be somewhat self-describing to others going forward. The usual adhoc approach to code re-use sees fragments of code getting moved around as soon as two or more areas start to need it. The code is often just placed in MyUtil classes or some other generic dumping area. Which is fine, and certainly recommended to copy-and-paste!
So what are the benefits of SOC?
At a high level applications have three things: storage, logic and a means to interact with them (be that by humans and/or other applications). Once you separate these, you can start to define layers within your application, each with its own set of concerns and responsibilities to other layers, and the application as a whole. Careful consideration and management of such layers is important to adopting SOC.
- Evolution. Over time, as technology, understandings and requirements (both functional and technical) evolve, any one of these layers may need to be significantly extended, reworked or even dropped. Take a look at UI technology over the last 10 years as a prime example of this.
- Impact Management. Performing work or dropping one or more of these layers should not unduly impact other layers, unless the requirements lead to that.
- Roles and Responsibility. Each layer has its own responsibility and should not drop below or over extend that responsibility. For example dropping one client technology / library in favour of another should not mean losing business logic, as this is the responsibility of another layer. If the lines of responsibility get blurred it erodes the purpose and value of SOC.
On the Force.com platform, there are two distinct approaches to development, declarative (point-and-click) and traditional coding. Either can be used on its own or in conjunction. These two approaches fit into the standard SOC layers as depicted in the following image:
When You Don't Need SOC on Force.com
One of the key benefits of Force.com, is its declarative development model, the ability to create objects, fields, layouts, validation rules, workflows, formula fields etc without a single line of code. Declarative development is faster and easier, and already implements a degree of separation of concerns. So if your app is heavily data centric, you'll get by with delivering a large portion of your application this way!
So while not code, what you can achieve with declarative development is still very much an architecture layer in your application, one that I will talk about more later.
When to Use SOC on Force.com
If your app is process-centric and/or getting pushed to implement more complex calculations, validations or richer UI experiences, you'll be dipping into the land of Apex code. Force.com provides many places to place Apex code: triggers, Visualforce controllers, APIs, batch Apex, email handlers, etc., the list goes on. You can make a huge investment in developing and testing code, but it's the business logic that you should be most concerned about protecting.
We will start to explore some rules for defining what goes into these in the further parts of this series. For now consider the following...
- If you had to replace or add another UI to your app (e.g. Mobile) how much of that code would you be rewriting/porting that has effectively nothing to do with the UI's responsibility, but more to do with inserting, updating, validating and calculating in your app?
- If you wanted to provide a public facing API (such as REST) to your logic, how would you do this? What parts of your existing code base would you call to implement the API?Would you use action methods in your VF controllers, passing in bits of view state?
- If you were asked to scale your application logic via batch Apex, as well continue to provide an interactive experience (for smaller volumes) via your existing UI, how would you share logic between the two to ensure the user gets consistent results regardless of the size?
- Visualforce provides a means for you to partition your code via MVC (a form of SOC for client development), but simply using Visualforce and Controllers does not guarantee you have implemented it. For example how complex are your action methods in your controllers? Do you have any code does more than just deal with handling content to and from the user?
- How easily can new developers find their way around your code base? How much time would they need to learn where to put new code and where to find existing behaviour?
Depending on how you've placed your code, you may already be in good shape to tackle some of the above. If not, or just curious, hopefully the upcoming articles will help shed a bit of light for further thought.
This page is the first describing Enterprise Application Architecture patterns, particularly focused on applying them on the Force.com platform. If you attended Dreamforce 2012 this year, you may have caught a presentation on this topic. In the meantime, if you missed the session and fancy a preview of the patterns that help support SOC. You can find the Github repo here along with slides and a recording. For now, please feel free to comment, make suggestions and requests for topics and use cases you would like covered and I'll do my best to include and answer them!
The next article in the series can now be found here. Links to the rest of the series can be found in the Links section below.
Here are a few links to other resources, the DF12 session and discussions of late that relate to this post. These will give you some foresight into upcoming topics I'll be discussing here. Enjoy!
- Apex Enterprise Patterns - GitHub Repo
- Apex Enterprise Patterns - Service Layer
- Apex Enterprise Patterns - Domain Layer
- Separation of Concerns (Wikipedia)
- Any documentation on writing reusable code?
- Martin Fowlers description of some of the upcoming patterns I'll be discussing in respect to Force.com.
- Slides from my Dreamforce 2012 presentation
- Video recording of a re-run of the session I did at Dreamforce 2012.