こんにちは! dely株式会社サーバーサイドチームの安尾です。
本記事はdely Advent Calendar 2019の5日目の記事になります。 qiita.com adventar.org
昨日は辻さんが「Jupyterもいいけど、SageMath使って可能性もっと伸ばそう!」という記事を書きました。 tech.dely.jp
本日は「スピード優先の開発で溜まった技術的負債の返済計画(サーバーサイド編) 」というタイトルで、今delyのサーバーサイドチームの技術的負債についての考え方から、負債返済のために具体的に行なっていることをご紹介したいと思います。
技術的負債とは
抽象的な言葉なので、組織や人によって微妙に定義が異なるのではないかと思いますが、僕たちのチームでは「未来の開発スピードを下げる原因となるプログラムやアーキテクチャのこと」を総称して技術的負債と呼ぶようにしています。
具体例を挙げると、
- 複雑で修正が困難なプログラム
- サービスがスケールした際にボトルネックになるアーキテクチャ
- テストが書かれていないプログラム
- メンテナンスされていないgemの利用
- 実装者の退職や異動によって、開発目的や正確な仕様がわからないプログラム
のようなものになります。
技術的負債に対する考え方
技術的負債というと、とてもネガティブなイメージをしてしまいがちですが、必ずしも悪いものだとは思っていません。 特にプロダクトのフェーズによって負債に対する考え方は大きく変わると考えています。
例えばまだユーザーが少ない新規サービスの場合、いかに高速にPDCAを回して資金がなくなるまでにサービスをマーケットフィットさせるかということが重要になります。
そういうフェーズのサービスにおいては、未来の開発スピードを考慮して、機能のリリースが遅れるくらいなら、あとで直さないといけないことが分かっていても早くリリースすることを優先することが合理的な判断だと言えることも多いでしょう。
クラシルにおいても、やはり立ち上げてからしばらくはスピード優先でガンガン開発してリリースするというスタイルを取っていました。
とは言え、その状態を続けていると負債の返済に追われて、追加機能や機能改善がだんだんできなくなってくるという状況が発生してしまいます。
クラシルでも大小含めてこれまでにも色々と問題が発生していましたし、今後何か問題が起こった際のインパクトや、これからだんだんエンジニアを増えていくであろうことを考えると、このまま前進し続けるより、一旦スピードを落としてでもある程度工数を使って負債を返しておくことで未来の開発スピードを上げられるという判断から負債の返済をチームの目標の一つとして取り組んでいくことになりました。
技術的負債返済計画
それでは、今サーバーサイドチームがどのような手順で負債返済を行なっているか紹介していきたいと思います。
1. 負債の洗い出し
もともと負債が色々と溜まっているという認識はそれぞれ持っていたり各自で優先度が高いと思っている部分についてはドキュメントにまとめたりしていたのですが、全体像を誰も把握できていない状態で負債を返済しようと言っても何から手をつけて良いか、また本当にそれが優先すべき負債なのかというのが分からない状態でした。
そこで、まずは負債を一通り洗い出すことで全体像を把握しようというところから始めました。 やり方としては、まず僕が過去に課題として話題にあがったものや思いつく限りの負債をスプレッドシートにまとめて、それをベースとして各自が思いつく限り追加していくという形を取りました。
なお、一度まとめて終わりににするのではなく、日々の業務で新たに発見された課題があればここに追記しアップデートしていくことで、なるべく課題が埋もれていかないように気をつけています。
2. 優先順位付け
次にそれぞれの負債に対して重要度を5段階に分けて優先度付けをするということをしました。 重要度の基準については一旦下記でいくことに決めました。この基準についても会社の状況によって変わってくると思うので、今はこれにしていますが、都度変えていけば良いかなと思っています。
- セキュリティインシデントの原因になる
- バグの原因になる
- アップグレードの妨げになる
- 開発スピードを落とす要因になる
- その他
洗い出した時点では大量にあって何から手をつけて良いか分からなかった負債一覧も重要度をつけてみると意外と本当に重要な負債は限られていることが分かってきました。
3. 担当決め
次に重要度が高いものを優先し、誰が何をやるかを決めました。 やり方は基本挙手制にしました。理由は単純で自分で取り組みたいものに取り組むのが一番モチベーションも上がるし、結果としてパフォーマンスも上がると思ったからです。
これをやった個人的な感想としては、課題によって求められるスキルが大きく変わるので、得意なものばかり選ぶのではなく各々が成長させたいスキルに関連するような負債を選択することで機能開発だけでは身につきづらいスキルをつけることができてとても良いなと感じています。
基本的に2、3の作業は四半期に一度目標設定の際に定期的にやっていく形にしようと思っています。
返済すること以上に未来の負債の予防がとても大切
たまった負債を返していくことはもちろん重要ですが、それと同じかそれ以上に、新規の開発がすぐに負債化しないように予防するということを僕たちはとても大切にしています。 新規開発で負債を予防するために色々と工夫しているのですが、今日はその一例を紹介していきたいと思います。
ルール決め、ドキュメント化を行う
サーバーサイドのエンジニアが1人2人のときにはあまり気になっていなかったことですが、3人、4人と増えるに連れて、ルール化されていない部分のやり方が違う部分というのが結構あることがわかってきました。
例えば、
- 管理画面のテストを書くかどうか
- Controllerにもmodelにも書きづらいようなコードをどこに置くか
- 新機能の実装時にどの程度のドキュメントを書くか
のようなことが人によって違うことが分かってきました。 短期的に見ると特に問題はないことかもしれませんが、僕たちはこういった細かい違いが属人化となり後々大きな問題となって返ってくると考えています。
なので、こういったルールがない部分を見つけるとこのままで良いのかを考え、後々問題になりそうだと判断したことについてはルールを決めてドキュメント化し、新しいメンバーが増えた際のオンボーディングで伝えるという運用をしています。
設計レビュー
僕たちのチームでは、新機能や機能改善を行う際には、サーバーサイド設計仕様書を書いて他のメンバーに共有して、実装に入る前にブラシュアップするということを徹底しています。
また、これはサーバーサイドのメンバーだけではなく、SREのメンバーも一緒にやることで、仕様を満たしているかということだけではなくその後中長期的に安定して運用できるかというような観点も含めてレビューをしています。
これをやることで1人で考えるよりもより良い設計になりますし、コードレビューやリリース前になって思わぬ問題に気づくというリスクを減少する効果もあります。
更にはドキュメントが残るので、実装時にいなかったメンバーでも、この機能はなぜ実装されたのか、どういう経緯でこういう設計になっているのかということを調べることが可能になります。
安易に管理画面に機能を追加しない、利用頻度が低い機能は削除する
割と最近決めたことではありますが、結構有効なのではないかと思っているのがこちらです。
エンドユーザーが使うアプリやWebに機能というのは、多くの方の目に触れて様々なフィードバックがあるので、徐々に洗練されていく傾向があるかと思いますが、社内メンバーが使う管理画面となるとそうではないので、エンジニアが社内からの要望に応えて気軽にどんどん機能を追加していった結果、誰も全体像が分からなくなってしまうということはよくあるのではないでしょうか?
クラシルにおいても時間と共に管理画面が肥大化し、誰も全体像が分からないというような問題が発生していました。 その対策を議論し、極端な話そもそもコードがあるから負債化するのでコードがなければ負債化しないよねということになり、できる限りコードを増やさない方法を考えようという取り組みをしています。
具体的には、月一以上の頻度で使われる機能については管理画面に残すけれど、それより低い頻度でしか使わないものは削除して、必要に応じてエンジニアが手動なりスクリプトなりで対応するという形です。 そうして機能は必要最低限にすることによって、次のステップとしてドキュメントを整備したり、足りていないテストを書いたりするのも楽になるし、CIにかかる時間も短縮されるという感じで副次的なメリットも色々ある取り組みとなりました。
最後に
本記事では、クラシルのサーバーサイドが技術的負債についてどう考え、どのように返済を行なったり、未来の負債を予防するためにどのようなことをしているかを紹介しました。 技術的負債に苦しんでいる方にとって少しでも参考になると嬉しいです。
また、サーバーサイドチームでは、一緒に技術的負債を返しつつ、中長期的な視点で開発・運用を行なってくれる仲間を募集しています!
これまで誰にも解決できなかった食や暮らしの課題を解決し、一緒に世界をより良くしていきましょう!!
次回は伊ヶ崎さんが「データサイエンティストと機械学習エンジニアをやって思ったこと」というタイトルで投稿します!