This document defines universal coding conventions for keeping codebases simple, coherent, and easy to evolve.
In this context, duplication includes semantically equivalent code that can be deduplicated with small, low-risk refactoring.
It is not limited to textually identical snippets.
If multiple overloads represent the same operation, choose one canonical implementation and delegate the other overloads to it.
- Overloads do not re-implement the same logic (even if the code is not textually identical), for example serialization, schema loading, or common request building.
- A reader can point to one canonical overload that contains the real implementation.
- Keep one overload as canonical.
- Rewrite other overloads to delegate to it by adapting parameters.
- External API compatibility, when the overload set is constrained by a public interface.
Prefer constructor parameters, fields, and method signatures typed as interfaces or abstract classes. Use a concrete class type only when you need an API that is not available via an abstraction.
- Constructor-injected dependencies are typed as stable abstractions, not as implementation classes.
- A class does not expose its internal implementation details in its public API via concrete types.
- Change dependency types to existing interfaces/abstract classes when available.
- If the dependency library has no suitable abstraction, wrap it with a local interface and inject that instead.
- Framework constraints where only a concrete type is injectable or proxied.
- Value types and data records where an abstraction would reduce clarity.
Do not add or keep parameters that do not change observable behavior at any call site.
- Every parameter is used either in the function body or by at least one call site for an observable behavior difference.
- Remove the parameter and simplify call sites.
- If the parameter must exist for compatibility, deprecate it and record a removal plan.
- Public API stability requirements, when the parameter cannot be removed yet.