Beyond Public and Private: A Scale for Measuring Code Change Impact
We've all been there. You're staring at a line of code, your task is to change it, but a cold fear creeps in. You ask yourself: "What will break if I touch this?" 😨
In modern software development, this isn't a trivial question. The answer can range from "nothing" to "everything, everywhere, all at once." Our tools give us some clues, but they often don't tell the whole story. What we need is a shared vocabulary to talk about the risk of change.
Let's propose one: The Change Impact Scale (CIS).
The Illusion of Access Control
As programmers, our first line of defense against unintended consequences is access control. Every language has a system for defining a "blast radius" for our code.
- In Swift, we have a rich vocabulary:
private,fileprivate,internal,public, andopen. Each provides a clear, compiler-enforced boundary on what code can see and use other code. - In Go, the system is beautifully simple: identifiers starting with a capital letter are exported (public), while those starting with a lowercase letter are unexported (private to the package).
- Rust enforces strict privacy by default. Anything you want to expose outside of a module must be explicitly marked with the
pubkeyword. - OCaml uses interface files (
.mli) to explicitly declare the public API of a module (.ml), hiding implementation details by default.
These tools are fundamental. They are the bedrock of encapsulation and good software architecture.
But they are not enough.
Access control tells you who can call your code, but it tells you nothing about how they depend on it. A public function might be safe to change, while a private string constant might be a time bomb. This is because of hidden, implicit contracts that the compiler can't see.
Introducing the Change Impact Scale (CIS)
The CIS is a heuristic, a rule of thumb, designed to create a shared understanding of risk. It grades a change on a scale from 0 to 5, considering not just its visibility (Scope) but also the nature of its connections (Coupling Type).
CIS 0: Atomic Change (Fully Isolated)
- The Litmus Test: The change is completely invisible from the outside. No tests would need to be updated.
- Examples: Renaming a local variable inside a function, refactoring the internal logic of a
privatemethod without changing its behavior. This is the safest change you can make.
CIS 1: Controlled Internal Change
- The Litmus Test: The change's impact is contained within a single module, and your compiler is your safety net.
- Examples: Adding a parameter to an
internal(Swift) or package-private (Java/Go) function. The compiler will force you to fix every call site, leaving no room for runtime surprises.
CIS 2: Brittle Internal Change (Implicit Contracts)
- The Litmus Test: The change breaks something within your own codebase, but the compiler cannot see the connection. This is the domain of "magic strings" and runtime failures.
- Examples:
- Configuration Keys: Renaming a key in a YAML file that is read as a string in your code.
- CSS Selectors: Renaming a CSS class in a stylesheet without updating the HTML/JSX that uses it.
- Reflection: Relying on the string name of a method or class, as is common in logging or some DI frameworks.
CIS 3: Cross-Module / Service Contract
- The Litmus Test: The change breaks a contract with a "trusted peer" that you control, but which is deployed independently. Coordination is required.
- Examples:
- Changing the JSON schema of an internal microservice API. The downstream service will fail to parse the response.
- Modifying the schema of an event published to a message queue (Kafka, RabbitMQ), breaking consumer services.
CIS 4: Public Contract
- The Litmus Test: The change breaks a contract with "the outside world." You don't know all your consumers and must manage the change with versioning and deprecation policies.
- Examples:
- Removing a field from a public v1 REST API.
- Altering a
publicfunction in an open-source library you publish to npm or Maven.
CIS 5: Petrified Contract (Immutable Reality)
- The Litmus Test: The contract is so foundational that changing it would cause a catastrophic cascade of failures across an ecosystem.
- Examples: The structure of the JPEG file format, the meaning of an HTTP status code, or the syntax of a core language keyword like
if.
Standing on the Shoulders of Giants
The idea of classifying dependencies isn't new. The CIS is a practical heuristic inspired by more formal computer science concepts.
Connascence: A term coined by Meilir Page-Jones, connascence is a way to measure software dependency. It means "born together" and describes the degree to which two components must change together. There are many types, like Connascence of Name (when multiple components must agree on a name, like a function name as a string—a perfect fit for CIS 2) and Connascence of Position (when the order of values matters, like function arguments). CIS can be seen as a simplified, practical application of this powerful idea.
Coupling and Cohesion: These are foundational principles of software engineering. CIS is, at its heart, a tool for identifying and communicating high-risk forms of coupling. A CIS 5 change represents the tightest possible coupling, while a CIS 0 change is completely decoupled.
How to Use the CIS in Your Team
The real power of the CIS is in communication.
- During Code Reviews: Instead of a vague "this seems risky," you can say, "This looks like a CIS 3 change because you're modifying a shared API model. Have you coordinated with the mobile team?"
- When Planning Refactoring: "Our logs show a lot of runtime errors from CIS 2 changes. Let's prioritize refactoring these config strings into type-safe constants."
- In System Design: "Can we design this interaction to be CIS 1 by using a compiled gRPC client instead of a CIS 3 dynamic JSON contract?"
Conclusion
Access controls are essential, but they only show us part of the picture. By also considering the type of dependency, the Change Impact Scale gives us a richer, more accurate way to assess risk.
It provides a shared vocabulary that allows us to move from fear and uncertainty to informed, confident decision-making. The next time you're about to make a change, ask yourself: What's the CIS level? 👍