Reader small image

You're reading from  Salesforce Lightning Platform Enterprise Architecture - Third Edition

Product typeBook
Published inNov 2019
Reading LevelIntermediate
PublisherPackt
ISBN-139781789956719
Edition3rd Edition
Languages
Concepts
Right arrow
Author (1)
Andrew Fawcett
Andrew Fawcett
author image
Andrew Fawcett

Andrew Fawcett has over 30 years of experience holding several software development-related roles with a focus around enterprise-level product architecture. He is experienced in managing all aspects of the software development life cycle across various technology platforms, frameworks, industry design patterns, and methodologies. He is currently a VP, Product Management, and a Salesforce Certified Platform Developer II at Salesforce. He is responsible for several key platform features and emergent products for Salesforce. He is an avid blogger, open source contributor and project owner, and an experienced speaker. He loves watching movies, Formula 1 motor racing, and building Lego!
Read more about Andrew Fawcett

Right arrow

Application Domain Layer

The objects used by your application represent its domain. Unlike other database platforms where the record data is, by default, hidden from end users, the Lightning Platform displays your record data through the standard Salesforce UI, reports, dashboards, and Salesforce Mobile application. Field and relationship labels that you give your objects and fields are also used by these UI experiences. From the moment you create your first object, you start to define your application's domain, just as Salesforce Standard Objects represent the CRM application domain.

Martin Fowler's Patterns of Enterprise Application Architecture also recognizes this concept as a means of code encapsulation to combine the data expressed by each object with behaviors written in code that affect or interact with that data. This could be Apex Trigger code, providing...

Introducing the Domain layer pattern

The following is Martin Fowler's definition of the Domain layer (http://martinfowler.com/eaaCatalog/domainModel.html):

"An object model of the domain that incorporates both behavior and data."

Like the Service layer, this pattern adds a further layer of separation of concerns and factoring of the application code, which helps to manage and scale a code base as it grows.

"At its worst business logic can be very complex. Rules and logic describe many different cases and slants of behavior, and it's this complexity that objects were designed to work with. A Domain Model creates a web of interconnected objects, where each object represents some meaningful individual, whether as large as a corporation or as small as a single line on an order form."

Martin's reference to objects in the preceding quote is mainly...

Implementing design guidelines

As with the previous chapter, this section provides some general design and best practice guidelines for designing a Domain layer class for a given object. Note that some of these conventions are shared by the Service layer, which also calls the Domain layer because conventions such as bulkification apply to the logic written here as well.

Naming conventions

The key principle of the Domain layer pattern is to lay out the code in such a way that it maps to the business domain of the application. In a Lightning application, this is typically supported by Custom Objects. As such, it's important to clearly indicate which Domain layer class relates to which Standard or Custom Object:

  • Avoid acronyms...

Domain class template

The implementation of the Domain class in this chapter utilizes the Financial Lightning Apex Enterprise Patterns library, which is open source and is included in the sample code of this chapter. In this library, the Apex base class, fflib_SObjectDomain, is provided to help implement the Domain layer pattern.

A basic template for a Domain class utilizing this base class is shown in the following code snippet:

public inherited sharing class Races extends fflib_SObjectDomain { 
  public Races(List<Race__c> races) { 
    super(races); 
  } 
 
  public class Constructor 
    implements fflib_SObjectDomain.IConstructable { 
    public fflib_SObjectDomain construct(
List<SObject>sObjectList) { return new Races(sObjectList); } } }

The first thing to note is that the constructor for this class takes a list of Race__c records, as...

Implementing Domain Trigger logic

The most common initial use case for a Domain class is to encapsulate the Apex Trigger logic. In order to enable this, a small Apex Trigger is required to invoke the triggerHandler method. This will route the various Trigger events to the appropriate methods in the Domain class (as shown in the preceding screenshot), avoiding the need for the usual if/else logic around Trigger.isXXXX variables.

The name of this trigger can be anything, though it makes sense to match it with that of the corresponding Domain class. Once this is in place, you can ignore it and focus on implementing the Domain class methods as follows:

trigger Seasons on Season__c ( 
  after delete, after insert, after update,  
  before delete, before insert, before update) { 
    fflib_SObjectDomain.triggerHandler(Seasons.class); 
} 

In the next section, we will explore how Apex...

Implementing custom Domain logic

A Domain class should not restrict itself to containing logic purely related to Apex Triggers. In the following example, the code introduced in the previous chapter to calculate championship points has been refactored into the Contestants Domain class. This is a more appropriate place for it, as it directly applies to the Contestant record data and can be readily shared between other Domain and Service layer code (which we will look at later in this chapter):

public void awardChampionshipPoints(fflib_ISObjectUnitOfWorkuow) { 
   // Apply championship points to given contestants 
   Map<Integer, ChampionshipPoint__mdt> pointsByTrackPosition = 
new ChampionshipPointsSelector().selectAllByTrackPosition(); for(Contestant__c contestant : (List<Contestant__c>) Records) { // Determine points to award for the given position...

Object-oriented programming

One of the big advantages of using Apex classes is the ability to leverage the power of object-oriented programming (OOP). OOP allows you to observe commonalities in data or behavior across your objects to share code or apply common processing across different objects.

An example of such a commonality in the Formula 1 world are rules; every aspect of the sport has a set of rules and regulations to comply with, such as drivers owning an FIA Super License, the weight of the car they drive should be at least above a defined minimum, and ensuring that a team has not exceeded the maximum distance while testing their cars. Such compliances are checked regularly, both before and after a race.

Creating a compliance application framework

...

Testing the Domain layer

Testing your Domain code can be accomplished in the standard Lightning manner. Typically, test classes are named by suffixing Test to the end of the Domain class name, for example, RacesTest. Test methods have the option to test the Domain class code functionality either directly or indirectly.

Indirect testing is accomplished using only the DML and SOQL logic against the applicable Custom Objects and asserting the data and field errors arising from these operations. Here, there is no reference to your Domain class at all in the test code.

However, this only tests the Apex Trigger Domain class methods. For test methods that represent custom domain behaviors, you must create an instance of the Domain class. This section will illustrate examples of both indirect and direct testing approaches.

...

Calling the Domain layer

The Domain layer is positioned with respect to visibility and dependency below the Service layer. This, in practice, means that Domain classes should not be called directly from the execution context code, such as Visualforce Controllers, Lightning Component Controllers, or Batch Apex, as it is the Service layer's responsibility to be the sole entry point for business process application logic.

That being said, we saw that the Domain layer also encapsulates an object's behavior as records are manipulated by binding Apex Trigger events to methods on the Domain class. As such, Apex Triggers technically form another point of invocation.

Finally, there is a third caller type for the Domain layer, and this is another Domain class. Restrict your Domain class callers to the following contexts only:

  • Apex Triggers: This calls via the fflib_SObjectDomain...

Updating the FormulaForce package

As described in Chapter 1, Building and Publishing Your Application, utilize the source code provided with this chapter to create a new version of your package and install it in a test org. Keep in mind that the new Verify Compliance button added in this chapter has been added to the Driver layout since the last release of the package. Since layouts are non-upgradable components, this will need to be added manually after installation in the test org when upgrading, as will any new Custom Fields added throughout this chapter.

You would typically notify users of post installation steps through your upgrade and installation guide. You will also have to ensure that users are made aware of any Lightning Components as part of your solution. As previously noted, packaging Lightning pages creates a dependency on the My Domain feature having been...

Summary

In this chapter, you've learned a new way to factor business logic beyond encapsulating it in the Service layer—one that aligns the logic—implementing the validation changes and interpretation of an object's data through a Domain class named accordingly. As with the Service layer, this approach makes such code easy to find for new and experienced developers working on the code base.

A Domain class combines the traditional Apex Trigger logic and custom Domain logic, such as the calculation of championship points for a contestant or the verification of compliance rules against the cars, drivers, and teams.

By utilizing Apex classes, the ability to start leveraging OOP practices emerges, using interfaces and factory methods to implement functional subsystems within the application to deliver not only implementation speed, consistency, and reuse, but...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Salesforce Lightning Platform Enterprise Architecture - Third Edition
Published in: Nov 2019Publisher: PacktISBN-13: 9781789956719
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Andrew Fawcett

Andrew Fawcett has over 30 years of experience holding several software development-related roles with a focus around enterprise-level product architecture. He is experienced in managing all aspects of the software development life cycle across various technology platforms, frameworks, industry design patterns, and methodologies. He is currently a VP, Product Management, and a Salesforce Certified Platform Developer II at Salesforce. He is responsible for several key platform features and emergent products for Salesforce. He is an avid blogger, open source contributor and project owner, and an experienced speaker. He loves watching movies, Formula 1 motor racing, and building Lego!
Read more about Andrew Fawcett