2019/07/13 に行われたGo Conference '19 Summer in Fukuoka で発表した資料です。
https://fukuoka.gocon.jp/ja/speakers/budougumi0617/
GoConference’19 google/wireを使ったGoらしいアーキテクチャへの取り組みGo Conference ‘19 in Summer2019/07/13 Yoichiro Shimizu @budougumi0617
View Slide
GoConference’19 2Yoichiro Shimizu @freee K.K.https://budougumi0617.github.io/
GoConference’19 3
4
今日のゴール● google/wireの概要・利用方法を紹介する● (私が考える)Goらしいパッケージ設計の共有する● 実際にgoogle/wireを使ったコードの紹介する● google/wireのCons/Prodを共有する5
google/wire6/
Dependency Injection7
github.com/google/wire● DIを行うためのCLIツールと実装用APIライブラリ○ 2018年7月に公開されたgoogle/go-cloudに付属○ 同年12月頃に独立したリポジトリに分離○ 現在 v0.3.0(beta release)○ DIの定義をするライブラリ○ 定義からDIコードを自動生成するCLI8
wireがもつ2つの概念● Provider○ どのような依存関係があるのか● Injector○ どうやって依存を解決するのか9
Providerwire.NewSetで定義10
wire show11
Inejctorwire.Buildで定義12この宣言はBuild Constraintsを使ってgo build時には使われない
wire gen依存性を解決したコードを自動生成13wire genで生成したこちらのコードが go build時に利用される
Inejctor先ほど程度ではあまりメリットを感じないが…14
wire gen自動生成結果クリーンアップ処理もよしなに書いてくれる15
wireを使ったアーキテクチャ16/
その前に17/
Goらしい設計とは?18/
良いアーキテクチャ設計をしたい● Goにおいて何をもって「よい」と言えるのか?○ フラットパッケージにすればよい?○ DDDのような本のレイヤー構成通りにすればよい?● 言語思想に沿った設計を心がける○ Simplicity19
Simplicity - 徹底的な簡潔性● GoのMission○ Creating software at scale○ Running software at scale● システムは成長する際に、デザインの簡潔性を通してのみ、安定し、安全であり、首尾一貫したままでいられる20Go's New Brand の Mission, プログラミング言語 Go まえがき より
● 小さなInterfaceで他pkgへの依存を絞る○ 高々1つしかメソッドを持たないXXXer● Interfaceとダックタイピング○ 利用package側でInterfaceを宣言疎でひとつのことをうまくやるレイヤー構成21
コード22/
各レイヤーの実装イメージを簡単に紹介● 題材: OAuth2.0トークンを生成するHTTPサーバ○ HTTPリクエストパラメータを使って認可サーバからトークンを生成する○ 生成したアクセストークンをDBに永続化23
package構成24entity データの定義domain ドメインロジックの実装repository データの永続化usecase ドメインモデルとリポジトリからシナリオを作るhttp HTTPとプリミティブなパラメータを仲介app Injectorを配置し自動生成コードを置く
entity素朴なデータ構造25
domainドメインロジックの実装ダミー認可サーバを使ったテストなど結構真面目に書いている26
repositoryRDBMSに対するCRUDUTではsqlmockなどを利用27モックで済ませているのは基盤ライブラリを使っているからという事情もある
usecase 1リポジトリ層に対する抽象化28
usecase 2ドメインモデルとリポジトリを組み合わせる層UTではgo-mockを利用wireでSetを定義29リポジトリは各ユースケース共通になることが多いのでドメインモデルのみ DIしている
httpHTTPリクエストをプリミティブなパラメータに分解UTではgo-mockとhttptestを利用wireでSetを定義30
app全ての依存関係の解決方法を定義wire genでコードを自動生成する31HealthCheckやメトリクスチェックなどアプリとして必要な機能も全て DIしている
所感と利点32/
● package間のインターフェイスにwire wayができる○ wireが使いやすい構造 == 疎な構造● パッケージ間の依存関係を機械的に表現できる○ wire show● あまり独自要素がない○ ロジック部分に癒着しないので最悪すぐ辞められる使っていてよいところ33
● 単純にDIコードを書かなくて済んでいる○ 自動生成前 36行 / 自動生成後 91行■ 4 API, RDS, KMS, Redis etc...● wireコマンド自体も使いやすい○ エラーメッセージなどが親切使っていてよいところ34
● 先月にbetaリリース○ まだ破壊的変更が入る可能性がある● 単純に依存するツールが増える○ wire”コマンド”もバージョン管理しないといけない● Interface増えがち○ wireのためのInterfaceになっている気もする難しいところ35
まとめ36/
今日のゴール● google/wireの概要・利用方法を紹介する● (私が考える)Goらしいパッケージ設計の共有する● 実際にgoogle/wireを使ったコードの紹介する● google/wireのCons/Prodを共有する37