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 Service Layer

If your application was considered a living organism, the Service layer would be its beating heart. Regardless of how the environment and the things that interact with it change over time, it must remain strong and be able to adapt. In this chapter, we begin our journey with the three coding patterns: Service, Domain, and Selector, which were introduced in Chapter 4, Apex Execution and Separation of Concerns.

In this chapter, we will review the pattern as set out by Martin Fowler and then review how this has been applied to the Lightning Platform in Apex, describing design guidelines born from the separation of concerns we defined in the previous chapter.

One concern of this layer is interacting with the database; a later chapter will cover querying this in more detail. This chapter will focus on updating the database and introducing a new pattern...

Introducing the Service layer pattern

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

"Defines an application's boundary with a layer of services that establishes a set of available operations and coordinates the application's response in each operation."

The use of the word boundary in Martin's definition is interesting, as this literally represents the point of separation or boundary between the concerns of the application's business logic in the Service layer and execution contexts caller. This might be a Visualforce or Lightning Component Controller class or a Batch Apex class, as illustrated in the UML diagrams shown in the previous chapter.

The following illustration shows just some of the types of callers that an Apex Service layer is designed to support. By following...

Implementation of design guidelines

Having studied the Separation of Concerns in the previous chapter and reflected on the previous illustration, the following design guidelines help to ensure that the Service layer is agnostic of the caller, easy to locate, and encourages some Lightning Platform best practices, such as bulkification. Note that bulkification is not just a concept for Apex Triggers; all the logic in your application must make efficient use of governed resources.

Naming conventions

A colleague of mine used to reference the following when talking about naming:

"There are only two hard things in Computer Science: cache invalidation and naming things."
– Phil Karlton

In my career so far, I have...

Handling DML with the Unit Of Work pattern

The database maintains relationships between records using record IDs. Record IDs are only available after the record is inserted. This means that the related records, such as child object records, need to be inserted in a specific dependency order. Parent records should be inserted before child records, and the parent record IDs are used to populate the relationship (lookup) fields on the child record objects before they can be inserted.

The common pattern for this is to use the List or Map keyword to manage records inserted at a parent level, in order to provide a means to look up parent IDs, as child records are built prior to being inserted. The other reasoning for this is bulkification; minimizing the number of DML statements being used across a complex code path is vital to avoid hitting governor limits on the number of DML statements...

Services calling services

In the previous chapter, I described a reuse use case around a FormulaForce application feature that awards championship points to contestants. We imagined the first release of the application providing a Custom Button only on the Contestant detail page and then the second release also providing the same button but on the Race detail page.

In this part of the chapter, we are going to implement the respective Service methods, emulating this development cycle and, in turn, demonstrating an approach to call between Service layer methods, passing the Unit Of Work correctly.

First, let's look at the initial requirement for a button on the Contestant detail page; the method in the ContestantService class looks like the following:

public static void awardChampionshipPoints(Set<Id>contestantIds) { 
 
  fflib_SObjectUnitOfWorkuow = 
Application...

Contract-Driven Development

If you have a large piece of functionality to develop, with a complex Service layer and user interface client logic, it can be an advantage to decouple these two streams of development activity so that developers can continue in parallel, meeting up sometime in the future to combine efforts.

An approach to this is sometimes referred to as Contract-Driven Development. This is where there is an agreement on a contract (or service definition) between the two development streams before they start their respective developments. Naturally, the contract can be adjusted over time, but having a solid starting point will lead to smoother parallel development activity.

This type of development can be applied by implementing a small factory pattern within the Service layer class. The main methods on the service class are defined as normal, but their internal implementation...

Testing the Service layer

It is tempting to allow the testing of the Service layer to be done via tests around the calling code, such as Apex controller tests. However, depending solely on this type of testing leaves the Service layer logic open to other use cases that may not strictly be covered by the controller logic. For example, a certain Apex controller will only pass in a single record and not multiple ones. Make sure to develop specific Apex tests against the Service layer as the functionality is developed.

Mocking the Service layer

Sometimes, the data setup requirements of the Service layer are such that it makes writing Apex tests for controllers or other callers, such as Batch Apex, quite complex and thus expensive...

Calling the Service layer

The preceding examples have shown the use of the service class methods from Lightning Component Apex controller methods. Let's take a closer look at what is happening here, the assumptions being made, and also at two other callers, an Apex Scheduler and a Visualforce Apex Controller. Throughout the rest of the book, you will also see other examples such as Batch Apex and Platform Event Subscriptions. 

Keep the following in mind when reviewing the following use cases:

  • There is no need for the calling code shown in the following sections to concern itself with rolling back changes made within the service that may have been made to object records up to the exception being thrown, since the caller is safe in the assumption that the Service method has already ensured this is the case.
  • Error handling in each of the following sections is unique, yet...

Summary

In this chapter, we have taken the first step in developing a robust coding convention to manage and structure the coding complexities of an enterprise application. This first layer encapsulates your application's business process logic in an agnostic way that allows it to be consumed easily across multiple Apex entry points, both those required today by your application and those that will arise in the future as the platform evolves.

We have also seen how the Unit Of Work pattern can be used to help bulkify DML statements, manage record relationships and implement a database transaction, and allow your Service layer logic to focus more on the key responsibility of implementing business logic. In the upcoming chapters, we will see how it quickly becomes the backbone of your application. Careful adherence to the guidelines around your Service layer will ensure it remains...

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