#code #implementation #software-engineering #clean-code


A clean code structure helps finding code easily, a favor a modular decomposition.

The structure supports two kinds of decomposition: infrastructure/domain, and domain-layer decomposition.


Separating what is domain related from infrastructure-related purposes, as proposed by the onion architecture[1]. Anything that is specific to a framework or a specific technology implementation is pushed to outer layers. Everything that is implementing the business rules and policies is encapsulated within the "domain". Layers integrate through contracts: infrastructure implements a capability defined in an interface, then dependencies are injected into the domain.

There are many benefits from such decomposition. The fist benefit is that thinking about the application in terms of domain policy and dependencies is helping with thinking abstractly. The inversion of dependency makes the code easier to inject, and so control a certain state for the infrastructure for test purposes, making testing much easier. This creates a situation favorable to a TDD, or at least more iterative approach, where what's built is already validated. Then the infrastructure itself can be tested separately, and changes to infrastructure integration are easily identified. This means that integrations that are hard to test can be exempted from integration-testing and tested manually. This kind of decomposition also ensures conceptual integrity by containing the "dirty secrets" of infrastructure implementation. It makes evolutions on the infrastructure (package upgrade, switching libraries, switching frameworks) more isolated work.

These typically end up stored in either distinct packages resulting in separate binaries (dll, jar, ...) or in separate folder that could be easily split into separate packages if the need appears later. For example if the app needs a desktop version and a web version, two application and infrastructure packages can be built and the app shipped with each. The different layers include:

graph TD

  subgraph internal

  domain --> contract
  infrastructure --> contract
  infrastructure --> deps{{dependencies}}
  application --> domain
  application --> infrastructure
  application --> config{{configuration}}

domain decomposition

The domain layer implements the policies and rules that effectively create the value of the application. This layer will typically reside in a single package. The "naive" way of organizing it is usually by layer, grouping things like views together, entities together, etc. Since the different parts of a given feature move together cohesively (e.g. an entity, its view, the actions related to them), it makes more sense to group them by features. The application also becomes more navigable[2] and readable.


Clean code requires a proper structure.


[2]: Clean architecture {TODO: add clean architecture to ref} - discusses a few approaches such as packaging by layer, by features, or by components (which is similar to onion)

[1]: Jef Palermo / Onion Architectureref is slapping a name onto the architecture which encapsulates domain and pushes infrastructure to the outlayers.

Package your classes by feature and not by layers