クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

システムと金の関係を改めて考えてみる

この記事はクラウドワークスアドベントカレンダー1日目の記事です。

クラウドワークスでマネジメントとかプロダクト戦略とか色々やっている@ysk_118です。
11月は実は登壇3連戦で、ちょうど昨日のデブスト2019が最後でした。というわけでちょっとぎりぎりになってしまいましたが、クラウドワークスアドベントカレンダー今年もやっていきます!

なぜこの記事を書こうと思ったか

f:id:yo-iida:20191201224857p:plain

最近は経営の議論なども色々理解が進んできたので金の話も考えるようになってきたのですが、そこで「うわ、私の理解浅すぎ...?」と思ったのが、

このシステムは持続的に金を生み出していけるのだろうか?

ということです。

というのも、先日の通期決算でも出ているようにサービスの売上は成長していっていますが、以前の記事で書いている通りコードの総量や変更量は鈍化傾向にあり、複雑化したシステムの中に見えていない技術的な負債・リスクがどれくらいあるのか?それによってこの先売上の成長が鈍化するリスクがどれくらいあるのかがあまり科学できていない、ということに気づいたためです。

よくある見積もり

さて、みなさんはシステムを開発する前に見積もりはしているでしょうか?

プロダクトオーナーなどビジネス的に責任を持つ人はある施策でどれだけ売上のインパクトがあるか試算をするかと思います。
また、プロダクトオーナーの要求に対し開発チームはそれがどれくらいの期間でリリースできるのかを見積もります。*1

例えば、あるシステムを作り売上が1000万/月作れると試算し、開発チームはそれを3ヶ月でリリースできると見積もったとします。
議論を簡単にするため開発チームに80万/月のプロダクトオーナー, エンジニア, デザイナーが計5人いたとすると、開発にかかる人件費は80万×5人×3ヶ月で1200万です。リリース後2ヶ月目には(営業)利益が出るという計算になります。*2

では、このシステムは持続的に2ヶ月目以降には利益を生み出し続けることができるでしょうか?

リリース後起こる問題

メンテナンス費用が見積れていない

当然ながらシステムは作って終わりではありません。リリース後にバグが見つかったり、使っているライブラリのバージョンアップをしなければいけなかったりメンテナンス費用がかかります。

上記の例で開発チームがそのままの体制で継続すると運用費用として400万/月が残りますので利益が出るのは3ヶ月目以降になります。

それだけならいいのですが、この観点で問題となるのがリリース後継続的に機能改善を目的とした追加開発を計画する場合です。

プロダクトバックログで追加開発対応とバグ対応やバージョンアップ対応などを一列に並べて優先順位順に実装を進めるチームは多いと思いますが、そのうち追加開発費用とメンテナンス費用のバランスを取りながらKPI設計しているチームはどれくらいあるでしょうか?
追加開発の側面しか見ずにKPI設計を行ってしまうと、EOLが発表されてバージョンアップなどの対応が差し込まれた時にKPIを外すリスクが発生してしまいます。
弊社でもこのような維持管理の活動に対する見積もりのコミュニケーションはまだまだできていないことが多いため改善中のコミュニケーション設計についてはまた別の機会に書きたいと思います。

開発チームの入れ替わりを想定できていない

組織は常に人の入れ替わりを考慮しておく必要があります。開発当初はチームで認識を合わせて進めますが、後から入って来た人がすぐにオンボーディングできるかどうかはドキュメントや設計、利用している技術スタック次第で変わります。

開発した直後は運用できていても、実装者がいなくなった後、誰もメンテナンスできない状態になるというのはありがちな問題です。

費用観点では、アーキテクチャ設計にどれだけの費用をかけるか、また新しい技術にチャレンジする場合、それを技術的投資と捉えるのならばその投資の回収プロセスはどうするのかまで検討する必要があります。
きちんと組織で新しい技術に対し知見を広める、誰でも運用できるようにする、その結果プロダクト開発の生産性が上がる、といった回収プランまで考えられていないと技術的投機となってしまい後に負債化してしまいます。

技術的負債の考慮ができていない

設計にどこまで費用をかけるかとのトレードオフな部分もありますが、たいていのシステムはリリース時点で何かしらの技術的負債*3を抱えています。機能の追加開発を継続的に行っていくならなおさら技術的負債の取り扱いに注意する必要があります。

短期的に捨てる前提のシステムであれば雑に作り、期待する利益を回収したあと捨てるという戦略も十分にあり得ます。この場合、運用中に発生するコード変更のしにくさは一定の生産性を毀損していますが、システムを捨てる期限までの期間で元が取れることが見積もることができれば問題ありません。

一方、中長期にユーザーに価値があり追加開発をしていく前提のシステムであれば、定期的に技術的負債を返済することを計画として織り込まなければどんどん負債は大きくなり、いずれ返済できなくなってしまいます
技術的負債の返済費用はコード量に対して線形に増加するのではなく、大きくなればなるほど影響範囲が予測しづらくなるため心理的な負担も含めると返済費用は二次関数的に増加していきます。
実際に複雑な箇所の改修は、予測できなかったトラブルが発生して切り戻しのリリースを何度もやるといったケースもあります。技術的負債の返済はコード量に対して利子のように返済費用が大きくなっていくと捉えておくべきでしょう。

これらが費用としてどう表れるかというと、

  • 追加開発前提で引いていたKPIがリリーススピードの低下によって達成できない
  • システムのパフォーマンス劣化が発生しユーザーが離脱し、KPI達成されない

といった具合で売上のコントロールのほうに影響が出ます。

システム開発にかかる金

以上の問題を踏まえると、システム開発にかかる金は開発費用(イニシャル, ランニング)と売上以外にも以下のようなものを考慮すべきです。

  • 開発費用
    • 人件費
    • 外注費
    • 外部サービスの初期費用
  • 運用費用
    • インフラや外部サービスのランニング費用
    • テクニカルサポート(ユーザーからの問い合わせ調査対応など)
    • メンテナンス(バージョンアップ対応など)
    • 機能改善
  • 技術的負債
    • 機能の変更容易性を下げる負債要素
    • 機能のパフォーマンス劣化を発生させる負債要素
  • システムが生み出す売上
    • システムが稼働することによって自社に入る売上

システムの寿命

システムは何かの機能や体験を提供するわけですが、システムが利用される環境は時間とともに変化していきます。そのため、ユーザーに受け入れられ支持を得てから状況が変わりユーザーから使われなくなっていく寿命があると考えるべきです。

機能改善を行いユーザーのニーズの変化に対応していくことができる場合システムの寿命を延ばすことができますが、常に追加開発できる費用がかけられるとは限らないため何もしなかった場合の寿命もしくは確認のマイルストーンを考えておけると良さそうです。

システムと金の持続性

以上の変数を整理すると、システムが存続する期間全体で、

開発費用 + 運用費用 + 技術的負債返済費用 < システムが生み出す売上の総額

となっていることがシステム全体が利益を生み出している状態と言えます。

技術的負債をどのように見積もるか

さて、ここまで技術的負債の返済費用を見積もってKPI設計に盛り込めば勝つる!というテンションで書いてきましたが、残念ながらこの見積もりは難しく、こうやればいいというものはありません。

しかしながら参考にできそうな指標はあります。

現在クラウドワークスでは冒頭に述べた通り開発生産性をいかに上げるかが課題となっており、プロダクト全体を俯瞰的に捉えリファクタリング戦略を推進する専任チームを発足してリファクタリングを進めています。

そのチームでは技術的負債をどれくらい減らしたかをCodeClimate Qualityによって計測しています。取り組みの詳細はこちらの記事を参照ください。

CodeClimate Qualityではファイル単位でRemediation Timeという指標を計測してくれます。これは日本語にすれば修復時間ですが、技術的負債を解消するのにかかる時間をCodeClimateの基準で数値化してくれているものです。

この指標の算出には、メソッドやファイルなどのサイズ、ネストした制御構造などの制御フロー、メソッドやブーリアンロジックの複雑性、コピペコードの検出など10の観点で解析を行っているようです。

codeclimate.com

crowdworks.jpのモデルの中で最も複雑なモデルはjob_offer.rbという3000行近い巨大クラスが存在するのですが、CodeClimateによるとこのファイルのRemediation Timeは2weeksだそうです。感覚的にはまったく同意できない(笑)ので、あくまで参考値にしかならなさそうですが、実際の返済費用をRemediation Timeに係数をかけて見積もってみるというアプローチはできそうです。

f:id:yo-iida:20191129214019p:plain

目的はいかにKPIの計画に技術的負債の返済費用を織り込むかなので、正確な見積もりを出すことよりもモニタリングすることが重要だと考えます。

また、すべての技術的負債を盲目的に返済しつづける必要があるかというと、そうでもないとも考えています。なぜなら、残念ながらプロダクトのほとんどの機能は使われていないからです。コアとなるプロダクトの重要な機能は全体の2割くらいであるというパレートの法則を考慮すると、リファクタリングの活動もそこに集中したほうが費用対効果が高そうです。

まとめ

経営寄りの視点から業績とシステムの生み出している価値の関係を考えてみると、これまで見えていなかったギャップがありそうだなと感じ、このような整理を考えてみました。

まだ実践できているわけではないのでこれがどれくらい妥当性があるかはわかりませんが、今後も引き続きシステムの持続性について様々な観点から考えていきたいと思います。

明日はTerraform職人の@minamijoyoがtfupdateについてなにかいいことを書いてくれます!

*1:近年はNoEstimatesといった考え方もありますが、上場企業という仕組みの上では業績予想とそこに向けての軌道修正をいかにやるかが求められますので、ユーザーに価値を素早く届けることとそれによって業績がいかに伸びるかを広い視点でコントロールしにいくことが必要になります。

*2:人件費を売上原価に含めるのか販管費に含めるのかは細かい状況によって異なりますが、本題とずれるため深掘りしません。ここでは販管費として扱っています。

*3:技術的負債が適切な表現かは議論の余地がありますが、ここでは様々な理由により発生する、後々の開発生産性(変更容易性など)やシステムのパフォーマンスを下げるソフトウェアの複雑性を指します。

© 2016 CrowdWorks, Inc., All rights reserved.