When Google announced Android Studio, I was highly intrigued. I've spent years of my life in Eclipse, and my secret hope has always been that sometime before the heat death of the universe, we'll get a better IDE for Android development. (I'm not here to drop a truth bomb on Eclipse's flaws; hating Eclipse is like hating gravity at this point.)
As an experiment, I began using Android exclusively on my side projects at home. I've grown to like it quite a bit: it has a nice layout editor, I like the refactoring support, and I have fewer issues with IDE stability. However, the part of Android Studio that I like the most is its integration with Gradle, the build tool. I did not expect this.
In my previous big Android projects, I've always had two separate build process. There's the build process within Eclipse itself, used for compiling and execution as an engineer writes code. Then there's this separate build process, usually driven by ant, to create build artifacts; these builds are often part of a continuous integration pipeline and used for testing/submission. (Sure, you could simplify by mandating that everyone builds everything all the time with ant. Here's the problem with that: Eclipse is right there! It's taunting us with its fast, easy builds.)
Two build processes is problematic because they need to generate the same binary. That's not easy; every time you tweak your class path or a dependency in Eclipse, you need to make the equivalent change in your build.xml. I've never found a good way to automate this, or a forcing function for synchronizing these build processes manually. As your project gets bigger and you take on more dependencies, entropy does its thing and inevitably the build processes begin to diverge. This leads a lot of problems. QA finds a mysterious crash in the APK created by ant, which no one can reproduce in Eclipse. We change the classpath in Eclipse, then ant fails and no one realizes it until QA threatens us with pointy sticks. Working through these problems is a waste of everyone's time.
Android Studio has a great solution, which is that it uses Gradle, a first-class build system, for builds within the IDE. Need to create an APK for QA? Just use the exact same Gradle command on the command line. All of your app's dependencies and all steps within the build process are thus made explicit via your Gradle config file. There is one and only one build to rule them all.
Could you do the same thing with Eclipse? Maybe. There is a Gradle plugin for Eclipse; I spent a few hours of quality time with this and made very little progress. I can't imagine integrating that plugin across a large engineering team without a lot of cursing and adult beverages.
I think this choice in tooling is pretty indicative of the difference between Eclipse and Android Studio. With Eclipse, you can do anything, given you get the configuration right. The odds of this occurring straight-away are low. In Android Studio, the defaults are much smarter, obviating the need for much of the configuration. It's convention over configuration all over again.
I have written many design documents in my day. In most cases, the documented design had only a passing relation to the final implementation and rapidly became a fossil on our wiki. In the best case scenario, the document closely matched the implementation and I took great pains to update it with each iteration upon that codebase. I then left the company, and they promptly ditched my entire solution regardless of the awesome doc. In short, my track record with these documents is not exactly stellar. Regardless, I still think design documents are a good idea for a couple of reasons.
The first, most obvious reason that design documents are helpful is that it's a forcing function for actually thinking deeply about software design. I am not advocating a thousand pages of sequence diagrams here. Simplying laying out the components and their dependencies is helpful: it informs the sequencing of the work, you have to think about the trade-offs involved, and it allows you to form initial ideas on the size and scope of the problem. This sort of documentation won't answer all hard questions about this particular design, but it is helpful in calling out many of these questions.
The second, sneakier yet more important reason that design documents are helpful is that they give you an opportunity to analyze an ambiguous problem and propose an elegant solution. It's hard to do that well, and it turns out this can be important for your career. Think of it this way: if you work in a growing organization, there's a bunch of good code being written. Consequently, if you want to differentiate yourself and ensure great opportunities come your way, it may take more than good code.
There are plenty of ways to differentiate yourself (mentoring, championing best practices, officiating the office ping pong tournament). I'd argue that writing and presenting effectively on software design is one of the rarest and thus one of the best. Additionally, the hardest and most important problems often have an element of design. These problems aren't just distributed randomly. If you want to work on them, it benefits you greatly to have a strong record of proposing designs and seeing them through implementation to delivery.
At this point, I have clearly convinced you (odds of this actually being the case: 48%) and you are firing up your text editor to begin your journey to Documentation City (odds of this actually being the case: 0.48%). How do you get started? My suggestion is to start small, with respect to the size of the document, scope of the problem, and amount of review. As you look at more problems in this way, you'll iterate on your approach and find a style that works well for your team and its problems.
Good intentions can go awry quickly in the world of software development. Imagine this common scenario: there are multiple teams building related projects at the same company. At some point, someone realizes that these teams tend to generate a lot of duplicate code; why not just create a common library that all the teams can reuse? Everyone agrees it's a brilliant plan, and so code begins to shift from each team's codebase into the common library.
Fast forward to two years later. Now everybody is using the common library to solve a lot of hard problems. That's good! At the same time, people would rather have a tickle fight with a komodo dragon than actually wade into the common code and make a significant change to the existing logic (author's note: tickle fight with a komodo dragon is not a euphemism). Why is everyone so afraid of the common code? Since a bunch of different teams have touched the common code, it's a giant mishmash of conflicting coding standards and duplicate abstractions. Even worse, all products now depend on it. The common library has become a Jenga tower, growing taller and more wobbly with each change. Everyone is now afraid to make sweeping changes in there, lest they send the tower tumbling down.
How did the common code get into this state? Well, it's because we're humans and that's we do: make a mess of our common places.
This problem is well known in certain circles as the tragedy of the commons. Wikipedia describes the problem as "the depletion of a shared resource by individuals, acting independently and rationally according to each one's self-interest, despite their understanding that depleting the common resource is contrary to the group's long-term best interests." This theory has been applied to problems like population growth, pollution, traffic jams, and now, janked-up codebases.
So, if this is a common problem because we humans are a bunch of dumb dumbs, what's the solution here? Well, this guy Ronald Coase proposed a solution that won him the Nobel Prize in Economics, and it's actually relevant to our problem. Coase theorized that, if property rights are well defined and negotiation costs are low, then just by assigning property rights, the interested parties will negotiate their way to a solution to the negative side effects.
How would you apply that fancy book learnin' to the common library? Well, you'd start by splitting the common library up into smaller packages, with an established owner for each package. Then, you make it easy for the teams to communicate and negotiate changes to these newly split-up packages.
Let's say that Team A owns the common Logging package and Team B suddenly wants a new feature in that library. In the olden days, Team B would've just hacked this up. Since it's not their codebase, they'd move fast to get this in, leaving few comments and no tests. After all, that's what everybody does in the common library and they know there's no one to call them out on it.
That won't happen here, though, since Team A is now married to this codebase. Team A could propose something like, "You guys do the work, then we do the code review and we'll own this long term." Team B could then make a counter-offer, like "How about you make the change, and in exchange, we'll implement your Feature Request X in the service client library that we own?"
You've now gone from a massive codebase with zero owners to a bunch of small codebases, each with a motivated owner driven to ensure quality throughout the lifetime of that code.
As it turns out, ownership and fast, easy communication solve lots of software problems. Let's do more of these things!
Today is my last day as a full-timer at Famigo. It's been a great 2+ years, and I'm very grateful for all the things I've learned and all the friends I've made. However, it's time for my next adventure. Next week, we move to Seattle where new, big challenges await. (I'll go into more detail on my new job in a later post.)
Why are we leaving? We've built fabulous products at Famigo, raised VC money, had lots of cool stuff written about us, and the company continues to charge ahead. Not only that, we have great friends in this city and a wonderful house. Why go? Well, all of this startup stuff has been way more complicated than I expected. Allow me to explain.
You Can't Put Life On Hold
I joined Famigo at the ground-level as cofounder and CTO. My plan was to immerse myself in my work and make this company a great success. I knew that would probably take years, but I was ready to make the commitment. In true comedic fashion, we immediately found out that my wife was pregnant. All of a sudden, questions about user retention and referral mechanisms looked trivial compared to questions about diaper rash and tummy time.
My plan to put real life on hold and focus on the startup failed in a million different ways. We had health issues, car issues, house issues, and family issues. Not only was all of that stressful for our entire family on top of the startup rollercoaster, it was also expensive. And, unfortunately, I couldn't pay for any of these expenses with Famigo stock options, even if I offered them with no vesting and a ridiculously low strike price. (Note to American economy: come on, man!)
Even more than the issue of money, there's the issue of time. The idea of doing a startup is something that had appealed to me for a long time. It was my dream. After a couple of years, I began to realize that my dream was causing all other dreams to be deferred. We wanted more kids, my wife wanted to take some time to be a stay at home mom, we wanted to give my son a neat childhood with plenty of adventure. Slowly, I began to realize that pursuing this startup dream to the exclusion of everything else was a little bit selfish.
The lifecycle of a startup wasn't what I was expecting. There's a lot written about huge successes like Instagram, where lots of good things happened. There's also a decent amount written about startup failures, where lots of bad things happen. There's not much written about all the startups in the middle, where you experience some success but Facebook isn't exactly shaking in its boots.
Everything was a surprise; that goes for just about every good and bad thing that happened to us. You can read about startups all day long, but ultimately, that's no preparation for the experience itself. Deals take way longer or way shorter than expected, helpful people appear or disappear as if by magic, and the key human relationships beneath the business can spontaneously combust. Not all of these surprises are bad, but they are a constant.
The tough part about all of the surprises is that it makes it impossible to plan anything. That's tough, because things like families, investors, and employees like to know what might happen next. Do the inherent surprises behind a startup ever end? I'd venture a guess, but then life would find a way to surprise me.
Do It Anyway, But Do It Right
Given what I've written thus far, would I do this again? Would I recommend this experience to others? Absolutely. I have had a blast, I've learned so much, and I have met some of my best friends this way. I am incredibly proud of the entire experience. I also discovered an unexpected benefit: if you're a technical person and you do it right, people notice.
When I say 'do it right', I mean build something fabulous that people know about. Both parts of that are equally important. As an introspective person, I feel weird drawing attention to the work I do, either here on this blog or on Twitter. (You probably would not guess this from the giant ego fest that is my website!) It simply must be done, though. If you don't do it, no one will, and then you run the risk of all your hard work never getting the notice it deserves.
If you do manage to build something fabulous that people know about, you will be inundated with incredible opportunities. Then, when you decide you need to find your own next adventure, you will quickly find something great. That's what I did. Onwards!