Good and Bad Layout

You can't know if something is good until you learn what a similar bad thing looks like. A bad thing might be perceived as good until you experience a truly good thing. Take, for instance, coffee. For someone who has never had it, almost any coffee can be considered as coffee, and it may even be unquestioned. But when after trying various kinds you take a sip of Supreme coffee made well, you no longer think that coffee from a Nespresso machine is tasty.

So, what makes a project layout bad? Can it even be bad? Why should we bother about it?

Bad Layout

Have you ever been supporting a project with so long list of files scattered in the root directory, so it takes you several scrolls to get to the README file on the project's repository homepage on GitHub?

Have you ever been maintaining a project where half of the application is contained in the main package, and the entirety of the main package resides at the root level of the repository?

How often do you find unnecessary artefacts in a repository after building an application or running tests?

How often did you need to replace or move parts of a project and then fix the imports to fix an import cycle, or when the structure no longer makes sense?

How often do you find a folder that exists only to contain another folder?

Positive answers to any of these and other similar questions are signs of that you've encountered a bad project layout. When working with such a project, even as simple operation as building a binary can turn into trouble since you don't know whether the resulting binary will be accidentally included with the next commit or not.

So what are the characteristics of a suboptimal layout anyway? It can be nearly anything that leads to any of the following symptoms:

  • a long list of files scattered at the root or any other level of a project
  • a long list directories scattered at the root or any other level of a project
  • files of different purposes are mixed at the root or any other level
    • code and configuration files (the app's configuration files)
    • code and CI scripts
    • code and tool's configurations
    • images or any other content
  • there is no definite place for outputting build artefacts
  • .gitignore does not exclude anything that should not be committed
  • the structure does not support or reflect architecture of a project
    • having both app and server directories at the same level - does this project provide an app? Or a server? Or it's a poor project layout design?
  • the project structure leads to leakage of implementation details to the public API surface level
    • users can use parts of the implementation that are supposed to be internal
    • thus maintenance of the project is now complicated and slowed down since the public API is much broader than it should be
  • the project structure is unnecessarily complicated and contains a multi-level hierarchy that implements a taxonomy of packages

A mixture of even two of the symptoms listed above can significantly complicate project development and maintenance in long-term. Even worse may things become if a project is large, and is being developed by more than one person. Suffering can be endless, if that's an open-source project, and it's a popular one.

So you really want to invest in a good project structure that will help and support you as the application evolves. What does make a good layout?

Good Layout

Now as we have learned some of symptoms of a bad project layout, it's time to know how a good one looks and feels like?

Overall, a good structure should be unnoticeable in everyday work. It exists, but as if it were invisible. Once defined, described and set, it just guides you. It limits the number of mistakes, helps to onboard new developers, supports maintenance routines, and does help in many other different ways. Let's look at some of those.

A good design for layout suits well for a project:

  • if a project is a library, the layout should reflect and support that
  • if a project is an application, then the layout should make development and maintenance easier
  • if a project uses the monolithic repository approach, it's clear where different services, libraries and other parts reside, and where to add new things.

A good layout limits the chances of misplacing something:

  • when files and directories are logically and functionally well organised, it's harder to misplace a new file
  • the structure helps in deciding whether a new file should be a part of the existing tree, or it deserves a new level.

A good layout reduces the mental load required to work with a project day by day:

  • it's clear where binaries should go
  • test coverage reports do not pollute commits
  • changing CI configuration is straightforward
  • files of different purposes are grouped in a way that makes logical and functional sense
  • it's hard to accidentally commit and push garbage files.

A good layout simplifies navigation through a project:

  • it's convenient and easy to navigate in an editor/IDE
  • the homepage looks nice and well organised
  • in a terminal window, it's easy to work with files using standard and simple console tools.

A good layout helps you to maintain a project in a healthy state:

  • implementation details are kept private, yet still available as exported within a project
  • the possibility of creating an import cycle is reduced by design
  • the structure and hierarchy represent the business logic and relations between different parts of a project.

As you can see, a good layout is more than just the opposite of the symptoms of a bad one. A good layout is the foundation for a development process focused on producing great software. If you have it, then you've got more mental energy to focus on creative solutions for hard problems. If you don't, then part of the energy is wasted.

The layout of a project depends on many factors. The most important one is the kind of a project. The layout will be different for a library, a single application or service, and for a monolithic repository, while there are some commonalities that make better any kind of a project.

As we now have learned what makes a good layout, it's time to know how to structure projects of different types.