Breaking the monolith on Salesforce
For many implementations that I worked so far, they tend to become a “Big Ball of Mud” — of course, this is not exclusive to the Salesforce ecosystem, but some challenges are specific. Currently, I work in a product company that is a Salesforce ISV (Independent Software Vendor that ships software using the Salesforce platform).
Then talking to some colleagues and other fellow software engineers I started to dive deeper into this subject to evaluate: why we get into such trouble? Is this truly a problem? What are the alternatives?
Because the implementations usually start small and simple, but eventually the companies begin to realise the value they can get from Salesforce, and quickly they become complicated.
Then due to lack of Salesforce tooling, it was nearly impossible or quite expensive to pay the technical debt.
- Leveraging the database that would drive business logic through triggers.
- API calls such as REST or SOAP.
- Dynamic instantiation through Type.forname.
Is this a problem?
Yes but only if you want to scale:
- Have a bigger team working in the product.
- Separate delivery cadences.
- More autonomy to teams.
- Smaller and more frequent deliveries.
The Continuous Delivery book was published in 2010 and articulates why you should deliver frequently - go for it if you are not familiar with the subject. If you are like me, you probably already researched Continuous Deployment — and thus I would highly recommend Accelerate book to learn more about the data behind high performance IT companies and what capabilities they leverage to do so.
That allows synchronous loosely-coupled integrations. What?
Yes, now you can have a class (let’s call it producer) that implements Callable — that is not the point yet. Then you can have another class (consumer) that instantiates the producer class sending the parameters.
- The producer can evolve with no limitation around interfaces: means ISVs can deliver Managed Packages without shipping “Global Interfaces” — that is a significant benefit on the sense that they can deprecate code gradually.
- You can plug potentially any class that implements Callable interface in the code path, and as long as they do they respect the agreement made: happy days!
- Means different teams can work in parallel and deliver in a separate cadence.
I would not advise any small implementation to start with loosely-coupled integrations because there is a price to pay: communication (between the team producing the class and the team consuming it) and engineering practices to support it well. So, monoliths are an excellent way to start given they are easy to build and maintain (on a small scale).
However, I do advise any significant implementation out there or ISV to consider the usage of Callable interface — for synchronous integrations. And if they are looking for asynchronous integrations: Platform Events, but that is a whole new article.
Then teams can start to breakdown how they deploy: because they decomposed their dependencies. But that is also another article, a good one, perhaps the next one!