TLDR; Code that changes together should be moved closer.
I've picked it from:
The principle of proximity focuses on how well organized your code is with respect to readability and change. Proximity implies that functions that are changed together are moved closer together. Proximity is both a design principle and a heuristic for refactoring hotspots toward code that's easier to understand.
— Software Design X-Rays by Adam Tornhill
Not convinced yet?
It may remind you of the Common Closure Principle, or Single-responsibility principle from SOLID. It's not the same thing, and it is better than both of them.
Common Closure Principle #
Classes within a released component should share common closure. That is, if one needs to be changed, they all are likely to need to be changed.
— Common Closure Principle
Common Closure Principle is the proximity principle—but backward. It's hard to apply and often leads to overcomplicated code. Instead of planning what will change with what, it's better to watch it after some passes and refactor. I wouldn't say it's false, but the Proximity Principle is more practical in my experience.
The Single-Responsibility Principle #
(...) every class in a computer program should have responsibility over a single part of that program's functionality, which it should encapsulate. All of that module, class or function's services should be narrowly aligned with that responsibility.
— Single-responsibility principle
The Single Responsibility Principle is a vague construct. Maybe it applies to pure functions, but it's hard in practice with anything else—especially classes. Think about it—your class can be instantiated and at the same time handles some business logic. Those are two things already. If you want to argue that it doesn't count, think of an exact list of things that do count. Logging. Metrics. Annotations to prevent unauthorized requests. But, the worst thing is that it often leads to code that violates The Proximity Principle. With your misaligned quest for objects to have one responsibility, you end up with scattered code. A single business change requires changes all over the place (shotgun surgery).
Humans learn (and get mastery) thanks to the process called chunking.
In cognitive psychology, chunking is a process by which individual pieces of an information set are broken down and then grouped together. A chunk is a collection of basic familiar units that have been grouped together and stored in a person's memory.
— Software Design X-Rays by Adam Tornhill
So good groups can help you familiarize yourself with a big codebase. Project structure makes a difference, and most of the programmers know about it. That's the reason why I often quote:
There are only two hard things in Computer Science: cache invalidation and naming things.
— Phil Karlton
What about proximity? It's one of Principles of grouping
The Gestalt law of proximity states that "objects or shapes that are close to one another appear to form groups". Even if the shapes, sizes, and objects are radically different, they will appear as a group if they are close.
— Wikipedia: Principles of grouping
If you're not convinced that graphic design principles are essential for code organization, then think about biological interpreters of code—humans. Even if your compiler or interpreter doesn't care how you format code, then you do. Your coworkers care as well. It's the reason why there is a whole wikipedia article about indentation styles and why it redirects from tabs vs. spaces page.
In practice #
- Keep code that changes together in one file
- Keep files that change together in the same directory
Let's see an example of
Button React Component:
📁/Button/ 📄 Button.js 📄 Button.test.js 📄 Button.css 📄 Button.story.js
I've given some more examples from other languages in Working Effectively with(out) Tests. -> Where do we put tests?, but I can recommend the whole post. It's focused on tests but will give you a more practical example of using the Proximity Principle to reason about your test code.
More reading: #
- Software Design X-Rays by Adam Tornhill
- Working Effectively with(out) Tests
- Why I Recommend Unit Tests in the Src Folder by Jim Lynch
- Java unit tests, directory layout [closed]
Want to learn more?
Sign up to get a digest of my articles and interesting links via email every month.