Skip to content

Archive

Code Quality

63 articles
Software Engineering 04 Sep 2026 8 min read

Replacing Boolean Parameters with Explicit Operations

A boolean parameter can make an API compact while making each call harder to understand. Consider this call: save(document, true) What does true mean? Overwrite an existing document? Validate before saving? Publish immediately? The caller knows only if they remember the parameter definition or inspect the function.

Software Engineering 04 Sep 2026 9 min read

Remove Duplicated Knowledge, Not Similar Code

Developers often learn the DRY principle as “do not repeat yourself.” That shorthand can lead to the wrong refactoring: two blocks look similar, so they are merged into one abstraction. Later, the two cases evolve for different reasons, and the shared abstraction fills with flags and exceptions. The more useful idea is narrower: avoid having the same piece of knowledge represented independently in multiple places. That distinction changes how you refactor. Similar code is only a clue. The real question is whether the copies encode one decision that must stay consistent, or different decisions that merely happen to look alike today.

Software Engineering 04 Sep 2026 9 min read

Parse Input into Trusted Types

A common validation problem is not that a program forgets to check input. It is that the program checks the input, keeps the same weak representation, and then has to remember what was already proved. Suppose an order accepts a quantity as an integer. The boundary rejects zero and negative values, but every later function still receives an ordinary integer. Nothing in that representation distinguishes a checked quantity from 0, -3, or an integer created somewhere else. The validation happened, but the result of that validation was not captured.

Software Engineering 04 Sep 2026 9 min read

Assertions That Expose Broken Assumptions

A program can produce the wrong result long after the code that caused the problem has run. A function corrupts an internal value, several operations accept it, and an unrelated component eventually fails. By then, the stack trace points at the consequence rather than the cause. Assertions help shorten that distance. An assertion states an internal condition that the programmer believes must be true at a particular point in the program. If the condition is false, the program reports a broken assumption immediately instead of continuing as though the state were valid.

Software Engineering 03 Sep 2026 11 min read

Using Decision Tables to Tame Complex Rules

Conditional logic often becomes difficult before it becomes large. Three or four business conditions can interact in enough combinations that a developer can no longer tell, by reading nested if statements, whether every case is covered or whether two branches contradict each other. A decision table is a compact way to make those combinations explicit. It lists the conditions that affect a decision, the meaningful combinations of those conditions, and the outcome for each combination.

Software Engineering 03 Sep 2026 7 min read

Mutation Testing for Stronger Test Suites

A test suite can execute every important line of code and still miss serious defects. Coverage tells you which code ran, but it does not tell you whether the tests would notice if that code behaved incorrectly. Mutation testing examines that gap. It makes small, systematic changes to production code and runs the tests against each changed version. If the tests fail, the mutation is killed. If they still pass, the mutation survives and points to a place where the suite may not distinguish correct behaviour from incorrect behaviour.

Software Engineering 03 Sep 2026 8 min read

Modeling Workflows with Explicit State Transitions

Many business objects have a lifecycle. An order may be created, approved, fulfilled, or cancelled. A support ticket may be open, assigned, resolved, or reopened. Problems begin when those lifecycle rules are represented only by a status field and scattered if statements. As the system grows, different code paths can start disagreeing about which changes are legal. One handler allows a cancelled order to be approved, another silently ignores the request, and a third checks a different set of statuses. The status values are visible, but the rules connecting them are not.

Python 03 Sep 2026 9 min read

Model Finite States Clearly with Python Enum

Many programs represent a small fixed set of states with plain strings: status = "paid" That looks simple, but the string carries no built-in guarantee that it belongs to the set of states your application actually supports. A typo such as "paied" is still a valid Python string. So is an unexpected value received from a file, database, message, or HTTP request.

Software Engineering 03 Sep 2026 8 min read

Designing Invariants That Make Invalid States Hard to Represent

Many software defects are not caused by complicated algorithms. They happen because the program reaches a state that should never have been possible: an order has a negative quantity, a completed job has no completion time, or a configuration contains two options that cannot be enabled together. An invariant is a condition that must remain true for a particular object, module, or operation to be valid. Designing around invariants turns assumptions into enforceable rules. The result is usually less defensive code, clearer interfaces, and failures that occur closer to their cause.

Software Engineering 03 Sep 2026 8 min read

Designing Errors for Actionable Failures

Errors are part of a program’s interface. They tell callers that an operation could not produce its promised result, but useful error handling goes further: it preserves enough meaning for the caller to decide what to do next. Weak error handling tends to fail in two opposite ways. Some code hides failures by returning defaults, logging and continuing, or catching exceptions too broadly. Other code exposes every low-level detail directly, forcing callers to understand implementation choices that should have remained private.

Software Engineering 03 Sep 2026 8 min read

Controlling Mutation with Defensive Copies

A class can expose a small, carefully designed interface and still lose control of its own state. The problem appears when the class stores a mutable value that other code can also modify. Imagine an order object that accepts a list of line items. The constructor validates the list, calculates a total, and assumes the items will now change only through the order’s methods. If the caller still holds the same list, that assumption is false. The caller can modify the list directly, bypassing validation and leaving the order’s cached total inconsistent with its items.

Software Engineering 03 Sep 2026 6 min read

Choosing Test Doubles Without Hiding Design Problems

Test doubles are useful when a test needs control over a dependency that would otherwise be slow, unpredictable, expensive, or difficult to observe. They can also make a test suite fragile when every internal interaction is replaced and asserted. The goal is not to avoid test doubles. It is to use the least powerful double that gives the test the control or evidence it needs. Start with the reason for replacing a dependency Before introducing a double, identify what makes the real dependency unsuitable for this test.

Software Engineering 03 Sep 2026 9 min read

Choosing Composition Over Inheritance for Behavior Reuse

Reusing code can create a dependency that lasts much longer than the code being reused. A common example is inheritance: a new class extends an existing class because it needs some of its behavior. The first change is convenient, but later the subclass may inherit assumptions, state, and lifecycle rules that it never wanted. Composition offers a different relationship. Instead of saying that one type is a specialized form of another, an object receives or owns another object that provides a capability. The behavior can then be replaced without changing the object’s identity.

Software Engineering 02 Sep 2026 6 min read

Feature Flags Without Permanent Complexity

Feature flags let teams separate deploying code from exposing behavior. A change can reach production while remaining disabled, then be enabled for internal users, a small percentage of traffic, or a selected customer group. That flexibility reduces release risk, but every flag also creates another possible execution path. If flags are added casually and never removed, the codebase accumulates conditional behavior that becomes difficult to reason about and test. The engineering goal is therefore not to maximize the number of flags. It is to use flags as temporary control points with explicit ownership and a planned end state.

Software Engineering 02 Sep 2026 8 min read

Code Reviews That Improve Change Quality

Code review is one of the few engineering practices that can improve a change before it reaches production while also spreading knowledge across a team. It can catch defects, expose unclear assumptions, improve maintainability, and help engineers understand parts of the system they did not write. It can also become slow and frustrating when reviewers focus on preferences, authors submit changes that are too large to reason about, or nobody is clear about what approval means.