Hard-to-change packages

The problem

You open a ticket that says "change the return type of one method." Two hours later you have touched eleven files and broken four tests in packages you had never heard of before. The package has 25 incoming dependencies, and the relevant behaviour sits inside code that is already difficult to understand. Nothing about the change stays local. The package is hard to change for two reinforcing reasons: many consumers rely on it, and its internals demand careful work.

Why it matters

The packages that slow down a team are not always the most complex ones. A complex package that nothing depends on can be refactored on its own timeline. A simple but heavily depended-on package is constrained by its callers. The genuinely hard-to-change packages are where both problems collide: high fan-in from callers who cannot be notified easily, and enough internal complexity that even finding the right place to make a change takes meaningful effort. These are the packages worth investing in before a major feature push.

Where to start

Begin with Topology.

Step by step

  1. Filter for packages with high fan-in.

    Start exploring in Topology so the Workflow Wizard applies the current model's 75th-percentile Fan-in threshold and turns on Hide isolated. That keeps the widely depended-on packages without pretending one fixed number fits every model.

  2. Apply the Cyclomatic Complexity (Max) heatmap.

    Red packages contain the most complex individual code while already serving many consumers. This is the combination the workflow is looking for: difficult internals behind a widely used boundary.

  3. Inspect a candidate's coupling profile.

    Select a red package and compare fan-in, complexity, and Instability in the Metrics tab. Instability is secondary context here. A high value means outgoing dependencies dominate the package's total coupling, so a heavily consumed package may also carry broad outward dependency exposure.

  4. Open the package internals.

    After the Metrics comparison, optionally open Classes or Files inside the selected package to find which concrete internals carry the complexity. Often one or two contributors account for most of the load, giving you a more focused refactoring seam.

Interpreting results

The risk is not high fan-in alone or high complexity alone. The hard-to-change packages are where complexity meets coupling: many consumers depend on them, and their internals are difficult to understand safely. Instability does not define this shortlist and does not say that the code changes frequently. If Instability is also high, outgoing dependencies dominate total coupling, adding another sign that the package carries broad structural responsibility. Strengthen the package boundary, reduce dependencies on concrete internals, or split the package to contain the blast radius of future changes.

Export & share

With the 75th-percentile Fan-in filter, Hide isolated, and Cyclomatic Complexity (Max) still active, use Snapshot as PNG on the focused Topology view. It records the actual shortlist for a planning discussion.