The Great Law of Unix and its progeny is to do one thing and do it well. Although Unix programs may have great complexity, they are focused and modular. This has certainly lead to the amazing success of Unix, BSD, Linux and other *nix operating systems in the tech world, but I think that this law is more generally applicable than simply 'how to write Unix programs.'
My previous post is, in essence merely a re-statement of this law. When pushing a release or change to your product, keep your focus. It is far better to make a few changes that will make a big difference, than lot's of meaningless fiddling (Though don't forget that big and little changes should be measured on their effect on the user's experience, not how much effort they require).
I learned this lesson again today when I was working on my Arch Linux install. I use LinuxMint for my day-to-day computing, but, in the interest of learning more about how Linux is built, I've been slowly working on getting a usable system on my second partition. Like with code releases, one thing I've learned is to not try to change too much at once. My initial plan was to build the entire system from scratch in an extreme minimalist style (OpenBox, SLiM, Chrome and a Terminal) but I quickly found that there is a great deal more complexity in doing that than I had anticipated and I've had much more success since switching to XFCE and more 'mainstream' technologies.
Some day I will probably reduce my system even further, but for now, I've learned that minimalism is a process of taking away more than it is a process of adding the minimum amount possible.
This isn't your ordinary guide to deployment and tools. As a matter of fact, this is somewhat of an anti-guide -- a guide on how to approach tools and deployment -- rather than a guide to any specific approach. I was inspired for this by a post yesterday to Hacker News by Hynek Schlawack on Python Deployment Anti-Patterns and other tools used in doing Python web development. The article and associated discussion on HN are both excellent and I highly recommend a read.
However, I often find that articles and resources like these can actually be quite counterproductive to my as a developer. I look at these lists and think to myself, "Oh no, I'm not using all of the best practices! I should switch over my development stack to ensure maximum scalability and stability for the long term." Then I spend several hours researching the tools, reading tutorials, reading docs, messing with the server, probably breaking something, fixing it and generally coming back right back to where I started with maybe a few tweaks to my process.
The problem with this philosophy is that it's a bit like putting an air spoiler on my Honda Accord. Certainly the right spoiler, air-filter, tires, etc will make improve the performance of my car, but right now, I need to focus on getting to work and shipping a product. Playing around with a deployment system for a massively distributed system is pointless when you're building out your initial product and trying to nail down the core feature set and build a customer base.
However, sticking with what you know and never moving onward is a surefire recipe for stagnation and boredom as a developer. I got into technology because I didn't want to be bored and I wanted to be pushing the limits of what I can do and I want to have a solid stack and is up to date and using current best practices. There is usually a reason why smart, successful people are developing and implementing such practices.
So here has become my approach to keeping up with best practices and scaling up my applications, while not wasting time with pointless Yak Shaving: one new deployment feature per deployment. Instead of trying to build out the perfect stack from the beginning, I take what I currently have, and know and try one new thing. Maybe I switch to RabbitMQ instead of Redis for message passing. Maybe I use Supervisord instead of upstart for process management. Whatever it is, I optimize for one big improvement to my workflow per big improvement on the user side. This way the stack and architecture grows and improves as the interface does. The additional advantage here is that as I get more comfortable with these technologies, I start to think in those terms and start to build them into my projects from day 1.
This past week I had finished a big project for my work and was trying to decide what to build next. We had discussed several major new projects that included a major overhaul of one of the core interfaces to our application. However, instead of starting that, I took some time to fix a bunch of nagging little bugs that had been bothering me (and our users) for some time.
Don’t forget the little stuff. It represents your biggest opportunity to get maximum impact for a minimum of effort. Yes, I could have re-architected our front-end stack to implement new features, but fixing bad copy, broken CSS and a poor user interface served our customers far better than that would have. The key word in MVP is viable. It isn’t just a minimum product; it has to be one that validates and implements (successfully) your business model. Otherwise, it’s just junk.
There is a second reason to think about the little stuff: putting the user first. Sometimes, it is tempting to fall into the trap of wanting to take out a new canvas and make big, bold strokes to hit your targets. Certainly, not falling into ruts is a key startup success trait. However, by taking what you have and re-focusing on what about it is broken, you get much closer to a workable product than constantly starting over. A good engineer doesn’t start over their project from scratch every time they find a mistake. A good engineer fixes it and refactors it into a good, workable product. The same holds for designing your product. Making it better is more rewarding and more beneficial to your users than starting over.
Sometime in April of 2012, I came into work to find out that my crazy co-workers had, over a bottle of scotch, spent the previous evening throwing together an experimental dating site called CupidCurated. I admired their audacity and congratulated them for pulling it off and then chuckled to myself as I went back to 'real' work on StartupDigest VIP. You may have read about this a few weeks ago. This is the story of what comes next and what it really means to build a minimum viable product -- from the engineer who built it.
Two weeks later, I went down to Monterey to visit my in-laws. I had basically forgotten about CupidCurated at this point when I got a phone call late on Sunday evening from Chris McCann. This is when our fastidious editor compiles our event newsletters, so I picked up immediately, thinking something must be wrong with our CMS.
"How quickly do you think you can get CupidCurated up?", Chris went straight to the point.
"There's a demo day in San Francisco next Wednesday and we'd like to show CupidCurated at it."
My heart skipped a beat.
"I'll see what I can do..."
So began one of the craziest 9 days of coding of my life. The next morning, I immediately cloned our EC2 stack, forked our master Github repo and started to figure out how I could actually make this all work in 9 days. It's all very well and good to think of dating and recruiting as being parallel interactions, but how do you actually take one and turn it into the other. Could you take OKCupid and turn it into a LinkedIn killer?
The first step was to remove all unnecessary parts: activation, account editing, password resets. These are all key for a real product, but they're just wasting time in a demo. Then, I set Chris and Brendan on the task of re-writing all our copy to be 'dating-ish' rather than 'recruiting-ish'.
There was no way of getting around the core interaction of the application logic. A recruiting product helps companies and engineers meet. A dating site helps girls and guys meet. I made the crazy decision that women would be companies and men would be engineers (well, that one isn't so crazy, I guess). For the demo, the key was to validate the interaction, not the matching. Obviously, in a real product you want to optimize the matches that happen on your site, but for a true MVP, you just need to figure out if it answers the human side of the equation: the interaction, before you optimize the machine side. By Friday, I had a site that actually followed the workflow of a dating site.
The problem was, it still looked like a recruiting site.
The most important part of an MVP is that it needs to feel like a real product. It can be crap on the inside (and believe me, this product was a hodgepodge of hacks, improvisations, and plain old guesses on the inside), but, again, MVPs are about validating the human side of the equation. Will this product match what a human wants out of it? And to that end, it needs to feel real. So, I knuckled down over the weekend on design. I picked Imprima for the font as it has a nice, clean, sans serif feel, with a hand-written twist. I found a nice background on Subtle Patterns and played around with the color scheme to make it feel more Cupid-like.
And you know what? It actually looked like a dating site. It felt like a dating site, but could it actually handle demo day? I was fully prepared to spend the entirety of Life 3.0 huddled in a corner, casting spells of 'resurrect server' through the evening, but it actually handled the load quite nicely, which just goes to show you how useless premature optimization is.
I think MVPs are sometimes hardest on engineers. We're naturally lazy and therefore predisposed to the philosophy that if it isn't worth doing right, then it it isn't worth doing at all. However, this turns out to be wasteful as evidenced by the the countless engineers who spend their weekends working on over-designed, under-validated side projects that are never going to get off the ground.
Yes. The demo that I created for Life 3.0 was a monster an adventure, but, you know, life is too short to work at a boring company.