A look at the 10x paradigm
devup.co
devup.co
Personally I think the narrative works better when you think there are 1x programmers and 0.1x programmers. And a very large number of developers are actually between 1.0 and 0.1. These 0.1x programmers somehow manage to solve problems by simply puttering away at it over time. For example, these programmers might start out reading a web service into an XML file, re-opening that XML file to process the result, copying that file someone else that is never read again, taking the result and inserting it into a database table, reading the table to create an aggregate result, and then finally inserting that result into another system. And they do this all day long every day for every problem they come across.
Not everyone is quite that bad, there are 0.5x programmers who know better than that but still manage to write 6 classes to solve a problem that could be done in a single 2-screen long function.
Tools and processes can help and code reviews are pretty invaluable. Any good process will have weeded out 0.1x programmers already and they will settle in those places without them.
Isn't the former promoted as better programming? IoC, decoupling, Law of Demeter, testability etc
Best practice doesn't mean "make as many classes as possible" although I would probably break up two-pages into a few different functions (large functions, even when they are good code, invite programmers who come later to add to them in a messy way).
And yes changing things in six places means you did something wrong, but that's easy to do when you start by splitting things into six places. The worst, of course, is when developers don't change it when it needs to be changed and instead just keep adding. Once you have something so designed it makes removing and changing code more painful than adding code.
It took 4 times as long to produce the solution that was 4 times bigger and more complex than it needed to be. Maintaining that huge body of code forever is more than 4x the effort over time than a single small function. And that's how you get a 0.25x (or less) programmer.
The sweet spot has a nice tradeoff between extra-time spent, and ease of migrating to a full-blown complicated and extensible solution. For me, I generally write my code in that middle ground. Stubbing out parts of my solution and then coming back to fill it in. In that sense, having separate functions with clearly-defined input/outputs or portions of work, aides me in completing my solution.
You can imagine a million ways those assumptions break down, as well as a million ways they seem to but should actually be stuck to. Knowing the difference is the tough part.
# A person that does things no one else can.
A problem requires calculating taxes for an invoice. Someone who computes this programmatically is better than a person who hand calculates everything.
A problem requires calculating the area under the curve. Someone who uses calculus is better than someone who only knows algebra and geometry.
A problem requires charging a user's credit card once on checkout. Someone who understands idempotent operations is infinitely better. (I was charged 3 times for a single purchase yesterday, and now disputing with the merchant.)
# A person that grows the people around them.
A person growing teammates to 2x or 3x their previously level has a cumulative 10x impact.
This can be teaching how to approach problems, choose the right abstractions, make engineering tradeoffs, manage risk, write robust code that is easily testable, etc.
# A person that makes others more efficient.
If the average dev waits 1 hr for a build, and someone reduces that to 5 minutes then they have saved: x devs * y builds / day * 55 min
This has indirect effects such as maintaining flow state, minimizing context switching, etc.
# A person that brings down the teammates.
A dev that builds fast enough (5x), but grows tech debt such that the rest of the team operates at 0.5x. By definition they are a 10x relative to their teammates. :P
I think that the anti-judgment folks are trying to achieve something good, but they're throwing out the baby with the bathwater. We need to make a distinction between judging behaviors and judging people. The former isn't just good, it's fundamental--the only way to improve your behaviors is to judge them. But judging people is generally pointless, at least without some sort of temporal limitation--almost everyone starts at a new job as -0.5x net contribution until they're onboarded and improves from there.
Thank you. Did anyone read the damn article? It's all over the place -- borderline nonsensical. I suppose it's intended to be a promotion of their company. Color me unconvinced.
One is by doing more, by throwing around more code and building more features. This is the kind that the article talks about. It's quite hard to maintain this kind of multiplier, no matter how much technical debt you're willing to create. I can think of one example of someone like this, and his multiplier was definitely not 10x. At the time, he was at best labelled "up-and-coming." He'd go home over the weekend and write thousands of lines of code, and then the team would come in and find everything broken.
Another is by doing less, and simply being at a higher level than others.
In my experience, no-one gets to 10x by just banging harder and letting other people clean up the mess. Even if you do, those aren't the people whose impact is felt for years after they leave, at least not in any positive sense. You get to 10x by being the one person who can spot the mess the rest of the team is about to create before they've written the first line. Your impact isn't felt for years by writing code: it's felt by setting the architecture, by making design decisions that constraint people into writing good code for years to come.
Yeah, that's a good one. Cleaning up your messes is a way to improve your architecture skill quickly. I can give you other ideas that will quickly push you to 10x skill level:
* Focus. Put away your phone, don't surf the internet at work. That alone will raise you above the crowd and let you go home early.
* Fix bugs early. Don't send them out to QA, don't send them to customers. Once your bug count starts increasing, it's a death cycle that slows you down like molasses.
* As soon as bugs (or problems) come in, try to think of a way to avoid that problem in the future. Over time, you'll develop habits that will serve you well.
Clever and elegant architecture will always beat clever programming.
It's almost always a large part of how "10x programmers" achieve so much.
10x effectiveness comes out in different way on different projects, be it new code vs existing code, or knowing enough about the solution space vs being in an unknown world.
Where good people win is that they adapt quickly when there are signs that the design doesn't work. A lot of people just "stick to the plan" although everybody knows that it won't work.
It's not about that, it's about keeping what you do nimble enough to always be ready for change when it comes. That means not having duplication in the system, having things well factored and encapsulated so there's a distinction between the abstract and the implementation so at any time any component can be made a change point and become pluggable. What makes a good architecture good is that it can be changed without scrapping the whole thing or breaking the whole thing.
> Where good people win is that they adapt quickly when there are signs that the design doesn't work.
It's not that they do adapt quickly, it's that they "can".
> A lot of people just "stick to the plan" although everybody knows that it won't work.
Because they're stuck with a bad design that can't be changed due to issues like bad factoring, lots of code duplication and copy pasting, etc.
From my experience they just don't try. There are (almost) always ways to improve.
Instead, you should look at how those requirements will be produced. If your architecture "thinks" the same way as your users, it will be able to be modified easily to include more of their thinking. So instead of trying to predict future requirements, you should attempt to capture and accurately model the way your users think about the problem. Sometimes that creates designs that mathematically/algorithmically seem pretty ugly. But in the long run I'll often discover that the ugliness exists for a reason--people mostly only add complexity to their mental models because that complexity allows them to solve a problem. So even when the domain expert's thinking seems overcomplicated, it's usually actually the least complicated model that accurately represents the problem.
Quite often in super early projects, the domain is not understood, so the architecture reflects the learning (or misguided assumptions).
Rather, listen to your users problems, listen to what they think a solution is, then let your design team determine if there is a better and more simple solution. Sometimes there may not be, but often there is.
When you get requirements from your users, they're going to mix in how they think about the problem with how they think that problem should be represented in the program. The problem with that is that they don't know what computers can do, so they can't possibly be expected to know how the problem should be represented in the program. And in fact, the UI, which is the only thing they ever see, will probably be more task-oriented than representation-oriented, so they probably will never see how your program actually models the problem and therefore won't be able to suggest good changes to it.
Ultimately, though, there's an underlying mental model that the user is using for the task. And for most fields, there's really only one correct mental model, so I actually disagree that expert users have different mental models, at least not with significant differences.
I have a few enterprise projects now over 10 years old that began as simple projects. It took having enough understanding of the domain and problem set and then anticipating what was expected to grow and change, and what did not.
No design is complete in the start. It needs to find a balance between being a foundation for exploring and developing through the problem domain, but remaining flexible. I think a lot about managing and mitigating risks through clever and simply designed architecture that can do a lot. The less there is to the design the more it can remain flexible to deal with new facts.
The fine balance of over architecting/abstracting vs under abstracting/architecting is for me a matter of finding the balance between the size, impact and possible number of unknowns about what I'm trying to design when I begin vs the future. Where possible, understanding the domain before daring to design or interpret is often the most important factor.
For the few large enterprise systems I've designed in unrelated fields in the past 10 years, I haven't ended up throwing away or majorly refactoring the schema or design. What did change is the stack and tools that became available and making sure I kept a laser focus on an n-tier architecture so different layers of the presentation, business logic and app logic could be swapped in and out over it's lifetime. I guess I can say comfortably that risk of designs falling apart was minimized, and luck has increased because I didn't begin without an understanding of the core principles, entities, and interactions ultimately the details and workflow the system has to manage.
I can't stress the importance of keeping things as simple as possible, because complexities are guaranteed to arise in the future.
To me, features, and schema changes over time can become like perpetually flying bullets.
I absolutely have refactored or adjusted as I go? Sure. Does all of it get thrown away? Rarely. Have I over-architected a solution to cover my butt and the new facts never came, totally. Has a new tech, stack or library come out that made me need to replace what I had built or modified to do what I need, always.
I do lots of paper models to try and see the core patterns, and what could be interpreted in a number of different ways should something grow in that direction. This type of strategy is far more difficult when working in a problem space where there is a lot of research and development.
How about you? Would love to hear how you approach things that have different balances of known/unknown facts.
I think that generally I'm maybe a 5x programmer when it comes to architecture. Architecture is what I'm good at.
But when I come onto a team for the first time, they don't just give me the keys to the kingdom. I don't get to make large-scale architectural decisions immediately. Instead, they have me work on smaller sections of the application. And when I'm working on smaller sections, the attributes that make me good at architecture work against me. I generally work slowly, taking a step back to understand the problem from the user's perspective, and modeling that understanding in code rather than writing code that short-sightedly solves only the problem at hand. That works well for architecture, but in smaller sections it just appears slow, like I'm not producing. It does have positive effects in the long term even for small sections of code, but those benefits aren't seen until long enough later that I don't really get credit for them. The result is that I don't make a good impression at first and it takes me a long time at a new job before I'm given authority to make architectural decisions.
It would be easy for me to blame other people for not seeing my "genius" here but the truth is that this is only a problem I can work on--I need the flexibility to be able to demonstrate productivity early on and make a good impression, otherwise my poor self-presentation gets in the way of me contributing to the team in the most effective way possible.
So I guess what I'm saying here is, you need both. It's not enough to just have elegant architecture, you also have to have quick programming skills.
Quite often, simpler and less code makes it easier for others to participate.
Joining an existing project requires a demonstrated ability to build the trust to refactor and re-architect anything over time. Otherwise patchwork works.
And clever elegant architecture and clever programming will beat either alone. It's not an either or situation, you want them all.
Also, dealing with a skilled programmer is not just a matter of top-down policy: a 10x programmer may have a different opinion about tools and processes and will not be happy on simply conforming - as opposed to the programmer who doesn't know better.
>but nobody wants to be a 10x manager.
How would one go about becoming a 10x manager? Like, what would that person accomplish?It also matches with the fact that skill in general is an exponential distribution, not a bell curve.
If one were to assume some sort of power law or Gaussian tail distribution, it is logical to assume that a few 10x programmers exist. However, they are going to be sufficiently rare that you are not likely to be able to find them or recruit them.
A more interesting question is if there are 3-4x programmers, and if so, is it feasible to find and recruit them? I have worked with people (rarely) that I would consider 4x programmers.
I've seen many developers implement some functionality in a record amount of time, but the resulting code was later discovered to be a) bug-ridden, b) difficult to maintain, c) unscalable or d) all of the above.
I think this describes most code that's ever been written.
An excellent talk that can put this in perspective for non technical people.
No matter what it's called, you're talking about people that don't use best practices, for better or worse. Best practices will get you where you're going in a predictable way, but there is a ton of inefficiency, as they don't take your specific problem into account.
When I was new to moving away from best practices, I wrote a lot of difficult to understand code that was very performant. I spent my evenings reading documentation, reading the code of the people I admired (mostly decompiled framework code), and was very excited to put what I learned into practice and learn by experience. It made me proud to write code that out-performed my coworker's code by orders of magnitude. I worked for one of the top 100 most trafficked sites in the US, and on a platform that was not designed for that level of traffic (none are).
A month later, the lead architect and I had a discussion that did not go my way. I was asked to write a very public and humbling apology to the team, and that apology still exists hosted on the internal network at that company (in a place that is easy to find). I had a lot of talent, but not a lot of wisdom. From that day on, I was to work on the most difficult projects exclusively, and under direct supervision of that architect. We worked on maintaining the performance edge, but doing so in a way that is easy for other developers to understand and extend. He taught me to interface directly with the other departments and senior management to make changes to the development process before work got to development; to enable us to do our best. It was a difficult road, and I was yelled at a lot; but eventually the architect cleared me to work without supervision. What followed is the most productive two years the company I worked for had ever had. I was promoted multiple times, was awarded patents, and was able to do a lot of lasting good. I had a hand in every project, feature, and department. I designed and internally evangelized a few myself, and had become the go-to guy to get difficult things done. You know this company, if I told you their name you'd recognize them and their product immediately (you've likely used my work).
I left about 4 years ago to build my own company. I do consulting during the day, and take jobs that require a hero to survive (to stay sharp). Since I left, there have been no significant new features or achievements out of the company I left.
Moral of the story: If you're talented, your idea of a good night is reading documentation and decompiling/memorizing products you like, and want to be a 10x developer; get someone you admire to yell at you, rip your work apart every day, and tell you that you're garbage for a year. It will do you (and your company) a lot of good.
I was never literally told that I was garbage, but I was made to feel that way. It was necessary, I was getting mixed messages; some of the managers loved me, product loved me, the designers loved me, the other developers didn’t know what to think of my work. Technically everything was written concisely, extensible (by someone who understood it), performed very well, had few bugs (if any), and was pixel perfect when compared to the comps. I was giving people what they wanted, quickly and relatively bug free. I lacked discipline, and my architect was ex-military. He effectively stripped me of my ego, and I am very glad he did. I imagine the apology was a plan to make sure management and other developers didn’t encourage me (and it worked).
The year of discipline was the best thing that could have happened to me. It completely changed the way I thought about software development. It wasn’t just me anymore, it was everyone. It made me a much more effective employee, and taught me to spread complexity out. I am still fast, the code is still performant, but I stopped building black holes and do more of my code and process optimization in architecture, design, and process and less in fringe techniques. I still use fringe techniques when there is no “normal” way to accomplish what needs doing (and we can’t change what needs doing), but they come with full explanations now, are built to be discoverable, and I spend significant time training a second person in how to do the same in case I am hit by a bus.
Before, if management gave me the requirement that they should be able to flush a Doberman down the toilet, I would build them the world’s most powerful (and frightening) toilet. After, I knew to argue that we should be burying dead Dobermans outside, and I knew how to get management to agree.
TLDR: I am considered a 10x developer by my co-workers, but early on I was one of the scary people this post is warning about.