As the author of Salesforce.com’s official instructor-led course for Lightning Developers – Dev601: Programming Lightning Components as well as the Trailhead Lightning Component Framework Superbadge, I’ve spent a lot of time developing hands-on exercises that illustrate the mechanics of custom app development on the Salesforce.com platform.
What that course doesn’t officially cover, however, are design patterns for creating components for optimum re-use and application maintainability. Therefore I decided to author this blog article to act as additional reading materials for that course. Note that this post does assume that you are already quite familiar with Salesforce Lightning Component development.
Before we can discuss a pattern strategy, let’s define a couple of terms.
Tightly Coupled Components
A Tightly Coupled App is one where all of the components are nested within a container-component.In effect, you can treat the parent component as a de facto controller, handling any Lightning component events thrown by its members (typically by setting public properties and calling public methods of components other than the one that threw the event).
For instance, consider a scenario where a user chooses from a select-box of beers as illustrated by Figure 1. The BeerSelector component throws a component event containing the beer selection back to FriendsWithBeer.cmp. FriendsWithBeer.cmp then takes the beer selection and programmatically sets a beerId attribute in c:FWB_BeerContacts which triggers and APEX request, displaying a list of all contacts who like that particular beer.
Loosely Coupled Components
Loosely Coupled components, illustrated by Figure 2, are assembled into an application with Lightning App Builder and therefore have no direct parent component other than a Lightning App Builder template. The only way these components can therefore communicate with each other is via Lightning Application events. In this scenario, encapsulation of functionality is an absolute-must as business users have the freedom to include or exclude any installed Lightning App Builder-enabled components in your Salesforce org.
It’s a fair question. If you’ve tracked the progress of Lightning App Builder over the last few release cycles, it’s pretty clear that Salesforce is expending a lot of effort in this particular area of the framework. Having components that can be surfaced by both developers (as strongly-coupled apps), yet retain the flexibility to be deployed in App Builder, helps future-proof your code. It would not surprise me if within a couple of years, the vast majority of custom lightning applications are assembled using App Builder by both developers and power-users/admins.
Bringing it all together
I therefore suggest that you organize your Lightning applications around three separate tiers, as illustrated in Figure 3:
- The Functional Tier are comprised of utility components that do all the actual output within your application. I’m talking about Lightning Base Components, utility components such as custom grids/tables, custom buttons, and whatnot.
- The Declarative Application Tier are components that invoke Apex methods, encapsulate business logic, and pass data to the functional tier components for output to the user. These components also fire and listen to component events. A strongly-coupled Lightning application would consist of only components from the Declarative Application Tier and the Functional Tier.
- The Orchestration Tier invokes components from the Declarative Application Tier, re-firing custom Lightning Component events as custom Lightning Application events. They serve as a wrapper for the Declarative Tier components that you want to surface in Lightning App Builder. They also wrap components in lightning:card, as this is the preferred methodology (in Winter 18) to ensure that your component is not transparent against the new Winter 18 Lightning custom background.
You’ve probably inferred from the slides above that I’ve settled on a few naming conventions:
- Functional component names start with a lower-case letter and are camel-cased.
- Declarative Application Tier components start with applicationName_ComponentName. Since the name of my sample app is Friends With Beer, I’ve abbreviated the app name to FWB. Therefore, FWB_BeerSelector, FWB_BeerContacts, and so forth.
- Orchestration Tier components are prefixed with applicationName_App_ComponentName
- Component event names are prefixed with applicationName_evt_ComponentEventName
- Application event names are prefixed with applicationName_aEvt_ApplicationEventName
Feel free to critique these choices and concepts in the comments section below. In (hopefully) about 30 days, you’ll be able to view my detailed explanations of these concepts (including a code walkthrough) as a Pluralsight video play-by-play with my fellow Lighting Component instructor Don Robins!
Need immediate help? For Lightning Component consulting, development, and best-practices code-reviews please send an email to firstname.lastname@example.org. My company, Fig Leaf Software is a certified Service-Disabled Veteran-Owned Small Business located in Washington, D.C.