Get your constants in a row!

Joris Westerveld
4 min readJan 31, 2021

As a developer mainly concerned with the Salesforce.com platform, frontend work can be quite a new adventure, especially if you have had a focus around backend (apex) for years.

Now clearly this does not hold you back to write the occasional web component (you wouldn’t be here)! However, like myself you might have quite some considerations when writing these components. Years of backend doctrine don’t translate well to frontend, which feels a little icky:

  • Although “LWC” is a framework, it does not guide us really in regards of enterprise development. How does “Separation of concerns” work? Where are the layers?
  • We are comfortable with a 75% minimum test coverage for backend; more often than not we hold a standard of 0% for frontend.
  • Backend naming conventions and years of industry standards meant we could piggyback on all of Java’s efforts. For frontend we’re a little at loss where to look .

One of the smaller things that bugged me is the use of constants in Lightning Web Components. We use them often in Apex to get regularly returning values shared among the codebase. Using them in frontend seems like a no-brainer, but getting them there somehow feels difficult, over the top and feels like spaghetti code. To get around this, we often just define the values in both back -and frontend:

Often we just define our constants in two places. Fast and easy.

Now this comes with the obvious downsides:

  • You have to make very sure these values are identical. They are constants for a reason; business logic could very well depend on it.
  • Ironically, when a constant changes, you have to change it on multiple locations. Also: try to find the usage of a constant in your IDE when they occur in both front and backend without an obvious link!

Bring in the constant service and constants class!

Now take a look at this very simple example of a constants service component and a constants apex controller:

What we have here is a simple controller class that defines two constants, one of which is directly taken from the account domain layer class. One method has been made available as API for a component to consume: constants() . It returns an instance of itself, which as we will see shortly, is exactly what we need. This is a good way to structure your controller code; you are in full control of what constants to expose to the frontend, while reusing values found across the domains of your codebase!

The modest service component simply exports the imperative apex call, which essentially is a Promise containing the result from the backend.

Now let’s get this service in action!

This time, instead of the component defining it’s own constants, it gets them from the service component instead. Talking about separation of concerns!

Just like the labels, we make sure that the CONSTANTS property is available and properly populated. We apply the @track decorator to actually represent changes to the object and rerender appropriately. This is because the call for constants is asynchronous (more about that later).

Now your component might not make use of the connectedCallback lifecycle hook. Let’s take a look at another approach:

Here we open up the CONSTANTS property with the @api annotation. Whenever the property is called for and the constants are not set, the call is made to fetch them. The eagle-eyed immediately remarks that the first button press would actually return undefined . This is correct — because the extra call to the server to fetch the constants is asynchronous, it will never be in time. This could be solved by returning a Promise as part of the CONSTANTS property.

(credits partly go to this great question on stackoverflow)

What about Custom Metadata or Labels?

Importing Custom Labels in a Web Component is dead easy, and as Salesforce guarantees their availability upon load, it almost feels like a solid way to deal with constants. Unfortunately labels are way too volatile to use as such. First off, you would have to hook backend constants to Custom Labels. Secondly, the moment someone accidentally removes (or worse: translates) a label, your business logic breaks.

Same arguments count for Custom Metadata. Although they are a little less prone to accidental changes, they are primarily meant for application configuration, not the representation of constant values in a system. (The fact that Custom Metadata retrieval in LWC is still as much work as retrieving normal data does not help either).

Synchronization

Now a last remark on the async nature of Javascript. The above solution to get constants to your frontend comes with one big disadvantage: you need to wait for them.

When the server is a little slow, your constants might come in (too) late. This means that when you have logic that is dependent on constant values upon load, you definitely want to build in checks (read: promises, async/await) to make sure the values are actually there!

Let me know what you think! Do you have a better approach? Worry about the async nature and unnecessary Javascript spaghetti for a problem that might not really exist? Very curious to hear from you!

--

--

Joris Westerveld

Salesforce Consultant and Flowmaster, Passionate about Lightning, passionate about Trailhead, Passionate about plants.