エンジニアがドメインロジックに 集中するためのコアパッケージ整備 / freee prepare a core package for microservice

B9a64a1c5873755ce9df629f05e3e12d?s=47 Makoto Shiga
January 21, 2020

エンジニアがドメインロジックに 集中するためのコアパッケージ整備 / freee prepare a core package for microservice

B9a64a1c5873755ce9df629f05e3e12d?s=128

Makoto Shiga

January 21, 2020
Tweet

Transcript

  1. freee 株式会社
 エンジニアがドメインロジックに
 集中するためのコアパッケージ整備
 2020.01.21

  2. • 新卒はソシャゲバックエンド ( Perl )
 • 2社目アニメ関係の会社でレガシーシステムの AWS移管など
 • 2017年8月

    freeeにjoin
 ◦ サービス基盤チーム
 ◦ スピード改善と負債返却が好き
 ◦ 最近はデッドコードを殲滅させる方法を考えて る
 
 Shiga Makoto / @MacoTasu 志賀 誠
 freee株式会社 / サービス基盤 / エンジニア
 2
  3. 3 コアパッケージが指すもの
 • 今回の話では各サービスで共通して使われるパッケージのこと
 ◦ e.g. logger, error, security周りの対応 etc...

  4. 4 話すこと
  03 コアパッケージ導入
  02 コアパッケージ仕様策定・作成
  01 コアパッケージ作成に至る背景
  04 振り返り・まとめ


  5. 01 コアパッケージを作成にいたる背景
 5 Section

  6. freeeにおけるサービスの変化


  7. 
 PRODUCTS

  8. 8 これまでのfreeeのサービス
 • 主要なサービスは大体がRails
 • RailsなのでComponent周りは大体同じ構成
 • Componentで足りないものは、社内のgem等を利用
 • Railにのっているので、improvementやbugfixなどの恩恵にあやかれて

    いた

  9. 2018年
 フィーチャーリリース数
 
 278件
 
 
 リリースカテゴリ
 既存機能の改善・拡充
 78.8% 新機能リリース


    15.8%
 その他(セキュリティ強化等) 
 5. 4%

  10. 10 ファットになったRailsサービス
 • Deployに時間がかかる
 • コード全体の見通しが悪くなった
 ◦ 設計の問題でもある • プロダクトに関わる人が増え、機能の責任の境界が不明瞭


    • etc...

  11. 11 2018年はマイクロサービス開発が進む
 • モノリシックから分離できる機能のマイクロサービス化
 ◦ メモリフットプリント、学習のしやすさなどからGoが多い • Kubernetesを使ったマイクロサービスの基盤が整う
 • 2019年も続々とマイクロサービス誕生


  12. 12 マイクロサービスの数


  13. 13 誕生したGoのマイクロサービス
 独自実装 A Aをベースにし た独自実装 etc ... ※図はイメージ


  14. 14 マイクロサービス化を経て
 • Pros
 ◦ モノリシックな開発のときに抱えていた問題が解決 ◦ 同時並行で複数のマイクロサービスの開発が進み、それぞれで知 見が溜まった •

    Cons
 ◦ 各チーム間でノウハウの共有がうまくいかずに、ミドルウェア周りの 整備の工数が増えていた ◦ 微妙に構成が違うサービスが生まれた
  15. 15 本来あるべき姿
 • エンジニアの多くはユーザに届けたい価値があって開発している
 ◦ loggerやerrorなどの機能も必要だが、各サービス単位で作り込ま なきゃいけない状況は本質ではない サービス基盤が共通で必要なパッケージを作成
 各エンジニアはドメインロジックに集中できるようにする


  16. 16 コアパッケージを使えば
 マイクロサービスを簡単に作成でき
 利用者はドメインロジックのみを作り込め ばいい状態を目指す
 目指すべきゴール


  17. 02 コアパッケージを仕様策定・実装
 17 Section

  18. どんなパッケージを作るべきか


  19. 19 ターゲットになる範囲


  20. 20 共通部分の洗い出し
 • やったこと
 ◦ 全マイクロサービスのコードを読んで、機能を洗い出す ◦ 使用感をGoogleDocs上で、各サービス担当者にヒアリング ◦ 愚直に調べた

  21. 21 調査段階で気にした点
 • 外部パッケージはGoらしい作りになっているか
 ◦ contextを受け取れる場合、中継し後ろに渡している ◦ 異常系のときはerrorを返す、panicは致命的な問題だけ ◦ goroutine

    safeな作りになっているか ◦ goのエコシステムを利用しているか ▪ golint, go vet… • 開発がアクティブであるか、スター数、今後の展望など

  22. コアパッケージ作成


  23. 23 パッケージ作成で気にしたポイント
 • デファクトとしてのパッケージを作る
 • 拡張性
 • 簡単に組み込める


  24. 24 パッケージ作成で気にしたポイント
 • デファクトとしてのパッケージを作る
 • 拡張性
 • 簡単に組み込める


  25. 25 デファクトとしてのパッケージを作る
 • 提供するパッケージは使えば、品質の保証と改修の恩恵を受けれる という意味でのデファクト
 • 強制して使ってくれというものではない
 ◦ ※ セキュリティ関連の対応は除く

    • 利用者の技術選定の余地は残す

  26. 26 パッケージ作成で気にしたポイント
 • デファクトとしてのパッケージを作る
 • 拡張性
 • 簡単に組み込める


  27. 27 拡張性
 • 利用者側の様々なユースケースで使えるように拡張性をもたせる
 • 詳細な振る舞いなど、外から渡したいであろうものはinterfaceを用い たダッグタイピングを使う
 • 実装は go-cloudを参考


  28. 28 拡張性: HealthCheck pkgの例
 // Checker wraps the CheckHealth method.

    type Checker interface { CheckHealth(strict bool) error } type entry struct { checker Checker } // Service provides health check HTTP handlers. type Service struct { entries []entry } // Add appends for Checker. func (s *Service) Add(name string, c Checker) { // … appends Checker into entries. } 
 // CheckReadiness returns error if any checker is unhealthy. func (s *Service) CheckReadiness(strict bool) error { for _, e := range s.entries { if err := e.checker.CheckHealth(strict); err != nil { ... } } return nil } 
 

  29. 29 パッケージ作成で気にしたポイント
 • デファクトとしてのパッケージを作る
 • 拡張性
 • 簡単に組み込める


  30. 30 簡単に組み込める
 • 利用されてこそ価値があるので簡単に組み込めることは重要
 • パッケージ導入にあたって依存関係にある箇所の解決は面倒
 • Googleが作っているwireというパッケージを使う
 


  31. wireとは
 • wireは静的DI(Dependency Injection)ツール
 ◦ パッケージから設定の値など依存に当たる部分を別に切り出して、 注入という形で後から読み込むことで疎なパッケージを実現できる • wireはシンプルにいうとProviderとInjectorの2つの概念がある
 31

  32. Provider
 32 DB package • 特定の型を返すために必要な引数(dependency)を受け取り、返り値 として特定の型を返す
 DB 接続情報 接続情報を受け取り


    sql.DBを返す関数
 依存にあたる引数

  33. Injector
 33 DB package • Providerを組み合わせて依存関係を解決し、特定の型を返す
 Injector.go config package 接続情報

    DBを使う Server package Providerを並べる

  34. Injector
 34 DB package • Providerを組み合わせて依存関係を解決し、特定の型を返す
 Injector.go config package 接続情報

    DBを使う Server package wire_gen.go Providerを並べる
 wire genコマンド実行
 DBコネクションを持つServer のオブジェクト生成するコード を生成

  35. 35 コアパッケージ作成の改善点
 • 作成段階でユーザにとってあるべき、使いやすいパッケージとはにつ いて議論することに時間を要しすぎた
 ◦ 実際に使われていないものの最適解を見つけること難しい ◦ 2人の間での理想が見えたら、迷わず作りきってフィードバックをも らうことが最短ルートだった

  36. 03 コアパッケージ導入
 36 Section

  37. 37 ドッグフーディングしてもらう


  38. 38 アナウンス
 • 社内のQiitaに使い方を書く
 • 社内のSlack #go などに告知を流す
 • コアパッケージを使ったチュートリアルを作成


    ◦ claatというツールを使い、markdownからCodelabs形式の画面 を作成
  39. 39 作成したチュートリアル


  40. 40 社内のGo大好きな一部の人は使っ てくれた


  41. 41 まだ全体で見たら使われてない状況 


  42. 42 課題を整理
 • パッケージが多すぎてイマイチ何があるかわからない
 • 使うとどういう利点があるか伝えれてきれていない
 • 使われる物を作れていなかった可能性もある?
 
 


  43. 43 対応
 • エンジニアに親しみがあるGodocをちゃんと整備する
 • 社内のエンジニア皆が集まる場で宣伝しより認知度あげる
 • マイクロサービス委員会をつくる
 • 各チームの目標にのせる


  44. 44 対応
 • エンジニアに親しみがあるGodocをちゃんと整備する
 • 社内のエンジニア皆が集まる場で宣伝しより認知度あげる
 • マイクロサービス委員会をつくる
 • 各チームの目標にのせる


  45. 45 委員会とは
 • 弊社独自の文化(呼び方)
 • ◦◦委員会は、◦◦について興味・一家言ある人達が有志で集まっ て◦◦について話し合い、時には社内のデファクトを定義したりする 
 • マイクロサービス委員会、フロントエンド委員会 etc...


  46. 46 マイクロサービス委員会
 • マイクロサービスのデファクトとは何かついて話し合う場
 • 参加者
 ◦ マイクロサービス開発に関わってるメンバー • コアパッケージを利用した感想やほしい機能などのを話し合い、方針

    を決めていく
 ◦ 決まった方針をサービス基盤チームでパッケージに反映 ◦ この場から各機能のデファクト方針ドキュメントが作成された
  47. 47 例: エラー通知
 • エラーはBugsnagに通知する
 • projectは基本各サービス単位
 • 環境がわかるようにステージを作成する
 ◦

    検証環境のみタグ名で判別する • severityを適切に設定する
 • 発生したら通知を受けて即対応、平常時は0
 • サービスに関するmetadataの情報と、追加の情報を設定できるように する
 • WARN, ERRORはSlackなどに通知すること

  48. 48 対応
 • エンジニアに親しみがあるGodocをちゃんと整備する
 • 社内のエンジニア皆が集まる場で宣伝しより認知度あげる
 • マイクロサービス委員会というマイクロサービス関係者が集まる場を 用意する
 •

    各チームの目標にのせる

  49. 49 各チームの目標にのせる
 • freeeでは3ヶ月ごとにチームで取り組む目標を決めており、そこにの せてもらうと導入も捗る
 ◦ 各プロダクトの責任ある人に依頼し、チームの目標に乗せてもらい 導入進めている

  50. 50 経過
 Goのマイクロサービス系で
 ほぼ導入の目処は経ってきた


  51. 51 コアパッケージ関連のPR数遷移


  52. 04 振り返り・まとめ
 52 Section

  53. 53 コアパッケージ整備を進めてみて
 • 散らばっていたノウハウを吸い上げ、デファクトについて言語化、共通 認識を作れた
 • 既存サービスの基底部分を見直し・改善が進んだ
 • 爆速でマイクロサービスを立ち上げられる基盤ができた


  54. 54 まとめ
 • 整備のタイミングはノウハウがたまり、サービスが増え始める前のタイ ミングが効果的
 • 共通して使われるパッケージの作り方はgo-cloudがかなり参考になる
 • 整備、導入をする際は会社としてちゃんとリソース割くこと大事


  55. スモールビジネスを、
 世界の主役に。

  56. 56 参考リンク
 • freeeのマイクロサービス基盤とWire導入
 • wireやhealthパッケージを作成する際に参考
 ◦ github.com/google/go-cloud