Slide 1

Slide 1 text

サービスを長期的にGoで開 発・運用していくために 岡本 洋輔
 @yoskeoka


Slide 2

Slide 2 text

目次 ● 自己紹介 ● 会社紹介 ● 長期的にGoで開発・運用していくために ○ 3rd Party 技術の評価

Slide 3

Slide 3 text

● Engineer@Money Forward, Inc. ● MFBC API推進部 ● 京都拠点所属 ● 最近よく書く言語 ○ JavaScript/Go/YAML/HCL 我が家のGopherくんたち

Slide 4

Slide 4 text

Money Forward について

Slide 5

Slide 5 text

マネーフォワードの事業 『 統合報告書「Forward Map」2022』より引用

Slide 6

Slide 6 text

開発体制

Slide 7

Slide 7 text

開発チームごとにそれぞれのやり方でやっている
 自分の所属している開発チームの例
 ● 構成: PdM, PO, デザイナー, エンジニア
 ● エンジニアはFEからインフラまで一気通貫
 ○ 各メンバーで得意領域は異なる 
 ● スクラム開発を採用
 
 開発体制

Slide 8

Slide 8 text

● インフラ運用は社内のインフラ専任チームにある程度お任せしている
 ○ 各サービスごとのAWS/k8sをプロビジョニングしてくれる社内基盤サービスがある 
 ○ どんなリソースが必要かは開発チームが設計する必要がある 
 ○ アプリケーションの運用責任は開発チームにある (AWSのように責任共有モデル )
 ○ 社内インフラ基盤を紹介している blog記事
 ■ https://moneyforward.com/engineers_blog/2021/12/28/next-service-platform/
 ■ https://aws.amazon.com/jp/solutions/case-studies/moneyforward/
 ● アプリケーションの利用技術はチームの裁量で決まる
 ● デプロイワークフローはGitHub -> CircleCI -> k8s(EKS) が基本の流れ
 社内の開発基盤

Slide 9

Slide 9 text

長期的に運用するサービ スを開発するために

Slide 10

Slide 10 text

API推進部では「Money ForwardはAPIが全然公開されていない」という課題を解 決するため、「Money Forward 法人向け」の全サービスが利用するAPI基盤サー ビスを開発しています。
 話の背景

Slide 11

Slide 11 text

20以上のサービスがAPIを公開するときに利用してもらう重要基盤なので、運用が 始まったら長期で利用される前提!!
 話の背景

Slide 12

Slide 12 text

長期間使われることを考慮しつつ、API基盤が整わなければ他サービスのAPI開 発が進まないので、基盤を最速で提供する必要がある 
 ● 早く作りたいから、よくあるパーツはライブラリ等を利用しコード量は少なくした い
 ● でも適当に選んでしまうとスタートから技術的負債をたくさん抱えた状態に 
 
 技術的負債は作った瞬間から発生するので、0にはできない。
 が、技術選定や設計で最小化する努力はするべき。
 こんなことを考えていました

Slide 13

Slide 13 text

● アーキテクチャ設計
 ● コード設計
 ● 実装方法検討
 ● 技術・ライブラリ選定
 ● 運用体制
 ● 監視
 ● DevSecOps
 ● コスト最適化
 ● その他、多数・・・
 長期的に開発・運用するために必要な要素 今回話すこと

Slide 14

Slide 14 text

3rd Party 技術の評価

Slide 15

Slide 15 text

OSSや有償で技術を提供してくれているものが3rd Party技術
 
 インターネットの成長、ソースコード共有サービスの登場などを背景に、
 3rd Party技術の選択肢、ありがたいことに非常に沢山あります
 3rd Party 技術の評価

Slide 16

Slide 16 text

ありふれたアルゴリズム・技術要素なら標準も含め、ライブラリも複数あ る、でもどうやって選ぶ?
 ● GitHub stars ⭐ が多いもの?
 ● awesome-go に載っているもの?
 ● 技術記事(medium, dev.to, Qiita, Zenn, etc..)に載っている?
 ● Stack Overflow で教えてもらう?
 3rd Party 技術の評価

Slide 17

Slide 17 text

リストアップはしたとして、どのように比較する?
 Webサーバーのライブラリを例にしても大量にある。
 ● net/http (Go standard library)
 ● Gin (https://github.com/gin-gonic/gin)
 ● Echo (https://github.com/labstack/echo)
 ● Beego (https://github.com/beego/beego)
 ● Revel (https://github.com/revel/revel)
 ● その他多数・・・ 
 (2022/12月時点だと awesome-go の Web Frameworks には52個載ってる)
 
 3rd Party 技術の評価

Slide 18

Slide 18 text

自分たちに合う技術・ライブラリかどうかは外野の評判ではなく、自分たちにとって のメリット・デメリットを比較する。
 ● 必須機能を満たしているか
 ○ 単体・または組み合わせで技術的課題を解決できるのか 
 ● 便利機能や拡張性が、運用していくと役立ちそうか
 ● ドキュメントの量やコミュニティによる技術記事は適量か
 ○ コードベースが大きく難解なものであればあるほど、これらが充実していないと扱っていくの が難しい
 ○ 逆に、コードベースが小さく、シンプルであればコードを読めば済む 
 ○ チームの技術力によって相対的に変わる 
 3rd Party 技術の評価

Slide 19

Slide 19 text

比較要素
 ● メンテナンス体制は?
 ○ メンテナは誰?個人?企業?コミュニティ? 
 ○ 色々なケースがあるので、どの体制が良いとは一概に言えない 
 ○ 個別のライブラリについてメンテナンスの実態を把握しておきたい 
 3rd Party 技術の評価

Slide 20

Slide 20 text

比較要素
 ● メンテナンスの実態は?
 ○ issueやPull Requestは対応されているか 
 ■ バグ報告や機能提案の Feedbackを行ったときに対応されそうか 
 ■ issueが立っていないなら、いずれ自分が作成する側になるが、選定段階で確 認するのは難しい・・・ 
 ○ 必要に応じたリリースはされているか 
 ■ 機能追加とかは無くていいので、セキュリティ Fixが迅速におこなわれるか 
 ■ 毎年2回のGoの新バージョンリリースがあるので、互換性確認はされているか 
 ● メンテされているなら CIのtarget version等に追加が発生する 
 3rd Party 技術の評価

Slide 21

Slide 21 text

比較要素
 ● コードは読みやすいか?
 ○ Goはソースコードへのアクセスしやすい言語なのでドキュメントにない挙動の理解は ソースコードが頼りになる 
 ○ 奇抜なことをせずに、素直に実装してあるコードが読みやすい 
 ○ テストコードやExampleが充実していると読み解きやすい 
 ● 自分たちの環境と共通点を持つところでの利用実績があるか
 ○ システムの規模感など 
 ○ ちょっと試してみた系のブログ記事は沢山あるかもしれないが、多大なワークロード に耐えられるかのベンチマークが必要 
 3rd Party 技術の評価

Slide 22

Slide 22 text

比較要素
 ● ライセンス
 ○ Copyleft系ではないか? 
 ■ 商用コードとしては意図しないライセンス汚染をされないようにしたい 
 ○ 商用の場合のライセンスは?商用は別のデュアルライセンスではないか? 
 ■ その場合のコストは適正か 
 ○ No Licenseではないか?
 ■ ライセンス無しであれば、使ってはいけない 
 ■ ソース公開されていても利用許諾してないことになる 
 ■ どうしてもの場合は、メンテナにライセンス明記してくれと頼む 
 3rd Party 技術の評価

Slide 23

Slide 23 text

比較要素
 ● まずは小さく試してみる
 ○ サンプルがあれば動かしてみる 
 ○ プロトタイプとして使ってみたい箇所に組み込んでみる 
 
 評価の観点は色々あるけれど、カテゴリ毎に何十個と候補のあるGoのライブ ラリそれぞれについて丁寧に評価なんてしていられない!
 3rd Party 技術の評価

Slide 24

Slide 24 text

色々な考えはあるけど、メンテされなくなったときのことも考えてみよう。
 これから新しい技術、ライブラリを使うということで新しいものに対するワクワ クが先行して、メリットばかりに目が行きがち。
 しかし、OSSでも商用サービスでも、いつかは終わりが来る。
 今はイケイケの流行っているライブラリでも、2年3年後にどうなっているかは わかりません。
 終わることも考慮

Slide 25

Slide 25 text

Webライブラリの例だと
 ● net/http: メンテ◎
 ● Gin: メンテ△ (issues/PR が溜まりすぎて処理できていない)
 ● Echo: メンテ◎
 ● Beego: メンテ◎
 ● Revel: メンテ× (2019に入った頃からほとんど開発動いていない)
 ※個人の主観による判断です (2022/12時点)
 ● Gorilla Toolkit (gorilla/mux等) メンテ終了しました😢
 ○ https://github.com/gorilla/mux/issues/659
 ○ 2022/12/10にメンテしないことが決定し、アーカイブされた 
 終わりは身近なところに

Slide 26

Slide 26 text

メンテされなくなり、メンテを引き継ぐことも出来なければ、ライブラリのライフサイク ルは終わりに向かう。
 メンテされていないものを使い続けることはできない。
 そのとき代わりを用意しやすいかの指標が「捨てやすさ」。
 
 
 
 「捨てやすさ」を評価

Slide 27

Slide 27 text

捨てやすさのイメージ ・・・プログラムを構成するブロック ・・・捨てる必要が生じたプログラム 捨てやすい 捨てられない (運命共同体) 捨てづらい

Slide 28

Slide 28 text

以下の観点で評価が高い場合、捨てやすいと判断できる
 ● 解決したい課題を最小で解決してくれる
 ● 適切な抽象化がされたinterfaceが公開されている
 ● 標準ライブラリとの互換性や親和性が高い
 ● メンテを引き継ぐことができるコードライセンスである
 
 
 
 具体的に捨てやすいとは

Slide 29

Slide 29 text

● 必要な箇所で必要なデータを渡せば、求める結果をくれる
 ○ こちらのコードにそれ以上の干渉をしてこない 
 ● フレームワークと呼ばれるものはその逆で、こちらのコードの書き方、設 計を変更することを求めてくる
 
 自分たちの失敗例:
 ● wireがDI Frameworkだということを認識せずに導入し、コードの書き方が wireありきのも のになってしまった
 ● wireの不満があっても、からみつく鉄線のごとく抜けるのにはひと苦労しそう 
 1. 解決したい課題を最小で解決してくれる

Slide 30

Slide 30 text

interfaceを接点として、既存コードへの影響を与えずに差し替えることができる。 
 
 例えば、io.Reader, io.Writerは適切な抽象化がされているので、メモリ、ストレー ジ、ネットワーク等を扱う様々なI/O系ライブラリが依存している。
 そのため、ストレージの読み書きに使うとあるライブラリを捨てて、別のものに入れ 替えるといったことが容易にできる。
 
 
 
 2. 適切な抽象化がされたinterfaceが公開されている

Slide 31

Slide 31 text

● 標準ライブラリで再実装することが容易になる
 ○ Goがv1.0リリースから10年間、互換性を最大限保ってきたので、 Goの標準ライブラ リには安心して依存できる 
 ● GoのGin, Echoといった軽量Webフレームワークはほとんどnet/httpと 1:1での書き換えが可能なため、メンテナンスされなくなったとしてもダ メージは少ない
 ○ 逆にnet/httpでいいじゃないという Gopherが多い理由でもある 
 
 
 
 3. 標準ライブラリとの互換性や親和性が高い

Slide 32

Slide 32 text

4. メンテを引き継ぐことができるコードライセンスである メンテがされなくなって、代わりを探すことも、自前での再実装も難しいような 重要なライブラリならば、引き継ぐしかない
 ● 前のメンテナとかろうじて連絡が取れるならばメンテナにしてもらうことが できる
 ○ メイン業務を持ちながらアクティブなメンテナを続けるのも難しいが・・・ 
 ● ライセンスが改変、配布自由のいわゆるPublic Licenseであれば、自分 たちのorgにforkして必要なメンテナンスを続ける
 


Slide 33

Slide 33 text

以下のようなライブラリは、捨てやすい
 ● ライブラリの大きさが解決したい課題にフィットしてる
 ● 依存関係をコントロールできる
 ● 標準ライブラリをinterface互換で機能強化したもの
 以下のような場合は終わりが来ても継続して使える
 ● 引き継げるライセンス体系
 具体的に捨てやすいとは

Slide 34

Slide 34 text

まとめ

Slide 35

Slide 35 text

まとめ サービスを長期的に開発・運用していくために・・・
 ● 3rd Partyのライブラリを使うときは、利用できなくなるリスクにも目を向 けて、「捨てやすさ」も評価してみよう
 ● 捨てる必要が生まれたときにプログラム全体が崩壊しないようにするた めに、依存関係がシンプルになるコード設計をしよう


Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

おまけ

Slide 38

Slide 38 text

APIはこれだけやって初めて価値提供できたと言える
 ● 0. APIの基盤を用意する
 ● 1. APIの開発と公開 (社内の他サービスがそれぞれ提供する)
 ● 2. APIを利用するアプリ開発または連携機能実装 (社内または社外)
 ● 3. 連携機能を利用するユーザーが使う
 大元となる「0. APIの基盤」を早くリリースしないと、
 その後の価値提供に続かない󰝊💨
 API基盤を最速で提供する必要性

Slide 39

Slide 39 text

Ginがあまりメンテされていないというのはどうやって判断したのか?
 GitHubのOpenなissues/PRを確認
 https://github.com/gin-gonic/gin
 
 メンテあまりされていない例 475 issues の中には1年以上放置されているものも多数ある。
 それに対しアクティブなメンテナは2人。
 弊社内で、実際に使っていて困ったバグの issue/PRが存在しているが、1年ほど放置されている。


Slide 40

Slide 40 text

Revelがメンテされていないというのはどうやって判断したのか?
 
 メンテされていない例 GitHubのContribution Graphを確認
 https://github.com/revel/revel/graphs/contributors
 最初のメンテナが一通り作り上げて、停滞していたの を次の方が少しメンテナンスを続けていたが、今はほ ぼ触られていない。
 という状況が見える。


Slide 41

Slide 41 text

ホットリロードツールで freshやrealizeがよく使われていたが、もう何年もメン テされていない。(最近は代わりにairがよく使われるようになっている。)
 ※airはfreshがメンテされていないこと&機能面の不満により作られたと READMEにて説明されている
 - https://github.com/cosmtrek/air
 メンテされていない例は沢山ある

Slide 42

Slide 42 text

持ち直した例も
 gqlgenは一時期メンテする人がいなくなったが、「メンテされてないので は?」というissueをきっかけにコミュニティが復活した。
 ● https://github.com/99designs/gqlgen/issues/1571
 メンテされなくなった後持ち直すことも

Slide 43

Slide 43 text

捨てやすさを気にしない例外もある プロダクトの寿命が短期または長期化するか不明なときはその限りではない
 ● PoCのとき
 ○ なんでもいいので、まず動いて評価できないといけない 
 ● 新サービスで勝負するとき
 ○ まず動いて価値を届けることが必要