Adam James

September 2, 2021

Defining 'High Quality' for My Code

Untitled_Artwork-1.png

I've been spending a lot of time this past year figuring out what I can do with my career. I've been really struggling through the pandemic times to understand myself and how I can live happily in this world while still facing challenges and 'stepping up' to solve problems and be as good a person as I can be. It's a tall order, and if I'm honest with myself I've been spinning my wheels a bit.

I've been steadily working on Clojure libraries for 2D and 3D programmatic CAD, but I have not been pushing forward as much as I think I can. Nor have I been working with much urgency or focused direction. To a degree I am being gracious with myself; it was a hard year for many people, and I must confess it was hard for me too. But I'm not making excuses, just recognizing where I'm at. If I want to build the career I'm envisioning, I've got to step up my efforts.

One area I know how to improve is my code quality. I'm ready to step beyond alpha-level libraries and into releasing real tools. It's time to stop prototyping and time to start solidifying. I want to be known as a developer who cares about his code and his tools. I will strive to be a programmer with high quality code standards and consistently good output. That's doable for sure, but I need a clear idea of what 'high quality' actually looks like as I write my libraries and applications.

What Others Have to Say

I asked about signifiers of high quality Clojure(script) code on Twitter and received a few replies. In particular, I am intrigued by David Nolen's suggestion that a high quality library has:

  • Very little change over a long period of time (years)
  • Preferably no breaking changes in that whole time

Which I think implies that the library writer must signal that their code is reliable, stable, and well planned. These are excellent criteria, yet are quite subjective and open-ended. In order for a library to be reliable, it must indicate both what it does and does not do. In order for a library to be considered stable, it must demonstrate reliability over time by continuing to successfully do what it did before. Basically, if you want your code to be high quality, you have to design it, and you have to mean it. You've got to deliver on your design.

I suspect each developer and team builds a rather intuitive understanding of these goals as they gain experience, but there are also many tools that programmers can use to help. Metrics are rarely the whole story, but they can provide a useful proxy for the more subjective elements of work.

Vikram Rangnekar pointed me to Go Report Card in this tweet as a perfect example of how one can use tools to help build a set of metrics for assessing your code's (proxy) quality. I'll be using this site as an example when improving my own measures.

Finally, Vincent Cantin listed his main criteria as follows:

  • Simple API
  • very few or no side effects
  • does not do more than needed

Which is another set of excellent and open-ended criteria. What truly counts as 'simple'? Is 5 'very few', or perhaps 3? How can you know for sure what is needed from a library? These, I think, are all answerable questions, but the interesting thing is that they are all context dependent. You cannot definitively say what a Simple API is without knowing what you want your API to accomplish. Very few side effects may actually be a rather large number if the side effects are the point of the library. Once again, we see that a design is a rather crucial element of high quality code.

Now that I have some insights from other people, I want to share some of the criteria I've come up with. These are ideas I hope to incorporate into my workflow going forward. I'm pushing myself hard this month to step up my programming skills, and these criteria are an important part of that effort.

Easy Stuff

It's nice to find some low-hanging fruit when building a set of criteria. Here are the things I know I can easily do that will improve the quality of my code.

  • Add doc-strings to my functions and namespaces. These show up in tooling and let anyone reading my code know the intended use for functions. 
  • Run a code formatter and linter while editing my code
  • Use git branches for feature development and bug fixing. Stop doing all of my development on the main branch
  • Use GitHub Issues to document and discuss bugs and design questions
  • Keep functions small, and don't worry about 'too many functions', it's probably fine. But, delete code regularly too. Clutter isn't helpful.
  • Only use macros when you really know they'll be helpful.
  • Write Stuff Down. Preferably in a spot you'll remember and see often. This is why I use org-mode.

Simple Stuff

I also know of a few other elements that can positively impact my code quality. These are simple, but not necessarily easy to do.

  • Create and maintain a thorough design document. Keep the scope tight and very clear.
  • Maintain a clear understanding of what will NOT be included in the library or program.
  • Create a list of minimum-required features needed for the code to be useful.
  • Keep a Change Log
  • Keep a readme and keep it updated.
  • Create examples for all kinds of use-cases from simple to complex. Make sure the examples are easy to use via copy-paste and git cloning. Make it easy for a new user to try them out, perhaps even in the browser if that is possible and makes sense.
  • Improve my tooling. Fix up weird annoyances with Emacs, properly learn paredit, get Clj-Kondo running, etc.
  • Use my libraries for real work as I'm building (dogfooding). For example, use Forge to work on design docs and 3D models even before it's complete. This should help me discover truly required features and uncover bugs or faulty assumptions in my design.
  • Add features carefully and slowly. Delete code.
  • Automate the annoying bits. This means having good, clear scripts and instructions for things like building artifacts, pushing to Clojars, running tests, doing dev. and prod. builds, and generating documentation sites.

High Quality from a High Level

I've touched on this already, but it's clear to me that high quality code is a subjective goal. That doesn't make in unimportant. In fact, I think the subjective goals are often the ones we have to pay more attention to, as they're subject to the 'out of sight, out of mind' problem. Maybe that's the real secret to high quality code: paying attention to what you're doing and why you're doing it.

Basically, I want to try internalize the ideas Rich Hickey talks about in the well-known Hammock talk. In particular, I want to remember his simple definition of design:

Analysis and Design is about two things: Identifying some problem that we're trying to solve, and assessing our proposed solution in terms of whether or not it solves that problem.

Easier said than done, but I'm not actually looking for easy, I'm looking to make a difference. So, I need to practice the skill of identifying problems and solving them.

To make a few things a bit concrete, I'll have to remember to:

  • State the problem I'm solving.
  • Write down potential solutions, and write down the questions you have relating to the solution's implementation details.
  • Research and write down the answers you find.
  • If there's no answer out there, validate and try things out yourself. "I don't know... let's find out!"
  • Write down the problems in your solutions
  • Critique other people's solutions to the same problems, not because they're wrong, but because you'll uncover new questions.
  • Think. A lot, and with pen and paper. 
  • Iterate over and over. Writing down your thoughts, discoveries, and decisions.
  • Get away from the computer. Do the thinking and design work in a quiet, distraction-free environment.
  • Have concrete questions and specific issues to chew on, and think about these things hard.

As is always the case, the best results take real effort. There's no quick and easy approach to  building high quality software. There are elements that can be automated, parts of the work that are easy, concepts that are simple, and skills that are clear enough to exercise. However, to really be a high quality developer, I know that I have to focus and put in the thinking effort. I need to design, solve, and iterate with a clear and focused eye on solving real problems, and that's hard work worth doing.

Support

If you want to support my work, you can provide a one time donation here:
https://ko-fi.com/adamjames

Or you can become a Patron of mine here:
https://www.patreon.com/adam_james

Support is never required by me, and anything I write or produce publicly (not explicitly as a paid product) is always free to consume with no obligation or expectation. I want to be a maker and a creator, and much of the time sharing work is reward enough. 

At the same time, we live in a world where money is very important, and I won't lie and say I don't need some. If you feel so inclined to share a donation, just know that I am extremely grateful.