Layered architecture heuristics

Domain

Application

core logic
business rules

algorithms

 

orchestration
workflow

glue

Write code in the domain layer to keep use cases thin

const getUserCdaMatchingTrial = ({
  user,
  trial,
}: {
  user: SiteUser;
  trial: Trial;
}) =>
  pipe(
    user.cdasList,
    ReadonlyArray.findFirst(cda => cda.sponsorId === trial.sponsorId),
    TaskEither.fromOption(() =>
      Failure.unexpected(
        `No CDA has been generated for user ${user.id} and trial ${trial.id}`,
      ),
    ),
    TaskEither.map(userCda => ({ userCda, user })),
  );

🙅‍♂️

export const addResearchSpecialtyToFacility = ({
  name,
  numberOfRecentTrials,
  facilityId,
  facilityRepository,
  timeService,
  authorizationService,
}: {
  name: ResearchSpecialty['name'];
  numberOfRecentTrials: ResearchSpecialty['numberOfRecentTrials'];
  facilityId: SiteId;
  facilityRepository: SiteRepository;
  timeService: TimeService;
  authorizationService: AuthorizationService;
}): TaskEither.TaskEither<
  UnexpectedFailure | ForbiddenFailure | UnauthorizedFailure,
  { facility: Site; researchSpecialty: ResearchSpecialty }
> =>
  pipe(
    authorizationService.checkCanUpdateFacility(facilityId),
    TaskEither.map(facility =>
      facility.addResearchSpecialty({
        name,
        numberOfRecentTrials,
        timeService,
      }),
    ),
    TaskEither.chainFirstW(({ facility }) =>
      facilityRepository.store(facility),
    ),
  );

👍

Call domain methods, not application use cases

export const createRandomTrialPreferencesForUser = ({
  repositories,
  services,
}: {
  repositories: Repositories;
  services: ServicesWithAuthorizationService;
}) => (user: SiteUser) =>
  saveTrialPreferences({
    facilityId: user.facilityId,
    answers: trialPreferencesAnswersFactory({
      trialPhases: answerWithAdditionalInformationFactory({
        answer: Option.some([TrialPhase.I]),
      }),
    }),
    ...repositories,
    ...services,
  });

🙅‍♂️

Call domain methods, not application use cases

const trialPreferences = trialPreferencesFactory({
  answers: trialPreferencesAnswersFactory({
    trialPhases: answerWithAdditionalInformationFactory({
      answer: Option.some([TrialPhase.I]),
    }),
  })
});
await trialPreferencesRepository.store(trialPreferences)();

👍

Layered architecture heuristics

By bastoche

Layered architecture heuristics

  • 123