https://www.youtube.com/watch?v=AHSHjCVUsu8
위의 밋업 동영상의 내용을 요약한 글이다.
세번째 발표를 두 번째에 작성
팀 스파르타 이동현 주관 발표
아키텍쳐는 견고해야 한다. ( 수정 과 삽입이 용이해야함 )
고수준의 의존성 방향을 지양해야함.
기존 Layered Architecture
각 단계가 서로에게 의존 함.
=> 기존 Layered Architecture 에서 의존성을 역전시킴!
=> 외부에 의존하지 않는 도메인 로직을 가질 수 있음!
핵사고날 아키텍쳐는 기본적으로 외부 & 내부 존재
내부는 도메인 계층으로 , 순수 비즈니스 로직 캡슐화 한 영역
외부는 기존 아키텍쳐 에서 , 도메인 영역 분리한 영역
Port / Adapter Pattern
Infrastructure 나 Interface 에 영향 받지않는 비즈니스 도메인 코드 작성 할 수 있음.
export type Applicants = any;
export class Recruiter {
constructor(
public userId : string,
public name : string,
public email : string,
public availableApplicants : Applicants[],
)
{}
viewResume(applicant:Applicant){
applicant.clickNumbers +=1;
}
saveResume(applicant:Applicant){
applicant.isSaved = true;
}
sendInterviewRequest(applicant:Applicant){
applicant.status = 'interview';
}
}
import { viewResumseRespDto } from '../../adapter/in/web/dto/response/viewResume-response-dto';
import { saveResumeRespDto } from '../../adapter/in/web/dto/response/saveResume-response-dto';
import { sendInterviewRequestRespDto } from '../../adapter/in/web/dto/response/sendInterviewRequest-response-dto';
export interface ApplicantLoadInPort {
viewResume() : Promise<viewResumeRespDto>;
saveResume() : Promise<saveResumeRespDto>;
sendInterviewRequest() : Promise<sendInterviewRequestRespDto>;
}
export interface IRecruiterRepository {
findRecruiterById(_id : ObjectId) : Promise<Recruiter>;
findApplicantById(_id : ObjectId) : Promise<Applicant>;
updateRecruiter(recruiter : Recruiter);
}
export class ApplicantService implements ApplicantLoadInPort {
constructor(
@Inject(Logger) private readonly logger : LoggerService ,
@Inject(ApplicantPersistenceAdapter) private readonly applicantLoadPort : ApplicantLoadPort ,
@Inject(ApplicantStatusPersistenceAdapter) private readonly applicantStatusLoader : ApplicantStatusLoader,
@Inject(InterviewPersistenceAdapter) private readonly interviewPersistenceAdapter : InterviewPersistencePort)
{}
async findApplicant(resumeId) : Promise<Applicant> {
return await this.applicantLoadPort.loadApplicant(resumeId);
}
}
@Controller('resume')
export clas ApplicantController {
constructor(
@Inject(ApplicantService) private readonly applicantService : ApplicantLoadInPort,
@Inject(Logger) private readonly logger : LoggerService,){}
=> 결론적으론 , 외부로 나가는 의존성 없는 도메인을 가짐.
export class newInterviewRequestedEvent {
constructor(){
public readonly name : string,
public readonly recruiterName : string,
}
}
this.eventBus.publish(
new newInterviewRequestedEvent(applicant.name,recruiter.name),
);