repository-pattern

1 posts

line

Code Quality Improvement Techniques Part 1 (opens in new tab)

Maintaining a clear separation of concerns between software layers requires avoiding implicit dependencies where one layer relies on the specific implementation details of another. When different components share "hidden" knowledge—such as a repository fetching extra data specifically to trigger a UI state—the code becomes fragile and difficult to maintain. By passing explicit information through data models, developers can decouple these layers and ensure that changes in one do not inadvertently break the other. ### The Risks of Implicit Layer Dependency When layers share implicit logic, such as a repository layer knowing the specific display requirements of the UI, the architecture becomes tightly coupled and prone to bugs. * In the initial example, the repository fetches `MAX + 1` items specifically because the UI needs to display a "+" sign if more items exist. * This creates a dependency where the UI logic for displaying counts relies entirely on the repository's internal fetching behavior. * Code comments that explain one layer's behavior in the context of another (e.g., `// +1 is for the UI`) are a "code smell" indicating that responsibilities are poorly defined. ### Decoupling Through Explicit State The most effective way to separate these concerns is to modify the data model to carry explicit state information, removing the need for "magic numbers" or leaked logic. * By adding a boolean property like `hasMoreItems` to the `StoredItems` model, the repository can explicitly communicate the existence of additional data. * The repository handles the logic of fetching `limit + 1`, determining the boolean state, and then truncating the list to the correct size before passing it up. * The UI layer becomes "dumb" and only reacts to the provided data; it no longer needs to know about the `MAX_COUNT` constant or the repository's fetching strategy to determine its display state. ### Strategic Placement of Logic and Constants Determining where constants like `ITEM_LIST_MAX_COUNT` should reside is a key architectural decision that impacts code reuse and clarity. * **Business Logic Layer:** Placing such constants in a dedicated Domain or Use Case layer is often the best approach for maintaining a clean architecture. * **Model Classes:** If a separate logic layer is too complex for the project scale, the constant can be housed within the model class (e.g., using a companion object in Kotlin). * **Dependency Direction:** Developers must ensure that functional logic does not leak into generic data models, as this can create confusing dependencies where a general-purpose model becomes tied to a specific feature's algorithm. Effective software design relies on components maintaining a "proper distance" from one another. To improve code quality, favor explicit flags and clear data contracts over implicit assumptions about how different layers of the stack will interact.