Crafting Better Software
Tags: coding, softwaredevelopment, beginners
Published: 2024-06-04 05:13:39



_Let me preface this by saying I am extremely pedantic and opinionated on what quality code looks like... I have been burned enough times to know._

## What do I know?
I have written and read a lot of complex and untested code over the years. I have had to maintain services and libraries that are so complex and have such poor coverage that understanding how they worked was nearly impossible. Most of my career has been focused on preventing and reducing complexity. 

# Guidelines
In an effort to guide engineers who aspire to be better, I would like to offer some of the most important takeaways from my career. I hope you find use in them and can avoid burning yourself and others. Hopefully, you can avoid the mistakes that I have made and that cost me so dearly.

## Focus on Abstractions
The most important skill for you to develop to become a better crafter of software is building abstractions and grouping them together in a coherent way. Most young engineers I work with will write code with no structure or will revert to established principles and design patterns. The most common one I hear is DRY. I would argue that DRY is a side-effect of writing quality abstractions. It should not be a focus, it should be an outcome. You should be asking yourself questions like:

1. Does the code make sense? Does it do one thing?
2. Does the code effectively and concisely communicate one idea?
3. Is the code un-ambiguous? Can the engineer make sense of it without having to read too much? 


## Good Software Has Layers
The best thing you can do as a software engineer is to spare your co-workers the pain of having to read more code than necessary to understand what is going on. The most effective way to do this is to introduce layers into your software. This should be done through modules. Doing this successfully means that someone can get a pretty good idea of what your software does just by looking at the directory structure.

Consider the following:
- /api
  - /chartData
- /lib
  - /shapes
    - /pie
    - /bar
    - /line
  - /dataProvider 
    - /timeSeriesDataFetcher
    - /categoricalDataFetcher
- /db


By looking at this, you can get a pretty good idea of what to expect. There is an api that vends chart data. I expect the chartData API to use dataProviders to fetch data using a db client. The return types will probably be formatted into a pie, bar, or line shape.

Now consider this:

- /controller
  - /customCharts
- schema
  - /customChartSchema
  - /customChartProvider


Notice how there is so much ambiguity? What is a controller? What charts are supported? Where does the data come from? 

## Treat Tests as Records of Intention
Believe it or not, I have had to make a case for writing tests over code. I have encountered developers who do not think it is a valuable practice. I can see how some may hold this belief. Especially if you are at a super early-stage startup and you are one of two people writing code. However, I would say that tests should be treated as documentation. They document the expected behavior of code, which not only serves you but also the developers you hire onto your team. They will have less of a hard time understanding what the intent of the code is. That is also less time you have to take out of your day to explain your code to them.

## Document Modules
Whenever you write a module, document the abstractions it encompasses and how they interact together. This makes it very clear what a module does on a high-level. Some may argue that it is not worth writing documentation because things are just going to change anyway.  I would argue that it is worth the extra 30 minutes. You save people way more than 30 minutes of their time. I know it is a chore, but there will never be a time you have the context of your code fresh in your mind. So get it down before you move on to the next thing. 

### Parting Words
If you take one thing away from this, I would say shelter your co-workers from complexity. All your effort should be put into making code as intuitive and coherent as possible. Your peers should not be cursing at their screens or burying their face in their palms. That is a sign of failure. If you have any questions or criticisms, please leave comments.