Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lcam 976 call stateless from stateful #395

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

starswan
Copy link
Contributor

@starswan starswan commented Oct 11, 2023

https://dsdmoj.atlassian.net/browse/LCAM-976

Call stateless service (SMAS) from stateful service (MAS). This includes a translation layer between stateful integer ids and their 'more friendly' code-based ids (so EMP_INC rather than 135). This will help support future work where CMA (or something similar) invokes the eligibility platform via an HTTP API call rather than a Java call (as now)

Note to reviewer: I think this PR might remove some side-effects from the API - specifically the calculation of the partnerAnnualTotal and applicantAnnualTotal fields (but there may be others). Is there some way we can determine if these are required? There are no tests that assert this behaviour.

Checklist

Before you ask people to review this PR:

  • Tests should be passing: ./gradlew test
  • Github should not be reporting conflicts; you should have recently run git rebase main.
  • Avoid mixing whitespace changes with code changes in the same commit. These make diffs harder to read and conflicts more likely.
  • You should have looked at the diff against main and ensured that nothing unexpected is included in your changes.
  • You should have checked that the commit messages say why the change was made.

@starswan starswan force-pushed the lcam-976-call-stateless-from-stateful branch from 1685c3c to c872ebf Compare October 11, 2023 15:00
@starswan starswan force-pushed the lcam-976-call-stateless-from-stateful branch 2 times, most recently from 14aa043 to 38afcf8 Compare October 12, 2023 07:57
@starswan starswan force-pushed the lcam-976-call-stateless-from-stateful branch from 38afcf8 to c18ba55 Compare October 12, 2023 08:05
@starswan starswan force-pushed the lcam-976-call-stateless-from-stateful branch from e575bd7 to 1d4b64e Compare October 12, 2023 09:32
@starswan starswan marked this pull request as ready for review October 12, 2023 09:33
@starswan starswan requested a review from a team as a code owner October 12, 2023 09:33
@starswan starswan marked this pull request as draft October 12, 2023 10:09
@starswan starswan marked this pull request as ready for review October 12, 2023 11:04
@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

95.7% 95.7% Coverage
0.0% 0.0% Duplication

Copy link
Contributor

@Mhowell494 Mhowell494 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to have a wider conversation about this work and whether it's really necessary. It doesn't seem to enable Phase 2 in any way and there are serious risks to our production services.

this.assessmentCompletionService = assessmentCompletionService;
this.meansAssessmentBuilder = meansAssessmentBuilder;
this.assessmentCriteriaDetailService = assessmentCriteriaDetailService;
this.incomeEvidenceService = incomeEvidenceService;
this.crownCourtEligibilityService = crownCourtEligibilityService;

statelessAssessmentService = new StatelessAssessmentService(assessmentCriteriaService, meansAssessmentServiceFactory, fullAssessmentAvailabilityService);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should follow the pattern we've used for the other dependent classes. We shouldn't be initialising this ourselves when Spring can do it for us.

Copy link
Contributor Author

@starswan starswan Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose this route as the current tests are based on mocking the dependencies. If this change altered the dependencies, it would alter the tests too which felt like a risk

requestDTO.getCaseType(),
requestDTO.getMagCourtOutcome(),
incomesFromSectionSummaries(requestDTO.getSectionSummaries(), assessmentCriteria),
requestDTO.getNewWorkReason());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If formatting a method call like this, please place the ); on a new line, I think it really helps the readability.

AssessmentCriteriaEntity assessmentCriteria = assessmentCriteriaService.getAssessmentCriteria(
assessmentDate, requestDTO.getHasPartner(), requestDTO.getPartnerContraryInterest());

BigDecimal summariesTotal = calculateSummariesTotal(requestDTO, assessmentCriteria);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The answer is yes, the side effects from this method are important. See my comments in the StatelessMeansAssessment class for ideas on how to mitigate this.

private StatelessInitialResult initialResult(@NotNull Assessment assessment,
@NotNull BigDecimal totalIncome,
@NotNull Map<AgeRange, Integer> childGroupings) {
public StatelessInitialResult initialResult(@NotNull Map<AgeRange, Integer> childGroupings,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should remove the incomes parameter here and the outgoings one in the fullResult method. Instead, the methods should accept a BigDecimal total. This way, the MeansAssessmentService can call calculateSummariesTotal and then simply pass in the overall total. Then it's just a case of moving the calcIncomeTotals and calcOutgoingTotals to the execute method.

final var children = mapChildGroupings(childGroupings, criteriaEntry.getAssessmentCriteriaChildWeightings());

final var totalIncome = calcIncomeTotals(criteriaEntry, caseType, incomes);
final var service = meansAssessmentServiceFactory.getService(AssessmentType.INIT);

// assessmentStatus has to be set 'COMPLETE' otherwise the return value is null
final MeansAssessmentRequestDTO requestDTO = MeansAssessmentRequestDTO
.builder()
.childWeightings(children)
.assessmentStatus(CurrentStatus.COMPLETE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a problem. It's perfectly valid for an assessment to be set as 'Incomplete' in MAAT.

requestDTO.setEligibilityCheckRequired(crownCourtEligibilityService.isEligibilityCheckRequired(requestDTO));
MeansAssessmentDTO completedAssessment;
boolean fullAssessmentAvailable;
final var childGroupings = childGroupingsFromChildWeightings(requestDTO.getChildWeightings());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to convert this when we're just going to do the reverse in the first line of initResult & fullResult? I'd update the methods to take the child weightings instead.

Comment on lines +65 to +70
public StatelessFullResult fullResult(Map<AgeRange, Integer> childGroupings,
AssessmentCriteriaEntity criteriaEntry,
boolean eligibilityCheckRequired,
CaseType caseType,
List<Outgoing> outgoings,
BigDecimal totalIncome) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, this is too many parameters, however, there is a degree of preference involved. That said, is there a way we could reduce this? For example, moving the mapChildGroupings call? A lot are being passed in just to build the MeansAssessmentRequestDTO, can't we just build this in the execute method instead?


class MaatToStatelessDataAdapterTest {

private static final AssessmentCriteriaEntity assessmentCriteria = TestModelDataBuilder.getAssessmentCriteriaEntityWithDetails();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SonarCloud report shows we don't have full coverage of this class.

@davidread
Copy link

I think we need to have a wider conversation about this work and whether it's really necessary. It doesn't seem to enable Phase 2 in any way

@Mhowell494 it was a while ago now, but this was a key next step agreed when we met on 18th August.

The issue is that the MeansAssessmentService 'MAS' used by MAAT production makes several deep calls into what is now considered the 'stateless business logic', bypassing the new StatelessAssessmentService 'SMAS'. As discussed, it seemed a bit risky having two different ways to call methods assessmentCriteriaSevice.getAssessmentCriteria, calculateSummariesTotal, Full/InitMeansAssesmsnetService.execute and FullAssessmentAvailabilityService. Better to get rid of that duplication and get MAS to call SMAS.

Yes it forces the issue of whether the new SMAS is good enough for MAAT production. Better to do that sooner rather than later. And the development of SMAS has been reviewed and approved by your team, so hopefully not far off.

there are serious risks to our production services

The PR description raises concerns about some untested side-effects and we'd appreciate your views on a practical way forward to address.

Very happy to discuss this all on a all if that helps

@Mhowell494
Copy link
Contributor

I think we need to have a wider conversation about this work and whether it's really necessary. It doesn't seem to enable Phase 2 in any way

@Mhowell494 it was a while ago now, but this was a key next step agreed when we met on 18th August.

The issue is that the MeansAssessmentService 'MAS' used by MAAT production makes several deep calls into what is now considered the 'stateless business logic', bypassing the new StatelessAssessmentService 'SMAS'. As discussed, it seemed a bit risky having two different ways to call methods assessmentCriteriaSevice.getAssessmentCriteria, calculateSummariesTotal, Full/InitMeansAssesmsnetService.execute and FullAssessmentAvailabilityService. Better to get rid of that duplication and get MAS to call SMAS.

Yes it forces the issue of whether the new SMAS is good enough for MAAT production. Better to do that sooner rather than later. And the development of SMAS has been reviewed and approved by your team, so hopefully not far off.

there are serious risks to our production services

The PR description raises concerns about some untested side-effects and we'd appreciate your views on a practical way forward to address.

Very happy to discuss this all on a all if that helps

Thanks @davidread, I think Jude has put a meeting in to discuss tomorrow.

I do recall the discussion on the 18th and believe I raised concerns at the time with the outcome being that we agreed to explore the idea, but as far as I'm aware there's been no discussion since.

I don't believe these changes make Phase 2 any easier to deliver and it's all going to have to be refactored in the future anyway when we update the calculation logic to work with the stateless schema objects. The only thing that's really been eliminated is the call to the FullAssessmentAvailabilityService, in return for a load of new mapping logic.

I did suggest a solution to the side effects problem in my comments above, but it would mean changing several method signatures or duplicated calls to calculateSummariesTotal. There would also need to be some conditional logic to handle the fact that MAAT assessments can have a null result if they're marked as 'Incomplete' in MAS or SMAS.

From my point of view, the underlying logic that deals with the calculations is shared between both implementations and we're confident that's it's robust. So I think for me that small amount of duplication is acceptable in the short term when weighed against the risks of introducing bugs, for what I feel is a fairly limited benefit.

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.

3 participants