Modernization starts with a safety baseline
Modernizing a legacy module does not begin with a rewrite. First, record how the module behaves today: its inputs, observable outputs, side effects, integrations, and failure paths. A baseline protects against silently changing the contract under the guise of a technical improvement.
A baseline is not a claim that current behavior is correct. It is a recorded comparison point that can be reviewed after each small step and separately compared with business expectations.
What belongs in the baseline
| Layer | What to record | Evidence anchor |
|---|---|---|
| Contract | public inputs, outputs, errors, and messages | API, public methods, integration contract |
| State | state changes, writes, events, and timestamps | tests, persistence code, logs |
| Dependencies | external clients, configuration, and feature flags | imports, config, environment, callers |
| Checks | existing tests, build, static checks, and manual scenarios | command + actual result |
| Recovery | rollback point, stop condition, and decision owner | Git baseline, runbook, review decision |
Invariants and characterization candidates
- the external API and result format do not change without a separate scope decision;
- error codes, messages, and important side effects remain consistent;
- the operation order is preserved when it affects money, data, or retry behavior;
- each characterization candidate has a concrete input, observable output, and evidence anchor;
- unknown behavior is marked as unknown rather than filled in with an assumption.
Preparation sequence
- Choose one module or business flow that belongs in the modernization slice.
- Read the current-state map, tests, configuration, callers, and external boundaries.
- Describe inputs, outputs, side effects, failure paths, and invariants.
- Run available focused checks, or mark them unknown if they cannot be run.
- Save the baseline and rollback point.
- Ask a reviewer to check whether the baseline describes actual behavior rather than the desired architecture.
When you must not move on to changes
Do not move on to refactoring if the scope covers several unrelated flows, there is no way to observe the result, or it is unclear who makes the business decision. Missing safety net is a reason to collect evidence first, not a reason to make the patch larger.
Rollback must be a practical action: a clear checkpoint, a bounded diff, and a check that returning does not leave partially moved state.
Canonical lesson source · JavaRush
Open JavaRush material