DFE-Digital / DFE-Digital/check-performance-data
[Tech debt] JourneyController holds domain logic and flow-specific ids
@davidgouge is already working on this.
Since Sep 8, 2026.
- Dominant language
- C#
- Stars
- 0
- Forks
- 1
- Avg merge
- 19h 21m
- Merged PRs (30d)
- 54
Description
Overview
JourneyController is 1,524 lines with 17 constructor dependencies. It is the largest hand-written file in the solution and it is a controller — against the CLAUDE.md rule that controllers must guard the request, delegate to a service, and translate the result.
It holds private static methods that are pure domain logic branching over Application types (RequestState, QuestionFlowConfig), which the rule names explicitly as belonging in Application. It also hard-codes question ids from specific flow config files, coupling a supposedly generic controller to the contents of three JSON files.
This matters beyond its line count: it is the file a new developer reads first, and the least representative example of how the team wants code written.
Evidence
Domain logic in the controller — src/DfE.CheckPerformanceData.Web/Controllers/Journey/JourneyController.cs:
| Method | Line |
|---|---|
FirstIncompleteEnquiryPage |
522 |
IncorrectGradeGap |
531 |
ResultDoesNotBelongGap |
545 |
MissingQualificationGap |
556 |
IsCohortWide |
1258 |
DetermineStatus |
1339 |
IsEvidencePageValid |
1347 |
Flow-specific constants at :43-48 — q-revised-grade, q-syllabus-code, q-missing-grade.
For scale: the next-largest hand-written file is 806 lines and the median controller is 87.
Proposed fix
- Extract an
IEnquiryCompletenessServiceintoApplication/Journey/, taking the four gap methods plusIsCohortWide,DetermineStatusandIsEvidencePageValid. These become directly unit-testable without an MVC context. - Move the flow-specific question ids out of the controller and into the flow config as typed metadata — e.g. a
rolefield on the question ("role": "revisedGrade") — so the controller looks a question up by role rather than naming its id. - Follow-up (can be a separate PR): split the results-enquiry actions (
ResultSearchPage/Post,QualificationSearchPage/Post,ConfirmResultsEnquiryAsync,EnquiryConfirmation) into their own controller.
Steps 1 and 2 should remove roughly 200 lines and several of the 17 dependencies.
Acceptance criteria
- No private method in
JourneyControllerbranches overRequestStateorQuestionFlowConfig. - No flow-config question id appears as a constant in the Web layer.
- The extracted service has unit tests covering each completeness gap.
-
QuestionFlowValidatorAlignmentTestsextended to pin the newrolemetadata against the configs. - No behavioural change to the journey — existing E2E tests pass unchanged.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.