Prepare to be shocked; all your customers are different!
As a CTO for a startup your mission is managing their differences in a way that maximizes your per-customer flexibility while keeping the development overhead low and scalable.
Here’s a catchy acronym (C.U.S.T.O.M.E.R.) for the type of approach we use at InsightSquared to keep every customer special while still building a scalable product.
1. Customer – know them well
You need to talk to your customers and understand their needs. Abstracting solutions when you don’t truly know the problem is a recipe for disaster. And don’t forget to be open to the idea of some custom engineering, the good ole days of clean polymorphism and a perfectly elegant object model went out the window the second you decided to tackle the real world.
2. Umbrella – keep as much under the umbrella as possible
Carefully pick your battles; the risk of allowing custom engineering into your product is if it goes unchecked, you end up with a giant scaling issue. As often as possible stick as many features under the same umbrella. Remember that code has a logarithmic cost to maintain so more isn’t better.
3. Sequester – keep customer code self-contained
To design a system that accepts customer code simply, you need to isolate the repercussions of changing code. A few key points for doing this.
a) Customer code should be releasable independent of the rest of the system and independent of each other.
b) Customer code should be forward and backwards compatible (within a few releases each way).
c) Customer code should be enabled/disabled with a very lightweight configuration-style change. This lowers the risks of pushing out code and allows you to rollback just the broken bits quickly and easily.
4. Testing – find the broken fast
More custom code is more code. More code means more bugs. More bugs means more calls at 3am that something is busted and nobody likes calls at 3am. The solution? High code coverage of your automated testing framework. If you’re not using Hudson or another CI tool you’re missing out on an invaluable tool to preserve your sleep.
5. Out the door – always be releasing
The rigor of traditional releases have their place in every product, but don’t make the mistake of binding that process to your custom code. With good sequestering and testing, customer code releases can be very safe and easy to maintain.
6. Monitor – pay attention
Just like you need automated testing, you need monitoring of your deployed environment. Every single traceback needs attention and if you’ve got a good customer code release process in place with backward and forward compatible customer code then the second something breaks in production you’re armed with an bevy of options:
a) rolling back
b) disabling the code
c) even doing a quick fix
This is a vast improvement over than the traditional model where these type of situations would potentially require a hotfix release or just telling the customer you’ll get to them in a week when you do your next release.
7. Engage – reengage your customers
The beauty of customer specific code is it’s a great reason to keep talking to your customer! Keep talking to them; the relationship between you and your customer is a valid asset and will help you grow the quality of your code.
8. Refactor – your customers are different but not entirely unique
Refactor, refactor, refactor. The fastest way to bury yourself under a mountain of customer code is not to recognize the similarities between features you’re implementing. Whenever you can, combine and refactor aggressively to cull as much code as possible. The flexibility of custom code is a godsend, but every line of code has a cost associated with it.