It is a New Year and time for a return to regular programming: the last couple of months were a bit sparse on the post side of things, mostly down to Dreamforce and the holiday season which both involved traveling. In January last year we formed the S. P. Keasey Trading Co. and set out on a mission to release as many AppExchange apps as we could; we were probably optimistic with our expectations for 2013, but we did learn a lot and 2014 is looking good. So what have I learned as a developer embarking upon the ISV journey? Here's a few of the lessons that jump out at me.
Good Test Methods Are Vital
This is pretty self explanatory and it's something I've covered a few times before now: make sure you right proper test methods that meticulously check the functionality of your code. I'll be the first to raise my hand and say I still take short cuts with this, but I'll also say that nearly every time I do it bites on the butt. I'll chalk this down as a lesson half-learned.
Optional Features Are a Headache
Something else I've written about previously but it does bear repeating: optional features are a bit of a pain to deal when when you're creating building for more than one org. As a consultant developer I only ever had to focus on one org at a time, if they had record types then I could use them, if they didn't I didn't, and the same goes for other such features like multiple currency support. When you're writing code that will be used in multiple orgs however, you can't have any static references to such things in your code. If record types aren't enabled then the RecordType object and RecordTypeId fields won't even exist, so the moment somebody tries to install a package that has code like this:
RecordType rt = [select Id, Name from RecordType limit 1]; // do stuff
it'll fail to compile and thy game will be over*. To get around this all references must be dynamic, and it's up to you as the developer to check whether a feature is enabled before you try to use it (of course in my real code I use a boolean to cache the existence of record types):
SObject rt = Database.Query('select Id, Name from RecordType limit 1');
// do stuff
This isn't a major issue, but when you start trying to test code that uses record types and get coverage in orgs which don't have them, things tend to get a tad complicated. I wrote about this earlier in the year and the super smart Dan Appleman followed up with a post on one way to deal with the situation.
Sales Is Hard
I always knew sales was a field unto it's own, but I really never expected to have long drawn out sales processes for cheap products. Having worked in the past on mobile games, and as a consumer of mobile apps, I got caught up in the idea that people would try something out, and if they liked it, they'd purchase it. This idea doesn't hold true for the enterprise, even if people do like your app they still need to sell it to the rest of the company, ensure that it won't conflict with existing customisations and whole lot more. In addition ,the person who sees your app as being something they could use is quite likely not the person who holds the purse strings, who is also not likely to be the person with the permissions to install the app; thus the purchasing requires substantial communication, and that takes time.
We're slowly but surely finding our way, Kris has been reading up on selling techniques for the subscription economy, and our branding seems to be working well. If you build it, they might well come, but don't expect them to come at any decent rate unless you invest time and money in sales and marketing.
The Community Is Awesome
|I'd show you the back but it's super-secret.|
Throughout the year we've had inspiring discussions with many people who've helped to catalogue our thoughts and point us in the right direction. I still have a S.P.K. beer coaster on my desk (with many, many coffee rings on it) that is scrawled with notes that I took whilst chatting with Blakely Graham and Eric Wu from Bracket Labs, who were kind enough to take time out of their day to talk to me about pricing, billing and more. There's plenty of ISV developers in the MVP crowd too, many of which I definitely consider as friends and I feel privileged to be able to say that.
Use The Cloud
Obviously as a Force.com developer I use the cloud for all my work, but make sure you use it for as much as possible. GitHub is great for keeping your code, Google Apps are there for email and calendars, Evernote helps you keep things close to hand wherever you are. This point is kind of moot but I wanted to emphasise it because using these tools hast just made my life a whole lot easier. A few days before Christmas my MacBook Pro rebooted itself while I was using it and it hasn't worked since (it seems to be a common graphics card failure on this model, yet Apple don't see it as a defect they're responsible for). Needless to say, I wasn't expecting it to spontaneously become a very expensive paper weight, but it's sudden demise has really not cost me anything in terms of my work. I picked up my little Windows hybrid machine and carried on from where I left off; the fact that this is possible using a completely different OS is really quite amazing, just a few years ago the loss of a machine would have cost a considerable amount of time even with good backups.
I'm very excited for this year, our products are building a following and becoming more and more powerful, we're making more friends and connections all the time, and the community just gets better and more engaging every day. I'm already looking forward to Dreamforce and the mind boggles to think of how bit it will become this time around; hopefully I'll see you there!