출처 : https://threedots.tech/post/basic-cqrs-in-go/
현재 저는 밥아저씨의 클린 아키텍처를 읽고나서 클린 아키텍처 구조로 코드를 작성하고 있습니다.
마이크로소프트 CQRS 설명서를 참고하세요!
-CQRS패턴을 넣기 위해 command/query 디렉토리를 나눴고, CQ를 포함하는 usecase.go를 만들었습니다.
모델로 분리하고 그 데이터 모델을 Usecase로 통합 합니다.
아직은 아무것도 만들지 않았기에 빈 구조체입니다.
Command의 company를 등록하는 핸들러를 만들도록 하겠습니다. command에서는 domain의 모델을 쓰는게 아니라 write에 해당하는 모델을 따로 만들어서 사용합니다. write모델을 따로 쓰는게 필수적인 것은 아니지만 필드 중에 외부에 노출 해야 할 필요성이 없는 것을 감출수도 있습니다.
package command
type Company struct {
Name string
Address string
JobOpening bool
write전용 모델은 도메인의 모델과 똑같죠?
아직 모델이 단순하기 떼문에 은닉 할 것도 없습니다. 그래서 domain에 있던 모델을 그대로 가져왔습니다.
추후에 데이터 생성 과정에서 정하지 않아도 되는 필드들이 생긴다면 달라 질겁니다.
package command
import (
"context"
"github.com/memoregoing/albacorn/company/domain/company"
)
type RegisterCompanyHandler struct {
repo company.Repository
}
func NewRegisterCompanyHandler (repo company.Repository) RegisterCompanyHandler {
if repo == nil {
panic("nil repo")
}
return RegisterCompanyHandler{repo: repo}
}
func (h RegisterCompanyHandler) Handle(ctx context.Context, cmd Company) (err error) {
co, err := company.NewCompany(cmd.Name, cmd.Address)
if err != nil {
return err
}
if err := h.repo.AddCompany(ctx, co); err != nil {
return err
}
return nil
}
여기서 중요한 점은 Handle함수는 행동이 결정 되었을 뿐 아직 구현되지 않은 상태입니다. 실질적인 구현은 추후 다른 계층에서 이뤄질 것이기 때문입니다. Usecase는 행동을 정의 할 뿐 구현하지 않기 때문에 구현 부분이 변경 되더라도 행동이 변하지 않는다면 Usecase는 변하지 않습니다.