Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GoとDDDでモバイルオーダープラットフォームを 型安全に作り直した話
Search
takuya kikuchi
February 22, 2022
0
97
GoとDDDでモバイルオーダープラットフォームを 型安全に作り直した話
2022-02-22 / GeekGig 『DONUTS×Showcase Gig』〜Goでゼロから作り直した話〜 の登壇資料です
takuya kikuchi
February 22, 2022
Tweet
Share
More Decks by takuya kikuchi
See All by takuya kikuchi
生成AI時代のソフトウェアエンジニアが持つべきケイパビリティを考える
tkikuchi1002
8
5.1k
RAGをテーマに考える、LLMの認知アーキテクチャとソフトウェア設計
tkikuchi1002
3
1.2k
生成AIの不確実性と向き合うためのオブジェクト指向設計
tkikuchi1002
3
6.7k
Azure AI SearchとPromptFlowではじめるRAG
tkikuchi1002
2
1.3k
法人向けChatGPTにおける Azure OpenAI Serviceの課題解決の過程と現在
tkikuchi1002
2
2k
LLMエンジニアリングを加速させるソフトウェアアーキテクチャ
tkikuchi1002
2
5.6k
WebAPIのバリデーションを、型の力でいい感じにする
tkikuchi1002
0
79
Kotlinのcoroutine、async/awaitと同じでしょ?って思ってたけど意外と洗練されててすごいなぁって思った話をさせてほしい
tkikuchi1002
0
110
使いやすいインターフェースについて考える
tkikuchi1002
0
36
Featured
See All Featured
GraphQLとの向き合い方2022年版
quramy
44
13k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
33
2.7k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Optimizing for Happiness
mojombo
376
70k
It's Worth the Effort
3n
183
28k
Rails Girls Zürich Keynote
gr2m
94
13k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
26
1.9k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.1k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
Transcript
confidential GoとDDDでモバイルオーダープラットフォームを 型安全に作り直した話 takuya kikuchi @ Showcase Gig 1 2022-02-22
GeekGig 『DONUTS×Showcase Gig』〜Goでゼロから作り直し た話〜
confidential ©Showcase Gig 2 発表者 - capybara (takuya kikuchi) -
twitter: @_pochi - Engineer Group Manager @ Showcase Gig
confidential ©Showcase Gig 3 GoとDDDでモバイルオーダープラットフォームを型安 全に作り直した話
confidential ©Showcase Gig 4 GoとDDDでモバイルオーダープラットフォームを型安 全に作り直した話
confidential ©Showcase Gig 5 モバイルオーダープラットフォーム モバイルオーダーと一言でいっても、色々あります
confidential ©Showcase Gig 6 モバイルオーダープラットフォーム モバイルオーダーと一言でいっても、色々あります 注文シーン 受け取りシーン
confidential ©Showcase Gig 7 モバイルオーダープラットフォーム モバイルオーダーと一言でいっても、色々あります 自宅から 注文シーン 受け取りシーン
confidential ©Showcase Gig 8 モバイルオーダープラットフォーム モバイルオーダーと一言でいっても、色々あります 自宅から 注文シーン 受け取りシーン 店舗で受け取り
confidential ©Showcase Gig 9 モバイルオーダープラットフォーム モバイルオーダーと一言でいっても、色々あります 自宅から 注文シーン 受け取りシーン 店舗で受け取り
ロッカーで受け取り
confidential ©Showcase Gig 10 モバイルオーダープラットフォーム モバイルオーダーと一言でいっても、色々あります 自宅から 注文シーン 受け取りシーン 店舗で受け取り
ロッカーで受け取り 店内で食べながら
confidential ©Showcase Gig 11 モバイルオーダープラットフォーム モバイルオーダーと一言でいっても、色々あります 自宅から 注文シーン 受け取りシーン 店舗で受け取り
ロッカーで受け取り 店内で食べながら テーブルまで配膳
confidential ©Showcase Gig 12 モバイルオーダープラットフォーム O:der Table: 店内飲食 O:der Kiosk:
Kiosk端末からの注文(イートイン・テイクアウト) O:der ToGo: テイクアウト The Label Fruit: テイクアウト(ロッカー受け取り) O:der Platform: 各プロダクトの共通基盤 and more
confidential ©Showcase Gig 13 モバイルオーダープラットフォーム O:der Table: 店内飲食 O:der Kiosk:
Kiosk端末からの注文(イートイン・テイクアウト) O:der ToGo: テイクアウト The Label Fruit: テイクアウト(ロッカー受け取り) O:der Platform: 各プロダクトの共通基盤 and more
confidential ©Showcase Gig 14 GoとDDDでモバイルオーダープラットフォームを型安 全に作り直した話
confidential ©Showcase Gig 15 モバイルオーダープラットフォームを作り直すぞ! DDDをやるぞ!
confidential ©Showcase Gig 16 DDD (ドメイン駆動設計) ドメイン駆動設計とはソフトウェアの設計手法である。 「複雑なドメインの設計は、モデルベースで行うべき」であり、また「大半のソフト ウェアプロジェクトでは、システムを実装するための特定の技術ではなく、ドメイ ンそのものとドメインのロジックに焦点を置くべき」であるとする。
出典: https://ja.wikipedia.org/wiki/%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9 %A7%86%E5%8B%95%E8%A8%AD%E8%A8%88
confidential ©Showcase Gig 17 わからん
confidential ©Showcase Gig 18 なんとなくやってみよう 書籍などを参考にしつつ、チームとしてこれくらいの理解でやってみた • いいプロダクトにはいいドメインモデルがあるらしい • ユビキタス言語を定めて、それを使って対話をするべきらしい
• エンジニアだけでなく、ドメインエキスパートを集めてモデリングをするとい いらしい • ドメインモデルと実装は一致しているといいらしい • 整合性を保ちたい範囲を集約とかいうらしい
confidential ©Showcase Gig 19 ドメインモデリングした • 登場人物 ◦ プロダクトマネージャー(プロダクトに詳しい) ◦
CS(飲食店のオペレーションに超詳しい) ◦ エンジニア(詳しくなりたい) • ホワイトボードツールつかって おしゃべりした ◦ 「「注文」って何?」 ◦ 「商品って?メニューって?」 ◦ ユビキタス言語を定めていく
confidential ©Showcase Gig 20 注文って何 • お金を払う行為は伴うの? • ファミレスでの「注文」と、デリバリーサービスでの「注文」って一緒なの? •
注文の単位ってなんだろう。 ◦ 3人で1つずつ頼んだ料理は3注文? ◦ 1人で3つ料理を頼んだらそれは3注文? Oxford Languagesの定義 ちゅうもん 【注文・註文】 《名・ス他》 1. 1. 品質・数量・形・寸法等を指定して、作らせたり送らせたりすること。 「―を取る」 2. 2. こうしてほしいと指図(さしず)をし、希望すること。 「―をつける」
confidential ©Showcase Gig 21 モデルの例 ※簡略化しています
confidential ©Showcase Gig 22 GoとDDDでモバイルオーダープラットフォームを型安 全に作り直した話
confidential ©Showcase Gig 23 Goで実装するよ • 全体設計 ◦ Onion Architecture
• 今日は主にドメイン層とユースケース層の話をします
confidential ©Showcase Gig 24 こいつを忠実に実装する
confidential ©Showcase Gig 25 ドメイン層: Order struct 定義 // Order
注文モデル type Order struct { orderID types.OrderID restaurant order_vo.Restaurant orderItems []*order_vo.OrderItem orderedAt order_vo.OrderedAt orderState order_vo.OrderState } • すべてValue Objectとし、プリミティブ型は扱わない
confidential ©Showcase Gig 26 ドメイン層: CreteOrder // NewOrder 注文を新規に作成する func
NewOrder( orderID types.OrderID, restaurant order_vo.Restaurant, orderItems []*order_vo.OrderItem, orderedAt order_vo.OrderedAt, state order_vo.OrderState, ) (*Order, error) { // 注文時間から、店舗で注文受付可能か判断す る accept, err := restaurant.IsOrderAcceptable(orderedAt) if err != nil { // 何からのエラーが発生したので注文失敗 return nil, err } if !accept { // 店舗設定により注文不可なので注文失敗 return nil, errors.New("注文受付時間 外") } // 注文オブジェクト生成 return &Order{ orderID: orderID, restaurant: restaurant, orderItems: orderItems, orderedAt: orderedAt, orderState: state, }, nil } • Entity / ValueObjectの生成は、必ず 専用のコンストラクタを利用する。 • 注文作成条件を満たさないような、 不正な注文オブジェクトは 生成できないようにする • 引数なども正しいものしか 渡ってこない前提で実装できる
confidential ©Showcase Gig 27 ユースケース層: CreateOrder ユースケース層の実装 • Entity /
VOを生成して • 永続化する それだけを行う。 「この場合注文できていいんだっ け?」というロジックはすべてドメ インモデルの中に含まれているの で、Usecase層は何もしなくてよ い。 // Create 注文を受け付ける func (o *CreateUseCase ) Create(ctx context.Context, input CreateInput ) (orderId types.OrderID, err error) { // DBトランザクション内で処理する err = o.dbClients.WritableClient. RunInWriteTx (略) (err error) { // ~~~~ 略 ~~~~ // 取得した商品情報から注文商品情報を組み立てる orderItems , err := vo.NewOrderItems (orderRequestItems , items) if err != nil { // 注文商品情報が不正 return } // 注文ステータス作成 initialState , err := vo.NewOrderState (input.InitialOrderState) if err != nil { // 注文ステータスが不正 return } // 店舗情報取得 restaurant , err := o.masterRepository. GetRestaurant (ctx, queryable, types.RestaurantID (input.RestaurantId)) if err != nil { // 店舗が不正 return } // 注文エンティティ生成 orderId = types.OrderID(numberingService. Generate()) orderEntity , err := entity.NewOrder( orderId , restaurant , orderItems , orderedAt, initialState , ) if err != nil { // 注文作成に失敗 return } // 注文を永続化 err = o.orderRepository. Persist(ctx, queryable, orderEntity) if err != nil { // ~~~~ 略 ~~~~ } return }) return orderId, nil }
confidential ©Showcase Gig 28 Goで実装したよ • DDDに従い、モデルを忠実に実装してみた ◦ モデリングが終わった頃にはほぼ実装内容も決まっていて新感覚。 ◦
ドメイン層はピュアなGo言語の世界なので、ユニットテストを書きやすい。プログラミングし てる!って気持ちになって楽しい。 • Goはゴリゴリのオブジェクト指向言語というわけではないが、十分に書ける。 ◦ Defined Typeがあるので、プリミティブ型に別名をつけるのが楽で快適 • 唯一気になるのは ◦ コンストラクタを経由しないオブジェクト生成を禁止できない ◦ (「こうすればいけるよ」募集中です )
confidential ©Showcase Gig 29 GoとDDDでモバイルオーダープラットフォームを型安 全に作り直した話
confidential ©Showcase Gig 30 おしまい