Hacking .NET and Startups

The Taxonomy of Terrible Programmers

The MarkedUp Analytics team had some fun over the past couple of weeks sharing horror stories about software atrocities and the real-life inspirations for the things you read on The Daily WTF. In particular, we talked about bad apples who joined our development teams over the years and proceeded to ruin the things we love with poor judgment, bad habits, bad attitudes, and a whole lot of other bizarre behavior that would take industrial pyschologists thousands of years to document, let alone analyze.

So I present you with the taxonomy of terrible software developers, the ecosystem of software critters and creatures who add a whole new meaning to the concept of “defensive programming.”

At one point or another, every programmer exists as at least one of these archetypes – the good ones see these bad habits in themselves and work to fix them over time. The bad ones… simply are.

The Pet Technologist

My personal favorite.

A pet technologist is born when they make the fatal mistake of falling in love with a piece of technology. It’s not a gentle, appreciative, “man this is a well-designed framework” sort of love – it’s inseparable, unrequited, Misery-obsessive love. And just like with spying, falling in love is a liability in our business.

No matter what the question is, you can trust that the pet technologist will have an answer: his or her pet technology.

“Hey, we need to implement a content management system in Rails, which database should we use?” Mongo.

“Multi-tenant blog engine?” Mongo.

“Business-critical compliance system?” Mongo.

“Inventory management system?” Mongo.

“Electronic medical records system?” Mongo.

“Distributed data warehouse?” Mongo.

And so forth.

They will invent reasons to include their pet technology in any project you work on, regardless of whether there’s a practical reason for it or not. They will vehemently, emotionally fight any decision against including their pets. Sometimes they might even resort to not telling anyone they’re using it, and will try to sneak it in at the last minute.

The Arcanist

Anyone who has worked on a legacy system of any import has dealt with an Arcanist. The Arcanist’s goal is noble: to preserve the uptime and integrity of the system, but at a terrible cost.

The Arcanist has a simple philosophy that guides his or her software development or administrative practices: if it ain’t broke, don’t fix it – to an extreme.

The day a piece of software under his or her auspices ships, it will forever stay on that development platform, with that database, with that operating system, with that deployment procedure. The Arcanist will see to it, to the best of his ability. He may not win every battle, but he will fight ferociously always.

All change is the enemy – it’s a vampire, seducing less vigilant engineers to gain entry to the system, only to destroy it from within.

The past is the future in the Arcanists’ worldview, and he’ll fight anyone tries to upgrade his circa 1981 PASCAL codebase to the bitter, tearful end.

The Futurist

The Futurist is the antithesis of the Arcanist – today is the future, and any code written with yesterday’s tools fills the Futurist with unparalleled disgust and shame. The Futurist’s goal is not noble – it’s to be seen as new and cutting edge. The Futurist’s measure of success is Hacker News karma and well-attended User Group meetups from his war stories, not effective programming.

The Futurist will breathlessly tell you with spittle-flying gasps about the latest JavaScript-does-something-it-shouldn’t experimental project he read about on Hacker News thirty minutes ago and has already forked to his Github. He’ll squeal like a teenage girl at a Justin Bieber concert every time Microsoft Research or the Server and Tools Team releases an obscure alpha of some technology he knows the name of but doesn’t understand.

The Futurist is responsible for more reverted commits than any other developer, and is often flabbergasted when his attempts to upgrade your database driver package to v1.0.13-alpha-unstable-prelease-DONOTUSE are rejected. His pleadings of “but it has Java Futures, so we get pure async!!11!1” do not stir the vigilant release manager.

The Futurist cares not for quaint, passing concerns about stability, maintainability, or teachability – it doesn’t matter to him if it’s impossible to hire Erlang developers. New is everything.

The DevOps Engineer, the QA Engineer, and the Release Manager are the natural enemies of the Futurist.

The Hoarder

The Hoarder is a cautious creature, perpetually unsure of itself. The Hoarder lives in a world of perpetual cognitive dissonance: extremely proud of his work, but so unsure of himself that he won’t let anyone see it if it can be helped.

So he hides his code. Carefully avoiding check-ins until the last possible minute, when he crams it all into one monolithic commit and hopes no one can trace the changes back to him. His greatest fear is the dreaded merge conflict, where the risk of exposure is greatest.

The Hoarder will openly tell you that his work is awesome but in confidence knows his code might suck. It probably does – but his fear of facing that possibility is what makes him who he is. The Hoarder is responsible for many last minute bugs sprinkled throughout the catacombs of the code base. His fellow engineers, tired of slowly going insane from invasion of subtle bugs, rose to fight him.

They invented tools like git blame and other weapons of accountability, and vengeance.

Ultimately, the Hoarder is damned and doomed – but there is hope for him in the short run. The day accountability comes for him at one job, his Dice resume is updated for another. The Hoarder will live to fight another day.

The Artist

A cousin of The Hoarder and The Futurist, the Artist pours his soul into every thoughtfully constructed line of code. The Artist is an emotionalist – his software is an expression of himself, a living embodiment of the genius he represents.

The Artist considers the important questions, like will my JavaScript be more syntactically beautiful without semicolons? How can I turn this perfectly readable for..each statement into a single line of LINQ? Will wrapping this block in a promise make it more… elegant?

The Artist and his code are one, which creates inevitable problems in the real world. Every JIRA issue containing documented, indisputable proof of a bug in his code is an act of artistic censorship on the behalf of users who “just don’t understand” or jealous colleagues who envy his genius. His lower lip quavers for minutes each time a UserVoice ticket announces its presence in HipChat, titled with the name of a feature he owns – even if the ticket in question is replete with the gentle patience and understanding of an early adopter.

The Artist is not long for this world, unable to have an objective discussion about his body of work with even the most sympathetic of colleagues, he withdraws from the company of his fellow developers and metamorphoses into The Island.

The Island

The Island is the ultimate loner in the taxonomy of terrible software developers, as he desires above all things to be left in peace with his favorite text editor and devoid himself of all human contact. The ideal condition for the Island is one where communication with the outside world is kept at a minimum and strictly at his convenience. Just code, no humans.

Unfortunately, reality and ideal often being far afield, the Island has to seek the company of others in order to live. So he is forced to communicate with co-workers or clients, and it is a tremendous burden for him indeed.

So he hides – he’ll miss meetings, fail to return phone calls, stay signed off of IM, keep the email client closed, and so forth. He’ll gladly spend hundreds of man-hours Gandalfing the documentation and project specs rather than simply ask someone on his team questions.

The Island is usually also a Hoarder – keeping his releases close to the vest until it’s absolutely necessary to share them. Anything to avoid people and their judgments.

And like the Hoarder, the Island is doomed. Software is a team sport and does not suffer those who do not play by its rules.

The “Agile” Guy

The “Agile” Guy is a utilitarian, who ultimately seeks to improve the efficiency and productivity of himself and his team. Unfortunately, both his understanding of “agile” philosophies and his implementation strategy are hilariously inflexible and rigid, an irony which is completely lost on him.

The “Agile” Guy’s intentions are noble: to improve the way software is made. He’ll introduce kanban boards with precisely four tiers for exactly every project and a meticulously calculated method for determining the exact number of business points and sprint points for every issue the team can encounter.

Any issue which takes longer than four hours must be broken up; any sprint longer than two weeks must be truncated. NO EXCEPTIONS.

All personnel must pair program with their designated pair programming partners at all times, no exceptions. All git commits must be done in this exact format and hours of work against a JIRA issue must be logged at regular intervals. No status updates are allowed at standups, which are strictly cut off at 10 minutes.

The “Agile” Guy forgets the purpose of the agile process to begin with – to be flexible and dynamic, and instead imposes round-hole order on square-peg problems. The JIRA board turns into a ghetto, a wasteland of broken promises and infeasible commitments. And from dusk to dawn the developers toil, pair programming all the way, while their “Agile” Guy overload looks proudly over his new empire, forged on discipline and process.

But the “Agile” Guy creates powerful enemies in his wake: the actual programmers responsible for getting things done, men and women who live in a world without luxuries of time or realizable schedules. Men and women who try to create order from chaos themselves, but are often at the mercy of failing networked file systems and poorly implemented drivers. Such intrepid souls do not suffer having the will of idiots imposed on them. Dissent and strife spread throughout the team; what follows is rebellion.

All “Agile” Guys meet their end by being torn down like the statue of a deposed dictator, complete with an Ewok luau in the Endor moonlight and the burning wreckage of their kanban Death Star smoldering in the distance.

The Human Robot

The Human Robot tries his best and his intentions are good. But he has a handicap: he interprets everything literally. The Human Robot is the world’s first true organic computer, which also means that every user-space detail of their work must be explained literally, byte-for-byte.

The Human Robot has his uses – he can find (and patch himself!) the subtle race condition created by minor JVM differences on your particular version of the Linux kernel, but ask him to implement a new feature and a monster is born. The Human Robot, unable to grasp concepts such as figurative language, imagination, abstraction, and creative interpretation, is stuck in a world where he can only process commands.

Your product lead asks the Human Robot to create a button that allows the end-user to share their documents via email with another end user; a week later the Human Robot delivers a fully functional high-throughput transactional email server embedded inside your application.

When a Human Robot is confronted about an issue with his or her work on the product, they will respond with the following sentence every time: “your requirement was not found in the specification for this project. We require additional pylons.”

This handicap rears its head most clearly in the team dynamics of a software organization. The Human Robot is the sort of person who needs a four-page-long decision tree and a finite state machine diagram to help him understand what does and does not qualify as sexual harassment in the workplace.

Human Robots often tend to be conference organizers (see PyCon 2013) and moderators on StackExchange.

The Stream of Consciousness

The Stream of Consciousness programmer is related to the Illiterate in that he too cannot read code. However, what’s fundamentally different about the Stream of Consciousness is that he can’t read his own code in addition to that of every other developer on the team.

In fact, the Stream of Consciousness programmer is best described as a “forward-only” cursor – the only way for them to solve their problems is to write new code, every time. Code reuse and refactoring are alien programming practices that the Stream of Consciousness will tell you they “understand,” but that’s only because they know the names of those concepts.

The Stream of Consciousness will happily add a third and fourth new interface to your application for writing to the filesystem, because their cursor has already moved past the first and second interfaces they wrote last week. Their code will be totally free of circular references, but that’s only because nothing ever gets used more than once.

The easiest way to determine if you’re working with a Stream of Consciousness programmer is to read their source code and look for comments along the lines of “hmm, I wonder if this works?” and “I really wish the kitchen had more non-dairy creamer.”

The Illiterate

As the name suggests, the Illiterate has a massive problem when it comes to reading other people’s source code.

The Illiterate, a close cousin of the Island, understands basic programming constructs and has a full grasp on the syntax of his / her preferred programming languages, but is totally blind when it comes to code written by other developers. We call this “code-blind” in extreme cases.

The illiterate can understand the basic “hello world” example, but beyond that he or she never developed the capacity to understand another programmer’s intent or the “Find Usages” button in Visual Studio. So the Illiterate is forced to work around this alien “other programmer” code in all of his or her day-to-day assignments – often duplicating the work of other developers and contributing to code bloat.

When confronted by other developers and asked “why didn’t you use our standard interface for rendering a dialog?,” the Illiterate will simply stare at his or her shoes and mumble inaudibly.

The Agitator

The Agitator, like the Human Robot, is a social retard. But unlike the Human Robot, has no good intentions. An Agitator is not born, they are forged through years of suffering through undesirable work environments and programming assignments.

Having been through shit work for years and years, the Agitator believes he or she now knows best and is determined to run things they see fit, whether they actually have the authority to or not.

The goal of the Agitator is to establish dominance and control over their work environment through the use of force and intimidation.

The Agitator sees themselves as the confluence of Grace Hopper and Che Guevara, a brilliant technical visionary casting off the chains of oppression by an ignorant and ineffective ruling class. The Agitator is seen by his or her teammates as an idiotic wannabe-alpha bully who gets into high volume arguments over when it’s appropriate to use Pascal case versus CamelCase.

The Agitator will routinely try to talk down peers and superiors both in an attempt to assert dominance. In many cases he will win, seeding dissatisfaction and discord in the workplace in the process.

In most cases the Agitator is beyond help, and management has no choice but to enforce the “No Asshole” rule and terminate him.

If you enjoyed this post, make sure you subscribe to my RSS feed!

10 Reasons Why You’re Failing to Realize Your Potential as a Developer

Since going full-time on my own startup 6 months ago, I’ve spent a lot of my time recruiting, evaluating, and working with a lot of different developers. My startup, MarkedUp, is an analytics provider for Windows 8 apps (and eventually, other platforms.)

Our technology is sophisticated and difficult even for large companies to master, so the bar is pretty high for developers who join our team. We’re selective about who we work with, but even with careful recruiting practices it’s still difficult to find developers talented enough to pull their own weight on a complex product like ours.

So I want to help average developers who want to improve by calling out 10 performance-killing behaviors that stagnate the careers of most developers.

Most developers stagnate both intellectually and productively after 4-5 years in industry; they adopt some tools, pick up some patterns, learn a language or two, and maybe they’re even able to work at a successful company and contribute to some important products. Great!

But what happens when you hand a developer a blank sheet of paper and the opportunity for them to own a product?

Most of the time: chaos and failure.

Many developers fantasize about being able to own a product and make big technical decisions, but the truth of the matter is most of developers can’t handle anything more complicated than building formulaic CRUD Rails websites using the same 30 gems each and every time.

So what are the behaviors that limit the growth of average developers?

You’re too afraid of failure to learn new tools / languages / frameworks.

During my first quarter at Microsoft I gave a talk to the LA .NET User’s Group on ASP.NET MVC3, which was in beta at the time. For the most part the attendees asked me thoughtful questions and showed a legitimate interest in what the ASP.NET team was cooking up in Redmond.

However, there was a trio of attendees who kept asking me a very suspicious set of questions:

“What are the weaknesses of ASP.NET MVC3?”

“Isn’t ASP.NET MVC too unstable for use in the enterprise?”

“But doesn’t ASP.NET WebForms already do a better job?”

I realized shortly after the Q&A was finished, when I had a chance to speak to them privately, that they were attending my talk to actively look for reasons why ASP.NET MVC shouldn’t replace WebForms at their place of work!

These developers were so afraid of trying something new and possibly failing that they actually went out of their way to research just the talking points they needed to not have to learn it!

This is an extreme example, but the point is the same: average developers cling to their favorite tools and stop learning new ones because they worry that leaving their pet languages and tools behind invalidates their years of experience.

Strong developers embrace the challenge and opportunity to learn new ways of doing things.

You won’t push your commits until the feature is “done.” (It’s never done!)

We call this “commit hoarding” at MarkedUp. This happens with developers who don’t have the confidence to tolerate criticism or scrutiny from the rest of the development team try to hide their work until it’s in a “finished” state.

Ultimately these developers hurt the productivity of the rest of the team, because we lose visibility into their daily output and they tend not to ask for help in the course of regular development. They’re responsible both for delays in shipping and for lots of last-minute bugs.

Strong developers recognize that they are not their code, and thus will put code out in front of the rest of the team more frequently and take criticism and suggestions with dignity and confidence.

You know just enough to be dangerous.

In an age where it’s become a lot easier for developers to work with threads, concurrent programming, distributed databases, and so forth you run into a lot of devs who can talk a good game. They can tell you all about thread pools, a hot new design pattern, or why a headless database is better than a masterful one in some scenarios.

They are able to know what something is and its potential benefits, but they don’t understand it.

I’ll give you a recent example: in C# 5.0 Microsoft recently introduced the async and await keywords, which make it radically easier to create and manage asynchronous callbacks. These keywords have even lead to the rise of some exciting new concurrent programming patterns like the TAP pattern.

However, do you know what this keyword has also lead to? A ton of average developers who suddenly think they can harness the awesome power of multithreading simply by wrapping every I/O call into a Task object in C#. They do this blindly, without any thought as to the costs of context-switching, multi-thread access to shared resources, and more.

And this creates dangerous, unpredictable, and very-difficult-to-test code in the hands of average developers who blindly uses this new toy everywhere.

Good developers not only know what something does, but they seek to understand why it was done this way and under what conditions it should be used.

Analysis paralysis.

Gandalfing the Documentation

Sometimes you’ll hear a member of our development team say “dude, stop Gandalfing the documentation and start coding something,” referring to the scene from The Lord of the Rings depicted above.

Analysis paralysis is a classic problem that affects lots of average developers; it’s often a problem of over-analysis, but in my experience the root cause is usually fear of making a bad decision.

Research is easy – implementations are hard! As a developer, you don’t want to make a mistake when it comes time to do the actual work. So just research the issue until the heat death of the universe and you’ll make a perfect decision for which you won’t ever be criticized!

Average developers worry about looking bad or making a mistake – they want to get it right on the first try.

Strong developers who are in unfamiliar territory don’t care – they’ll write shit code, unit test it, and throw it away in 45 minutes if they don’t think it can get the job done. Strong developers actively limit the amount of time they spend researching, because they recognize that it’s a trap – it feels like work but often isn’t.

You don’t invest in your tools or development process.

Average developers will spend a lot of time learning how some fancy new language feature or API works. They’ll invest a ton of time mastering the minutia of the Windows runtime or some new D3-based charting framework, but at the end of the day that doesn’t change the fact that they’re still average developers who churn out mediocre work at a glacial pace.

If you want to be a talented developer, you have to invest time into improving your skills and knowledge, and the number one factor that separates the men from the boys in most software markets is the ability to turn out production-grade code quickly. You can have both good code and speed – but you have to invest in your process you use for building it first!

Average developers don’t invest in their tools, their process, or their environment.

Think about it – when was the last time you took a step back and thought about the way you test your code or how you look for bugs? Have you tried experimenting with different types of abstractions for the same problems and seen which one produces more maintainable code? Have you tried picking up a new IDE or text editor to see if it can help speed up common tasks? What about investing in build or deployment automation?

Often times, the biggest improvement you can get as a developer isn’t focusing on improving the code you write – it’s optimizing your process for writing it.

Free protip for anyone who follows my blog regularly: the biggest improvement I’ve made in my own development process easily is decreasing my usage of interface-driven design and dependency injection. I do a lot more work using static classes and compositions these days and it results in radically less code to test and maintain.

You’re too embarrassed to ask for help.

When we started digging into the guts of Hive for some of our work at MarkedUp, we got a little stuck on how to tackle some problems we had specific to our use case. So what did we do? We reached out to one of the guys who wrote the O’Reilly book on Hive and asked him over LinkedIn. And he replied back!

We try to be self-sufficient developers to the furthest extent possible, but we also know when it’s more economical to simply ask someone for a favor versus beating our heads against our desks for hours on end.

Average developers get embarrassed and don’t want to reveal their ignorance, so they pretend they know what’s up until they commit some sort of horrible fuck-up in the codebase itself.

There is nothing wrong with saying “I don’t know how to do this.” Strong developers know this, so they go and ask for help when they’re stuck.

You don’t know how to make it easy for other programmers to work with your code.

Like an only child growing up, you never learned how to share your toys with anyone else. The same goes for your code – you developed some bad habits and an over-abstracted style that is impossible for other developers to follow.

An important part of working on any technical team is human parallelism – the ability for multiple people to be able to work simultaneously on the same codebase. But it’s also important for teams to be able to work asynchronously too – I should be able to make changes to your code when you’re away, and vice versa.

Average developers don’t think about their code this way – they simply set out to do a task and write it through to completion with the assumption being that they will always own that piece of code. Strong developers understand technical debt and try to limit it by designing code that is as maintainable and self-explainable as possible.

Writing readable code really requires developers to change their outlook – your code should last longer in the organization that you.

You don’t know how to read someone else’s code (or don’t want to.)

It’s an interesting paradox – average developers can’t handle a blank sheet of paper very well, but they can’t write the last 30 pages of a novel in progress either. Average developers are really hesitant to try to learn an existing codebase and often have to be handled all the way through it until they’re able to produce something.

A drastic example is when an average developer is brought in on a codebase written in a language / framework that they aren’t familiar with and will immediately want to rewrite it without a second thought to business value or time to market. It’s a type of pain avoidance – having to live with the precipitation of some other programmer.

Strong developers accept that the business costs in a rewrite are usually unacceptable and should be avoided, and they’ll diligently try to understand, learn, and modify the existing codebase sitting in front of them.

Reading code is harder than writing code, but strong developers invest time into learning how to excel at it.

You can’t code from the end-user’s point of view (you think too small.)

Average developers who manage to make it a lot closer to the “great programmer” end of the bell curve usually trip up here. You may have mastered some of the technical details and you may know how to work with other developers, but you’re still missing the most important piece: being able to see your code from the point of view of the real-world.

As a programmer, you job isn’t really to solve technical problems – you solve technical problems in order to solve business problems.

An average-to-bad developer will chase technical problems down deep rabbit holes without remembering why they were solving the problem in the first place. You’re not upgrading the version of MongoDB you’re using because there’s inherent value in upgrading – you’re upgrading because your team agreed that it was worth taking the risk to upgrade because of potential business upside due to new features / performance / reliability / whatever.

More offensively, average developers struggle and fail to produce anything of business value from scratch. When asked to design a new feature based off of a simple customer story average developers will take a rigid, literal interpretation of the story or spec and ship something that is barely useable by a human.

Average developers don’t anticipate other related use cases; don’t think about the end-user’s experience; and basically have to be managed heavily when working on anything user-facing. This is why so many of them get stuck writing line of business apps instead of products.

Great developers look at their code from the perspective of the end-user. How do I make this easier to solve my user’s problem? What are some other facets outside the literal content of the story that might make this feature even better for an end user?

If you’re a developer and don’t ask yourself these questions, then you’re not a great developer. You’re passable at best.

You aren’t able to judge the business value of any programming task.

Related to the previous issue – many technically strong developers fail to realize their potential due because they aren’t able to take a step back and look at their work from the perspective of the business or organization itself.

Strong developers are able to self-manage and make good business decisions about how they choose to invest their time. They’ll ask questions like:

Is this the most valuable thing I should be working on right now? How much time should I invest into doing this? Given the deliverables I have due in two weeks, is there something I can invest in right now that will make it a lot easier for me to hit that target?

Average developers don’t – they’ll take a spec and blindly implement it until it’s finished, without accounting for how their work relates to the company’s business goals and impacts other members of the team / other business groups.

The highest cost of any engineering team is development time, and average developers waste lots of it on minutia and technical tasks that are ultimately low business value.

Wrap up

If you want to be a better developer, it starts with changing the way you look at your code and how you program.

You have to understand and appreciate the business costs behind each line of code you write. You have to be able to step outside of your text editor or IDE and look at your work from the perspective of a customer or end-user.

You have to accept that your code will outlast you in any organization your work with, so design everything to be inherited by other developers one day.

Most importantly, never be afraid to take on new challenges and ask for help along the way. You won’t improve working alone in the corner on technologies you’re already familiar with. Software development is inherently social – learn how to bring other people into the experience.

If you enjoyed this post, make sure you subscribe to my RSS feed!

What It Takes to Actually Ship a Piece of Commercial Software

Last week our startup, MarkedUp, hit the first important milestone for an early stage technology: we shipped the first version of our analytics product and put it into the hands of actual end-users.

For those of you who don’t read my blog regularly (pretty much everybody, I suspect,) MarkedUp provides in-app analytics for desktop application developers. We’re focusing our company’s initial efforts on supporting Windows 8 and WinRT developers specifically.

Now, we still haven’t completely opened the doors to everybody – we’re capping registration for MarkedUp through the use of invite codes while we gather important UX feedback and reports on bugs we may have missed.

Nonetheless, we hit that important milestone and have live users! Yay!

However, here are some interesting facts about the timeline leading up to our ship date:

  • We were feature complete, with high test coverage and few known issues, a full two weeks before we were able to ship;
  • We didn’t have a design for the marketing parts of our site, like the homepage, until 48 hours before our launch;
  • We actually cut features from the product the night before our launch;
  • We started the process of gathering user feedback when we were about 50% finished with the first version of the product – by then we had demoable charts and tables (features of our analytics product) we could show to target users.

We weren’t able to ship for two weeks, two weeks (!) after we were feature complete – and we cut features the night before we shipped? Are we a bunch of crazy incompetent bastards? No!

Shipping Software: More Than Just Code

This wasn’t my first time participating in the ship process for a piece of software, but this was my first time running it.

I suspect my opinion on this will change the more often I do it. In my estimation, the time it takes to design, plan, and code the core product and its features constitutes only 40% of the actual work required to deliver a software product to market.

So, what were the things we spent our time doing leading up to launch?

Great question, I’ll break it down by category:

  • Feature development and functional testing – 40% of time;
  • Pre-launch UX testing and refinement – 20% of time;
  • Creating a demo application – 5% of time;
  • “Marketing engineering” – time spent coding features responsible for driving users towards conversion goals – 10% of time;
  • Graphical design / branding (largely outsourced) – 5% of time;
  • Writing documentation, tutorials, and setting up support infrastructure – 10% of time;
  • Writing and proof-reading marketing copy – 5% of time;
  • Planning and executing roll-out marketing – 2.5% of time;
  • Planning and executing roll-out software release – 2.5% of time.

One thing to bear in mind about these numbers – this was for a soft beta launch, not a top-down, TechCrunch-style launch. The amount of time spent on things like roll-out marketing is astronomically higher for a massive top-down launch.

What’s the trend here? Most of the the time we spent working on the product was spent on usability issues.

Like Jeff Atwood says, your app is merely a collection of details. There’s really two classes of details that matter:

  • Details that affect how the user engages with your product and
  • Details that affect how the user understands your product.

Marketing engineering, demo apps, copy writing, and graphical design are all investments we made into helping make our product easier to understand.

Documentation, support, and UX are all investments we made into helping make our product easier to use.

The bottom line here is that the auxiliary stuff needed to support your product, like documentation and support infrastructure, take a lot of time to do well. They’re as much a part of your user’s experience as the software is itself.

Shipping the Right Features at the Right Time

So we cut features right before we shipped, literally 24 hours before I pushed to production – why?

The answer is simple: we have specific goals for what we want to learn about our users with this version of our product. Any feature that we considered to be too unpolished, too complex, or too distracting was cut – even if we had a reasonably good implementation of it ready to deploy.

Every software release should be purposeful and careful – if you overwhelm your users with too many features and options during the first release, your user feedback gets diluted across that feature set and you never get a chance to learn what you are fundamentally doing right or wrong!

If you ship a bunch of poorly implemented features, you might churn through all of your early users way faster than expected and have to subsequently work harder to acquire enough users for the next iteration. If you ship a bunch of “distracting” features, you detract from the feedback that really matters to your business.

Ship software with the intent to learn and test very specific things in that release. Don’t ship for shipping’s sake.

If you enjoyed this post, make sure you subscribe to my RSS feed!



My name is Aaron, I'm an entrepreneur and a .NET developer who develops web, cloud, and mobile applications.

I left Microsoft recently to start my own company, MarkedUp - we provide analytics for desktop developers, focusing initially on Windows 8 developers.

You can find me on Twitter or on Github!

Recent Comments

Comment RSS

Sign in