Essays mature
This idea is complete, spare the occasional tending.

Advice for an Aspiring Programmer

As part of a career-researching activity, a friend’s teenager recently asked me a few questions about my career in software. I feel like part of my response was worth sharing, so I’ve cleaned it up and elaborated on a few things.


§

What advice would you give an aspiring software engineer?

Figure out how to stick out. There is a continuing effort to commodify software development towards particular tech stacks, methodologies, paradigms, languages, libraries, and toolsets in a misguided and futile attempt to pretend programmers can be fungible. While those efforts are doomed to failure, that hasn’t stopped huge well-financed companies from pouring billions of dollars into their efforts: LLMs and vibe-coding are just the most recent iteration of these efforts. Your task is to figure out how to make yourself non-fungible, while remaining marketable. There are several ways to go about this; I’ve ended up with niche specialization and cross-discipline skillsets.

Embrace networking. If you are going to work with other people, networking is essential. It’s not trying to get a high score on LinkedIn, it’s about being an interesting person and taking an interest in other people. It’s a long game, and often goes beyond mere professional connections. This field is full of the inept and the untrustworthy, and no one wants to work with either — networking is about establishing relationships of trust which will help you get through people’s filters.

Fart around. Spend some time trying a wide variety of projects and adjacent work: I got my start doing web development, and had some experience doing audio programming in a visual programming environment (Max/MSP) previously, but I waited far, far too long to try branching out beyond web development into other types of projects. In addition to learning more about the kinds of things you like and dislike, you’ll also learn a wide variety of ways to solve various problems. 

In addition to just having fun, some of the best insights in my professional work have come from doing audio programming or embedded devices and circuit design, even though my normal work has nothing to do with those areas. Having more tools in your problem-solving kit helps a lot.

Study ethics. Ethics provides a framework for you to draw boundaries around what ends you do and do not want your labors to serve, and how to determine if things you are asked to do align with your values. I know people who were attracted to shiny, interesting-sounding projects, only to learn (sometimes years later) they contributed to some defense contractor committing atrocities. Companies that want you to help them do evil are rarely up-front about it; some are outright deceptive, and even companies that seem to share your values will turn on those the moment it suits them.

Beyond that, even if you’re careful about choosing your employment so that your labors aren’t generally at odds with your values, you will still likely end up in situations where having a basis for making decisions you can live with will be important. The ends your work serves go beyond code, and even well-meaning people may want you to do something you find questionable in the name of expediency, deadlines, quarterly results, internal politics, or “satisfying the client”. Learning how to align your decisions with your values is not something you want to learn on the job, and especially not after the fact.

Study systems thinking. Software at scale is often comprised of interconnected systems under the control of varying teams and sub-organizations, and often exists in a broader context including outside actors; from the ones you want, like customers, to the ones you don’t, like attackers. Systems thinking is a framework for holistically understanding the boundaries, interactions, motivations, incentives, and behaviors of the various actors in a larger system, and how one might go about finding leverage points to change those.

Many ideas in systems thinking tend to be counterintuitive to someone schooled primarily in western logical rationalism, but prove extremely useful to understanding the kinds of complexity you will inevitably have to deal with in large software projects. I have lost count of the number of times I’ve heard someone ask “who could have predicted this?” about an undesirable outcome from some design, when the answer is: someone who has learned to think in systems.

Develop your introspection & curiosity. Personal introspection is something that I feel is wildly important to our field, and often sorely lacking. It proves especially useful with designing interfaces – not just graphical, but command-line, APIs, any place where there’s a boundary, but this applies to many things, even pure code. You’ll get a feel for how things should be, and how they shouldn’t, and your intuition will tell you when something is just off and you need to learn to listen to that, to poke at it, and to dig deeper. Introspection helps with asking “why does this feel off to me?”

Curiosity is the counterpart to introspection. Why do things work the way they do? You may at times be presented with opaque systems you need to figure out, you may notice some odd behavior of a system that sets off a feeling of wait, what’s really going on here? that eventually proves crucial to the viability of a project. A practice of being generally curious about things will, at the very least, help you pull in additional context for the things you’re working on, but sometimes it can entirely transform a project for the better.

§

What are some valuable skills for software engineers?

Communication, communication, and more communication. Learn to write clearly, learn to argue, learn to persuade; learn to wield language the way a surgeon uses a scalpel and the way an artistic painter uses their brush.

Even if you’re working alone, code is communication: with the compiler or interpreter, and with yourself across time. If other people are working on your code, it is also communication with them. It is much more difficult to read code than to write it; I’ve heard it said – and largely agree – that the process of reading code involves running it in your mind. Any impediment to clarity in the code makes that reading & interpreting process more difficult. Writing is a process of clarifying your thinking, and while some clarity in code comes from logic, it mostly comes from context and structure, and having an understanding of how to achieve these with written language will carry over to code.

More than that, communication touches upon nearly every other aspect of software development work: requirements gathering, documenting specifications, consensus-building, code review, quality control, the list goes on. Working on software often involves dealing with incredibly abstract concepts that don’t have perfect analogues in language or diagram, yet those are often the necessary and available tools to convey ideas, processes, and mental models which need refinement, clarity, and shared understanding.

You will be well-served by learning how to argue and persuade; both the art of argumentation through perhaps debate, but also more generally learning how to convince others of the merits of your viewpoint. While it helps to start from having a good viewpoint to win people over to, this is often not enough. If you work with other people, you will end up doing a lot of arguing and persuading anyway, so you may as well learn how to do it well.

Most people aren’t very good at persuading or arguing, especially STEM-focused software engineering types. People in our field often rely on pulling rank, being the first to be heard, being the loudest, using fallacies or thought-terminating clichés, or at the extremes treating chaos as a ladder. Some people are petulant gate-keepers, and some are great bullshitters. If you work with others you’re going to end up in arguments with them, often in the context of a team. Especially early in your career, if you’re not ready for these kinds of discussions, you’re going to lose, however unfair it may seem.

Building production software systems involves a lot of disputes, debates, and building consensus. It involves a lot of persuading people with money, control, or influence that some course of action is or is not worthwhile. Learning how to navigate these kinds of communications will pay off greatly.

§

How important is formal education compared to self-taught skills?

I have no formal education in software. My freshman year of college I took an “Intro to C” class: the entire quarter was spent on linked lists, and I did terribly. Six weeks later, a friend showed me NSCA Mosaic and the nascent World Wide Web; a year later I got a part-time job because I had taught myself perl. And so has gone the rest of my career. I ended up getting a degree in studio art, so I can’t really speak to the value of formal education in this field. But in the 30 years since, I have not once needed to write something to manage a linked list for anything other than an interview at a place it turned out I wouldn’t have wanted to work at anyway.

What I can say is that in my experience of this field, you will constantly be asked to learn new things, so getting good at learning new things on-demand and on-the-job is helpful. The internet, from blogs to youtube, has entirely transformed learning on-demand. Want to know something about A* pathfinding or particle systems for a game? Need to know how to wrangle Common Table Expressions or window functions in a database? You can get up to speed in an afternoon.

If you’re comfortable with finding a domain you like and staying there, great; I know people whose entire programming careers have existed in domain fields like health care, finance, or delivery logistics. Personally, I have flitted between these and others, and my ability to pick up what I need to know about things to the point where I can help domain experts solve their problems has been a real asset, and somewhat personally fulfilling.

Very little software work is pure computer science-y code wrangling that doesn’t involve a domain subject. I know people with CS degrees and doctorates who work on cutting-edge algorithmic stuff where they can ignore their employer’s domain, and they get paid extremely well, but they’re working on things like digital rights management, fine-tuning the extraction of money from advertisers, juicing content-promotion algorithms for maximum engagement, and personnel risk profiling in a way that often reinforces existing cultural biases. Maybe that kind of work appeals to you, but the opportunities to do it will probably come with compromises against your values about the world you’re helping your employer build.

Which is not to say that an understanding of algorithms or data structures is not important – they are! – but they are only one of the many things you will need to learn. In my experience, there are typically people around who know this stuff well, and leaning on them for this knowledge has, in the long run, actually helped everyone. In some ways, my lack of formal training has been an asset: I once took on a supposedly intractable problem about monitoring trends & moving averages at scale, and with inspiration from electronics and the E series of preferred numbers, and keeping the end requirements in mind, I built something that solved the problem elegantly when the people who knew their stuff wouldn’t even try.

I think that the answer for you will ultimately come down to the type of career you want, the type of work you want to be doing, and types of things you want to work on.


This is, obviously, my perspective from what has been a very odd career path. Like many in this field, I often feel like I would rather be doing something else. While the advice is already seasoned, please take it with a few grains of salt.