on what is 'software engineering'
today is my birthday. and on my birthday, there’s a take that circulates every few months i really want to address. it goes like this:
“leetcode interviews are broken. nobody inverts binary trees on the job. whiteboard coding selects for people who grind competitive programming, not people who build real systems.”
i want to counter argue leetcode is our saving grace.
let me preface by saying i love my job. i love the process of software engineering. i love providing a service, formulating algorithms, meeting problems in a conceptual reality with techniques that aren’t available when you’re sanding wood. compression. recursion. referential transparency. these are not object-oriented metaphors. they are materials. i want to explain why leetcode is the practice of working those materials well, because i think it is the DNA that separates engineers who write enterprise code from engineers who write the world’s most popular open source software.
the compound noun “software engineering” breaks down into two components. software, and, engineering. in enterprise, and especially in interviews, leetcode is treated as the software component. unnecessary algorithmic complexity that has nothing to do with real engineering.
the position of this post is that this reading is exactly backwards. leetcode is not providing unnecessary complexity. it is providing consistency, readability, and simplicity. that, that is the engineering component. and the problem is not leetcode itself. it is how leetcode is understood as a communication tool.
engineering, software
“software engineering.” linguistically “software” is the subject. the thing we make. the hard skill. the code. leaving “engineering” as the predicate, the modifier.
i think this is a huge misnomer, which affects our thinking of the role. invert it. what the compound actually denotes is engineering, applied to software. the discipline is not the noun. it is the verb. we are not producing software. we are engineering it. i will show this is not a semantic game. it determines what we think the job is.
if the job is software, competence is output. lines, features, velocity. if the job is engineering, competence is the quality of the reasoning that produced the output.
in every other discipline, engineering is the practice of understanding forces and materials well enough to derive the solution. civil engineers do not memorise bridges. they understand loads, stresses, constraints, and the bridge is derived.
software engineering is the same. task scheduling is getting the most urgent thing next, is a heap. a load balancer, is round-robin, is modular arithmetic. database sharding, is consistent hashing, is a ring. an LRU cache, is lookup and ordered eviction, is a hash map and a list. a reddit thread, is comments of unknown depth, is recursion, is a stack. the list goes on.
these are the forces and materials of what we build. the engineer who has internalised them sees through the product to the structure underneath. the engineer who hasn’t configures or reinvents the wheel and hopes it holds.
there is also a social dimension to this that most taxonomies leave out. engineering is not only the act of building. it is the act of communicating what was built, why, and how it should be changed. at its core this is a process of development driven by empathy. we make decisions and formulate best practices on many levels which surround the expected interactions of the people we’re working with.
now, within the “software engineering” industry, we judge others by whether a solution was made modular, operable, maintainable. whether it was structured so as to parallelise across teams of engineers, whether it communicates its intent to the next person who reads it.
what is especially important is whether the changes we made were additive or destructive, not both, which, has a three fold benefit of
- providing a guarantee current critical paths will not fail
- making the suggestions easier to review
- providing engineers an opportunity to discuss swapping in place, whether it’s in the current code review request or in a follow up.
these two-way handshakes are markers of whether the solution was designed at all. they arrive by soft skills guiding human to machine communication, which take precedence over the technical ones.
that is, we are “engineering software”. not “software engineering”.
this is the short story of every organisation building with AI where every process workflow meets its requirement, but people don’t feel listened to, and are left confused. the conversations that need to happen don’t.
the software, correct. the engineering — absent.
AI will continue the way of the latter. it produces code, and cannot yet sit with a person and understand what they actually need. it can’t make empathetic decisions, and cannot yet make people feel heard.
maybe one day MCP makes the world entirely self-service so interaction becomes negligible. this is the promised land every company in traditional engineering always wanted to get to, but found no silver bullets to take them there.
what leetcode teaches
the objection is that you don’t use linked lists in the wild. this is true. it also mistakes the content for the lesson.
leetcode teaches the optimisation stage. you take a complex problem and represent it in a simpler way that still solves the problem efficiently. you learn to do more with less. the naive solution works. the optimised solution works and communicates why it works. that transition from correct to elegant is the entire discipline of engineering compressed into forty minutes.
if you’ve read Cracking the Coding Interview, the part we actually evaluate in interviews is how the solution is written. this is entirely the “engineering” part where we ask questions like: can the candidate abstract away the complexity so that the code is not only efficient but legible; does the solution provide a clean interface at the call-site; if someone dives into the details, are the underlying structures exacting and minimal rather than heavy object-oriented hierarchies.
the goal is not cleverness. the goal is a zero-abstraction approach. without unnecessary layers or a framework where a function would do. the structure solves the problem and the code shows you how. if you just write the optimal solution you might get onto the next stage, but you will always lose to the candidate who breaks the problem down into smaller sub-problems, more manageable pieces.
when these powers combine, the zero-abstraction approach becomes a zero-cost abstraction approach. a term i like to coin, because if your abstraction hides implementation details and makes them harder to grok, it’s a cost. it can’t just be a pretty wrapper.
even functions, those tiny little atoms, are themselves abstractions and something we look out for when reviewing code. if they are clear and the interfaces are clean and the underlying structures are minimal, the abstraction is not a cost. it is a digestible, maintainable benefit. the caller does not need to understand the implementation. if they choose to look, the implementation should not be a labyrinth, but a precise machine that earns its place.
it’s no surprise if you’ve read how to write a dag that i’m a fan of this. a dict and a recursive walk replaced an orchestration framework. that is what the optimisation stage looks like when it escapes the whiteboard.
lingua franca
there is a deeper reason leetcode works as an assessment, and it has nothing to do with whether you will ever implement a trie in production.
leetcode problems converge on common solutions. prefix sums. sliding windows. topological sorts. monotonic stacks. two pointers. these are not parlour tricks. they are a shared vocabulary. when an engineer says “this is a sliding window problem,” every other engineer who has done the work knows exactly what that means. the structure of the solution, its complexity, its tradeoffs, its shape. one phrase, complete transmission.
this is a lingua franca (working language). and like any lingua franca, it is what enables people who have never met to collaborate at speed. the open source world runs on this. read the discussions on any serious OSS project and you will find engineers talking meaningfully about prefix sums, about amortised bounds, about the specific optimisation techniques that are common across all leetcode problems. that shared vocabulary is how a contributor and a maintainer converge on the same solution without a meeting. the vocabulary is the engineering.
but in enterprise, this vocabulary is treated as academic trivia. in open source, it is the operating language. that gap is not a difference of opinion. it is a difference of fluency. and it is, i think, a significant part of why the best open source software is structurally better than most enterprise software. the people who build it speak the same language. the language was learned on a whiteboard. it’s something to be admired, not indicted.
so, leetcode is apt. while it should not be a ritual or a memory test, we can say it is a measure of whether an engineer has internalised the common structures well enough to recognise them in the wild, communicate about them precisely, and build solutions from them rather than around them. to be familiar with it is also a measure of how much we care, and that’s what we really want to see in the process.
that is engineering. the subject was always the verb.
pick the boring thing. ship the work.