WHY WON’T THIS WORK?! Coding Angry for Fun and Profit
Why Building Apps the Wrong Way can be the Right Way
Writing good code is hard, but if building something the simplest, easiest way can still be frustrating, what effect does the extra cognitive load of trying to build it the right way have, when you’re just trying to experiment?
I know people who find peace in their code; engineers who find Zen when working on a complex problem. Each new method implemented, bug resolved, and puzzle unravelled is a step on a path that brings order to a chaotic universe, and with it, a sense of harmony, contentment, and happiness.
I am not one of those people.
I’m not saying I don’t find enjoyment in coding. I do.
The high when you’ve deciphered new APIs and manipulated them into making your device do something it couldn’t before is intoxicating.
You feel as a God amongst mortals, able to bend the universe to your will. All things are possible.
It’s just that until that moment, my emotional state hovers somewhere in the spectrum between white-hot rage and tear-inducing frustration.
Frustration is one our most common shared experiences
Though we engineers don’t often often talk about it with non-engineers. The animation below shows my face after 20 minutes of debugging a problem.
I spoke with a colleague recently — an experienced engineer new to Android — who wanted to write an app to automatically turn on his Internet-connected lights when he got close to his house. He’d done a course on Android, so he was familiar with Android fundamentals.
He talked a lot about his frustrations.
I figured it should take me about an hour to go from nothing to the app he described. Rather than sit down next to him and pair program, I figured I’d record myself writing the code (and cut out the (really) boring bits.)
This screencast shows the easiest, fastest, and wrongest way to build this app. It’s 16 minutes represents about two hours of real-time coding and debugging, and implements everything within a single Activity. There’s a thousand ways in which this implementation is wrong — and I spend some time at the end of the video explaining why everything should be done differently.
Developing real apps for mobile is complicated
A lot of people — myself included — spend a lot of time crafting the perfect code samples, walkthroughs, tutorials, and training, so when new developers are ready to write their first app, they’ve got all the tools they need to architect it correctly, and implement it efficiently.
But if you’re trying to get a feel for Android and figure out if an idea is possible, is it worth figuring out and implementing Fragments, Services, and Intent Receivers? Understanding the subtleties of the Activity and app lifecycles?
If you want to write a high quality app that users will love and VCs will want to shower money on — eventually, the answer will be a resounding yes. BUT, that doesn’t mean you have to learn all that stuff up front.
If you go into it knowing you’re going to start again, it can be fun to write something hacky and kludgy just to have some fun and prove your idea can be done. I think of it as an incentive to learn the hard stuff.
As a result of this throw-away work, learn something very valuable — it’s possible to do what we want: automatically turn on our Internet-connected lights when we get close to home.
Which. Let’s face it. Is pretty damn cool.
When I want to learn how to code using a new platform, API, or framework, I’ll start by experimenting, trying, and failing, until I make headway or get bored.
On Day One, I just want to download the SDK, fire-up an IDE, and experiment.
I’ll invest a few hours getting a feel for how things work without worrying much about the right way to do it. That’ll produce something ugly, buggy, poorly architected, and totally unscalable — but workable as a prototype.
Note that the getting started experience is critical here. If I spend those first few hours installing and configuring my development environment I may stop before I even start.
I’ll start by seeing what’s possible using my intuition — the same way I learn how to use new electronics. And I’ll use Stack Overflow, because, I mean, seriously, let’s be real.
Of course, much like with my new electronics, eventually I may read a manual or a book, do a course, watch a video, or review a sample — but that’s never where I start (which is more than a little ironic given how much time I spend creating those things for other developers.)
There’s an art to building apps that delight users
But when it comes to just making something work, it feels like coding should be predictable. A mobile app, at its root, is just manipulating transistors that let you create AND, OR, and NOT gates, that in turn can be used to create more complex logic — we’re really just dealing with logic circuits, which when you boil it down, is just a series of trues and falses.
These basic building blocks are used to construct increasingly complex APIs, frameworks, and platforms — which are in turn used to create increasingly feature-rich apps for users. Each step along this path effectively encapsulates best-practice implementation details, so we we don’t have to start every project defining an object, creating a linked list, and writing a quicksort algorithm.
We can conceptually translate incredibly complex systems into simple state machines
I can take a video on my phone with a few swipes and touches, and start watching it on my TV with a few more. When you stop to think about the number of interacting systems it requires (electricity, power distribution, digital-analog conversion, video recording, video broadcasting, LCD display, Chromecast, …) — let alone how each of those systems works down to the physical layer (not to mention the complex decision process by which I decided on which video to watch, and the intricate and protracted negotiations with my wife to determine a mutually agreed-upon selection), it quickly becomes a fractal of complexity and intimidation.
As engineers, the difficulty, frustration, and ultimately the thrill of victory comes from unraveling the complications caused by multiple layers of abstraction within our code, the interaction between those components, and the way those systems are experienced by the end user.
To effectively write and (especially) debug code, you need to keep significant parts — if not all — of the system in your head. That means everything from the high-level architecture of how the pieces fit together, to how each of those pieces works — at times, all the way down to the physical layer.
The frustration comes from being pulled down the stack
We’re constantly switching contexts between “big picture” conceptualizations of how the system as a whole should work, and the excruciating detail of how each of its parts are implemented.
Say you’re incorporating Wi-Fi and Bluetooth signals into a self-learning system to trigger a geofence more efficiently. When it doesn’t work, the problem could be anything from a misunderstanding of how the Bluetooth APIs work, to mis-reading your Bluetooth signals, or forgetting to call .show() on the toast you’re using to test if it’s working.
Minimize the depth and complexity of your problem stack
To lower my frustration — and maximize my enjoyment — I try to keep the scope of what I’m working on at any given time as small as possible. Once that’s working, I’ll take a step back and add more complexity, iterating quickly so that there’s a tight loop between solving a difficult problem and having a better version of my working app
In practice, that looks a little like this.
Each peak represents potential energy I can store, then expend while grinding through the coding and debugging tasks. The same general principle underpins most agile methodologies: Iterate quickly and stay flexible.
Take advantage of those highs as motivation for when you will throw your prototype away and build your app again, this time in a way that’s more robust, well-designed, and scalable.
Writing good apps is hard
Sadly, there’s no easy way to write apps. Whether you choose to build it the right way from scratch, or start with something crude and gradually refine it with each new iteration, you’ll eventually need to solve the same problems, and undergo many of the same frustrations.
Those frustrations are the price you pay for the moments of triumph — that incomparable feeling when you’ve manipulated a bunch of zeroes and ones into something that’s at once both inevitable and magical.
The secret to a long and happy career, is finding an approach that works for you — a technique that will let you bask in the sunlight of those highs more often than you spend in the dark depths of the lows.
For me, that means the right way to build an App is by starting the wrong way.
Are you a happy coder? What’s your approach to starting a new project?
The video within this post is a prototype of a new series where I’ll screencast myself going through the process of updating an old (circa 2011) location-based app to take advantage of all the new Android features. You’ll see me make mistakes, debug them, and make more mistakes. More on this later.