I’ve recently spoken with technical founders who’ve complained about their non-technical co-founders who refuse to do or learn anything technical, and it’s struck a nerve. One technical founder told me, “My co-founder refuses to learn the most basic SQL so that they can pull analytics on their own.”
As the worst engineer at iDoneThis, I’m the CEO. I haven’t coded seriously in about 7 years since I was in college, before I went to law school. My lack of coding chops has meant that I’ve often found myself asking the engineers to create tools for me that enable me to do my job. That behavior can get extremely distracting for the engineering team that’s trying to push the product forward, and it creates a negative dynamic in which engineering serves managers’ needs.
We began to hear from companies using iDoneThis that they wanted a place that aggregated a single employee’s activity and dones, and I thought to myself, “Simple profile pages is a feature that I could build in a few days!” So began a three week struggle in which I nearly gave up a bunch of times, before we triumphed as a team and got the profiles launched.
Off and Running
On Saturday, March 17, I got cracking, and things were looking up. I thought that I could crank out profiles over the weekend and I’d have something to show off to Rodrigo and Mike on Monday. The team cheered me on.
I have a basic working knowledge of Python and Django, so I didn’t have any trouble from the start. I had the routing set up, along with outlines of the Django views that would grab the data, and the templates that would display the data. I was just aggregating data (dones and likes) and displaying them on one page, which isn’t a very hard problem.
By the end of the day on Sunday, I felt like I was basically done. My logic that pulled the dones and likes and displayed them on the profile pages worked well. All I had left to do was style the profile pages and allow an editable bio and an editable profile picture. Fantastic!
A Huge Coffeescript-and-Backbone-Shaped Roadblock … NOT!
Going into work on Monday, I proudly announced to the team how far I’d gotten over the weekend. Rodrigo was enthused, but he told me that I should rewrite the frontend with Coffeescript and Backbone.js, because we were in the process of moving most of our client-side Javascript over to Coffeescript and Backbone, and I had to do some frontend magic anyway if I wanted to let users edit their bio inline.
Daunting, I thought, learning a new language and framework, but I figured that I could handle it. And I actually got off to a quick start. I went through the to-do list tutorial and tried to do some background reading. When I grasped the essential analogy (Coffeescript:Backbone::Python:Django), I got bored of reading and just started hacking away.
With a little beginner’s luck, I was able to code up the following/follow/unfollow/edit profile interaction pretty quickly, and I declared Monday a success. All I had left to do was the profile picture and bio editing, and I figured I’d be done by Tuesday and maybe I’d add more sugar to it. Man, I’m good!
Nevermind: A Huge Coffeescript-and-Backbone-Shaped Roadblock
On Tuesday, I thought I’d start with something simple: refactoring the display of the dones. Instead of it happening with Python and Django on the backend, I’d pass a JSON object to the frontend and render it with Coffeescript and Backbone.
Passing the JSON object over to the client was a confusing process because I kept thinking, “There must be a better way!” I ended up having to write methods to reconstruct Django objects as JSON objects, which felt incredibly primitive to me, but Stackoverflow didn’t seem to have a better solution.
Once I got the JSON objects to the client, I needed to display them. Up until that point, I’d only done a rough cut of displaying anything on the client-side, so I just wrote HTML as strings in the Coffeescript. Obviously, that wouldn’t cut it for displaying the dones, which involved a lot more HTML.
I looked around our code for the answer of what to do, and I found that we used a templating engine for Coffeescript called Coffeekup. It looked easy enough — just pass in the template and “this”, whatever that means, and it would render. I spent the next two days at a total standstill learning what the word “this” meant.
As a novice developer, when a simple statement like “$(‘#dailydone_display’).html(CoffeeKup.render(this.template, this))” doesn’t work, my first reaction is to go into “change random stuff” mode. To a beginner like me, so many things in an application work like total magic to the point where the application doesn’t always appear to be responding to logic. Applied to debugging, that means that changing random junk can get you to the answer often just as fast as attempting to deduce what the actual issue is.
Random junk I’m embarrassed to say that I tried: hitting refresh and hard refresh again and again in the browser, recompiling Coffeescript, restarting the web server, adding @s and $s in random places, renaming “template” to something else with the thought that “template” is a special word, and on and on. I probably spent a couple of hours in a zombie-like trance hitting the same buttons over and over, expecting something new to happen.
After awhile, I came to a dead end, and that meant that I could either ask Rodrigo to fix it for me, or I could actually try to figure out what was broken. I won’t lie, I went to Rodrigo first, but after 30 seconds of explaining what I needed from him, I realized that my question was of sufficient complexity that it would break up his day to help me with my problem, thus defeating the purpose of my attempting to build this feature in the first place. I struck back out on my own.
What does “this” mean? I’m still not sure.
I learned a lot from taking a deep dive on the word “this”. Probably the most lasting impression that the experience has had on me is an appreciation and sympathy for how the simplest steps can turn into deep dives into the depths of an abstraction you were told that you’d never have to worry about.
Modern web frameworks, languages, and platforms make it possible for even an idiot like me to build and launch a feature, but once one thing goes unexpectedly long, it can be a deep, scary exploration and adventure underground before getting back up to the surface. Everything is totally placid at the surface, but underground … well, let’s just say that I don’t want to go back there. That’s where you need the fat dudes with neck beards, not a skinny guy like me in tight pants.
I isolated the issue to the variable “this”, and then did some googling. After frantically changing random junk, my next vector of attack is always Google. But I found nothing. The word “this” is hard to google.
I ended up coming across the idea that Javascript can be quirky about the scope that it gives to “this”. I dove into the Javascript that the Coffeescript compiled down to, and I was able to associate the lower-level Javascript code with the relevant Coffeescript code, but I still didn’t really have much sense of the execution path was and what, if any, the bug had to do with “this”. I began to understand that “this.template” referred to the function “template” with respect to a particular scope — either the method of some instance of an object, or not —, but I didn’t understand which one.
During this time, I got extremely frustrated — irrationally so — and considered quitting a bunch of times. Why was I doing this? I wasn’t leveraging my strengths; I was wasting time. When am I going to code again? Rodrigo and Mike could do this 100x faster. What made me step back from the ledge was recommitting myself to the long view — we were trying to build a great software company and it is important that I be able to get in the trenches and support my team rather than have it support me.
I spent four hours reading about “binding” and what it had to do with scope, “this”, and event-handling. I got confused, because in JQuery, .bind() appears to have to do specifically with event-handling, whereas elsewhere, binding generically had to do with functions of which events are a specific type. My Javascript debugging hinted to me that the problem had to do with binding, because I discovered that “this.template” was represented as machine code, suggesting to me that it was “bound”. I understood that “template” could be bound to the wrong scope.
That’s when the mystery began to unravel. I remembered that my code had “_.bindAll @” in it, which I had copy-pasted from a Backbone tutorial that had gotten me started. I deleted it, massaged some other code, and voila! I was able to get everything working without really understanding why it broke in the first place.
Everything Else
I spent the next week adding avatars, adding bios, making the bios editable inline, adding profile settings, fixing bugs, cleaning up code, and messing with the styles. I kept thinking that I would be done the next day. That thinking went on for a week.
After two weeks (7x longer than I estimated), I got user profiles production ready. Rodrigo and Mike told me that it sucked and Mike had to spend another week making my database queries not take forever, paginating my dones, and actually deploying it.