Domain-Driven-Design principles are largely adopted in companies embracing microservice architecture and one of the key ideas is to separate the data model of the persistence layer from the business layer and the one of the business layer from the API layer, so that the business layer can be exposed to the outside world in a simplified way and its complexities can be hidden from external clients. Because the Salesforce development model and the primitives offered by the Lightning Platform do not map to any of other technologies, these principles can be interpreted in various ways.

Interpretation 1: Lightning components and any external integration must not depend on the SObject schema of the org (and therefore tags such as force:recordData can't be used). One key benefit is that you can refactor the underlying model without refactoring the UI or the external clients, and also support multiple versions of the API. The key drawback is that you need to write custom controllers or Apex Rest Endpoints for each interaction.

Interpretation 2: It is not possible to isolate in Salesforce the persistence from the business logic, because validation rules, workflow rules, triggers and other development primitives are coupled with the SObject model, and therefore even providing a separate API model brings limited benefits which might not be worth the overhead.

Interperetation 3: Lightning components are not external to the domain and they are part of the same release cycle of the other metadata on the org, so they are already coupled with everything else and you won't be able to relax this coupling. It is perfectly fine for them to depend on SObject schemas:

  • custom controllers needs to be used only when you need to read or write (transactionally) multiple or different sobjects
  • rest endpoints still remain useful to provide an API which abstracts away the SObject model and can be invoked from the outside (external systems)

Interpretation 4: Building on top of interpretation 3, is it possible to avoid writing controllers at all when you have to deal with read operations or non transactional write operations and invokes the SObject rest api, avoiding the cumbersome development model for Apex Server Side controllers?

Conclusion: Are there other interpretations, are there benefits or drawbacks we didn't capture in our analysis, and what is the SFDC developers community experience with those principles?

Old post

We are currently evaluating different strategies to interact with Salesforce inside Lightning Components:

  1. Write a controller, which guarantees you can provide transactional guarantees within a single backend call even when performing multiple CRUD operations
  2. Write a controller but never return SObjects, since SObject belongs to the persistence layer and we would like to have the freedom to change the persistence without changing the UI. (Does it even apply? Is the metadata / the org a monolith anyways?)
  3. Find a way to invoke API so you do not need to write controllers which go through the Metadata release process, which might be cumbersome

What are the experience of the SFDC developers community, and is the third even a possibility?

  • 2
    Your question is incredibly broad, which is really not well suited for this site. However, I am intrigued by it and want to try and answer. Can you expand a little bit on the ideas for each of your points? I want to make sure I address your actual question, and not what I think your questions are. Jul 19, 2019 at 15:28
  • Thanks for your comment. I have read my question multiple times and tried to rewrite it in a way that emphatize where some questions are coming from
    – Edmondo
    Jul 20, 2019 at 18:18
  • 1
    Controllers invoke service layer, typically by passing Ids. Controllers have the option to interact with the client using sobjects or via an abstraction. There are some OOTB benefits to using Sobjects (even if wrapped) -- specifically sobject fields. I don't think I ever have a controller directly interact with a domain (domain should be effectively a wrapper on sobject). That said, I'll admit we slavishly adhere to fflib pattern in our org.
    – cropredy
    Jul 22, 2019 at 1:12
  • Have you ever tried any of the approaches described above or did you simply used fflib as a way to "structure your code"? We are doing exactly the same, and now that our understanding of DDD improved we came to realize that fflib implements some concepts (selectors are repositories) but it doesn't dictate guidelines on the others
    – Edmondo
    Jul 22, 2019 at 7:05
  • #3 - never; #1 - usually because our domain mirrors OOTB SFDC objects like Order, Asset, Contact, #2 - occasionally - might be useful if domain was implemented by some managed package and we could swap the managed package over time for various reasons
    – cropredy
    Jul 22, 2019 at 20:16


You must log in to answer this question.

Browse other questions tagged .