Stop sharing code
Sharing code is overrated and it’s abused as the solution to code repetition. What’s the alternative? The answer is related to cohesion, code hotspots, and the law of proximity.
Cohesion
Cohesion refers to the degree to which the elements inside a module (e.g. a class) belong together. High cohesion means all the code in a module is related; low cohesion means that the module contains unrelated pieces of code.

Modules with low cohesion can lead to code hotspots — they’re like black holes of code and attract every feature. They harm modularity because they bind multiple features together. They make your codebase ill. Since there are multiple reasons to change hotspots, they grow indefinitely and are often a source of merge conflicts.
There are several reasons why code grows into hotspots. The most common reason is low cohesion, which means that the hotspot contains several unrelated parts and lacks modularity. Such hotspots attract many commits because they have too many responsibilities and those responsibilities tend to be central to your domain, which is why they change. Software Design X-Rays

There are two types of hotspots:
➡️ Business hotspots centralize many business operations (e.g. UserService) into one place. They have very low cohesion because they only share a broad business concept.
➡️ Technical hotspots centralize technicalities (e.g. a file full of enums); they are like the Hungarian notation on steroids because both highlight the technical type in place. Sorting technicalities by categories gives them too much spotlight and puts them ahead of high-level abstractions, which is backward thinking. You should avoid technical hotpots for similar reasons that you avoid technical stories — both focus on the wrong thing. They have no cohesion because nothing binds them together, except the technical side of it. These are the focus of the article.
Law of proximity
According to the law of proximity (one of the Gestalt Laws), things that are close together seem more related than things that are spaced farther apart. What does this have to do with code cohesion? I hypothesize that this law is not exclusive to the visual system. If you accumulate lots of unrelated technicalities in a file you start creating fake groups only because they’re put together.

My advice is to use the law of proximity to your advantage. Prefer creating groups of related code by functionality. Items that work closely together are placed next to each other. A bad group is “HTTP filters” because it’s technical. A good group is “Activate contract” because it highlights an actual business operation. This doesn’t necessarily mean that all related functionality should lie in the same place. This is only to make you think about the logical groups you want to create, which form your code's conceptual model. You should ask in which directions your code grows when new functionality arrives. If a place only grows due to technicalities, you have a code hotspot.
Pull the things that are unrelated further apart, and put the things that are related closer together. Modern Software Engineering
Contextuality
Segregating and sharing technicalities creates coupling between features. Tech files have too many unrelated reasons to change, which should ring a bell. Very few things, if any, need to be globally available (if it’s a shared concern like logging or monitoring, use dependency injection). If you need to share, you may be doing it wrong.
What’s the solution to avoid the centralization of technical artifacts? Split those files. Distribute their content. Put it into context. Then, make it private if possible.
In physics, the principle of locality states that an object is influenced directly only by its immediate surroundings. Principle of locality
Here are a few examples:
- Enums: If you have a file full of enums, you can distribute them; put them together with the entities and APIs that they belong to.
- Queries: files full of queries have many reasons to change. Make sure you distribute them where they belong to.
- Exceptions and errors: Why do you have files or folders full of exceptions? My advice is to put exceptions/errors near where they belong. Find them an owner. If an exception is thrown by a use case or an entity, then consider moving the exception near it. Learn more.
- Constants: Who hasn’t seen those typical files full of constants? I’m generally against constants, let alone files full of them. Even worse, I heard stories of endpoints that provide constants. Constants are a programming detail and code should not float around them. Put constants in their own contextual place. Even better: inline them if you can. Learn more.
- Data transfer objects: Serializers, models (e.g. MVC models), request/response models, and other DTOs should be placed where they belong — their creator or logical owner. This helps to create logical groups and thus reduces the code surface area. Some models can even be made private. (De)serializers are a good example of that. (Note that entities and value objects are not merely DTOs and thus can be global.)
- Utilities and helpers: Creating shared utilities is an antipattern, and is worsened if you pack them all in a file. It assumes things are going to be reused. Are you recreating something that’s part of the language standard library? Does it need to be shared? Isn’t it a symptom of a split decision?







