Getting better at software engineering

When you first started programming, what you had to do was fairly obvious: here are these loops and conditionals and functions. Learn how to use them. Or learn functions, recursion, conditionals, and lists if you want to take a path less traveled by. But either way, it’s like standing at the bottom of a cliff face. There’s nowhere to go but up. A few step up there’s the courses taught in a computer science degree, which I think are typically data structures and algorithms, operating systems, networking, compilers, and programming languages. I’ve never had anything to do with a computer science department, so I can only go by course listings and hearsay.

But, just like when climbing, you later find yourself in a place where the path up isn’t obvious. Is learning another language actually making progress or just moving laterally? Sometimes it is, such as when learning your first functional programming language. Sometimes it isn’t, such as learning Ruby after knowing Python. It depends on where you are already.

And the routes up the cliff diverge. The skillset of someone working on optimizing compilers targeting embedded systems is quite different from the skillset of someone working on desktop applications. One person may dive deep into optimizing network stacks, and another may become adept at navigating organizational politics and aligning groups. These are all software engineers.

Given that diversity, is there some kind of map of the cliff face that we can give a young software engineer to know what “getting better” can look like for them? It might be tempting to set out a checklist of stuff to learn, one after another, or a set of areas and what you need to learn to level up in each area. I’m not convinced that there are useful levels, especially that make sense for the whole of our field. After dredging through the literature, looking for some kind of principled way to addres this, I gave up trying to build a giant table. All I’m after is a taxonomy that is simple enough to be useful and comprehensive enough to provide a guide to more than a narrow part of software engineering. My highly idiosyncratic list of categories is:

Writing programs
Fluently producing code to solve specific, well specified problems. This may also include the translation of code from one form to another and the design of forms for expressing code.
Quality assurance & operations
Demonstrating that programs work as intended and keeping them working in the presence of real world conditions.
Debugging & exploration
Developing understand of an existing program and connecting its text to behaviors when it runs, both “how does this work?” and “why doesn’t this work?”
Mechanical sympathy
How programs map onto hardware and how to adjust programs to use the hardware well.
Data persistence
Maintaining and updating state over time so as to avoid corruption and data loss, be able to access it efficiently, and complying with controls and compliance requirements around handling it such as GDPR or HIPAA.
Isolation, coordination, & communication
Separating a program into pieces to make each piece easier to reason about, place it in a different computational environment such as one with different privileges or on a different machine, and how to make those pieces so they act as a whole.
Human communication & behavior
How to write and speak and listen to effectively communicate with other people so that more than one person can apply their efforts. How to incentivize people and understand behavior, and understand how to interfere in systems at the highest leverage points.
Development process & architecture
Laying out programs and organizing how the people involved work with them to be able to produce software that is fit for purpose with a minimum of friction, effort, and misery.
Self management
Skills to effectively self direct as part of an organization, such as taking responsibility, being adaptable, being self aware of how you are affecting the organization around you, setting priorities and adjusting work habits, and self care.
Knowledge to make software fit into its context, such as how businesses work, how to reason about incentives, how stakeholders and existing systems constrain it, and the mental models embodied into the software such as finance or physics or shipping.
Domain specific knowledge
Specific artifacts that a given area of programming requires, such as HTML and CSS for web development or GPU pipelines for graphics programming.

I will fill in the links above as they get written. Subscribe to get emailed when each is posted: