Module & Package Structure
Grouping by feature or by layer, what each does to change locality, and why cycles are a reasoning problem before they are a build problem.
A package is a claim about what changes together. Grouping by domain, feature or capability makes that claim; grouping only by technical type makes no claim at all.
controllers / services / repositories. It is genuinely good at cross-cutting technical change and at being guessable, and it scatters every feature across every folder.
orders / payments / users, each with its own layers inside. Requirement-shaped change becomes local, and shared concepts lose their obvious home.
One folder per use case, containing everything that use case needs. Change locality is close to maximal, and shared concepts have nowhere obvious to live.
A depends on B depends on C depends on A. What breaks is reasoning first, then initialisation order, then testability, and only last the build.
Move the shared concept, invert a dependency, introduce an interface — or merge two modules that were never really separate. The last one is the most under-used fix.
Depend toward the things that change less often than you do. It is a statement about rates of change, not about which folder sits lower in a diagram.
How big should a module be? Big enough that a likely change fits inside it, small enough that one person can hold it. "As small as possible" is not an answer to either question.