Understand Separation of Concerns
Learning Objectives
After completing this unit, you’ll be able to:
- Explain the business value of adopting separation of concerns.
- Use SOC to adapt your solution to changes in user requirements or platform technologies.
- Apply SOC to Salesforce development.
- Determine when to apply SOC.
Introduction
Software, like hairstyles, 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 also occurs in software. Complex organisms evolve systems for specialized purposes. Skeletons, muscles, and organs work as a unit, but they also interface with other systems to benefit the whole.
The same is true of complex enterprise applications. Separating the various concerns into different systems or layers makes code easier to navigate and maintain. When changes are made, the impacts and regressions on other areas are minimized, and a healthier and more adaptable program evolves.
Follow Along with Trail Together
Want to follow along with an expert as you work through this step? Take a look at this video, part of the Trail Together series.
Separation of Concerns (SOC)
Codey the bear often says, "The best code is written away from the keyboard." This is another way of saying that good code benefits from careful design and foresight. Keep this recommendation in mind when planning where to put your code. Coding should be easy when you know the path you’re going to take!
Complex code gets out of hand when you don’t partition it properly. When code is heavily intermixed, it becomes error prone, difficult to maintain, and hard to learn. Have you ever tried to debug someone's spaghetti code? And the problems get worse as you bring new developers into the party! Creating modules or libraries to share common calculations and processes among different parts of your application is often the first step in code reuse, which is, of course, a good thing!
Is SOC Then Just a Fancy Word for Code Reuse?
Yes... and no. SOC requires some upfront thinking about the internal plumbing of your application, including class naming conventions and coding guidelines. You want this planning to endure and be somewhat self-describing to others. Good code should tell a story. The usual approach to code reuse is moving fragments of code around as soon as two or more areas 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!
What Are the Benefits of SOC?
At a high level, applications have three things: storage, logic, and a means to interact with them, whether by humans, woodland creatures or other applications. When you separate these things, 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 these layers is important to adopting SOC.
- Evolution. Over time, as technology, understandings, and requirements (both functional and technical) evolve, a layer might need to be extended, reworked, or even dropped. Take a look at UI technology over the past 10 years as a prime example. How many JavaScript frameworks can you count before passing out?
- Impact management. Modifying or dropping one or more layers should not unduly impact other layers, unless this is the intention due to requirements.
- Roles and responsibility. Each layer has its own responsibility and must not drop below or over-extend that responsibility. For example, dropping one client technology or library in favor of another does not mean losing business logic, because this is the responsibility of another layer. If the lines of responsibility get blurred, the purpose and value of SOC are eroded and that's not good.
The Salesforce platform has two distinct approaches to development, declarative (point-and-click) and traditional coding. You can use either method on its own or in conjunction. The two approaches fit into the standard SOC layers as outlined below.
Presentation
- Declarative: Layouts, Record Pages, Flow, Record Types, Formulas, Reports, Dashboards
- Coding: Apex Controllers, Visualforce, Lightning Components
Business Logic Layer
- Declarative: Formula, Flow, Validation Rules, Sharing Rules, Approval Processes
- Coding: Apex Services, Apex Custom Actions, Asynchronous Apex
Data Access Layer
- Declarative: Data Loaders, Salesforce Connect
- Coding: SOQL, SOSL, Salesforce APIs
Database Layer
- Declarative: Custom Objects, Fields, Relationships, Rollups
- Coding: Apex Triggers
When You Don’t Need SOC on Salesforce
One key benefit of Salesforce is its declarative development model that lets you create objects, fields, layouts, validation rules, workflows, formula fields, and so much more without writing a single line of code. Declarative development is faster and easier, and it already implements a degree of SOC. If your app is heavily data-centric, and you can deliver a large portion of your application declaratively so don't recreate the wheel, just use it!
Although it’s not code, what you can achieve with declarative development is still very much an architecture layer in your application, which we’ll talk about more later.
When to Use SOC on Salesforce
If your app is process-centric or you are getting pushed to implement more complex calculations, validations, or richer UI experiences, you’ll be venturing into the land of Apex code. Salesforce provides many places to place Apex code, such as triggers, classes that include @AuraEnabled
methods, APIs, batch Apex, and email handlers.
You can make a huge investment in developing and testing code, but it’s the business logic that you are most concerned about protecting. We explore some guidelines for writing business logic at a later time but for now consider the following instances for using SOC on Salesforce.
- Replacing or adding another UI to your app — Consider how much code you need to rewrite or port that has nothing to do with the UI but affects your app’s inserting, updating, validating and calculating functionality.
- Providing a public-facing API to your logic — Assess which parts of your existing code base you would call to implement the API. Is using your
@AuraEnabled
methods a good basis for an API? (The answer is no.) - Scaling your application logic via Batch Apex — If you need to continue to provide an interactive experience (for smaller volumes) via your existing UI, how would you share logic between the two to ensure that the user gets consistent results regardless of the size?
- Working with complex logic in your Visualforce controllers or
@AuraEnabled
methods — Does any of your code deal with more than just handling information to and from the user? With Visualforce and Lightning Components, you can partition your code via Model–view–controller (MVC), a form of SOC for client development. However using controllers for all your code does not guarantee that you are following SOC in terms of your business logic. - Making it easy for new developers to find their way around your code base — How much time does a developer need to learn where to put new code and find existing behavior?
Depending on where you have written your code, you might already be in good shape to tackle some of the above scenarios. If not, or if you’re just curious, the upcoming units shed some light for further thought. The following table can also help decide whether to use these patterns based on the size and scope of the solution that you’re building.
Base Size of Solution or Code | Number of Developers | Requirements Scope | Number of Client Types & Interactions | SOC Appropriate? |
---|---|---|---|---|
Small | 1 to 2 |
|
| Typically not |
Small to Medium | 1 to 6 |
|
| Worth considering |
Large | > 6 |
|
| Definite benefits |
Resources