10x Rockstar Ninja Guru Jedi Developers
From time to time, we see job postings for a 10x ninja guru rockstar jedi programmer. Some of us cringe visibly when we hear such terms. The problem is excacerbated by the media that shows such genius social awkward programmers type really fast on the keyboard on really fancy UIs or raining chinese characters.
Given that we claim ourselves to be a few standard deviations removed in the desirable direction from the mean, in the normal distribution of the programmer population, a common and a fair question by clients goes a bit like this.
How do we measure this 10x productivity that you claim? If, I assign the same task to a 1x engineer and a 10x engineer, will the estimates differ? Will the 10x engineer be able to finish the task in one hour that would take the other engineer 10 hours?
There are many implicit assumptions and fallacies in the question. Lets lay them out one by one.
- Engineers need to be assigned tasks
- Engineers will be able to estimate a feature
- Implementations of a given functionality are equal or equivalent.
Lets analyze them one by one.
Engineers need to be assigned tasks
Software development development is a contact sport. It needs constant communicationbetween various stakeholders from Product Owner, UX/UI designers, Project Management, Engineering, QA and DevOps. But the goal is to get a team of people who can self-organize, prioritize stories and tasks and deliver the product in slices. The key here is communication and coordination rather than a top down task assignment. Each slice of software delivered requires involvement of all the members. The team members would collectively decide and pick up the next task that makes sense for the overall project direction.
Engineers will be able to estimate a feature
Software Estimation is a really hard problem. Often times we hear questions about how much would it take to build such an app. It is only fair that our clients have such an expectation as we have built many such apps before. That is the reason they engage us in the first place. But, as hard is it is to beleive, we have not done the same project twice. Almost everything that can be commodotized in software has been commodotized as open source libraries. Although, it may require some assembly. Most of the complexity comes in wiring up these open source components and massaging structures from one component to the other. Some of this complexity is essential to the problem with others might be accidental.
We build some of the most complex systems involving a lot of pieces that are not under our control. For example, lets take authentication and sign up as a feature. Its common enough and is pretty much all apps need it. But I've seen several hackathons where the team lost a lot of time building the perfect sign up / sign in flow. They would go overboard with registration, sign in with email/password, forgot password, login with facebook and unifying identities among federated auth sources like facebook, LinkedIn, Twitter and your own email/password authentication and corner cases such as changing the email address and verifying the new one etc. In fact, this is so complex, that there are startups and products that specifically solve this one problem like Stormpath and Auth0. Yet this feature can be overlooked or unless clearly specified it is impossible to estimate. Often times, its simpler to build what is necessary and iterate on it.
Implementations of a given feature are equal or equivalent
There are multiple ways to solve a problem. Sometimes the best possible course of action would be to not solve a problem. In other cases, a component may be very important to a system that it would need to be engineered well to ensure that downstream components and systems are not affected. Let me illustrate this with an example. Imagine you have two microservices which talk ReSTful HTTP/JSON. A naive approach would be to simply use a HTTP client. But when the other microservice is being serviced or is temporarily down, the overall reliability of the system suffers. One may need to be a highly available customer facing service while the other might provide services for your warehouse. When dealing with such a problem a good engineer would choose to implement exponential backoff to retry HTTP requests when initial call fails. On the other hand a great engineer might think of it in the following way.
- Does this need to be a synchronous call?
- Was ReSTful HTTP/JSON a conscious design decision or was it the default one?
- Can I implement it as a message queue so that it simultatenously takes care of the reliability and improves the performance?
- How can I provide feedback to the upstream system if the message consumer reports an error? Should it be a HTTP callback or should it read from a reverse queue?
While the same functionality can be achieved in both ways in some cases the exponential backoff might make sense while in other cases the message queue based approach might be more appropriate. The 10xers will have been exposed to enough systems to develop and intuition for such choices.
What we look for in great engineers?
We beleive that great engineers have the following traits.
This is by far the most important trait of a great engineer. Empathy for the client and the customer's pain is what drives great programmers to solve a problem. Unfortunately this is not a learnable skill. We call it "giving a damn". Most agencies say this that they care about the customer but we truly "give a damn" that your product succeeds. If not, we do not take up a gig.
As rational adults, we do not believe in get rich quick schemes. In a similar manner, there is no shortcut to becoming good at programming. As with any other craft or skill, technical skills and logical reasoning follow the 10,000 hour rule. That is why our team is primarily composed of people who have put in the hours or are deeply committed to this craft.
Daniel Kahneman writes about the slow and the fast paths of our brain and to be aware of our cognitive biases. The craft of software development predominantly engages the slow paths in the brain. But with experience we build intuitions for design that allow great engineers to visualize in terms of systems and interactions without having to consiously think through the solution. This might sound dangerously similar to architecture astronouts but this could not be farther from that. These engineers can roll up their sleeves and implement any of the components in the system but they slowly develop the intuition of it over time. For example, an experienced web developer working with frameworks like Rails would automatically think in terms of views, view models, service objects, controllers, db models and background jobs etc. While this decomposition would take a lot of effort in the initial stages, it comes naturally with experience and that is what we call design intuition.
Cal Newport's book on Deep Work summarizes the perfect conditions for being good at any craft. We have different ways of training our brain to get into a zone. For most people, a deadline would be a great motivator for forcing people to focus. So we've built a culture of perpetual deadlines to force people to focus. We choose to work with great engineers who do not need such external factors to focus. Focus is like a muscle that needs to be trained. So instead of perpetual deadlines, we we encourage pair programming. We strongly discourage crashing for a deadline and always focus on quality of the long term deliverable.