It’s difficult to describe the heavy heart I have at the news that my parents sold our family cabin this week. While reflecting on my memories of the “Lonesome Pine” I recognized that I really need to write these things down while the emotions are fresh.
It probably goes without saying that my sadness is not due to the fact that we won’t ever go to the cabin again, a place I’ve adored from my earliest memories. No, the sadness is rooted squarely in the happiness of the memories, knowing that we won’t be back to produce more of it. Of course our family will continue to forge new memories in different places and having different experiences, and all of those things will be awesome. But it won’t be at the cabin.
I recognize how silly that sounds, but it’s how I feel.
There was the time that Jamie and I launched off the road on our blue four-wheeler into a tree. I was probably 6 or so, Jamie 12 or 13. We were on a ride by ourselves several miles from the cabin and she lost control. We both walked away, and someone (Dad?) found us sometime later as we were walking back.
The abandoned ski-lift was always so mysterious. To this day I don’t understand how anyone thought it’d be a good idea. The hill (and there is only one) is insanely steep and insanely short. The best part about that lift was the view in all directions. The shell of the ski lodge walls nearby with the empty pool.
Leaving watermelon in the creek near the water tap to get them nice and cool for lunch the next day.
White bread sandwiches for lunch, and pluck’n’bread for dinner. Every. Day. Heaven.
Driving the water barrel’s down to the tap to get water every few days, and having to spend what felt like years waiting for the tap to fill the giant barrels. I still remember the feeling when my dad taught me how to siphon the water out of the barrels and into our tank up at the cabin. It was absolutely magic. You just suck as hard as you can from this empty hose and water comes out?! Crazy talk.
The slick red 1980s futons that could be a chair or a bed to sleep on. Every time we’d go to the cabin it was a race to see who would claim the futons first. We’d use the futons to slide down the steep stairs. I’m not sure when but at some point we got these green military surplus cots and that was like the upgrade of the century. Except they were impossible for my 12 year-old feeble arms to setup or take down.
Sleeping out on the deck under the stars on the cots or futons with Matt and Jason and Mitch telling jokes into the night.
The old narrow deck on the back of the cabin with the green painted door made for midgets. The balusters of the deck were kind of fancy carved, everything painted brown. The deck had a brown all-weather Astroturf carpet on it.
Sometime around 10 or 12 years ago we tore the old deck off and built a new one, with a concrete block “garage” below as the support structure. The garage became the new dumping ground of random junk we didn’t have the room to haul away: mattresses, boards, etc. The new deck didn’t have a railing for several years which I’m sure gave my mother about 50 heart attacks with all the grandkids running around. We laid a hard rubber floor on the deck and glued it down. I remember getting that glue on my brand new Dickie’s pants. I think we added the staircase that same year and the railing a few years later.
We always used to go to the cabin over the weekend and usually tried to make it to church in Mount Pleasant. I remember one time we were late for church (weren’t we always late?) and were driving down the Lodge road getting near a semi-blind four-way intersection. Right as we came upon the intersection, Grandpa Brown comes FLYING across going right to left in his old brown pickup. Maybe it wasn’t as close as I remember, but I honestly thought we were about to die.
We arrived at the mountain late one evening in the middle of a giant down pour. Our blue Ford Bronco, usually trusty, made it most of the way but eventually we were stuck in the mud. We had to unload the four-wheeler and drive everyone up on that in the rain.
The Meadow. Back before the sheep road was blocked off at the end of our road, it was a little quicker ride to get there. Even still, I always made it a point to go to the Meadow on every trip to the cabin. We used to setup targets in the meadow and shoot at them, or at the pot-guts if we could find any.
Ahhhh, the “Hour Ride”. The ride of legends. Dad found a new trail one year and took us. We had a red Honda Trail 110 motorcycle with a square back seat perilously close to the exhaust pipe. I swear I burned my leg on that stupid exhaust 20 times. The ride took you up past the meadow along a road through the beautiful aspen trees. The road wound its way higher for a few miles, then rounded a ridge and descended back down into a narrow valley. I remember how scared I was of that section of the road as the mountain fell away steeply from the road. I know now how “in control” my Dad was on that red Honda, but sitting on the back clutching to his shirt and trying not to burn my leg… it often felt like we were a single rock-to-tire away from plunging over that “cliff”. After descending into the valley you turn left into the trees down a steep and very rocky trail. This trail was simultaneously the dread and the excitement of the ride. Even after I learned to ride the four-wheeler and then two-wheeler bikes, I never really got super comfortable on that section. Short but sketchy. Once at the bottom it rejoined a (flat) dirt road the led you out of the mountains and to the outskirts of Mount Pleasant. We would always ride into town and grab a candy bar or drink from the gas station, then drive the few miles up the highway to the main entrance to Aspen Hills, and all the way back up the main mountain road to the cabin. I think the “hour ride” actually takes about 30 or 40 minutes.
True to form, Dad found another steep and rocky road that headed up towards Skyline drive. As legend has it, on my first trip up that trail, at some treacherous spot I got off the bike and wouldn’t go any further. We lovingly call that road “The No-Way BJ Trail”. I will miss it desperately.
The road to skyline is indeed a hard road, and if the weather’s bad you can forget about it. I can only ever remember successfully riding it myself once. Once on top of Skyline we rode a few miles down the highway and visited Matt’s memorial at the site of the avalanche. We found a road that went over “the other side” down into this incredible meadow that had the most amazing purple flowers and little streams.
The cabin and motorcycles are like Bonnie and Clyde, inseparably connected. You can’t know one without knowing the other. Our first motorcycle was the blue Yamaha four-wheeler, the first machine I ever learned to drive on my own. I now know it’s actually a pretty weak little thing, but man was it fun to ride. If you weren’t driving or lucky enough to be behind the driver, the other options were in front of the driver on the gas cap (OUCH), or on the front or back racks. I probably still have butt bruises after all these years from those dang racks. I don’t ever want those bruises to fade.
At some point dad bought that red Honda Trail 110. That was the first two-wheeled motorcycle I learned to ride. Then Deskin came into the family and somehow commandeered a Suzuki 250 two stroke. That thing was crazy loud and I never got the hang of riding it, was too hard to keep the engine on, especially on steep hills. Deskin, Scott, and Tim would ride the motorcycle up the super steep hill under the lonesome pine and jump the road above. I never had the guts to try it.
While I was on my mission I got a letter from Mom saying that they were at the cabin over conference weekend (October 2002). All the boys rode the bikes down to Fairview and came back with a brand new yellow four-wheeler. Dad also went and snatched up three more four-stroke Yamaha’s: a YZ 400F, YZ 420F, and YZ 250F. The 250 has always had issues with it but was more my size and I always loved ripping around the mountain on that thing. Dad also bought a few smaller bikes for the younger kids to learn on, a Yamaha 50 and 125.
When I was younger, I would dig for Indian Clay in the hill next to the driveway. It brought me such happiness to realize that my kids did the same exact thing as me.
It was inconceivable to be at the cabin with Grandpa Brown and not see him working on something. My most vivid memory of this was when he was nearing ninety years-old and to see him out on the gravel driveway with a shovel clumsily trying to dig up the tough weeds. He meticulously cared for the cabin and it clearly left an impression on me.
Every so often I was able to bring a friend or two. One year I brought Tyler, and it was a disaster. He got food poisoning the first day and was puking his guts out the entire trip. He also claims he pooped his pants and had to leave his soiled undies in the bushes. To his dying day, he will never refute his position that the hot dogs had worms in them. (Everyone else on the trip was completely fine). :)
A few years ago Deskin rented a little Skid-steer and took it up to the cabin. We used it to widen the driveway, parking area, and to flatten and extend the picnic area. I cut down a bunch of dead trees on the lot to create a series of posts we buried in the ground to hold back the hill’s erosion into the picnic area. The area today is so much more functional and enjoyable.
The Sheep Road was a little road that joined the lower main road below our property with the road our cabin is on. Sheep herders would use the road to move their sheep up to the meadow. For many years we would use the sheep road to get to the cabin faster, and you’d have to drive up and around these aspens that would almost take the paint of your car if you weren’t careful. In recent years someone bought the lower lot and blocked the road, and another family bought the lot at the top of the sheep road and cut it off there, preventing you from getting to the meadow easier.
A few years ago Dakota and Scott made a little circuit you could ride the motorcycles down the steep hill below the cabin to the sheep road, then back up and through the trees of our empty lot, all the way onto the main road, then back down the driveway. Was a fun little track to ride, if not really sketchy through the trees.
There’s the motorcycle track halfway down the mountain (just past the intersection where Grandpa Brown almost creamed us in his truck). No trip to the cabin was complete without a trip to “the track”. The grandkids especially love the track because you can just go around and around and around and… you get the idea. There’s a big hump in the middle that you can get a little air on, if you like landing flat. The banked turns were always fun to zip around. My friend Cody flipped our yellow four-wheeler on its side trying to do donuts down at the track. He cracked some of the plastics. I (and my Father) were not happy about this.
The loft at the top of the cabin. Man. If there were ever a place made for kids to go and play. The little ladder hammered together by Grandpa Brown to get up there. The railing to stop us from plummeting to our deaths. I’m sure our mothers thought it was the grossest place you could ever send your kids, with spiderwebs, mouse poop, and just general dust and grime. We didn’t care man, that place was the best place for sleepovers at the cabin with cousins. Well, until we got comfortable sleeping out on the deck. But if the weather was bad, definitely the loft was the place to be.
One year we showed up after the winter and there was this giant dead bird on the carpet floor of the main room, with a dark blood stain on the old orange BYU surplus carpet, a hole in the window, shards of glass everywhere. We often found dead mice or spiders on the furniture covers, but this was a new high (low?).
One time Scott and I were on the road out of the narrow valley on the hour ride, he was a ways ahead of me, both us flying in 5th gear down this pristine gravel road. A rock flew into my shirt and I just ignored it. Suddenly the rock was moving around and I realized it was a Bee. When I was younger I had a bad allergic reaction to a bee sting, so this sent me into a crazy panic. Pelting down the road at 60 mph and I’m smacking at my chest to kill this bee. A sharp sting and I know I’m a dead man, so I slam on the breaks so that I don’t die in a fiery crash, and wait for my heart to stop beating due to the allergic reaction. Of course it doesn’t, and after several minutes Scott rides back to see what is going on. I sheepishly describe my moments of terror and we ride on home back to the cabin.
Riding motorcycles with my wife and kids. It’s brings unspeakable happiness to share this place I love, the roads and trails, the mountain air, the aspens and pines, the views.
Year after year after year of early April and October trips to the cabin to listen to conference on Grandpa’s old radio. The color of the aspens in the fall.
The never-ending toilet saga was… never-ending. You had to get a bucket of water to flush your business down, and sometimes it just didn’t work at all. If there was ever a reason not to like the cabin, it was the awkward plumbing situation. Which is why I chose to pee off the end of deck in the black of night.
We did take the liberty of installing a new water heater and plumbing for hot showers, which was better than the icy showers you could take with the portable shower bag. Despite this upgrade I don’t think I ever took a hot shower.
Most of these memories are at least partially true. Goodbye Lonesome Pine cabin. What a place to build a lifetime of memories.
Five years ago I was working at a struggling startup trying to make ends meet while building out an advertising platform centered around employment offers. I was hired to build a new analytics product for our clients and was fortunate to be given license to choose ruby as the language to build our new product with. We had an existing Java codebase that I needed to tie into and after some amount of research we decided that Protobuf was a good fit for cross-platform service communication.
I found the ruby-protobuf gem which had all we needed for the serialization usage. Unfortunately the RPC layer was unfinished and thus not an option. We certainly needed Protobuf for its RPC definition and so I wrote one. It was horrifying. I was newish to Ruby and definitely new to Protobuf and you can imagine how bad it was. All of my attempts to get patches merged to the existing library failed with nary a reply.
In that radio silence, I decided to fork the repo and released a separate gem called protobuf. Shortly afterwards I was laid off from that job and had to scramble to find something else, anything else. As fortune would have it, I stumbled on a new startup called MoneyDesktop (now MX) and was given a rad opportunity to rewrite an existing app from scratch.
Through the years at MX a whole slewofengineershelped me evolve the protobuf gem from a fledgling library that helped us out, to a library that has been adopted by lots of other great companies like Square and Lookout.
Present
In May of 2014 I left my friends at MX to continue growing at a different place under a different set of problems, and having left I now find it difficult to allocate time to working on the library. There’s been a fair amount of activity on the gem and I’ll admit to having a pretty high amount of maintainers guilt about not giving it the time I once had. It’s kind of dumb to feel guilty about not giving away my free time for free, but it’s pretty well documented that this isn’t just a me thing.
Case in point, I recently watched this great talk by Justin Searls about OSS maintenance problems. Justin really hit the nail on the head describing the lifecycle of OSS projects. It’s pretty clear I haven’t done a good job of keeping the community around this project healthy. The gem is after all, my* one hit wonder, so this is my attempt to change all of that.
After meeting with friends at MX recently, we developed a pretty solid gameplan to get things churning again.
Future
First of all, I’m moving the repo from my personal github account to a new github org called ruby-protobuf. Michael Ries at MX is spiking out some code that will eventually replace the serialization layer and public DSL of messages, enums, and service objects.
We want to modularize the gem into a series of libraries that you can include piecemeal based on individual usage (think RSpec). This will probably end up looking something like:
Core
protobuf-core
Extensible Compiler.
Message/Enum API (with minimal to no meta-programming).
Serialization.
RPC
protobuf-rpc
Depends on protobuf-core.
Service DSL with compiler for Service Descriptors.
Extensible Server and Client Implementations.
Transport(each depend on protobuf-rpc)
protobuf-rpc-socket
Vanilla socket client and server transport implementation.
protobuf-rpc-zmq
ZeroMQ client and server transport implementation.
Longtime contributors to the project will recognize a familiar story here. The existing client and server implementation have undergone relatively few overhauls in the last 5 years and are in dire need of some simplification. The message/field APIs are even more crusty, having been structurally untouched since being forked from the original ruby-protobuf gem.
The unit and functional tests are extremely unreliable due to the difficult nature of testing the zmq transport implementation. It’s my belief that we will get a lot more mileage out of splitting the gem up than we’ve ever had. This is our chance to learn from the past and produce something spectacular.
The version target for the changes proposed here are >4.x, though that is definitely up for debate. It may be advantageous to start the versioning scheme over from scratch and let the protobuf gem as it is today die off. That is a conversation that I expect the community to make the decision on.
I’m also excited to say that I’ll be reaching out to some past contributors and asking if they’ll be a part of “ruby-protobuf core”. There have been some awesome contributions in the past from motivated devs and I want to foster more brains on the project.
Lastly, if it’s not clear from all of the above, I am ready to give up the reins of the project to the community that depends on it. I’ll probably still have my hand in a few parts of the organization at first, but this really is about distributing ownership so everyone can move faster without me as the bottleneck. I’m so grateful to have worked on something so useful for a significant portion of my career, and I look forward to a time where future projects can bring me back into regular usage and contribution.
If you’ve worked with me in the past on the gem, I want to say Thank You for your work, and your patience. Let’s make this thing even better.
In July of 2010 I was hired at a tiny startup known as MoneyDesktop (now MX). We had a legacy PHP+Flex app inherited from a previous company, and as you can imagine, it was not pretty. One of the great things about working at a brand new startup is that you actually don’t have any customers yet, so the tech is about as green field as it gets. This is also one of the worst things, because at this stage you don’t know what you don’t know. We decided from day one to build a service-oriented architecture with Protocol Buffers running the intra-service communication. We ditched the PHP and ported the Flex to run on top of a Rails API service. So sue me.
Naturally, at first we got a lot more things wrong than we got right, but the seed of the architecture that we started was solid and it enabled us to move very quickly to produce a product that customers wanted. We created a system that in just over 12 months was starting to get out of hand. We used Rails for all of the “front-end” services but decided to use Sinatra to power others because they were “lighter weight”. At one point I started writing a custom event service, only later to find RabbitMQ (thank the heavens we found it before I’d gotten very far). We had a lot of duplication and not a lot of established patterns for how to be consistent. We were really good at clever solutions, but didn’t understand how damaging that was to the long term health of our software.
Finding Coal
In late 2011 we acquired a tiny startup and brought on their technical co-founder as our VP of Engineering, Brandon Dewitt. Brandon’s an incredibly smart engineer, and I feel truly blessed to have been able to code under his guidance and leadership.
For an entire month after the acquisition there was near-total radio silence from him from a leadership perspective. I started getting super antsy wondering what was going on, worried he was freaking out about our app or our team or the color of the paint on the walls. We had recently gone through some engineering management swing-and-miss situations, so we were really hoping things were going to work out with Brandon.
After about a month he finally opened up that he had some major concerns about the lack of consistency in our software practices, specifically how much technical debt we’d already accumulated in such a short period of time. Sure, we’d done a good job producing a working product, and we were clearly gaining traction in our industry, but at what cost? I remember well Brandon’s critique of one of our critical internal services, which had basically had one engineer working on it from day one. We’ll call that dev Hank. Hank was no longer with our company, for related reasons:
“It’s like, Hank has a house right next to a power plant. Hank wants to get power to his house so he can run the lights and the dishwasher and all that.
“But instead of plugging into the power station next door, he walks out into his front yard with a shovel, and he starts digging for coal. And he digs, and he digs, and he digs some more. He spends an incredible amount of time digging.
“And you know what’s the craziest part? He fucking found coal!!!”
A lot of our services were like that, we dug for coal when we had a power plant next door.
Over the next couple years we evolved the platform into a set of services that were cohesive and well-formed. Working at any layer of the stack was simple because every app was built with the same set of principles and style. We standardized using Rails for every service. We worked hard to solidify the patterns and tooling that enabled us to iterate quickly and produce good code. It’s easy for me to say that in 12 years coding, MoneyDesktop had by far the best codebase I’ve ever worked in. Of course the system wasn’t perfect by any stretch of the imagination, but it had “good bones”, and many of the engineers MoneyDesktop has employed over the years have vouched for its elegance.
Would we have gotten there without Brandon’s guidance? Maybe. I’ve worked for a lot of other companies where consistentcy wasn’t even a conversation, and it’s my belief that the focus on discoverability and consistency is what made that codebase work well.
Finding Consistency
A focus on discoverability and consistency should be an intentional and public decision that you make in your software organization. Your developers should know about it, and should hold each other to the standards you agree to.
What does discoverability and consistency mean? It means producing software (hopefully) free from the artifacts of bias, as agreed upon by your team. Do you have to use Rails or protobuf to be discoverable and consistent? Of course not. But you should seek to gain consensus. Here is a simple guide to becoming more consistent and discoverable in your codebase.
1. Get a Style Guide
I don’t blame you if you just rolled your eyes, I know I did when we got our first style guides at MoneyDesktop. But hear me out.
Style guides abound on github and other places for the language and framework you are using. Find the most idiomatic style guide you can, tweak it at a minimum, and preach it to your team. Get consensus. Get buy-in. Get a style guide.
The style guide really is one of the best things you can have. You will hire plenty of developers who have different opinions about bracing, spacing, how to name methods, size of methods, size of classes, feature X over feature Y… etc. Which one is “right”, or does “right” even exist?
The “right” style guide is the one whereby following it, your team can consistently produce relatively bug-free software in a timely manner.
A trivial example is bracing. Many languages allow you to omit braces for single line if/else blocks, but if you want to execute multiple statements per block, you’ve got to use braces (Heartbleed anyone?).
In this example spacing doesn’t save you (unless you’re in python), so you’ve got to use braces on the else if you want to execute both method calls. But now what do you do with the if statement?
You could leave braces off the if statement, but to be most consistent with the rest of your codebase, why not always use braces? Of course the language allows omitting braces in certain situations, but not in all situations.
Another example comes from ruby, and it’s one I wish the community would figure out. Ruby 1.9 introduced a new hash key syntax when your keys are symbols:
In both cases, the hash keys are symbols, but in 1.9 you may encounter either one. When I go to change a file with these keys, which do I use? Probably the same as what’s in the file, assuming their isn’t mixed usage. If there is mixed usage, or I’m creating an entirely new file… what then?
Pick style guide rules that help your team to be consistent now and in the future, regardless of the whims or fancies of Joe, Jane, or Janet Developer (or even fancy new fangled language constructs). I am not saying don’t use new language features. I’m saying question the consistency value of new features. I am also not saying how you should use braces or symbol syntax, these are just examples of discussions I have been a part of.
I have had individual developers complain to me about the usage of a style guide and I’ll be honest, it boggles my mind. If you find negative value in adhering to a style guide, what you’re saying is that your preferences are more important than the health of the codebase over time. Yes, I believe adherence to a style guide produces a healthy codebase.
Your style guide shouldn’t contain every possible rule anyone can conceive, merely the preferences which are generally controversial or tend to be confusing to your team. Preferences that drive Sally to produce code that feels different than Jeff’s. Everyone has their own style, and that style should never be discouraged as “wrong”. Just try to find a common ground that’s consistent and discoverable.
2. Use Trusted/Tested Community Libraries
Beginning developers want to write a solution for every problem that they can imagine. Experienced developers want to use everyone else’s battle-tested solutions wherever possible. Neither are wrong, but context is pretty important. If the problem you’re solving for has a well-tested and well-trusted solution produced by your language community, you really should be using it in your production system. If it doesn’t, produce it and then give it back to the community!
That being said, there’s a certain amount of taking for granted attitude that we would do well to squash out of our industry. Don’t go re-invent the wheel, but you should definitely study wheels. Read often. Learn a new software language every year. Subscribe to weekly mailing lists. Hop on that library’s IRC and ask questions. Stay familiar with the trends of the language and framework you are using. Go to user group meetings.
No software project is an island, so you should stand on the shoulders of those who’ve come before. Just don’t be ignorant about why they made the decisions they did.
3. Write Tests (and run them!)
Please, for the love of all that is holy, write tests for your software. Write tests when you add code. Write tests when you’re fixing bugs. Remove practices, processes, and roadblocks that stop your developers from testing.
Once you have those tests, run them during your development and release processes.
4. Get Feedback Often
Talk to your team weekly about how things are going (not necessarily the “what”, but the “why” and “how”). Talk about your style guides, the libraries you’re using (or should be using). Talk about your methods and processes. Hold weekly brown bag discussions. Teach others on your team about past experiences you’ve had. Start a book club and meet regularly.
Getting feedback will empower your developers to feel like there’s a reason they accepted the job offer. Give them a reason to stay, a reason to get or remain passionate about what it is you’re doing.
Finding consistency for your team is a valuable process you can go through. You’ll empower your developers to write better code and enjoy what they do. Your project’s health will thank you for it.
Software Development is about problem solving on a variety of levels of abstraction. From memory allocation, through function composition, to interaction design and usability, and about a million layers in between. We write software that is executed by machines to accomplish desired tasks; things like animating shapes across the screen of your mobile device, keeping a self-driving car in its lane, or ejecting a rocket booster at the appropriate altitude.
The machine is obviously important, but perhaps more so are the humans tasked with maintaining the executable instructions, of understanding their intended behavior. At some point in time, a human will need to reason about the code. The machines do exactly what we tell them to do, whether the instructions were our intention or not. The “best” developers are those who can write the simplest machine instructions to accomplish a given task, while also critically ensuring that the instructions are simple to reason about later in time for a human being (often the same individual).
You probably already know that the harder task is not the machine instructions, it’s the human component. As a beginner learning your first language, you can’t imagine what it’s like to effortlessly “think in the code”. Yet after years of experience, after learning and using additional languages, the task becomes “normal”. You can leverage the strengths of various languages without breaking a sweat.
But we still love to obsess over the machines, juicing every last bit of performance out of the smallest most obtuse piece of code we can manage. We say to ourselves, “Yes, I understand this one-liner, it’s very clever. I will definitely always know and understand what this thing is and why I wrote it like that.”
Except, of course, this is untrue. Our memories are provably horrible. How many times have you raged over a piece of code only to git blame and sheepishly read your name next to the offending lines. It happens. We’re fallible. We forget things. Admitting you have a problem is the first step to healing. It’s okay. We all do it.
And so we learn from our mistakes and we work really hard on the human part. We write code that accomplishes a task and is well designed from a human’s perspecitve. “No one,” we tell ourselves, “will ever be confused by this code. It is a bastion of clarity.” Other developers will review your code and agree, this could not be any simpler.
Yet all too often, time is money, and we don’t have the time to Make It Right. And so we do the best we can to solve the problem in a way that others will follow. Other developers will tell you, “We understand why you built what you built, and the complexity will have to do, because we have features to ship and more bugs in the bug lane.”
And so we move on. Plan. Estimate. Build. Ship. Test. Fix. Repeat. The (developer’s) circle of life.
Until one day it happens: you realize that you are missing a big, fat, giant, enormous step in this endless cycle of software development.
Did I ever stop and ask, “Is it useful?”
Oh sure, as an industry we talk about usability. UX is king, right? Except, (warning: controversial statement) nobody is doing UX. Everybody talks about doing UX, and we argue about button colors and css3 columns and font families and page views and a/b testing. But is the act of producing usable products built into the cyclical nature of our process? Do you have a team, or even a single developer, who is asking whether the thing they built is not only usable, but actually useful? Are you doing it consistently, on every feature and fix you produce?
On the hierarchy of needs for any application feature, Usefulness is Everest.
Beautiful: You thought about the outfit and even did your hair all fancy.
Usable: You built something that behaves well and is intuitive.
Useful: You built something that improves someone’s life.
You may be thinking that I’m writing this because I recently screwed this up. You would be correct.
I just spent two months building a new feature into the Nuvi platform. I spent nearly a month gathering requirements, meeting with our Account Management team, having numerous phone calls with the client, holding numerous design sessions with product and engineering. The problem was an interesting one that took more time to plan than I had initially wagered. In the end, we all agreed and understood what it was that I would be building. And so off into the weeds I charged, mental model for the problem rooted firmly in my mind.
Building the feature took about a solid month of software development, in between other responsibilities I have. I produced a working feature. It looked good (thanks to our design team). It was intuitive to use. It would definitely improve the lives of our clients and internal teams.
I deployed the feature to stage. Various issues arose immediately due to testing with actual data, and I solved them quickly. I deployed the feature to production, protected behind a feature flag. Better data, more fixes. Three more pull requests and stage/prod deploys out of the way, and I’m done right? Wrong.
I tried to use the tool to accomplish its only task: easily determine which monitor’s velocity is growing the fastest. There weren’t any syntax issues, all my tests were passing, the icons were all aligned beautifully, the sorting and filtering worked exactly as expected. Yet, it was horribly obvious how incorrect the velocity calculations were. The simple algorithm was completely, utterly, and embarrasingly incorrect.
WHAT?!
I had spent months discussing, designing, analyzing, writing tests, agonizing over class size and readability and composition and dependencies. How did I get it wrong? Why did it take so long to realize it was wrong? Conceptually fixing the issue was trivial, yet I had a non-trivial refactor on my hands if I wanted the code to be easier to reason about.
I am fascinated that I spent so much time thinking about and implementing a solution to this problem, writing tests for it, without realizing that my algorithm was not actually correct. I was, as an engineer, thinking about the problem from the code outwards, not the interface inwards. Only when I removed the code from the equation was I able to see how unuseful the solution was. Did the page “work”? Yes. Was it beautiful? Yes. Was it usable? Maybe. Was it useful? Definitely not. Thankfully, fixing the issue was about a day’s refactor and testing. Am I positive it’s useful now? No, not really, not until I get it in the hands of the client and ask for their feedback.
So next time you’re building That Thing, take some time to put yourself in the user’s shoes and just try to use the product. Ask yourself, is it Useful? You might be surprised what you find.
The dates for the last three posts I’ve written are from July 2011 and April of 2014. I used to write a lot (ish) and it was always fun to do. Somewhere along the way I fell out of the habit. Through the next 30 days I’m going to be writing a few posts to see if I can begin to rekindle the habit.
2008-09: 50 posts
2010-14: 12 posts
2015-: ???
It’s been said that the vast majority of one’s life is lived not through his words and actions but through the thoughts and emotions inside his own head. By writing, I hope to expose more of my internal life to my external self. Along the way I hope to understand myself more. I hope to understand the results in my life more.
I enjoy browsing Twitter and Instagram each day but I’ve noticed that I am in constant consumption of information and rarely take the time to create. I am looking to be in a more creative energy in my life, to take the time to think and meditate more often. I can see writing being one avenue towards building a system of being creative often.
I want to write more often because it puts me in a more contemplative mode. Writing will do that you. So will drawing, painting, playing piano, and a host of other activities. Periodic contemplation of your life path is a Good Thing.
How we spend our time is a fascinating concept to me. I think Derek Sivers put it most elequently, as he so often does:
[Time] really is limited. We can’t pretend it’s not. Time spent doing one thing is time spent not doing something else.
It’s so easy to waste time doing that stuff that’s of no importance, no challenge, no benefit to anyone, not even yourself.
The crux is the “easy to waste time” part. I have found myself at various times in my life “coasting”, which just means not really paying attention to why you’re doing the things you do. I believe it’s quite healthy to have time set aside to “do nothing” as they say. Filling up every minute of your day has never felt particularly healthy to me. What I’m most interested in is building a system where I regularly spend time contemplating, creating, purposefully doing, in addition to time spent purposefully not doing.
Keyword: purposeful.
During this 30 day period I’ll be drawing more as well, for similar reasons. I haven’t picked up a pencil to draw in nearly 10 years. Last night I tried to draw a picture of my daughter Bella. What an incredibly relaxing experience it was to just sit and do nothing but try to interpret light and shadow.