DFE-Digital / DFE-Digital/check-performance-data

[Tech debt] Decide what the Domain project is for

Open
#402 0 comments 0 reactions 1 assignee View on GitHub

@davidgouge is already working on this.

Since Sep 8, 2026.

tech-debt
Dominant language
C#
Stars
0
Forks
1
Avg merge
19h 21m
Merged PRs (30d)
54

Description

Overview

The Domain project contains six enum files totalling 87 lines. The 24 entities live in Persistence; the behaviour lives in Application services operating on DTOs. The solution is described as clean/onion architecture, and the innermost ring is empty.

Nothing here is broken — for a service that ingests supplier files, renders GOV.UK pages and posts change requests to a queue, an anaemic model is a defensible trade. But the project name sets an expectation the code has never met, and the practical cost is that genuine domain rules end up scattered across unrelated Application classes with no obvious home. That ambiguity is how the JourneyController problem happened: when there is no clear place for a rule, a controller is as plausible as anywhere else.

This is a decision to make, not a refactor to schedule. It should not be picked up as an implementation task without the team agreeing the direction first.

Evidence

  • src/DfE.CheckPerformanceData.Domain/ — 6 files, 87 lines, all enums (CheckingExerciseType, CheckingWindowType, CountryKind, KeyStages, RequestStatus, RequestType).
  • src/DfE.CheckPerformanceData.Persistence/Entities/ — 24 entity classes.
  • src/DfE.CheckPerformanceData.Application/ — 94 interfaces, 19,568 lines.

Candidate invariants currently scattered in Application that would have a natural home in a real Domain layer: the pupil inclusion codes [401, 403, 414, 421, 431], the exercise open/closed date rule, the laestab format and normalisation, and the dataset validation stamp.

Options

  1. Enrich Domain. Promote the genuine invariants above into small types with behaviour (e.g. a Laestab value type, an InclusionStatus, a DateRange). Highest value, most effort, and only worth it if the team will keep using it.
  2. Rename to Contracts. Accept that this is layered N-tier rather than onion, rename the project accordingly, and update CLAUDE.md and docs/architecture/ to describe it honestly.

What should not happen is a third option where the name keeps promising something the code does not deliver.

Acceptance criteria

  • A decision is taken and recorded as an ADR in docs/adrs/ (which currently holds one entry).
  • CLAUDE.md and docs/architecture/ describe the architecture as it actually is.
  • If option 1 is chosen, a follow-up ticket is raised for the migration.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.