サービスを長期的にGoで開発・運用していくためにやっていること
by
yoske
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
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のとき ○ なんでもいいので、まず動いて評価できないといけない ● 新サービスで勝負するとき ○ まず動いて価値を届けることが必要