Skip to content

Eliminate three feature-to-feature dependencies - #81

Merged
AhmadKharfan merged 2 commits into
developfrom
refactor/eliminate-feature-edges
Jul 29, 2026
Merged

Eliminate three feature-to-feature dependencies#81
AhmadKharfan merged 2 commits into
developfrom
refactor/eliminate-feature-edges

Conversation

@AhmadKharfan

Copy link
Copy Markdown
Owner

Why

Five feature modules depended directly on each other's implementations. That is the coupling this whole migration exists to remove: it means a feature cannot be built, tested or reasoned about without pulling in another feature's internals, and it is what the boundary check currently has to tolerate through a baseline.

This removes three of the five, each by the shape that actually fits it rather than by applying one pattern everywhere.

What changed

:feature:editor no longer depends on :feature:terminal. The editor's bottom panel now takes a terminalContent slot, and :app fills it with EditorEmbeddedTerminal. The editor describes where a terminal goes; the host decides which terminal. This needed no interface, no module and no DI lookup — for a single composable, an api module would have been ceremony.

New :feature:git:api module, holding the two things other features actually consume:

  • GitPanelApi — the panel's composable contract, previously declared in the same file as its implementation
  • gitErrorMessage — the git-exception-to-message mapper, pure Kotlin over a :domain type

:feature:editor and :feature:projects now depend on :feature:git:api instead of :feature:git. The implementation, GitPanelApiImpl, stays in :feature:git and is bound in :app.

The api module declares api(projects.domain) rather than implementation, because GitDiffTarget and GitException appear in its public signatures. Previously consumers only compiled because they happened to declare :domain themselves.

Boundary baseline reduced from 5 entries to 2. The check reported each entry as stale once its edge disappeared, and each was then deleted.

Behavior

No behavior change. The terminal renders in the same place with the same arguments; the git panel and error mapper are the same code reached through a contract instead of an implementation.

Scope

Two edges remain, both deliberately left for follow-ups because they need design rather than mechanical work:

:feature:editor:feature:buildrun. Thirteen symbols cross this boundary, and only one of them is an interface. Extracting it means auditing the full type closure first — the models are spread across four files, and RunTargetResolver is behaviour rather than contract, so it should move behind BuildRunApi rather than be exported alongside it.

:feature:settings:feature:git. Settings imports git's internal auth plumbing: GitAuthController, GitHubAuthDialog and their state and action types. This one should not be solved by exporting those types. Settings is not asking git to perform an operation — both features reuse a shared auth capability, and the honest fix is to extract that capability (or let settings own its account UI over the existing :domain repositories). Exporting the current prompt state would bless the accidental coupling, and it would drag :designsystem into a contract module.

Both remain in the boundary baseline, so neither can grow while it waits.

Tests

  • 714 tests passing, 0 failures.
  • The GitAuthController characterization tests added earlier are what will make the settings/git split safe when it happens.

Verification

From a clean worktree at the branch tip:

  • ./gradlew test detekt verifyModuleBoundaries :app:assembleDebug — BUILD SUCCESSFUL
  • 714 tests, 0 failures
  • Boundary report: 119 project dependencies checked, 2 baseline entries, 0 violations

Not verified: the terminal panel and git panel render correctly in the running app. The wiring is unchanged and the arguments are identical, but this was not exercised on a device. Worth a pass over editor → bottom panel → terminal tab, and editor → git panel → diff.

Note on the detekt baselines: gitErrorMessage's complexity and GitPanelApi.Panel's parameter count were already baselined in :feature:git. Those two entries were moved to the new module's baseline rather than regenerated, so no other finding is absorbed silently.

@AhmadKharfan
AhmadKharfan merged commit c714ae8 into develop Jul 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant