An introduction to Apex Enterprise Patterns
Over the years I’ve had the priviledge of seeing countless number of Salesforce projects spanning multiple industries, complexity, and size. A key ingredient common to successful projects I’ve found are those which incorporate great code architecture from the moment they get started.
Scaling Salesforce with Apex Enterprise Patterns
Over the years I’ve had the priviledge of seeing countless number of Salesforce projects spanning multiple industries, complexity, and size. A key ingredient common to successful projects I’ve found are those which incorporate great code architecture from the moment they get started.
I’ve now been using Apex Enterprise Patterns for over 10 years on Salesforce projects and it’s been one of the best tools in my toolset to use on new and existing projects. In this first article in a series of articles planned I’d like to share my experience of what I’ve seen with projects which do not implement these guidelines and to also gently introduce you to Apex Enterprise Patterns.
Unsustained velocity
Projects can be under a lot of pressure initially as there are so many tasks to get through! Before developers even start coding, teams have to create sandboxes, set up a release pipeline, configure a ticket tracking system, define user stories… the list goes on. There is a lot to do! Focus immediately shifts to feature delivery as soon as possible to keep stakeholders and end users happy.
Development teams which didn’t invest the time to structure their code base are still able to deliver feature after feature and typically move at an unprecedented rate never seen before from their respective IT departments. They know their work intimately and can tweak their implementations over and over to keep meeting new requirements. As time goes by confidence in the platform typically grows and more complex requirements start to flow into the development teams backlog. This is where I start to see projects starting to encounter their first pain points. One of the first challenges is scaling the development team size to help with increasing velocity. Onboarding new resources brings new challenges for the team to overcome and the challenge is knowledge transfer. Code which isn’t structured in a predictable manner can be difficult for new resources to know where to find or where to modify code within the code base. This can be frustrating for new team members who must rely on existing team members to guide them, further increasing onboarding timelines. Both taking precious capacity away from new features being developed. By not setting out guidelines on how to structure the application typically the following happens:
- No layers within the application are created.
- Business logic is written in the wrong layers.
- Separation of concerns is not followed.
- Duplicate code being scattered throughout the code base.
Ultimately, this leads us to a situation where changes take longer to implement and begins to hinder project velocities. The application becomes brittle and a tangled mess. This is definitely a sign of techincal debt which could easily be avoided through implementing the guidelines of Apex Enterprise Patterns.
Moving fast and staying fast!
Apex Enterprise Patterns is a set of guidelines which can help development teams structure in their code in a predictable manner. It’s not a framework of somesort, it’s guidelines on how to layer your application. Specifically, it details out where our concerns in our application should reside. An unstructured application typically suffers from poor separation of concerns and this is what the guidelines are attempting to address.
So let’s first cover what layers are described in the guidelines: controllers, services, domains, and selectors.
Controllers is where we should place any logic for interacting with a user to transform the incoming request into a request which can be understood by one of our services. Some logic may reside in controllers for basic validation tailored to the context it’s serving. For example, a Lightning Web Component Apex class or a batch Apex class are both forms of controllers, however both are serving two vastly different contexts. A common mistake is placing business logic inside this layer which will make code reuse difficult.
Our business logic should reside always within the service layer. This is where we should be spending majority of our time when implementing new features. Ensure to make this layer bulkified and caller agnostic. You never know where your code may be called from within the application so always design for bulk use to avoid nasty surprises. Being caller agnostic means having no assumptions on where the code is being called from. In other words, if your service tries to show a Visualforce error message when it was called from a batch job then an assumption has been made and would block reuse of the code. An improved way of managing this would be to allow the service to throw exceptions and allow controllers to fulfil their role: transform the response from the business logic into a suitable result for the context its serving.
Complex validation, providing record defaults, and or trigger handlers should all be written within the domain layer. Another benefit of having a domain layer is that we now have a great place to put all of those constants for picklists or default values! The strength of the domain layer is that is enables us to centralise where our business logic which interacts directly with our objects in one place.
And lastly, we should place all of our queries within one dedicated Apex class for an object (the selector layer) to help us with minimise duplicate code and reduce maintenance requirements. This is great as we avoid duplicate queries being scattered across the code base and helps adding or removing fields to existing queries as again only one location has to modified, vastly simplifying maintenance.
Earlier I outlined challenges with onboarding new resources into projects due to not knowing where to find or add new code. The basic guidelines I just described already give teams a general idea of roughly where functionality should go. This makes code discovery easier, more predictable, and simpler to transfer knowledge to new team members. All of the team now have the same vision on how to shape the application. To summarise the role of each layer:
- Controllers - focused purely on serving a particular context well. Try and keep business logic outside of this layer.
- Services - all of our business logic sits in this layer. This allows us to centralise and make more reuseable code.
- Domains - focused on complex validation, record defaults, and trigger handlers. Great for centralising logic around around sObject’s.
- Selectors - all queries for a particular sObject. Maximises reuse of queries and reduces maintenance.
Starting with your best foot forward
It can be very tempting at the beginning of projects to start hammering out those cool features, but this is the moment for project technical leaders to set out the guidelines to their respective teams on following the Apex Enterprise Patterns. Start with your best foot first! Take the opportunity to maximise the potential for success by investing the time initially getting your project and team members prepared. It takes hours, not days, to get the basics right.
You can begin with Apex Enterprise Patterns without a framework and still be able follow the recommended best practices. However, I would recommend considering a framework which has been designed from the ground up with the guidelines in mind, such as FinancialForce Library (FFLIB). This helps introduce a solid foundation into your application to build your project from.
There is a wealth of information available online to help you discover how to integrate this into your development lifecycle. Get started by following these Trailhead modules:
Next in this series of Apex Enterprise Patterns I’ll be deep diving more into each layer to share my experiences