docs: P14 design + plan for splitting the ContentService god object

Registers the next batch before implementation starts, so the design is
versioned and reviewable rather than living only on disk.

Scope: crearte-server only. content.go is 856 lines / 30 functions, the sole
outlier in internal/service (next largest production file auth.go is 234 lines;
content.go alone is 22% of the directory) and carries five unrelated
responsibility lines in one struct whose five fields are all shared repository
dependencies with no mutable internal state.

Three survey findings make the split low-risk rather than aspirational:
- the seven cross-line calls all target package-level helper functions, with
  zero method-to-method cross-line calls, so splitting creates no cross-service
  callbacks and no import cycle;
- each of the five handlers uses exactly one line's methods with zero overlap,
  so each dependency face narrows from 22 methods to its own 2-6 with no adapter;
- 11 of the 19 test construction sites only construct and never call methods,
  and a Go embedding spike (H1-H4, run in golang:1.24-alpine, vet clean)
  confirmed the promoted method set satisfies consumer-defined narrow
  interfaces — so the composite root keeps every construction site and all five
  serve.go wirings unchanged while handlers still narrow.

The survey also found ContentService.now is a dead field: zero s.now references
in the file, no test seam injecting it, while the sibling services that share
the pattern do use theirs (auth.go reads s.now(), cleanup.go has SetNow). It is
removed as part of the split rather than being assigned a line.

Two risks were falsified by measurement before designing: no code inside the
package reads ContentService's private fields (AccountService holds
repository.ContentStore, not *ContentService, so it is untouched), and the type
is never interface-ised, type-asserted, or used as a method value.

Deliberately out of scope: the 170-line Approve function (its seven phases are
mapped and logged for a later batch — one concern per batch), memory_content.go
(814 lines but a test double with zero non-test references), and handler
error-mapping dedup (92 WriteError sites but only 2 errors.Is checks, so the
duplication does not justify itself).

Verification plan: four gates in the dockerized toolchain plus structural
metrics (content.go under 120 lines, largest of the six files under 300, zero
service.ContentService references left in handlers, zero existing test files
modified) and three mutations the new architecture guard must fail on.
This commit is contained in:
2026-10-03 08:02:53 +08:00
parent 14d029e61b
commit ba1fe3ecb0
3 changed files with 450 additions and 0 deletions
+1
View File
@@ -72,3 +72,4 @@
| P11 服务端安全硬化 | `docs/specs/2026-10-02-p11-server-hardening-design.md` | `docs/plans/2026-10-02-p11-server-hardening.md`(已执行,2026-10-02:server 0.17.0 / deploy 0.7.0 / crearte 0.24.1) |
| P12 窄屏溢出修复与打磨批 | `docs/specs/2026-10-02-p12-narrow-viewport-overflow-design.md` | `docs/plans/2026-10-02-p12-narrow-viewport-overflow.md`(已执行,2026-10-02:crearte 0.25.0 / server 0.17.1 / deploy 0.7.1) |
| P13 暗色模式 | `docs/specs/2026-10-03-p13-dark-mode-design.md` | `docs/plans/2026-10-03-p13-dark-mode.md`(已执行,2026-10-03:crearte 0.26.0) |
| P14 拆分 ContentService god object | `docs/specs/2026-10-03-p14-content-service-split-design.md` | `docs/plans/2026-10-03-p14-content-service-split.md`(进行中,2026-10-03:crearte-server) |