line

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

The "Set Discount" technique improves code quality by grouping related mutable properties into a single state object rather than allowing them to be updated individually. By restricting state changes through a controlled interface, developers can prevent inconsistent configurations and simplify the lifecycle management of complex classes. This approach ensures that dependent values are updated atomically, significantly reducing bugs caused by race conditions or stale data.

The Risks of Fragmented Mutability

When a class exposes multiple independent mutable properties, such as isActive, minImportanceToRecord, and dataCountPerSampling, it creates several maintenance challenges:

  • Order Dependency: Developers might accidentally set isActive to true before updating the configuration properties, causing the system to briefly run with stale or incorrect settings.
  • Inconsistent Logic: Internal state resets (like clearing a counter) may be tied to one property but forgotten when another related property changes, leading to unpredictable behavior.
  • Concurrency Issues: Even in single-threaded environments, asynchronous updates to individual properties can create race conditions that are difficult to debug.

Consolidating State with SamplingPolicy

To resolve these issues, the post recommends refactoring individual properties into a dedicated configuration class and using a single reference to manage the state:

  • Atomic Updates: By wrapping configuration values into a SamplingPolicy class, the system ensures that the minimum importance level and sampling interval are always updated together.
  • Representing "Inactive" with Nulls: Instead of a separate boolean flag, the policy property can be made nullable. An inactive state is naturally represented by null, making it impossible to "activate" the recorder without providing a valid policy.
  • Explicit Lifecycle Methods: Replacing property setters with methods like startRecording() and finishRecording() forces a clear transition of state and ensures that counters are reset consistently every time a new session begins.

Advantages of Restricting State Transitions

Moving from individual property mutation to a consolidated interface offers several technical benefits:

  • Guaranteed Consistency: It eliminates the possibility of "half-configured" states because the policy is replaced as a whole.
  • Simplified Thread Safety: If the class needs to be thread-safe, developers only need to synchronize a single reference update rather than coordinating multiple volatile variables.
  • Improved Readability: The intent of the code becomes clearer to future maintainers because the valid combinations of state are explicitly defined by the API.

When designing components where properties are interdependent or must change simultaneously, you should avoid providing public setters for every field. Instead, provide a focused interface that limits updates to valid combinations, ensuring the object remains in a predictable state throughout its lifecycle.