Let me start by saying, “I don’t know.” Whether someone is allowed to call themselves a software engineer is a function of which country they live in, how the profession is legally defined there, and whether or not some form of legal certification is required to practice it. What I want to share is less about whether someone can legally call themselves a software engineer, and more about what I’ve observed people do throughout their work and what I believe a software engineer should be able to do.

Most certifications and academic programs focus on what a software engineer or developer should know, as opposed to what it is they will be doing throughout their career. I am not discounting the knowledge these programs instill, rather the expectations one builds going through in such programs. I went through four years of college, three more as a grad-student, and I’m currently finishing up grad-school. However, it is my experience working with startups and organizations, and conducting research in the field that I feel has contributed most to my understanding of software engineering. That being said, I am still young, and I do not consider myself an authority.

The best metaphor I can think of to exemplify the broad range of activities a software engineer does is hats. Each hat (or role) encompasses a set of activities a software engineer is expected to do. There are six hats in total that I’ve seen in practice or have worn at some point or another, and this post is my attempt at articulating them. The first two should come as no surprise to anyone, however, it is the last four that I feel are generally overlooked.

The Technical Hat

A software engineer is someone who knows the technical details of their field well enough that they should be at ease performing technical tasks. For instance, a software engineer should be able to write code, design database schemas, write tests, and so on. While most software engineering literature either focuses on specific subdomains of this role (such as testing, coding, or UI design), a software engineer should be–at least–comfortable doing all of them. Not a single specialization, not one or two, but all of them. Because of the way software is built nowadays, with architectural frameworks, external libraries, and all the other prebuilt components, isolating oneself within their comfortable little corner of the codebase is no longer an option. Changes that a developer makes, let’s say to the backend, will have significant impact on the frontend, or tests to say the least. Thus, a software engineer should have their finger in many pies so to speak.

The Managerial Hat

Eventually, a software engineer will be expected to helm a team, if not assume a managerial position. They will need to be able to set goals and deadlines, communicate with other forms of management throughout their organization, and do a bunch of administrative work that highly technical people generally consider a waste of time better spent coding. At this point in their career, their contributions to the team codebase will shrink to make time for all the other managerial tasks that will take up most of the day.

This is an important hat for a software engineer to have. Non-technical managers tend to be more metric-oriented, judging the efficacy of a process from a high level. The advantage a software engineer has when they wear this hat is that they know the intricacies of the development process. They know why things work the way they do, how writing software is less of a metric-oriented process, and more of a creative process. Ideally, while wearing this hat, one should strive to be a balanced mixture of manager and software engineer, as opposed to leaning too heavily one way or the other.

The Archivist’s Hat

You are a software engineer, or want to be. You write code. Good code is its own documentation. I’m sorry, but this is simply not true. There’s a lot more than just code in the codebase nowadays. There’s build tools, there’s test suites, there’s packaging tools, there’s deployment scripts. Then, there’s the entire development process that surrounds the codebase. The one that’s been so ingrained into your muscle memory that it feels as natural to you as breathing. A software engineer is responsible for documenting all of that.

Let’s break it down. By and large, there’s two types of knowledge a software engineer operates on when working on a project; explicit and tacit knowledge. Explicit knowledge includes (but is not limited to) code comments, architectural documents, requirements and design specs, and so on. If your project has records of all of that, you’re reasonably well covered in the “what am I reading” area. Tacit knowledge refers to everything you know, but have not put down on paper. This, almost always, covers the development process itself (and its subprocesses), team culture, communication with other organizational units, …etc. This is the “how do I do things” area. Often what you’ll find are simplistic descriptions of how to perform simple tasks. This, for some reason, is rarely included in a codebase, even though it’s just as vital as the other stuff.

To combat this trend in process documentation minimalism, be it consciously or subconsciously, development teams have created extensive onboarding processes. These range from courses on company culture, to pairing up with an experienced team member to learn the ropes, to telling the new hire they should read the tool docs. A software engineer should–similar to a memento mori–keep in mind that they are not immortal. Not to the project they’re working on anyway. They may leave, be replaced, or may have to onboard someone new. Having all of that knowledge stored away somewhere makes life significantly simpler, and similarly to how archivists constantly update their knowledge troves, a software engineer should always make sure that their documentation is up-to-date.

The Researcher’s Hat

A software engineer should have all the answers when it comes to creating software. If they don’t, they should know how to get them. I’m not referring to fixing errors and debugging code, these are a given. And for everything they don’t know, there’s StackOverflow. What I’m referring to is more high-level than code.

I mentioned earlier that writing software is no longer just about writing code. There’s a bunch of tools, languages, frameworks, libraries, and other stuff to think about when one wants to create software. Following a more goal-oriented approach to software development, a software engineer should be able to identify all the available options in front of them when it comes to tools, libraries, …etc. Even, and bear with me here, languages. While it may be easy for highly technical people to switch between programming languages because of the common constructs in their syntax, these programming languages are different. They were created with specific tasks in mind, and thus are more suited to specific types of projects.

To illustrate my point, I want to tell you a little bit about javascript. When it first started out, it was this very basic way of manipulating the DOM in HTML pages. It was a scalpel, meant to do something and do it well. It has, since then, grown into one of these cheap, massive multitools that can do everything, albeit not so well. Javascript has a ton of frameworks and libraries now that allow it to take on several roles, including backend development, data management, data visualization, and several other tasks. Now I’m not saying visualizations produced by Javascript are bad, they’re among the most beautiful, interactive, visualizations I’ve seen. What I’m saying is, if you want to do significant data extraction, transformation, and loading beforehand, you don’t use Javascript. Instead you use something like Python or R that is specifically meant to handle such complex operations efficiently.

Like an electrical engineer who knows when to use electrical tape or heat shrink tubing, a software engineer should determine what the best tool for the job is and go with it as opposed to what it is they’re used to. Because this doesn’t apply to just languages, it applies to everything! Libraries, frameworks, toolkits, continuous integration platforms, …etc.

The Philosopher’s Hat

Most people want to get into software engineering because it has a very low barrier to entry, but is capable of effecting change on a wide scale. Over the past two decades, it has been mostly software that changed the way people interact, how they behave, and how society functions, for better or worse. When I decided I wanted to pursue a career in software back in 2004, I started with all the lofty goals and best intentions in the world. I wanted to build software that improves quality of life, helps people in their work, and genuinely make the world a better place. With software, I honestly believed I could. Now that I’m older, my drive still hasn’t changed, but it is probably more mature than what my 16 year-old self had in mind at the time. Over the past two decades, I’ve seen how software can be a destructive force when left unbound by the rule of ethics. Just as it has the potential to be a force for good, it also has the ability to inflict great harm.

I named this the philosopher’s hat, but it’s probably more of a mix of a futurist’s ability to predict what will happen guided by a sociologist and psychologist’s ability to reason whether the predicted effect is beneficial or harmful to humans and society. But, it’s still a thought exercise at its core. A software engineer should be able to foresee what effect (either benefit or damage) the project they are working on (or have been tasked to create) will have, be it on individual users, groups of people, or the fabric of society. Similar to a physician’s oath to do no harm, I believe it is a software engineer’s responsibility to ensure that the software they create does not cause harm. While we do have codes of conduct in practice, I’m sad to say that the majority are more guidelines than detailed articles of law. It is a software engineer’s responsibility to point out what effects their software is going to have, and–if determined to be harmful–retire the project, or at the very least stop working on it in protest. Which brings me to the final hat.

The Hat of Accountability

Software engineering is a young discipline. Unlike other mature disciplines who have their well-established communities, well-defined procedures, certifications, and other neat stuff, software engineering is still like the wild west. Much like anyone could wield a gun and shoot people openly, anyone can write code and inflict it on the world without a shred of accountability save for what little software publishing platforms arbitrarily choose to enforce or what could damage national interests (but that’s a different topic). While the law is doing its best to catch up, it is a long and arduous process which will probably always be struggling to keep up with how software rapidly evolves.

In my opinion (and I heavily stress that it’s my opinion), software engineers should hold other software engineers accountable for bad software until such time as the profession becomes licensed. Similar to the other engineering professions, bad software that has the potential to inflict harm on a large scale and endanger lives deserves to be called out, and its creator needs to be held accountable. If a surgeon were to perform an illegal medical procedure, they would lose their license and be sued for malpractice. If an architect were to poorly design a 10-floor building only to have it fall on its occupants because of some design error, they would be punished. But these are heavily regulated professions with mature codes of conduct and well-established legal aspects. Software engineering is not like that, at least not yet. We as software practitioners should hold each other accountable.

Even though I’m older than I was 16 years ago, I still believe software has the potential to make the world a better place. While it may be moving too fast, I have no doubt that we will catch up to it, and in time it will be as mature as the rest of the engineering professions.

Well, thanks for sticking with this till the end. It’s taken me a while to try and sum up what, in my head, a software engineer should be able to do, and why. Like I said, I’m no authority on the matter, I’m just really passionate about software.