Return to Blog

Mastering Concepts, Not Code as a Software EngineerArticle by Brandon Burrus Posted on October 28, 2019 6 min read

As Software Engineers, one of the first things we learn to do is how to write code. But what is code, really? In a literal definition, code is simply the exact instructions given to a computer to execute some task, these instructions being written by us, the human. But code goes deeper than that. Code is the implementations of comprehensive ideas, the abstractions of complex models into simpler ones, and the concretion of conceptual theories into reality. That’s a lot of word salad mostly, realistically code is how we create the road from point A to point B in the software we create.

The problem occurs when that road starts forking. Suddenly the road can end in several different points, and edge cases can send us off unseen cliffs. To deal with increasing complexity, we as programmers came up with the idea of an abstraction, which is simply the idea of taking a complex task and making it easier to use by defining its inputs and outputs.

The first line of code you write, no matter what programming language, is written using an abstraction. Think about it: You don’t really know how the language is taking the text you give it and moving it into the console. You just know that if you give it an input, it will give you an output. A programming language is an abstraction itself, our programs themselves are merely layers of abstractions over each other, and if you dive deep enough, eventually you’ll hit binary (and even then, you could argue that you could go further, but let’s not get too crazy).

Ok, so abstractions help manage complexity, big deal right? Wrong! As developers, we need to learn how to create meaningful abstractions to write clean, manageable, well-written code. So how do you write an abstraction? Abstractions are the implementations of concepts. This is where programming patterns come in, the most common pattern you’ve probably heard of is OOP: Object-Oriented Programming.

In this paradigm, everything in a program is an object, thus objects themselves are literal abstractions. There are objects can represent Files, Numbers, Text, or more intangible things like Streams, Buffers, and Generators. But this is still a pattern, specifically a design pattern. There are structural patterns like MVC: Model, View, Controller. Data lives in the Model, the Views are generic (abstract) pieces represented to the user, and the controller reads the model, updates the views, the views get input from the user, tells the controller, who then updates the model.

Here is the main idea: if you understand the concepts and abstractions behind what you are building (or want to build), the code itself comes fairly easy and straightforward to write. Code now becomes the implementation of these abstractions and concepts that you are using. Let’s take a deeper look at a few of the most fundamental concepts/abstractions.

The function is one of the most powerful abstractions at your disposal (depending on the programming language, this might vary). Conceptually, a function represents an action that might take some inputs and might return some outputs (sound familiar?). In languages where functions are first-class citizens, the input to one function might literally be another function (it could also be an output from one too!). A function is an action, but it’s not an action that happens right away either. It could happen later, and even more powerfully, it’s repeatable.

We use functions to model all kinds of actions, from reading files, writing data to a database, requesting data from a network, and much, much more. If you master the concept of a function (and the related patterns like currying, callbacks, closures and more), it becomes one of the most capable ways to write well-written code. This is why names are so important; if a function does one thing, but it's named something completely different, the cognitive load of the person reading that code increases tenfold. Always use meaningful names in your code.

Structures are another fundamental concept to have a solid grasp of. I don’t mean a struct, like in C (although that is one kind of structure), I mean a collection of related data. A name you might be more familiar with is Data Structure. It could be a collection of related nodes that contain useful data, organized in a way that makes it easier to search through that data (Binary Search Tree). Or it might be a representation of something more abstraction, like an object with a subject, array of recipients, and body (an Email object).

Structures can inherit from other structures, be designed to fit together like composable lego bricks, or might simply represent a group of related data. By naming structures of data in our programs, we’re able to add simplicity in an organized fashion. It also helps to reduce cognitive load, as now when you see a Person object, you can guess that a person object probably has things like a first and last name, a birthday, two parents that are also Person objects, and more. It’s almost never that simple in the real world, but it’s better than the alternative chaos.

If you understand conceptually how the feature you are creating needs to behave, and also understand the programming concepts and abstractions you’re going to need to rely on in order to build that feature, the code practically writes itself. If you conceptually understand how this piece of your app behaves, finding and then fixing that bug also becomes a lot easier. If you understand conceptually how your new feature is and isn’t supposed to work, and you understand fundamental testing patterns, then writing tests for that feature also becomes fairly straightforward.

Concepts are more important to master than writing code is. Writing code is easy; mastering the concepts behind that code is very hard. If you want to get better at being a developer, focus on mastering concepts, not code. If you have a solid conceptual understanding of how things work and are related, you will grow as a programmer by leaps and bounds. Simply put, if you understand the concepts behind the abstractions in a codebase, it will make the comprehension of that code that much easier.