Nature, Individuality, and Developer Empowerment
January 18, 2022
The Thinker in The Gates of Hell
File copied from Wikipedia under the Creative Commons Attribution 2.0 Generic license. [source]
Programs are written in code. Code is described by programming languages. If you understand a programming language, given enough time, you can read a programâs code and understand how it works. There is no magic in programming.
Yet, when youâre new to programming, it feels like thereâs magic everywhere. Programs do weird things and itâs hard to understand why. Even after youâve mastered one area of an application, the rest of it may still feel like a looming shadow of uncertainty.
Iâd like to use this blog post to make the following three arguments:
- We shouldnât let fear of the unknown stop ourselves from understanding code
- Organizations are learnable systems we can understand and work with too
- Stifling fear and being inquisitive are important parts of gaining seniority
To help provide context on those points, Iâm going to bring in an example from an unusual source: a book on religious thought.
A Letter in the Scroll
Iâm midway through reading A Letter in the Scroll by the late great Rabbi Lord Jonathan Sacks. Itâs a magnificent read regardless of your personal spirituality -Iâm an atheist myself, raised Jewish- and Iâd highly recommend it in that context. The chapter titled âThe Idea of Manâ was particularly interesting to me as a developer in how it links ancient humansâ lack of power over nature with how they developed worldviews:
There have been culturesâancient Greece is the supreme exampleâthat saw the world in terms of vast impersonal forces⌠Seen in this perspective, the forces that govern the world are ⌠not addressed to us.
Contrast that with its description of Abrahamic religions:
The Hebrew Bible represents a radical alternative⌠We can do more than react to stimuli; we can contemplate alternatives and choose between them.
We can imagine and act on the basis of our imagination.
In other words, some ancient civilizations saw us as pawns at the whim of gods, while Abrahamic religions see us as players at the table, though still beholden to an influencing higher power. (Iâm slightly manipulating the chapterâs intent and ignoring many interpretations of the monotheistic God to make a more narrow point. For a real religious discussion, go read the book!)
Black Boxes
There is a parallel between those different worldviews and how professionals -software developers in particular- grow in their careers. Early stage developers often donât fully understand the APIs, functions, and other system they interact with. They use the concept of black boxes to skip understanding those systems deeply. No shade against black boxes â without them, the cognitive complexity of any task would be boundless. I often use the concept in my day-to-day programming.
One downside of thinking in terms of black boxes, though, is that it can get you in the habit of avoiding understanding systems. One of the most common mistake I see developers make is avoiding trying to understand a new area of code adjacent to what theyâre working on. Instead of understanding the system as a whole, they isolate their changes to just the areas they understand. They then are at risk of missing crucial context contained in those surrounding areas.
As an extreme example, I once came across a section of a project where a moderately complex set of code logic had convergently evolved in almost identical lines of code across several functions. That violation of DRY wouldnât be so bad on its own â except the functions were directly calling each other, making all but one of the sets redundant!
When asked why they hadnât moved or reused existing code, each developer whoâd contributed to the duplication indicated they hadnât looked deeper into the call stack. Each had treated other areas within the same section of the codebase as a black box.
Black boxes are a useful technique for simplifying designs in thought, but make sure you donât use it to the point of not understanding the systems at play. Remember youâre a human and can do more than react to stimuli. You can investigate and learn inner workings. There are no natural forces or magical impossibilities in programming.
Classifying Developer Levels
From reading âThe Idea of Manâ, I think I can finally articulate a succinct, easily explainable perspective on the differences between software developer job titles. In order:
- Junior developers: are getting their start understanding the âforces of natureâ around them
- Mid-range developers: are competent, perhaps confident, in manipulating those forces of nature
- Senior developers: have seen through the facade and can work with the systems behind those forces of nature
- Staff developers: are competent, perhaps confident, in manipulating those systems
To truly master your domain, you need to be comfortable treating areas as a black box or diving in questioningly as needed. I donât know if this is a particularly accurate or scalable judge of seniority. But Iâm going to try using it as a frame of reference for a while.
Systems of People
Organizations of people are systems, too. Rules governing their behavior and processes exist that are generally followed.
When you first join an organization, though, it can be hard to feel that itâs an understandable system. Assignments are given to you from the forces that be -a black box of decision-making- and are expected to improve the product in a pre-ordained way. Who are you, a cog in the machine, to question the powers around you?
The ability for developers to be inquisitive on assignments and general organizational decision-making around themselves is crucial for at least two reasons:
- Without understanding goals, youâre unlikely to execute tasks correctly
- Itâs exceedingly difficult to positively influence the organization around you if you never question, let alone attempt to manipulate, it
Understanding Goals
Tasks are not given in isolation: there is always underlying context and tasks generally support a larger team or business goal. Developers all too often aim to to satisfy the exact criteria given to them instead of thinking deeply on the best way to satisfy the backing context.
If a ticket is written requesting a cache to improve performance calling a slow endpoint, itâs tempting to take that request and dive in to implement a cache without further analysis. But maybe the endpointâs performance could be improved, eliminating the need for a cache? Maybe you should use an existing technique such as edge caching instead of (re-)implementing your own? Is that endpoint even called in a hot path, and if it is, can it be lazy-loaded to not be a blocker?
There is an old joke that developers would prefer hours of trial and error over a few minutes reading documentation. The same holds true for understanding requirements. A few minutes thinking deeply about the right solution can save hours implementing the wrong one.
Speaking Up
Systems of people are just that: systems of people. A system has well-defined inputs and outputs. A team makes decisions because itâs been given a set of goals to reach and resources to work with. Each person on that team is motivated by their own career incentives, goals to reach, and past experiences.
When a team process gives a result you donât agree with -a feature backlogged; an investigation cut short; whatever- that doesnât have to be the end of the story. Talk to the people involved in the process to learn why they came to that conclusion. Do they have information youâre missing, or vice versa? Ask around. Apply Five Whys. If you think you have information that wasnât considered, counterpoint with it. Iâve seen far too many silly decisions persist because a team member heard an incorrect decision and didnât question it.
In Summary
Treating systems you donât understand as âblack boxesâ is a useful tool, but shouldnât be overused to the point of avoiding understanding whatâs around you. Remember that there is no magic in programming: itâs all governed by logical systems. âSystemsâ means both the programming systems -APIs, frameworks, IDEs, languages, etc.- and organizational -data, OKRs, people, teams, etc.-.
I would much rather work with a developer whoâs pretty good at coding and pretty good at providing feedback on my pull requests, RFCs, and team planning than a developer who is amazing at coding and quiet on the rest.
What about you?
Many thanks to my excellent coworkers Rebecca Borison and Sanam Aghdaey for invaluable feedback and suggestions on this blog post! đ