Reader small image

You're reading from  Force.com Enterprise Architecture - Second Edition

Product typeBook
Published inMar 2017
Reading LevelIntermediate
PublisherPackt
ISBN-139781786463685
Edition2nd Edition
Languages
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

Chapter 6. Application Domain Layer

The objects used by your application represent its domain. Unlike other database platforms where record data is, by default, hidden from end users, the Force.com platform displays record data through the standard Salesforce UI, reports, dashboards, and Salesforce1 mobile application. Surfacing the labels and relationships, you give your objects and fields directly to the end user. 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 defaulting and validation, or code awarding championship points to contestant records or checking rules compliance.

This chapter will...

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 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 aimed at objects created from instantiating classes that are coded in an object-orientated programming language, such as Java or .NET. In these platforms,...

Implementation design guidelines


As in the previous chapter, this section provides some general design and best practice guidelines around designing a Domain layer class for a given object. Note that some of these conventions are shared by the Service layer, as it 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 Force.com application, this is typically supported by the Custom Objects. As such, it's important to clearly indicate which Domain layer class relates to which Standard or Custom Object:

  • Avoid acronyms: As per the previous chapter, try to avoid these unless it makes your class names unworkably long.

  • Class names: Use the plural name of your Custom Object for the name of your Domain class. This sets the tone for the scope of the record that the class deals with as...

Domain class template


The Domain class implementation in this chapter utilizes the FinancialForce.com 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 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 per the guidelines described previously. The code implemented in a domain class is written with bulkification in mind. The base class constructor initializes the...

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);
}

Routing trigger events to Domain class methods

The following diagram illustrates the flow of execution from the Apex Trigger to the Domain class, triggerHandler, to the...

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
      ChampionshipPoint__mdt pointsForPosition =pointsByTrackPosition.get(Integer.valueOf(contestant.RacePosition__c...

Object-oriented programming


One of the big advantages of using Apex classes is the ability to leverage the power of 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 Formula1 world are rules; every aspect of the sport has a set of rules and regulations to comply with, such as drivers owning a 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 in testing their cars. Such compliances are checked regularly, both before and after a race.

Creating a compliance application framework

In our FormulaForce application, we want to create a compliance framework that will check these regulations across the different objects while also providing a consistent user interface experience for the end user to verify compliance. The initial requirement is to place a...

Testing the Domain layer


Testing your Domain code can be accomplished in the standard Force.com manner. Typically, test classes are named by suffixing Test at 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.

Unit testing

Although developing tests around the Service layer and related callers (controllers, batch, and so on) will also invoke the Domain layer logic, it is important to test...

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.handleTrigger method.

  • Service layer: This layer directly creates an instance of a Domain class via the new operator or through...

Updating the FormulaForce package


As before, utilize the source code provided with this chapter to update your packaging org and upload a new version of the package. Make sure that you check for any components not automatically added to the package, such as Apex classes, objects, tabs, and Lightning Components tabs.

Tip

Remove any Lightning Components added to pages via Lightning App Builder before packaging. If you package Lightning Pages with your components on them, this will require your users to have the My Domain feature enabled and thus potentially limit the number of customers your package can be installed with. This is true, especially for those that have not yet fully adopted Lightning Experience.

Note that the new Verify Compliance button has been added to the Driver layout since the last release of the package in the previous chapter. However since layouts are non-upgradable components, this will need to be added manually after installation in the test org when upgrading, as will...

Summary


In this chapter, you've seen 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 also help support a common user experience. Domain classes can call between each other when required to encompass the behavior of related child...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Force.com Enterprise Architecture - Second Edition
Published in: Mar 2017Publisher: PacktISBN-13: 9781786463685
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 £13.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