Upgrade to Pro — share decks privately, control downloads, hide ads and more …

イベントソーシングとドメインモデリング

Kosuke Abe
December 22, 2024
160

 イベントソーシングとドメインモデリング

Kosuke Abe

December 22, 2024
Tweet

Transcript

  1. Πϕϯτ͸υϝΠϯϞσϦϯάͷཁ ʮϞϊʯͷ$36%Ͱ͸ͳ͘ʮίτʯΛ෼ੳ͢Δ͜ͱͰɺ;Δ ·͍๛͔ͳυϝΠϯϞσϧ͕खʹೖΔ l5IJTNFBOTUIBUUIFSFBSFOPPUIFSWFSCTXJUIJOUIFEPNBJO8IFO IPXFWFSPOFUBMLTXJUIEPNBJOFYQFSUTJOBOF ff PSUUPSF fi OFBO6CJRVJUPVT -BOHVBHF

    JUJTFYUSFNFMZSBSFUIBUPOFFOETVQXJUIBMBOHVBHFUIBUJT GPDVTFEPOUIFTFGPVSWFSCTz(SFH:PVOH lΠϕϯτιʔγϯά͸಺෦ઃܭ্ͷςʔϚͰ͋ͬͯɺσʔλϞσϧ্ͷ֓೦Ͱ͸͋ Γ·ͤΜɻ தུ ཤྺ͔Β࠶ݱ͞ΕΔ࠷৽σʔλͷܗ͚ͩΛ໰୊ʹ͢Ε͹Α͍Θ͚ Ͱ͢ɻͦΕͷΈ͕ۀ຿Ϣʔβʔͷؔ৺͝ͱ͔ͩΒͰ͢ɻzʰσʔλϞσϦϯάͰυϝ ΠϯΛۦಈ͢Δʱਿຊܒ
  2. type ArchiveArticleCommandService struct { Repository article.Repository } type ArchiveArticleCommand struct

    { ArticleID uuid.UUID } func (s ArchiveArticleService) Handle(ctx context.Context, command ArchiveArticleCommand) (article.Archived, error) { current := time.Now() anArticle, err := s.Repository.Find(ctx, command.AccountID) if err != nil { return account.Archived{}, errors.New(...) } event, err := anArticle.Archive(current) if err != nil { return account.Archived{}, errors.New(...) } if err := s.Repository.PersistEvent(ctx, event); err != nil { return account.Archived{}, errors.New(...) } return event }
  3. type ArchiveArticleCommandService struct { Repository article.Repository } type ArchiveArticleCommand struct

    { ArticleID uuid.UUID } func (s ArchiveArticleService) Handle(ctx context.Context, command ArchiveArticleCommand) (article.Archived, error) { current := time.Now() anArticle, err := s.Repository.Find(ctx, command.AccountID) if err != nil { return account.Archived{}, errors.New(...) } event, err := anArticle.Archive(current) if err != nil { return account.Archived{}, errors.New(...) } if err := s.Repository.PersistEvent(ctx, event); err != nil { return account.Archived{}, errors.New(...) } return event } ϦϙδτϦ͔Βهࣄू໿Λऔಘ
  4. type ArchiveArticleCommandService struct { Repository article.Repository } type ArchiveArticleCommand struct

    { ArticleID uuid.UUID } func (s ArchiveArticleService) Handle(ctx context.Context, command ArchiveArticleCommand) (article.Archived, error) { current := time.Now() anArticle, err := s.Repository.Find(ctx, command.AccountID) if err != nil { return account.Archived{}, errors.New(...) } event, err := anArticle.Archive(current) if err != nil { return account.Archived{}, errors.New(...) } if err := s.Repository.PersistEvent(ctx, event); err != nil { return account.Archived{}, errors.New(...) } return event } هࣄू໿ʹʮΞʔΧΠϒͨ͠ʯ ΠϕϯτΛ࡞੒ͤ͞Δ
  5. type ArchiveArticleCommandService struct { Repository article.Repository } type ArchiveArticleCommand struct

    { ArticleID uuid.UUID } func (s ArchiveArticleService) Handle(ctx context.Context, command ArchiveArticleCommand) (article.Archived, error) { current := time.Now() anArticle, err := s.Repository.Find(ctx, command.AccountID) if err != nil { return account.Archived{}, errors.New(...) } event, err := anArticle.Archive(current) if err != nil { return account.Archived{}, errors.New(...) } if err := s.Repository.PersistEvent(ctx, event); err != nil { return account.Archived{}, errors.New(...) } return event } ʮΞʔΧΠϒͨ͠ʯΠϕϯτΛ ϦϙδτϦʹ౉ͯ͠ӬଓԽ
  6. type ArticleRepository struct { Conn sqlx.DB } func (r ArticleRepository)

    PersistEvent(ctx context.Context, event article.Event) error { switch e := event.(type) { case article.Archived: if _, err := r.Conn.ExecContext(ctx, `INSERT INTO article_archivements (article_id, archived_at) VALUE (?, ?)`, e.ArticleID, e.ArchivedAt); err != nil { return errors.New(...) } case ... default: return errors.New(...) } } func (r ArticleRepository) Find(ctx context.Context, id uuid.UUID) (*article.Article, error) { var data articleData if err := r.Conn.GetContext(ctx, data, `SELECT articles.id, .... FROM articles WHERE articles.id = ?`); err != nil { return nil, errors.New(...) } return r.convertToAggregate(data), nil } શͯΛΠϕϯτͱͯ͠ӬଓԽ͢ΔͷͰ͸ͳ͘ɺ ϦιʔεͱΠϕϯτͷ྆ํΛ3%#ͷςʔϒϧͰදݱɻ ΠϕϯτͷӬଓԽͱू໿ͷ࠶ߏங͚ͩͰͳ͘ɺ ΫΤϦϞσϧͷߏஙʹ΋࢖͑ΔΑ͏ʹ ςʔϒϧΛઃܭ͢Δɻ ΠϕϯτछผʹԠͯ͡ߋ৽ܥͷ42-Λൃߦ ϦιʔεͱΠϕϯτ͔Βू໿Λ࠶ߏங