I’ve always been struck by Inversion of Control. It sounds cool. But the philosophy behind it is so clearly written in blood, feels more like OSHA law than other design patterns.
The Pattern
I love teaching, but this blog is mostly a creative outlet for me. That said, I love this topic so much I’m going to teach anyway.
Imagine a button component. Without IoC:
<SubmitButton />
<CancelButton />
<DeleteButton />
<SaveDraftButton />
Every behavior requires a new component. With IoC:
<Button onClick={() => submit()} />
<Button onClick={() => cancel()} />
<Button onClick={() => delete(id)} />
<Button onClick={() => saveDraft()} />
One component, infinite behaviors. You invert control. You trust your users to be competent enough to write the handler themselves.
The “Downside”
The downsides of this pattern are obvious. “My users need to write code themselves? How inconvenient!” Yes. Oh no. Not writing code.
I have always loved this pattern. React’s composition of components is such a beautiful expression of it. JavaScript leans into this hard with its forEach loops. Pass a function to a function to allow users to extend the function. Elegant. Poetic.
Why This Matters Now
Think about how cheap code has gotten to write. And how annoying it is to deal with systems that discourage or disallow customization.
Salesforce is only as useful as they are saving people time. If they become annoying to work with then they will lose profitability quickly. Here’s the question worth asking: is it easier to generate a report using Salesforce than it is to generate a Salesforce that does what I actually use it for?
Here’s what Salesforce will look like in a year or your money back (or they won’t be around much longer):
const mySalesforce = new Salesforce({
onNewLead: async (lead, agent) => { /* ... */ },
scoreLeads: async (leads, agent) => { /* ... */ },
renderDashboard: async (data, agent) => { /* ... */ },
generateReport: async (query, agent) => { /* ... */ },
onStageChange: async (deal, agent) => { /* ... */ },
});
Not just hooks on new leads. Everything. How it scores. How it renders. How it reports. How it reacts. Pass functions for all of it. Get out of the way everywhere.
What value does your service provide that won’t erode as code becomes more disposable? Your ability to get out of the way at the right time is how you keep customers.