Petar Marinov

Balancing Consistency and Innovation

Dec 28, 2025
Code Design Refactoring
4 Minutes
763 Words

Background

When reviewing code, I sometimes ask whether there are alternatives and what the potential tradeoffs are. Often, there are great ideas, followed by “but we wanted to keep it consistent with the rest of the code”.

The Value of Consistent Code

A base level of consistency is achieved by coding standards like naming conventions, formatting, and code organization. Coding standards improve readability and make code easier to understand, reason about, and collaborate on. They can be defined, enforced, and automated with tools, so they are an easy win.

More interesting, and more important, is the conceptual consistency of a codebase. Consistent abstractions, common patterns, predictable APIs, standardized error handling, and logging: these are some of the tools lowering the cognitive load. Less cognitive load means getting aware of the big picture without having to dive into details, and reduces bugs from mismatched assumptions. Familiar patterns make it easier to reason about, refactor, and extend code, and faster onboarding of new team members. A consistent codebase structure is easy to navigate and understand.

Conceptual consistency gradually emerges by identifying common problems and solutions. Once you have the comfort of consistent patterns, the danger is to stop thinking about them and treat them as rules.

Unchecked Pursue of Consistency

Demanding consistency without reasoning doesn’t bring much value. “We’ve always done it like this” is not good enough. Enforcing consistency may backfire, replacing critical thinking with compliance. It can promote copy/paste development without putting too much thought into it. Especially these days, with AI code generation, where every pattern in the code is interpreted as a requirement. It is not necessarily a bad thing since it can promote a good practice. Whether a practice is good or bad depends on the context, which is not only the surrounding code but also the nature of the business problems being solved.

As an example, imagine a “constants” class, holding various values like MaximumFileSize, DaysInYear, and RetryCount. Someone had to use a constant in two places and created the class. Someone else needed another one, and the constants class looked like a good place. In time, the constants class becomes a coupling point of totally different concepts. Trying to be consistent prevented a better solution, like moving the constants closer to their usage or grouping constants on a domain-specific basis.

Sometimes the concept we want to be consistent with becomes obsolete. Languages and class libraries evolve and get better, doing more things in better ways than before. For example, a .NET 6 source-generated logging can replace a custom wrapper, removing code and adding compile-time safety and reduced object allocation out of the box.

Another example is an established project structure kept consistent while the problems it aimed to solve changed. Imagine a service layer using repositories, where most of the services do nothing but proxy to the repository. This may happen to a project structure established early, with a limited understanding of the problem being solved, but following “best practice” or even someone’s preference. In practice, it has become an unnecessary level of indirection, followed for the sake of consistency, instead of being a useful abstraction. Or maybe this was the closest consistent pattern in the project, incorrectly chosen to be consistent with.

Finding the Right Balance

When something feels off, stop for a minute and think about it. Ask questions, look for documented decisions. Chances are that the current pattern is fine given the circumstances. Try different approaches and make sure you have a better alternative and good arguments supporting it. Maybe you have stumbled into something new that needs to be handled differently, or just something has drifted out of relevance.

Raise a discussion with your team. Don’t be harsh on the current state, remember that decisions were taken in the past with the information and assumptions at that point in time. Who knows, maybe you decided it back then.

Have in mind that changing an established pattern will introduce inconsistency for a while. Sometimes, a one-time change can be pulled off. Most of the time, it won’t be practical to do a wholesale refactoring. For example, the new approach can be used only for new development and gradually replaced elsewhere. Everyone needs to realize the long-term benefits at the cost of short-term inconvenience.

Finally, document the decision. Next time the question is raised, you’ll have the context and reasoning behind the decision. It is remarkable how quickly these details can be forgotten.

Conclusion

Consistency is a powerful tool when used deliberately. However, it can promote resistance to change and improvement if misused. To mitigate that risk, apply critical thinking, be pragmatic, collaborate, and push change when it brings improvement and reduces complexity.

Article title:Balancing Consistency and Innovation
Article author:Petar Marinov
Release time:Dec 28, 2025
Copyright 2025
Sitemap