Slide 1

Slide 1 text

GoConference’19 google/wireを使った Goらしいアーキテクチャへの取り組み Go Conference ‘19 in Summer 2019/07/13 Yoichiro Shimizu @budougumi0617

Slide 2

Slide 2 text

GoConference’19 2 Yoichiro Shimizu @freee K.K. https://budougumi0617.github.io/

Slide 3

Slide 3 text

GoConference’19 3

Slide 4

Slide 4 text

4

Slide 5

Slide 5 text

今日のゴール ● google/wireの概要・利用方法を紹介する ● (私が考える)Goらしいパッケージ設計の共有する ● 実際にgoogle/wireを使ったコードの紹介する ● google/wireのCons/Prodを共有する 5

Slide 6

Slide 6 text

google/wire 6 /

Slide 7

Slide 7 text

Dependency Injection 7

Slide 8

Slide 8 text

github.com/google/wire ● DIを行うためのCLIツールと実装用APIライブラリ ○ 2018年7月に公開されたgoogle/go-cloudに付属 ○ 同年12月頃に独立したリポジトリに分離 ○ 現在 v0.3.0(beta release) ○ DIの定義をするライブラリ ○ 定義からDIコードを自動生成するCLI 8

Slide 9

Slide 9 text

wireがもつ2つの概念 ● Provider ○ どのような依存関係があるのか ● Injector ○ どうやって依存を解決するのか 9

Slide 10

Slide 10 text

Provider wire.NewSetで定義 10

Slide 11

Slide 11 text

wire show 11

Slide 12

Slide 12 text

Inejctor wire.Buildで定義 12 この宣言はBuild Constraintsを使ってgo build時には使われない

Slide 13

Slide 13 text

wire gen 依存性を解決したコードを自動生成 13 wire genで生成したこちらのコードが go build時に利用される

Slide 14

Slide 14 text

Inejctor 先ほど程度ではあまりメリットを感じないが… 14

Slide 15

Slide 15 text

wire gen 自動生成結果 クリーンアップ処理も よしなに書いてくれる 15

Slide 16

Slide 16 text

wireを使った アーキテクチャ 16 /

Slide 17

Slide 17 text

その前に 17 /

Slide 18

Slide 18 text

Goらしい 設計とは? 18 /

Slide 19

Slide 19 text

良いアーキテクチャ設計をしたい ● Goにおいて何をもって「よい」と言えるのか? ○ フラットパッケージにすればよい? ○ DDDのような本のレイヤー構成通りにすればよい? ● 言語思想に沿った設計を心がける ○ Simplicity 19

Slide 20

Slide 20 text

Simplicity - 徹底的な簡潔性 ● GoのMission ○ Creating software at scale ○ Running software at scale ● システムは成長する際に、デザインの簡潔性を通してのみ、 安定し、安全であり、首尾一貫したままでいられる 20 Go's New Brand の Mission, プログラミング言語 Go まえがき より

Slide 21

Slide 21 text

● 小さなInterfaceで他pkgへの依存を絞る ○ 高々1つしかメソッドを持たないXXXer ● Interfaceとダックタイピング ○ 利用package側でInterfaceを宣言 疎でひとつのことをうまくやるレイヤー構成 21

Slide 22

Slide 22 text

コード 22 /

Slide 23

Slide 23 text

各レイヤーの実装イメージを簡単に紹介 ● 題材: OAuth2.0トークンを生成するHTTPサーバ ○ HTTPリクエストパラメータを使って認可サーバからトークンを 生成する ○ 生成したアクセストークンをDBに永続化 23

Slide 24

Slide 24 text

package構成 24 entity データの定義 domain ドメインロジックの実装 repository データの永続化 usecase ドメインモデルとリポジトリからシナリオを作る http HTTPとプリミティブなパラメータを仲介 app Injectorを配置し自動生成コードを置く

Slide 25

Slide 25 text

entity 素朴なデータ構造 25

Slide 26

Slide 26 text

domain ドメインロジックの実 装 ダミー認可サーバを 使ったテストなど結 構真面目に書いて いる 26

Slide 27

Slide 27 text

repository RDBMSに対する CRUD UTではsqlmockな どを利用 27 モックで済ませているのは基盤ライブラリを使っているからという事情もある

Slide 28

Slide 28 text

usecase 1 リポジトリ層に対す る抽象化 28

Slide 29

Slide 29 text

usecase 2 ドメインモデルとリポ ジトリを組み合わせ る層 UTではgo-mockを 利用 wireでSetを定義 29 リポジトリは各ユースケース共通になることが多いのでドメインモデルのみ DIしている

Slide 30

Slide 30 text

http HTTPリクエストをプ リミティブなパラメー タに分解 UTではgo-mockと httptestを利用 wireでSetを定義 30

Slide 31

Slide 31 text

app 全ての依存関係の 解決方法を定義 wire genでコードを 自動生成する 31 HealthCheckやメトリクスチェックなどアプリとして必要な機能も全て DIしている

Slide 32

Slide 32 text

所感と利点 32 /

Slide 33

Slide 33 text

● package間のインターフェイスにwire wayができる ○ wireが使いやすい構造 == 疎な構造 ● パッケージ間の依存関係を機械的に表現できる ○ wire show ● あまり独自要素がない ○ ロジック部分に癒着しないので最悪すぐ辞められる 使っていてよいところ 33

Slide 34

Slide 34 text

● 単純にDIコードを書かなくて済んでいる ○ 自動生成前 36行 / 自動生成後 91行 ■ 4 API, RDS, KMS, Redis etc... ● wireコマンド自体も使いやすい ○ エラーメッセージなどが親切 使っていてよいところ 34

Slide 35

Slide 35 text

● 先月にbetaリリース ○ まだ破壊的変更が入る可能性がある ● 単純に依存するツールが増える ○ wire”コマンド”もバージョン管理しないといけない ● Interface増えがち ○ wireのためのInterfaceになっている気もする 難しいところ 35

Slide 36

Slide 36 text

まとめ 36 /

Slide 37

Slide 37 text

今日のゴール ● google/wireの概要・利用方法を紹介する ● (私が考える)Goらしいパッケージ設計の共有する ● 実際にgoogle/wireを使ったコードの紹介する ● google/wireのCons/Prodを共有する 37