Chapter 10: Anti-Corruption Mechanisms
2026.08.10Prologue: The Law of Entropy Increase and the Destiny of Software
The second law of thermodynamics, the law of entropy increase, tells us a harsh universal truth: in an isolated system, disorder (entropy) always tends to increase. A drop of ink in a glass of clear water will eventually turn it into a uniformly diluted ink solution, never the reverse -- it will never spontaneously separate back into clear water and the ink droplet. Living things can maintain their highly ordered structures only because they are open systems, constantly absorbing energy from outside to resist entropy increase.
Software systems are no exception to the fate of entropy increase. Every requirement change, every emergency bug fix, every new team member joining, is like a tiny perturbation, injecting new "disorder" into the system. Without a continuous, active input of "negative entropy," any well-designed system will, over time, inevitably drift toward decay and chaos.
The refactoring we performed in Chapter 9 was a large-scale injection of "negative entropy." We expended enormous energy to restore a chaotic system to a relatively ordered state. But this is far from enough. If we want this order to be lasting, we must transform this one-time "deep cleaning" into a daily, institutionalized "housekeeping habit."
Anti-corruption mechanisms are the "housekeeping habits" and "immune system" we design for our software systems. They are no longer the personal skill of a heroic architect, but a set of simple yet profound rules and cultures woven into the team's daily workflow.
In this chapter, we will explore the two most core anti-corruption mechanisms:
- At the code level, we will establish a new set of Code Review standards, acting like a sharp "code doctor" that can identify and eliminate complexity "cancer cells" as soon as they appear.
- At the team collaboration level, we will learn how to build and maintain a "Concept Dictionary" with product managers, eliminating the vague language that leads to "conceptual compression" at the source of requirements.
Our goal is to make resisting software decay shift from "passive repair" to "active prevention," becoming the second nature of every team member.
Section 1: New Code Review Standards -- Ban New Interpretive ifs, Mandate New Descriptive columns
Code Review is the last and most important line of defense for ensuring code quality in the software development process. However, traditional Code Review often focuses too much on "tactical" aspects like code style, naming conventions, algorithm efficiency, or design patterns. It neglects the more profound "strategic" issue for the long-term health of the system -- the boundary between data and logic.
To establish effective anti-corruption mechanisms, we must "upgrade" the standards of Code Review. We are no longer satisfied with code that "looks beautiful"; we demand code that "grows healthily." To this end, we propose a new standard that is simple, counterintuitive, yet extremely powerful:
"Ban new interpretive ifs; mandate new descriptive columns."
Let's delve into this seemingly radical rule.
What is an "Interpretive if"?
An interpretive if is an if statement whose judgment condition relies on data that cannot directly and clearly express the business intent. To understand the meaning of this if, the reviewer must perform a "translation" or "interpretation" in their mind.
These if statements are the direct manifestation of "conceptual compression" in code -- the "precancerous lesions" of system decay.
Common types of "interpretive ifs":
Magic value judgments:
// The reviewer must consult documentation or comments to know what type=30 means if (order.getType() == 30) { // ... apply platform subsidy ... }- Root of decay: The business concept of "billions subsidy order" has not been given due respect in the data model. It has been compressed into the number
30, which has no business meaning. - Review comment: "What business meaning does
30have here? Should we add abilling_modelfield to theOrdertable, using a clear value likePLATFORM_SUBSIDYto express this?"
- Root of decay: The business concept of "billions subsidy order" has not been given due respect in the data model. It has been compressed into the number
Combined state judgments:
// The reviewer must simultaneously understand the `status` and `is_vip` fields and infer their combined meaning if (order.getStatus() == 2 && order.isVip()) { // ... enable VIP fast shipping ... }- Root of decay: The independent business fact of "whether the order is eligible for fast shipping" has not been data-ified. The code is forced to "infer" this fact at runtime by "computing" a combination of multiple fields.
- Review comment: "'Fast shipping eligibility' seems like an independent business concept. Could we calculate this eligibility at order creation time and persist the result in a new boolean field
is_eligible_for_fast_shipping? That way, theifhere could be simplified toif (order.isEligibleForFastShipping())."
Hard-coded judgments based on external context:
// The reviewer needs to know that user_id=88888 is the CEO; this knowledge exists outside the code if (user.getId() == 88888) { // ... skip marketing push ... }- Root of decay: The attribute "whether the user needs do-not-disturb" has not been modeled.
- Review comment: "This is an 'exceptional case' logic. We should introduce a user tagging mechanism, tag the user with
DO_NOT_DISTURB, and then checkuser.hasTag("DO_NOT_DISTURB")here."
The common characteristic of "interpretive ifs" is that they force the reviewer and future maintainers to play the role of "code detective." They must look at the if statement as a "crime scene" and work backward to infer the business scenario in the author's mind at the time. This is a huge, continuous cognitive drain.
What is a "Descriptive column"?
The counterpart to the "interpretive if" is our antidote -- the descriptive column.
A descriptive column is a database field (or object property) whose name and value can directly, clearly, and unambiguously describe an independent business fact.
Characteristics of a "descriptive column":
Name as documentation: The field name itself explains its business meaning.
- Bad:
type,status,flag - Good:
billing_model,shipping_method,is_payment_locked
- Bad:
Value as fact: The field's value is a direct manifestation of business language, typically using enums or booleans rather than magic numbers that need "translation."
- Bad:
1,2,30 - Good:
PENDING,CONFIRMED,FAILED;true,false
- Bad:
Single responsibility: One field describes only one independently changing dimension.
- Bad:
order_type=10simultaneously represents "enterprise customer" and "monthly billing model." - Good:
customer_type='CORPORATE'andbilling_model='MONTHLY'are two independent fields.
- Bad:
The core of our new Code Review standard is a "power shift": We no longer trust the complex judgment logic in code; we only trust the descriptive facts clearly recorded in the database.
Implementing the New Standard in a Code Review Conversation
Let's look at a simulated Code Review scenario to experience how this new standard works.
Developer's submitted code:
Requirement: For orders originating from the "campus channel," if the amount exceeds 100 RMB, shipping is free.
Code implementation
ShippingFeeCalculator.java:public Money calculateShippingFee(Order order) { // ... other logic ... // New logic if ("CAMPUS_CHANNEL".equals(order.getSource()) && order.getAmount().isGreaterThan(100)) { return Money.ZERO; } // ... default shipping fee logic ... return new Money(10); }
A traditional Code Review might comment:
- "The magic number
100should be defined as a constant." - "
order.getSource()might benull; you should add a null check." These comments are not wrong, but they are at the "tactical" level and don't address the root cause.
A Code Review comment based on the new standard:
"Hi [Developer], thank you for your submission. I noticed there's a new interpretive
ifhere. At runtime, it 'infers' a new business fact -- 'whether this order is free shipping' -- by combining information from the two dimensionssourceandamount.According to our 'conceptual decompression' principle, we should avoid this kind of real-time 'fact inference' in code. Could we consider 'migrating' this logic to the data level?
Suggested approach:
Add a new, descriptive
columnto thet_ordertable:shipping_fee_waiver_status(enum:NONE,APPLIED,NOT_APPLICABLE), or a simpleris_shipping_fee_waived(boolean).Move this
ifjudgment logic to the core order creation or update flow (e.g.,OrderService). There, calculate once whether this order should be free shipping, and persist the result to this new field.Then, the code in
ShippingFeeCalculatorcan be simplified to:if (order.isShippingFeeWaived()) { return Money.ZERO; }The benefits of this approach are:
- Logic made explicit: The important business fact of 'free shipping' is no longer hidden in a piece of code, but becomes part of the order data that anyone can query directly.
- Separation of concerns:
ShippingFeeCalculator's responsibility is simplified to just reading a determined state, while the complex logic of calculating this state is centralized inOrderService, a more appropriate location.- Better performance: We avoid repeating this judgment every time
calculateShippingFeeis called.What do you think of this approach? It might make your change scope slightly larger, but it will make our system healthier in the long run. We can discuss the implementation details together."
See? This Code Review conversation is no longer about nitpicking code style, but a deep discussion about system architecture and data models. The reviewer plays the role of an "architecture guardian" concerned with the system's long-term health.
Challenges and Strategies for Adopting the New Standard
Undoubtedly, pushing such a "radical" standard will encounter resistance.
- Resistance from developers: "I'm only changing one line of code, and you're asking me to change the database and the core Service! That's too much trouble!"
- Resistance from project managers: "Why does this small requirement take so long? We need it to go live next week!"
Response strategies:
- Step by step, build consensus: Don't try to force it overnight. Start with internal tech sharing sessions, explaining the harm of "conceptual compression" and the benefits of "data decompression." Use the cases from this book to help everyone empathize.
- Start with "critical areas": Choose 1-2 of the most core and complex modules in the system (e.g., orders, users), and announce that the new standard will be strictly enforced in these modules. Be more lenient in non-core areas.
- Reward "good design," not "fast code": In the team's performance evaluations and technical recognitions, publicly praise cases where complex logic was eliminated through excellent data modeling. Shift the team culture from "fastest feature delivery" to "lowest future maintenance cost."
- Provide "scaffolding" support: If developers are required to add new configuration tables, the team should provide a generic, easy-to-use "dynamic configuration service framework" so they can easily create and manage these tables, rather than starting from scratch every time.
- Executive support is crucial: Explain the long-term value of this methodology to your technical director or CTO. When project scheduling conflicts with architectural principles, there needs to be a higher-level authority to support "doing the right thing, not the easy thing."
This new standard is the first and most effective barrier against code decay. It acts like a filter, forcing all "business complexity" attempting to enter the system to be separated: simple, descriptive facts are allowed into the database; complex, interpretive logic is kept out of the code, or "digested" into simpler forms.
Persistently enforce this standard, and over time, your codebase will undergo visible changes: the number of if/else statements will significantly decrease, cyclomatic complexity will continuously drop, while the database tables and fields will become richer and more expressive. Your system will evolve from a relic that requires "archaeology" to understand, into a clear, easy-to-read "business storybook."
Section 2: Team Collaboration -- How Product Managers and Developers Unify the "Concept Dictionary"
The root of code decay often lies not in the code itself, but at the source of the requirements -- vague, inconsistent, compressed business concepts. If product managers and developers have differing understandings of core business concepts from the start, no matter how strict our Code Review standards, we cannot prevent chaos.
A typical scenario:
- Product manager: "We need a 'premium order.' This type of order gets priority shipping and dedicated customer service."
- Developer A (responsible for orders): They understand "premium order" as a
typeof order and add a value5toorder_type. - Developer B (responsible for customer service): They understand "premium order" as a reflection of user status, so they add a check
if (user.isVip())in the customer service assignment logic. - Developer C (responsible for warehousing): They understand "premium order" as a service level, so they add a
priorityfield in the shipment.
The vague concept of "premium order" has been "translated" into three completely different technical implementations in three different places. The system's consistency was already compromised the moment the requirement was proposed.
To solve this problem at its root, we need a collaboration tool that bridges the gap between business and technology -- the "Unified Concept Dictionary," which is also a practical application of the "Ubiquitous Language" idea from Domain-Driven Design (DDD).
What is a "Unified Concept Dictionary"?
A "Unified Concept Dictionary" is a living document, jointly created and maintained by all project stakeholders -- product, development, testing, design, etc. It aims to provide a single, authoritative, unambiguous definition for every important, potentially ambiguous business concept in the project.
The form of this dictionary can vary: a shared Wiki page, a Confluence space, or even a Markdown file in the code repository. The core lies not in the form, but in the content and the collaborative culture it represents.
A good dictionary entry should include the following parts:
- Concept Name: The same word used by both business and technical people. For example: "Order Fulfillment Process."
- Aliases: Other names this concept might have had historically or in different departments. For example: "Shipping Process," "Outbound Process." (Recording aliases helps eliminate communication misunderstandings.)
- One-Sentence Definition: Use the simplest, non-technical language to describe the core of this concept. For example: "Refers to all states and operations an order goes through from successful payment to reaching the user."
- Attributes/Dimensions: What independent attributes make up this concept? This is the application of "conceptual decompression" at the requirements stage.
fulfillment_method:Own-warehouse shipping,Supplier direct shipping,Store pickupdelivery_priority:Standard,Express,Specialinventory_strategy:Pre-reserve stock,Real-time deduction
- Behaviors/Operations: What operations can be performed on this concept? For example: "Start picking," "Packing completed," "Handed off to courier."
- Business Rules: Important business constraints related to this concept. For example: "Only orders with 'Express' priority can be packed at night."
- Invariants: Core constraints that must remain unchanged under any circumstances. For example: "An order cannot be simultaneously in 'Shipped' and 'Canceled' states."
- Questions and Clarifications: Record valuable questions raised during discussions and the final clarifications. For example: "Q: For 'Supplier direct shipping' orders, does our system still need to deduct inventory? A: No, inventory is managed by the supplier's system."
How to Build and Maintain the Dictionary?
Building a dictionary is not a one-time project, but a continuous process that integrates into daily work.
Kickoff Workshop
- At the start of a project, gather all core stakeholders for a 2-4 hour "concept storming" workshop.
- Goal: Identify the 5-10 most core business concepts in the project and create the first version of dictionary entries for them.
- Method: Use visual collaboration methods like "Event Storming," where everyone puts sticky notes on the wall to collectively map out business processes, naturally surfacing core concepts, commands, and events.
Integrate into Daily Requirement Reviews
- In every requirement review meeting, make the "Concept Dictionary" a mandatory agenda item.
- When the product manager introduces a new feature, the team should consult the dictionary together and ask these key questions:
- "Does this new feature introduce any new business concepts? If so, we need to create a dictionary entry for it."
- "Does this new feature modify or extend the definition of an existing concept? If so, we need to update its dictionary entry."
- "Does the terminology used in the requirements document (like 'special order') have a more precise definition in our dictionary? Should we use 'order with fulfillment method of store pickup' instead of this vague term?"
Reference in Code Review
- Integrate the "Concept Dictionary" with the code review process.
- When a developer uses a variable or class name that conflicts with the dictionary's definition, the reviewer can directly link to the dictionary and comment: "According to our Concept Dictionary, the 'fulfillment process' should be named
FulfillmentProcess, notShippingFlow, to maintain consistency." - This makes the dictionary an objective basis for code quality, not just a "suggestion document."
Developers as Contributors
- Developers are often the first to discover conceptual ambiguity or conflict during implementation.
- Empower developers: When they find a problem, encourage them not to simply "guess" an implementation, but to proactively initiate a "clarification request" in the dictionary, @mentioning the product manager and relevant parties for discussion and definition.
- This creates a virtuous feedback loop: Vague requirements -> Developer's question -> Team clarification -> Dictionary update -> Clear implementation.
The Transformation Brought by a Unified Dictionary
When a team genuinely practices the "Unified Concept Dictionary," the transformation it brings is profound:
- Communication costs drop dramatically: When everyone uses the same language, misunderstandings and rework are greatly reduced. The product manager's requirements document becomes as clear as a "system specification sheet."
- "Conceptual compression" is stopped at the source: By carefully decomposing concept "attributes/dimensions," we complete the most important "conceptual decompression" work at the requirements stage. What the developer receives is a requirement that has been clearly deconstructed, not a big ball of mud.
- Data model and business stay isomorphic: Because the naming and structure of the code originate from the dictionary's definitions, the resulting data model and code will naturally and highly consistently reflect the true structure of the business. This "isomorphism" is the foundation of long-term system maintainability.
- Newcomer onboarding accelerates: The "Concept Dictionary" becomes the "best introductory guide" for any new member (whether product, development, or testing) to understand the full landscape of the business. It is more authoritative and systematic than any outdated documentation or scattered verbal handovers.
Building and maintaining a "Unified Concept Dictionary" requires investing extra time and effort. It demands that the entire team, especially product managers, change their way of working. But this investment is the necessary cost of building a healthy software system that can resist entropy increase. It is buying the most expensive and worthwhile "communication clarity insurance" for the future of the entire project.
Chapter Summary: From "Firefighting" to "Fire Prevention"
In this chapter, the final one of this book, we explored how to move from "one-time refactoring" to "sustained health," building powerful "anti-corruption mechanisms" for our system.
We deeply recognized that software decay is an inevitable trend under the law of entropy increase. To fight this trend, we need to shift from passive "firefighting" to active "fire prevention." To this end, we proposed two core mechanisms at two levels:
At the code level, we established a new Code Review standard: "Ban new interpretive ifs; mandate new descriptive columns."
- This standard forces us to scrutinize every new logical judgment, challenging the bad habit of trying to "infer" business facts in code.
- It is an institutionalized practice of "conceptual decompression," forcibly migrating business logic from volatile code to stable data, thereby continuously reducing the system's cognitive complexity.
At the team collaboration level, we advocated for building and maintaining a "Unified Concept Dictionary."
- This "living document" becomes the bridge spanning the gap between business and technology, ensuring all project stakeholders speak the same "ubiquitous language."
- It "decompresses" and clarifies vague, compressed business concepts at the source of requirements, fundamentally eliminating design flaws caused by misunderstanding.
These two mechanisms -- one acting on "implementation," the other on "source" -- together form a powerful "anti-corruption closed loop." They transform the philosophy of resisting complexity from the individual heroism of a few architects into a collective discipline woven into the daily work of the entire team.
Book Conclusion: Data is the Boundary, Redundancy is Wisdom
Thus, we have completed the entire journey of "Data as the Boundary: Refactoring Software Complexity."
We began with a counterintuitive assertion: for the sake of code simplicity and maintainability, we must embrace data redundancy.
We established a core metaphor -- "conceptual compression and decompression" -- using it to re-examine the software complexity we take for granted.
- At the micro level, we learned how to use "dimension decomposition" and "rule data-ification" to eliminate "universal fields" and "exceptional case logic."
- At the meso level, through the "Snapshot Pattern" and "separation of concerns," we introduced the "time" dimension into our data, resolving the confusion between "current state" and "historical intent."
- At the macro level, using the "Double-Ledger Pattern" and "System Reconciliation Theory," we established trust and eventual consistency across unreliable distributed boundaries.
- Finally, at the action level, we provided a safe, reliable refactoring roadmap and a set of team collaboration mechanisms to resist future decay.
Running throughout the book is a simple yet profound thread: drive complexity out of code, and let it return to its rightful place -- data.
We no longer pursue storing information with the fewest fields and the most normalized structures, because we deeply understand that in the economic model of modern software engineering, one hour of an engineer's "cognitive cost" is far more expensive than a terabyte of storage cost.
The "redundancy" we advocate is not blind data duplication, but a strategic, intentional "conceptual redundancy" in exchange for logical clarity.
- One extra field means one less
if/elsethat needs "translation." - One extra table means an independent business concept gets an independent, clear "home."
- One extra record means retaining an immutable "fact copy" for reconciliation in an unreliable world.
Data is the slowest-changing, most stable part of a system. Code is volatile and fragile. A healthy system should have a rich, descriptive, rock-solid data foundation, and a thin, generic, execution-only logic code layer.
Data defines the boundaries of business. Data should also be our ultimate boundary against complexity.
May the ideas and tools provided in this book become your powerful weapons against software entropy increase and system complexity refactoring. May you no longer be a confused digger at a "code archaeological site," but an "architect" capable of building clear, beautiful, evolvable systems with the most solid brick -- data.
The journey ends here, but your own journey of refactoring your system has just begun. Good luck.