Keeping a Clean Shop
Published: 2022-02-15 21:58:16

Most engineering disciplines encourage keeping the work environment clean and organized.  For some, like chemical engineering, this is basic health-and-safety practice.  But for others, it's about quality and efficiency -- avoiding lengthy searches for that 10mm socket, and having the right tools and materials at-hand when they're needed.

![I got 99 sockets, but a 10mm ain't one](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f2zsnys2h35bt03aosd7.png)

Cleanliness is especially important in a shared environment.  Your shop-mates want to know that they can find a tool or material quickly, and not at the bottom of a pile.  They don't want to be surprised by hidden hazards, and they want a clean place to do their work.  Shared spaces such as hacker-spaces and professional labs accomplish this with practices and processes: a clear place for every tool and material, written safety and cleaning processes, and shared expectations around how each person will leave the space.

What are the parallels in software engineering?  Our "shop" isn't a place, or our laptops, but the code we work on.  And, any software project today is a shared environment, whether among co-workers at a company or among contributors to an open-source project.

From this perspective, I suspect we've all encountered some "dirty shops."  That might be an open-source repository where the tests aren't passing, with a months-old "fix the tests" issue in the tracker.  Or maybe a codebase where one developer has carefully balanced un-documented invariants across the codebase, then moved on to greener pastures -- leaving everyone else afraid to touch anything.  Or maybe it's just a repository where things are kind of OK but expectations aren't clear around code style, tests, or documentation.

![Messy server wiring](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58yo91z5be6zlk5yjx80.png)
 
As with a physical shop, it's still quite possible to make beautiful things in these environments, but work gets slower and more frustrating as time goes on.  Even the simplest task has to begin with cleanup -- getting the tests working, figuring out why the same thing is done three different ways, and then updating the documentation for a feature that landed a month ago.  It's tempting, too, to just skip the cleanup and just do the minimum to get the task done, compounding the problems.

To focus on the positive, here are some characteristics of a clean software project:

 * *Passing tests that are easy to run locally and in CI*

    If the tests aren't passing, subsequent changes may break more tests.  The project should have a clear expectation that functionality is not considered finished until it is tested.

 * *Up-to-date documentation*

    Documentation that is out-of-date after later changes, or that has not been updated to cover new functionality, can lead to confusion and wasted time for future developers and users.

 * *Documentation and automation for developers*

    Expectations for developers should be clearly written down and, where possible, supported by automation.  Code style is an easy example: most languages now have tools that will automatically reformat code to fit a defined standard, so neither the author nor the reviewer wastes time thinking about where to position a curly-brace.

    But this goes beyond code style.  Application architecture, design principles, project-specific code patterns, review guidelines, release processes, and so on.  Everything should be written down, _in the repository._  Then, the information travels with the code, and can be changed when necessary using the same processes as used to change the code.

    This documentation also includes a code of conduct.  Much like wearing a white coat in a lab, this can seem unnecessary until that bottle of HCl tips over on the bench.  A CoC ensures that _when_ an emergency occurs, no time is wasted trying to figure out how to handle it.

 * *Shared tools and support*

    A good project makes common things easy.  For example, if the application is a command-line tool, then it should have robust support for adding subcommands, options, help messages, and so on.  This gives a clear "happy path" for a task-focused developer, allowing them to complete their task efficiently without adding unnecessary complexity.

 * *Clear implementations with no hidden dependencies*

    Most sophisticated projects have a "core" that is a bit more complex than the rest of the codebase.  Perhaps it's performance-critical, or implements some sophisticated algorithm.

    The core can become a hazard if a developer can't safely modify it, either because it is so incomprehensible that they can't figure out where to start, or because it contains hidden dependencies that cause a chain of failures whenever anything is changed.  When a project's core becomes unmaintainable, the project is implicitly "finished" -- it might get bugfixes or features tacked onto the periphery, but its core functionality ceases to evolve.  If the project is the secret sauce at your startup, this might be a problem!

It can be hard to judge the cleanliness of your own shop, or codebase.  It's always been like this, it works fine, and you know intuitively which pile to look under for that elusive 10mm socket.  So here are some ["cleanliness smells"](https://en.wikipedia.org/wiki/Code_smell) that might help you evaluate a project:

 * Do newcomers need a lot of one-on-one assistance to make a successful contribution?
 * For open-source projects, do people stick around and revise their contributions?  Do they make second contributions?
 * Do others often suggest rewriting parts of the project?
 * Do "easy" tasks often cascade into a long sequence of fixes?
 * Do developers "code around" some parts of the codebase, instead of feeling empowered to modify it?

In an increasingly collaborative world of software engineering, here's hoping we can all keep our shops a little cleaner.

[cover photo: [@mtneer_man](https://flickr.com/photos/mtneer_man/2713091999/in/photostream/)]