2026-04-20-ability-center-naming-design.md 12 KB

Ability Center Naming Design

Status: Draft approved in conversation, pending user review of written spec

Goal

Define a long-term naming system for this repository so it can evolve from a single OutlookReport implementation into an ability-center that hosts multiple business capabilities. The first capability domain is exam-sprint, and within that domain the system will support multiple report types, starting with outlook and later achievement.

Core Decisions

Repository identity

  • Rename repository identity from ability-service to ability-center.
  • The repository should represent a multi-capability center, not a single service or a single report flow.

Domain identity

  • The first business capability domain is exam-sprint.
  • exam-sprint is the bounded context.
  • The stable business resource inside that context is report.
  • outlook and achievement are report types, not top-level domain names.

Resource model

  • External API centers on exam-sprint reports.
  • Internal domain centers on ExamSprintReport.
  • Report generation, storage, PDF rendering, and download delivery are implementation concerns around the report resource.

Type model

  • OUTLOOK represents the 临考突击展望报告.
  • ACHIEVEMENT represents the 临考突击成果报告.
  • New report types should be added by extending ExamSprintReportType, not by inventing a new top-level domain.

Architecture Naming Model

Top-level structure

ability-center
├── ability-center-runtime
├── ability-center-kernel
└── abilities
    └── exam-sprint
        ├── contracts
        ├── application
        ├── domain
        └── infrastructure

Module responsibilities

ability-center-runtime

Purpose:

  • Spring Boot startup
  • HTTP wiring
  • runtime configuration
  • module assembly
  • adapter entrypoints

This module should not become a place for business rules.

ability-center-kernel

Purpose:

  • cross-capability foundational abstractions
  • shared exception base classes
  • response envelope primitives
  • stable, domain-agnostic conventions

This module must not contain exam-sprint specific request, response, state, or rendering concepts.

abilities/exam-sprint/contracts

Purpose:

  • external request and response contracts
  • report type enums used by public interfaces
  • stable contract objects shared across runtime and application boundaries

This module describes interfaces, not adapters.

abilities/exam-sprint/application

Purpose:

  • use case orchestration
  • generation workflow coordination
  • dispatching and scheduling coordination
  • transaction boundaries
  • invoking domain policies and infrastructure ports

This module answers: how is a use case executed?

abilities/exam-sprint/domain

Purpose:

  • report aggregate and related value objects
  • report type policies
  • business rules and state transitions
  • repository and generation port interfaces

This module answers: what is correct in business terms?

abilities/exam-sprint/infrastructure

Purpose:

  • Azure Blob Storage implementation
  • in-memory or future persistence implementations
  • PDF generation implementation
  • template rendering implementation
  • type-specific rendering adapters

This module answers: how does the system talk to external systems?

Naming Layers

The naming stack must follow this order:

  1. business capability domain: exam-sprint
  2. stable business resource: report
  3. report type: outlook, achievement
  4. implementation concern: generation, rendering, storage, delivery

The naming stack must not follow this order:

  1. storage technology
  2. PDF generation mechanism
  3. async task mechanism
  4. current single report type

Package Naming

Root package

  • Current: cn.yunzhixue.microservice.ability
  • Target: cn.yunzhixue.ability.center

microservice should be removed from the primary package identity because it describes a deployment style, not a stable business model.

Target package layout

cn.yunzhixue.ability.center
├── kernel
├── examsprint
│   ├── contracts
│   │   └── report
│   ├── application
│   │   └── report
│   ├── domain
│   │   └── report
│   ├── infrastructure
│   │   └── report
│   └── adapter
│       └── http

Type-specific implementation packages

Type-specific rendering or handling belongs below the report capability, for example:

cn.yunzhixue.ability.center.examsprint.infrastructure.report.rendering.outlook
cn.yunzhixue.ability.center.examsprint.infrastructure.report.rendering.achievement

This keeps outlook and achievement visible where they are truly relevant, without allowing them to dominate the whole bounded context.

API Resource Design

External resource identity

Public APIs should expose the resource as report, not task.

Target paths

  • POST /api/exam-sprint/reports
  • GET /api/exam-sprint/reports/{reportId}
  • GET /api/exam-sprint/reports/{reportId}/download

Explicitly rejected public path

  • GET /api/exam-sprint/reports/downloads?storageKey=...

storageKey is an infrastructure detail and must not be a public resource lookup mechanism.

Public resource behavior

  • Clients create a report.
  • Clients query a report.
  • Clients download a report artifact when available.
  • Clients select the report type through a contract field, not through a new top-level capability path.

Public Contract Design

Top-level request

Use a stable request that supports multiple report types:

  • CreateExamSprintReportRequest

Recommended fields:

  • reportType
  • payload

Report type enum

  • ExamSprintReportType
    • OUTLOOK
    • ACHIEVEMENT

Top-level response models

  • CreateExamSprintReportResponse
  • ExamSprintReportDetailResponse
  • ExamSprintReportGenerationStatus

Recommended common response fields:

  • reportId
  • reportType
  • generationStatus
  • createdAt
  • updatedAt where applicable
  • expiresAt
  • downloadUrl
  • failureReason

Why reportId instead of taskId

taskId reveals processing mechanics. reportId reflects the business resource that the client actually owns.

Domain Model Naming

Core aggregate

  • Current direction to retire: OutlookReportTaskRecord
  • Target direction: ExamSprintReport

Repository

  • Current direction to retire: OutlookReportTaskRepository
  • Target direction: ExamSprintReportRepository

Internal identity and state naming

Recommended internal terms:

  • reportId
  • reportType
  • generationStatus
  • storageObjectKey
  • fileName
  • failureReason

If the system keeps an internal generation workflow object separate from the public report aggregate later, that internal split must still preserve ExamSprintReport as the stable business-facing root concept.

Application Layer Naming

Recommended target names:

  • ExamSprintReportController for the runtime HTTP entrypoint
  • ExamSprintReportApplicationService
  • ExamSprintReportGenerationDispatcher
  • AsyncExamSprintReportGenerationDispatcher
  • ExamSprintReportGenerationWorker
  • ExamSprintReportRetentionScheduler

The public-facing HTTP controller should not expose task in its name. Internal asynchronous and retention mechanics may still use generation, dispatcher, worker, and scheduler where that precision adds clarity.

Infrastructure Naming

Recommended target names:

  • ExamSprintReportStorage
  • AzureBlobExamSprintReportStorage
  • InMemoryExamSprintReportStorage
  • ExamSprintReportPdfGenerator
  • PlaywrightExamSprintReportPdfGenerator
  • ExamSprintReportRenderer
  • ClasspathOutlookExamSprintReportRenderer
  • ClasspathAchievementExamSprintReportRenderer

outlook and achievement should appear in infrastructure names when differentiating type-specific rendering or handler implementations.

Outlook Payload Naming

The current OutlookReport request payload should become a type-specific payload instead of a top-level API request.

Payload type

  • Current direction to retire: CreateOutlookReportTaskRequest
  • Target direction: OutlookExamSprintReportPayload

Top-level payload fields

  • reportMetadata
  • readinessOverview
  • syllabusMasteryProfile
  • pastPaperVocabularyProfile
  • highFrequencyVocabularyProfile
  • vocabularyFrequencyBands
  • sprintPlanOptions
  • diagnosticCaseStudy

Nested payload types

  • ReportMetadata
  • ReadinessOverview
  • SyllabusMasteryProfile
  • VocabularyProfile
  • DimensionScore
  • VocabularyFrequencyBand
  • SprintPlanOption
  • DiagnosticCaseStudy

Specific field decisions

ReportMetadata

  • reportVersionLabel
  • learnerName
  • targetExamName
  • sprintPeriodLabel
  • authorName

reportTitle is rejected because the current meaning is closer to a version or label than the document's actual primary title.

ReadinessOverview

  • summary
  • currentStage
  • keyInsight
  • readinessScore

SyllabusMasteryProfile

  • masteryPercent
  • diagnosis
  • recommendation
  • dimensionScores

VocabularyProfile

  • masteredWordCount
  • totalWordCount
  • masteryPercent
  • diagnosis
  • recommendation
  • sampleWords

Vocabulary profile field names

  • current examVocabulary → target pastPaperVocabularyProfile
  • current commonVocabularyMastery → target highFrequencyVocabularyProfile

commonVocabularyMastery is rejected because it mixes a vague scope (common) with a narrow metric word (mastery) while actually representing a full profile object.

VocabularyFrequencyBand

  • bandLabel
  • masteryPercent
  • targetPercent

SprintPlanOption

  • planName
  • cadenceLabel
  • focus
  • actionItems
  • expectedOutcome
  • tagLabel (recommended addition)

cycleLabel is rejected as a long-term field name because it currently mixes at least two meanings: cadence text and recommendation-style tagging.

DiagnosticCaseStudy

  • title
  • context
  • diagnosis
  • strategy
  • keyTakeaway

Naming Rules for Future Report Types

When a new report type is introduced, apply these rules:

  1. Add a new ExamSprintReportType value.
  2. Keep public resource paths unchanged under /api/exam-sprint/reports.
  3. Add type-specific payload and rendering/handling classes under the report capability.
  4. Do not invent a new top-level capability domain unless the business domain itself changes.
  5. Keep common report lifecycle naming shared across all types.

Names to Retire

The following names should be retired from the long-term primary naming system:

  • ability-service
  • microservice in the root package prefix
  • OutlookReportTask... as a primary resource family
  • taskId in public contracts
  • storageKey in public contracts
  • VocabularyModule
  • commonVocabularyMastery
  • cycleLabel as a single overloaded field
  • /api/reports/outlook/tasks
  • /downloads?storageKey=...

Accepted Long-Term Vocabulary

The long-term naming language should prioritize:

  • ability-center
  • exam-sprint
  • report
  • reportType
  • outlook
  • achievement
  • generation
  • retention
  • storage
  • renderer
  • kernel

Migration Guidance

This design is about naming direction, not implementation sequencing. The migration can happen incrementally, but every incremental step should converge on the same final vocabulary:

  1. rename repository and root identifiers
  2. establish module layout and package roots
  3. replace public API resource naming
  4. replace public contract naming
  5. replace domain and application naming
  6. move type-specific concepts under the report type model

No intermediate rename should introduce a second temporary vocabulary that conflicts with this target system.