Zum Hauptinhalt springen
← All posts

When No One Wants to Touch a Feature: Architecture Over Rewrite

Why a single feature can suddenly become impossible to estimate in planning poker — and how modularization and tests make it manageable again.

When a team suddenly gives only high estimates for a single feature during planning poker, it's rarely about the size of the task. It's a signal: the architecture is too tightly coupled at that point. Here's how that gets fixed — a scene from practice.

Tuesday, 9am, planning session. Everyone estimates the effort for each open task with cards, face down — then everyone reveals at once. A low number means simple, a high number means costly or unclear.

For one feature, the table was suddenly covered in high cards. The team visibly didn't want to touch it.

The reason wasn't laziness. This one feature was tangled up with everything: database, UI, interfaces, external API calls. Touching it meant risking half the system.

A round like that isn't a game. It ruthlessly reveals where a team feels the greatest risk.

My call: don't build it. Take it apart first.

We re-cut the feature along its interfaces and its testability — into five independent modules, each with automated tests from the start.

In the next round, the same feature came up again. This time: five small cards. "We don't dare touch this" had become "doable."

Nothing about the scope had changed. Only the structure.

Why these criteria matter

Modularization doesn't follow a gut feeling — it follows three criteria.

First, complexity. It shouldn't exceed a certain threshold. A common older rule of thumb put that threshold at roughly three person-days of implementation effort per unit. With AI-generated code, people tend to look at line count instead — there's no fixed reference value here on purpose, since it depends heavily on how compact the language and environment are.

Second, clear interfaces. Even where interfaces technically exist, they need to actually be used, with the related functionality placed in separate modules — recognizable by a clear boundary like an API call or a database query.

Third, and most important: testability. A unit test checks a piece of the program with a clearly specified function. If the path from input to output of a module can be described unambiguously, it can be tested. Regardless of everything else, this is the deciding factor for me: restructuring a larger module so that testable sub-modules emerge from it.

And then scalability enters the picture

Modularization also has a direct effect on performance and scalability. It's a fundamental difference whether five or five thousand users access the same database function at the same time. Blocking calls that work fine unnoticed at five users often need to be replaced with a different form of synchronization once load grows.

That shows how broad this whole subject actually is — it can't be solved with a few months of ramping up on the side. That's why we recommend bringing in the specific expertise needed, instead of building it up slowly and painfully in-house.

A module built to these criteria doesn't need to be touched again — unless the specification itself changes. It becomes a building block like a Lego brick: clearly bounded, reusable in other contexts. That archive of reusable, tested building blocks is often the real, underrated value of a development team.

Nothing about the scope of the work changes through modularization. Only whether it feels manageable or terrifying.