I've been a full-time software developer for just over a decade. In my initial years, I focused solely on tackling pressing software challenges. Collaborating with talented colleagues and taking on responsibilities was fulfilling, fostering my professional growth. However, as my career progressed, I began to contemplate more effective approaches. I was certain that there existed avenues to create a more significant impact for myself, my peers, and the organization.
I'll discuss the evolution of my perception of a "great software engineer" since my social media query two years prior. It will further highlight how both individuals and organizations can harness this insight, and its application within XL8 today.
How It All Started
In the latter part of 2021, I posed a question on social media: "What distinguishes the top-tier software engineers you've encountered?"
Numerous individuals shared their insights, and an esteemed mentor of mine recommended exploring scholarly papers. It was enlightening, but embarrassingly, I could count on one hand the number of papers I've read since graduate school.
Initially overwhelmed, I simply searched for "great software engineer" and stumbled upon Paul Luo Li's paper titled "What makes a great software engineer?". Given its length of 300 pages as a PhD thesis, I hesitated about diving in. However, its recent publication in 2015 and over 100 citations piqued my interest, especially after reading the compelling abstract. Embarking on this reading journey, I later realized the serendipity of discovering such an insightful paper on my first attempt.
Finding The Traits Of Great Developers
The authors meticulously examined a myriad of studies focusing on the education, competencies, and behaviors essential for developers. Subsequently, they carried out comprehensive interviews with 59 developers at Microsoft (MS) who were at Level 2 or higher, meaning they had some level of competency, and identified a concise list of 54 personal traits (personality, knowledge, behavior, etc.) that developers should have.
They then surveyed more than 2,000 developers at MS and asked them to rate the importance of these items as follows:
(After describing the trait in detail) If an experienced developer---whose primary responsibility is developing software---did not have this attribute, could you still consider them a great developer?
Respondents were prompted to select from the following options for reference:
- Cannot be a great developer if they do not have this
- Very difficult to be a great developer without this, but not impossible
- Can be a great developer without this, but having it helps
- Does not matter if they do not have this, it is irrelevant
- A great developer should not have this; it is not good
- I do not know
(Note that the authors intentionally used the term “developer” instead of “software engineer” in the survey to differentiate people on engineering teams that did not write code. I’ll also use the term “developer” for consistency.)
Though the study's exclusive focus on MS posed a limitation of the study, the researchers thought that MS had enough diversity; they had multidisciplinary software teams in different countries. At the same time, they believed that familiarity with the terminology and the shared culture could add greater consistency to the analysis.
The survey yielded the following results: (Source: “What Makes a Great Software Engineer”, Table 4.4. Attributes of great software engineers, ranked and with ratings distributions)
The first two traits were “Pays attention to coding details” and “Mentally capable of handling complexity”. The third was “Continuously improving”. The fourth and fifth were “Honest” and “Open-minded”, and the sixth was “Executes” that the developer knows when to stop thinking and start doing.
Perusing the list, the authors expressed surprise to see that the two last-ranked traits, "Hardworking" and "Trades favors," had a fairly high percentage of "A great developer should not have this" (over 5%). Authors didn't expect to see these as detrimental traits, given that they were selected from in-depth interviews with experienced developers.
Hence, they initiated subsequent interviews to discern the underlying reasons, and it turned out that it wasn't so much that these traits were inherently bad for developers. Rather, it was bad for developers to be in a situation where they had to do this.
- The need to work overtime could be a sign of poor design or unsustainable practices.
- The need to trade favors could be a sign of a culture where decisions are made based on subjective opinion rather than rationale.
Pursuing excellence as a developer often requires advocating for organizational and cultural changes to sidestep situations where these traits become necessities. At XL8, we recognize that being hardworking and trading favors can sometimes be solutions to immediate challenges. However, we strive to create an environment where relying on these traits is the exception, not the norm.
Five Essential Competencies Of Great Developers
Having scrutinized the survey findings and subsequently interviewing 40 of the developers' chief collaborators (artists, content planners, data scientists, designers, and electrical engineers), the authors identified five essential competencies of great developers:
- Be a competent coder
- Maximize current value of your work
- Practice informed decision-making
- Enable others to make decisions efficiently
- Continuously learn
However, I believed that a slight reordering and a nuanced interpretation could potentially enhance their effectiveness in terms of evaluating these competencies as a hiring manager, or leveraging it to change our lives. Here is what I did.
- Write great code
- Practice informed decision-making
- Enable others to make decisions effectively
- Maximize current value of your work
- Learn effectively and continuously
I'll proceed to elucidate the author's stance on each competency, complemented by my insights, especially keeping in mind how I would use each competency from a junior developer's perspective. Here are key takeaways:
- Maximize the current value of your work by building on the foundation of great code, practicing informed decision-making, and helping your colleagues make decisions effectively.
- Persistently refine your learning strategies. Learn how to write better code, how to better practice informed decision-making, how to better enable others to make better decisions, and how to better increase the current value of your work.
- If you're a junior developer, set a top priority on writing great code and learning effectively and continuously.
- Each of these competencies should root in a genuine understanding of and interest in tangible, real-world challenges.
1. Write Great Code
The Top Priority of Junior Developers
According to the author, delivering exceptional code entails an acute focus on nuances that transcend mere functionality. Examples of these details include error handling, memory consumption, performance, security, and style.
A developer's proficiency is inherently doubted if the quality of the code they produce is poor, even if all their other skills are excellent. Multiple studies, including the one referenced here, have elevated "writing great code" as the core skill for junior developers.
Yet, the bar for this greatness isn't overly stringent: the authors assert that superior code merely serves as a baseline, and that it doesn't make you a great developer. The implication is that beyond a certain level, efforts to build other competencies are more effective. Then what is that “certain level”?
How Great Should The Code Be?
While quantifying excellence is challenging, certain traits do offer clarity. I’ve observed thoughtful code that leaves the code reviewer with fewer questions. For example:
- Adherence to established best practices, conventions, and guidelines that govern aspects such as security, style, and performance.
- Logical and coherent structuring of variables, functions, classes, files, etc., with robust commenting or documentation wherever ambiguity might arise.
- Comprehensive delineation of the decision-making process, especially when multiple paths to implementation are viable.
- Pull Requests for bug fixes should elucidate the bug, affected users, and verification procedures post-fix.
- Pull Requests introducing new features should detail the feature's relevance, the targeted user base, and future performance metrics.
- Assurance that the new changes are seamlessly integrated, avoiding detrimental side effects on the existing codebase.
These standards, both explicit and implicit, are what XL8 developers strive to uphold, and we encourage our junior developers to do the same. Such deliberateness, of course, might be time-consuming particularly in the immediate time frame. Ultimately, the assessment hinges on the equation of problem complexity plus the balance between invested thoughtfulness and the time spent for resolution, determining the overall code quality.
2. Practice Informed Decision-Making
Fostering Process Over Outcome
Next up is decision-making. To build your decision-making skills, the emphasis should be on refining the process itself rather than fixating on the outcomes, as outcomes can manifest irrespective of your intentions.
‣Example decision-making process:
- Accurately defining the problem.
- Proposing a hypothesis amenable to validation or refutation.
- Identifying and sourcing missing information.
- Implementing the decision.
- Monitoring outcomes.
- Seeking feedback and iterating accordingly.
Merging Data-Driven Insights with Caution
Practicing 'informed' decision-making necessitates a data-driven approach, avoiding biased interpretations or hasty conclusions. New insights, even if you don’t like it, should serve as catalysts for reevaluating prior decisions.
Debugging is a good example. Often, developers prematurely attribute issues to external factors, overlooking their own possible oversights. I've seen this happen a lot with experienced seniors.
In my experience, if you think it's not your problem (e.g., a problem with a specific browser), you're usually wrong. And if it really was a browser, you should not always blame the browser for similar scenarios, because sometimes you could end up ignoring a catastrophic problem that's really your fault.
Embracing Diverse Perspectives with Patience
Combatting biases and impatience requires introspection and exposure to varied perspectives. The truth is, you really don't need to do as much right now as you think you do. Once you take a breath and see how different people - friends, coworkers, customers, competitors, bosses - interpret things, it's harder to maintain your own biases.
Obviously, it's hard to act rationally when people are rushed and stressed because adrenaline and cortisol are being released. The same goes for organizations, which is why smart organizations deliberately incorporate slack into their schedules and resources, and smart individuals learn to manage their stress with meditation and other practices.
Architecting a Dynamic Information Ecosystem
Consistent informed decision-making hinges on easy access to credible data. Therefore, constructing a system that funnels diverse, high-quality information is invaluable:
- “Diverse” suggests openness to all forms of information, not just those that align with personal beliefs.
- “High-quality” implies discernment in sourcing, such as leveraging curated newsletters, but being wary of underlying biases.
- “Dynamic” underscores the importance of not just ingesting but also disseminating information, since sharing and discussing thoughts amplifies learning a lot.
- A "system" ensures a seamless flow of information, minimizing conscious effort and maintaining motivation. For instance, having a study group with someone you love and respect will keep you accountable and committed.
3. Enable Others To Make Decisions Effectively
Elevating Teams Through Constructive Inquiry
Central to the competencies listed, this third one uniquely underscores the importance of collaboration. Though singular in its mention, its impact on fostering teamwork cannot be understated.
Great developers share knowledge and insights, enriching their teams and bolstering the organization's decision-making capability. But where does that leave junior developers? Their contribution lies not in immediate performance but in their evolution. By candidly expressing their uncertainties and seeking answers, juniors enrich the organization. Hence, they shouldn't shy away from questions out of fear of being perceived as less competent.
Vulnerability breeds trust, Amplified by Context
Conventional wisdom suggests trust precedes vulnerability. However, recent studies contest this idea, positing that displaying vulnerability — combined with mutual risk-taking — accelerates trust-building. This trust is inherently tied to clarity and mutual understanding.
Consider the acclaimed design book, Don't Make Me Think. Its essence is user clarity, where there's no room for doubt or ambiguity regarding functionality. There’s no second guess like "What's this for?" or "What's that for?”.
Similarly, in teamwork, there's what I term the A-B-C problem. Juniors might encounter issue 'A', attempt solution 'B', and if unsuccessful, enquire about 'C'. Such as, "How do I anchor an HTML element to the top?" Often, responses to these direct queries remain ambiguous and less helpful. It underscores the importance of providing the entire context. When 'A' is comprehensively understood, 'B' becomes clear, making 'C' unnecessary. Perhaps, the designer never intended to anchor the HTML element in the first place.
In line with this, XL8’s communication guideline document emphasizes the importance of "Sharing Context" on the very first page. We explicitly encourage team members to request context when it's missing, reinforcing the idea that seeking clarity is always appropriate, not rude.
Cultivate a Transparent Culture with Thoughtful Defaults
Regardless of one's willingness to ask, the organizational culture plays a primary role in facilitating or preventing this curiosity. Thus, creating a culture that values openness and vulnerability is paramount.
Defaults profoundly influence behaviors within organizations. For instance, a 2003 research highlighted stark differences in organ donation rates across countries, attributed solely to opt-in versus opt-out checkboxes. Such simple policy shifts can have profound implications.
Similarly, when choosing between “Do Not Disturb” hours and “Open Hours”, which promotes more interaction? Most likely, it's the former since its default promotes dialogue over silence. Instead of mere verbal encouragement, it's pivotal to establish an ambiance that organically promotes open dialogues.
4. Maximize Current Value Of Your Work
Synergy of Systemic Vision and Prompt Action
All of the great code crafted from informed decisions and collaborative efforts culminates in the creation of "value." To amplify this inherent value, you need to be able to strike the right balance between thoughtfulness and speed (a notion mentioned in "Write great code"). This dual approach requires:
- Building for the long term, anticipating things that might become problems later, or how requirements might change
- Don't stop to analyze, but rather jump in, execute, and get feedback, even if the uncertainty scares you
Of the two, the latter is more favorable for startups, but you're at a disadvantage if you go to either extreme.
Swift Execution Enhanced by High-Impact Habits
As rapid action becomes the focal point, integrating habitual behaviors that offer maximum return for minimal effort becomes paramount.
For example, at the micro level:
- Avoid hard-coding single values; instead, abstract them into variables.
- Opt for "mode" rather than a "boolean" even when dealing with binary options, especially if the choice goes beyond a singular component.
And from a broader perspective:
- Think about what hypothesis you’re trying to test,
- Deliberate on the essential data required to validate or refute these hypotheses.
In essence, the current value of your work is maximized when you can flexibly move back and forth between systemic thinking and immediate action, depending on your current situation.
5. Learn Effectively And Continuously
Curate Information for Relevant Knowledge and Minimize Distractions
Learning to learn effectively is the beginning of all growth. It pays off with compound interest, so the earlier you do it, the better.
As knowledge evolves and gets refined, continual updating with new information becomes essential. But more information isn't always better - some information is just a distraction, like unprocessed “Big Data” being a pile of garbage. You should elevate the signal-to-noise ratio by sieving out irrelevant or imprecise content. A robust strategy involves segregating data into: facts, interpretation, and predictions.
Some examples of good signals are insights that make connections to existing knowledge outside of my domain of expertise, or evidence that I may be wrong under certain conditions.
To illustrate, Charles Darwin, despite his conviction about the theory of evolution in 1836, only presented “On the Origin of Species” 23 years later. His autobiography recounts a diligent practice of noting counter-evidence to his beliefs, understanding its ephemeral nature in memory compared to corroborative information. This meticulous accumulation equipped him to address most challenges post-publication.
Get A Little More Effective Every Day
I believe the key to effective learning boils down to this question: How can I grow a little more effective every day?
- Find what I need in the real world right now,
- learn only as much of the relevant theory as I need,
- and as soon as I learn it, execute and gain self-feedback.
Then, the inevitable question would be, how does one discern these real-world requisites?
Maintaining a journal provides invaluable insights. Chronicling weekly time-intensive activities can spotlight areas ripe for improvement. For instance, frequent meetings in a professional context demand honing meeting efficiency to boost overall productivity.
If it's something you do often, you're better positioned to self-observe and get feedback on how well you're doing. You'll have more opportunities to learn, and if you improve, you'll see a bigger increase in your quality of life.
Harnessing Essential Developer Competencies
How might we capitalize on the insights of the "five essential competencies of great developers" within our everyday professional environment and organizational structure?
For Juniors: Map, Evaluate, and Elevate
Juniors can take a look at each of these competencies, particularly the knowledge and behaviors described in "Write Great Code" and "Learn Effectively And Continuously" against their own skill set. Identifying and bridging competency gaps becomes the journey. As an illustration, if informed decision-making appears challenging, cultivating a habit of deliberately recording daily decisions alongside their justifications becomes useful.
For Seniors: A Blueprint for Talent Acquisition and Growth
And if you're a senior, you can use these for hiring and performance assessments. Reflect on the indicators that unveil a candidate's mastery over these competencies. If pinpointing such indicators becomes arduous, it might signal the need to revamp hiring methodologies or learn advanced interviewing techniques. Periodic assessments, duly documented, not only serve as a retrospective lens but also as a guidepost when mentoring juniors.
For XL8: Embedding Competencies in Talent Dynamics
These competencies are also a great way to evaluate any position, as long as you replace "Write great code" with domain-specific expertise. At XL8, we infuse these competencies within our hiring and integration processes, regardless of the role – be it project managers, designers, developers, or interns. This framework not only facilitates feedback but has consistently showcased its efficacy.
Points of Consideration
However, there are a few things to keep in mind when using this research. First of all, this study, like any other, is not an absolute truth. It has clear limitations and is subject to interpretation by the authors and my own.
For instance, the study's stance on "decision-making" gravitates towards Herbert Simon's rational framework, which they deem more pertinent to software engineering than Gary Klein's intuition-based naturalistic approach. While I don't wholly resonate with this viewpoint, I discern that the study's reliance on surveys and interviews, rather than direct observation, could be a determining factor. Nevertheless, the criterion remains invaluable.
Additionally, while the paper’s title might suggest mastering these five competencies ensures greatness in software engineering (i.e., sufficient conditions). But the actual study was "You can't be a great software engineer without these." (i.e., necessary conditions). They offer guidance and trajectory, not an ultimate endpoint.
Concluding Thoughts
Looking back, I realize that I didn’t always adhere to the advice I've shared for juniors in this post. It's through my curiosity about concrete, real-world problems and the myriad of trial and error experiences in addressing them that I've come to appreciate this knowledge.
Even if you aren’t deeply entrenched in cutting-edge fields like artificial intelligence, research papers can significantly address challenges faced by both individuals and organizations. The "5 essential competencies of a great developer" presented in the paper have served as invaluable guides for me, aiding in hiring new team members and nurturing juniors at XL8. I hope this article proves beneficial as you seek to hire, evaluate, and refine developers in your organization or as you chart your own journey towards expertise.
Written by Hwidong Bae, Frontend Team Lead at XL8