🍡

プロダクトを伸ばし続けるために技術的負債と改めて向き合ってみた。

2024/03/08に公開

はじめに

こんにちは、レバテック株式会社のCTO室でテックリードを担当している河村です!

今日は技術的負債と改めて向き合うために、技術的負債に対する考え方とレバテックではどのように技術的負債の返済を進めようとしているかについて、整理がてら記事にしてみました。

あくまで、個人的な見解も含まれている記事です。
技術的負債の定義もプロダクト、システム、環境によって変わると思います。それでも、世の中のエンジニアが少しでも幸せな開発体験に繋がればいいなと思い書きました!

※ 組織の観点については深くふれません。あくまでシステム目線のお話です(正直、そこまでふれられるほどまだまだ解像度が高くないです笑)

技術的負債ってそもそもなにか?

まずはChatGPTに聞いてみましょう。

すごく簡単にまとめると、技術的負債とは、
「ソフトウェア開発において、妥協してきた効率的でないやり方が借金のように溜まりに溜まり、保守性や拡張性が低下し、開発速度や開発者体験が低下すること」 
だと解釈できます。

妥協してきた効率的でないやり方は常日頃やっているなぁという印象はたしかにあります。
例えば、以下のようなことが挙げられるかなと思います。

  • テストを書くことや自動化することを後回しにする
  • RDBの外部キー制約やユニーク制約を考慮しない、NULL許容のカラムを作ってしまう
  • OS、フレームワーク、ライブラリのメンテナンスを行わない
  • ...

妥協してきた効率的でないやり方でいうと、開発以外でも以下のようなこともあるんじゃないかなと思います。

  • プロジェクトを少しでも進めるために人を増やす
    • 質よりスピードを優先してしまう(結果、早くはならない笑)
    • コミュニケーションの複雑度、リソースの競合が発生し、思わぬ品質低下を招く
  • 本来のプロダクト・サービスの理想像を考慮せずに、暫定で機能を開発してしまう
    • この機能に依存してしまい、本来作りたかった機能が開発しづらくなる
  • なんでもかんでも仕組みや業務を自動化してしまい、管理するシステムが増えすぎてしまう
    • その保守のために人を増やすが、本来進めたい部分に人は増えず、徐々にがんじがらめになっていく笑

という感じで、いろんな理由や背景で技術的負債は溜まってしまうものなのかなぁと思っています。

技術的負債が溜まるとなにが問題なのか?

これもChatGPTに聞いてみましょう。

「開発速度の低下」「品質の低下」「保守コストの増加」といったあたりは、かの有名なt_wadaさんの資料として質とスピードの中でも出てくる「保守性」といったところの話と近そうですね。

また、全体的に見ると、負のサイクルが発生する可能性があるとも考えられそうですね。

技術的負債による負のサイクル

そして、これらの問題が大きくなると、
プロダクト開発の観点で以下のような問題が発生します(これが一番辛い)

  • プロダクト目標達成が遅くなる
  • プロダクト目標達成ができなくなる

プロダクト目標達成ができなくなってしまうと、会社の経営としての目標も達成が難しくなってしまいます。だからこそ、技術的負債を返済していかなければいけないと考えています。

だけど、すべての技術的負債を返済するにはとても時間と工数がかかるものです。
そこで、技術的負債に優先度を設定して優先度が高いものから返済していくという判断が必要になります。
次に、技術的負債の優先度をどうやって設定するのかを考えてみたいと思います。

(技術的負債の返済計画とかはめもりーさんの技術的負債が生まれる背景を理解して,アーリーからレイター向けの根本的なアプローチを考えるとかShin TakeuchiさんのCTOの頭の中:技術を財務で表現するがめちゃくちゃ参考になりますね)

技術的負債の優先度ってどうやって設定するのか?

プロダクトやサービスを開発する上で重要な観点として、以下の2つがあると考えています。

  • プロダクト目標達成
    • プロダクトやサービスの目標を達成して経営や事業の目標を達成するため
    • この目標達成に必要なのがプロダクト開発
  • 継続的な開発・運用
    • 一度、リリースしたプロダクトやサービスは、継続して開発・運用する必要があり、この継続ができない状態だと経営や事業の目標にも影響するため
    • この目標達成に必要なのが開発者体験・開発生産性

上記2つを優先度に基づいたマトリクスで表すと、以下の図のように表現できます。

プロダクトやサービスを開発する上での優先度マトリクス

ここで、このマトリクスに技術的負債の観点を加えると、以下の図のように表現できます。
「プロダクト目標達成」と「継続的な開発・運用」において優先度が高い技術的負債 、それが優先度の高い技術的負債であると考えられます。

技術的負債の優先度マトリクス

「プロダクト目標達成」と「継続的な開発・運用」において優先度が高い技術的負債とはどんなものがあるのか?
それはプロダクトやサービスであったり、開発環境や技術スタック、さらには組織・体制なども関係し、一概に定義ができるものではないかと思います。ただし「プロダクト目標達成」のために必要であれば、経営目標を達成にも必要だということが言えます。

また「プロダクト目標達成」の優先度は高くないけど「継続的な開発・運用」の優先度が高いもの、これも定義ができるものではないけど、できる限り日々の改善活動でなんとか対応した方が良いと考えてます。
なぜかというと「プロダクト目標達成」に直接寄与しない対応となると、開発以外の方々(特に経営側)に説得するのが難しいからです...

プロダクト目標達成に寄与しない開発ってあるんか!?と言われるとなんとも言い難いですが😅

そのために、「20%ルールを設けて日々の改善活動で技術的負債を返済」を行ったり、
「短期的に集中して技術的負債を返済」を行っているところもあるのかなと思っています。

だからといって「継続的な開発・運用」の優先度が低いというわけではありません。
なぜなら、「継続的な開発・運用」を楽にすることでよりプロダクト開発にコミットできるようになるからです。つまり「継続的な開発・運用」を楽にすることは間接的にプロダクト開発の生産性向上に繋がります。

これでより、プロダクト目標達成に寄与しない開発ってあるんか!?とはなりますが、なにが重要かってどこを目指して開発するかってことなんですよね😇

簡単にまとめると、以下になります。

  • 「プロダクト目標達成」と「継続的な開発・運用」の観点から優先度を設定
  • 「プロダクト目標達成」と「継続的な開発・運用」双方の優先度が高いものを対応すべき
  • 「プロダクト目標達成」の優先度が高くないものは日々の改善活動で対応したほうが良い
  • 「継続的な開発・運用」を楽にするとプロダクト開発にコミットできるようになる

レバテックにおける技術的負債の返済

※ いろいろ前提や背景をすっ飛ばして説明します🙏

レバテックの事業(プロダクト)目標

レバテックは事業ポートフォリオ構想という戦略を掲げており、既存事業である「IT人材支援」をメインに、HRTech、教育、M&A、内製化支援など、社会・全産業の問題解決を加速させるため、様々なサービスやプロダクトの開発に取り組んでいます。

事業ポートフォリオ構想

その中でも「繋げる」領域がレバテックの中核を担う事業となっており、主にレバテックフリーランス、レバテッククリエイター、レバテックキャリアといったエンジニアと企業をマッチング=「繋げる」ような事業が該当します。

この「繋げる」領域の事業(プロダクト)において以下の”価値提供”を目指しています。
つまり、以下の価値提供を目指してソフトウェア開発を行っていく必要があるということです。

理想形を実現するために必要な価値提供

※ 上記の価値提供はまだまだ解像度が高くないため、絶賛、ロードマップを作成中です!!笑

レバテックの事業(プロダクト)目標を達成するための課題

上記の価値提供を目指すために、現在、レバテックのシステムが直面している課題が以下になります。

理想形と現状のシステムとのギャップ(課題)

今回の記事では簡単な説明だけして、詳細な内容の説明は割愛させてください。
(そろそろこの記事も飽きてくる頃だと思うので笑)

  • プロダクトの変更容易性
    • ※ 後続の章で説明
  • レバテック(共通)IDの整備
    • レバテックではユーザーに対して共通のレバテックIDというものを発行しています
    • ただし、登録の導線によってはIDを発行できない仕組みとなっており、ユーザーの判別が正しくできていない状況
    • そこでユーザーの登録導線や登録後の体験の見直しを行っています
  • リファレンスデータの策定と統一
    • スキルや職種といった”リファレンスデータ”がプロダクト間で異なっている状態
      • リファレンスデータ=スキルや職種など
      • マスタデータ=スキルや職種が紐づいたエンジニアや案件/求人など
    • このため、プロダクトやシステムを横断する時にマッピングが必要だったり、分析もしづらい状況
    • そこでスキルや職種といったレバテックにおける価値の高いリファレンスデータの策定と統一を行っています

プロダクトの変更容易性

プロダクトの変更容易性の低下となっている原因として考えているのが以下になります。

プロダクトの変更容易性低下の原因

「分散されたモノリス[1]」と「大きな泥だんご[2]」の2つがあるのやばくね?って思う方もいると思いますが、事業としての成長を最優先で行ってきた企業で、規模も大きくなる過程で技術的負債の返済ができていなければ、こんなものかなと思います笑

なので、個人的には「分散された大きな泥だんご」なんて表現が正しいのかなと思います😢

そして、これこそがレバテックにおける技術的負債であり、「プロダクト目標達成」と「継続的な開発・運用」双方の優先度が高い技術的負債であり、この返済のために必要なのがドメイン(業務)の理解だと考えています。

ドメイン(業務)の理解がないまま技術的負債を解決しようとしても、システムの技術スタックを変えるだけであったり、軽量DDD[3]みたいなことを行ってアーキテクチャだけを整えるだけみたいなことが発生し、根本的な技術的負債の返済につながらないケースが多くなってしまいます。
(技術的な課題だけであれば、全体の20~30%ぐらいは解決できるかもですが)

そこで、ドメイン(業務)を解き明かしながら技術的負債の返済を行っていくのですが、(きっと)ここで気になるのが以下だと思います。

  • なぜ「分散された大きな泥だんご」が出来上がったのか
  • 「分散された大きな泥だんご」に対してどういった戦略と戦術を行うべきなのか(行っているのか)

それはまた、この課題に対する解像度が上がった時に、整理がてらお話しさせてください笑

今を楽にするということも大事

先ほど、「継続的な開発・運用」を楽にするとプロダクト開発にコミットできるようになるというお話をしましたが、少しだけふれさせてください。

「分散された大きな泥だんご」を抱えた状態で開発を進める上で、一番、辛いことは「継続的な開発・運用」ばかりにコストがかかってしまい、プロダクト開発にコミットできないことです。
つまり、今の開発状態を少しでも楽にしないと根本的な技術的負債の解消は難しいということです。

「継続的な開発・運用」の中でコストがかかっているのが、「障害対応」と「メンテナンス」になります。具体的に以下のようなことを指しています。

  • 障害対応
    • インシデントや障害発生時の暫定対応
    • 再発防止のための恒久対応(根本的な解消はできていないが)
  • メンテナンス
    • OS、ミドルウェア、ライブラリ、フレームワークの定期的なアップデート

これらを少しでも楽にするために新しい技術や仕組みを導入することで、「継続的な開発・運用」を楽にしようと試みています。

  • O11y(Observability[4])による障害コストの削減
  • ノーコードツールを活用したテスト自動化による障害コストの削減
  • NewSQL[5]によるゼロダウンタイムの実現とメンテナンスコストの削減

上記の例はきっとレバテック開発部のだれかが記事にしてくれるか自分が書くと思うので、詳細は楽しみにしていてください!

(世の中にはいろんな技術的な手段があって、手段を検討するだけでも大変ですね😂)

まとめ

  • 技術的負債とは、妥協してきた効率的でないやり方が溜まり、保守性や拡張性が低下し、開発速度や開発者体験が低下すること
  • 技術的負債が溜まるとプロダクト目標達成が遅くなるまたはできなくなってしまう
  • 技術的負債の優先度は以下の観点を重要視している
    • 「プロダクト目標達成」と「継続的な開発・運用」の観点から優先度を設定
    • 「プロダクト目標達成」と「継続的な開発・運用」双方の優先度が高いものを対応すべき
    • 「プロダクト目標達成」の優先度が高くないものは日々の改善活動で対応したほうが良い
    • 「継続的な開発・運用」を楽にするとプロダクト開発にコミットできるようになる
  • レバテックでは上記をもとに技術的負債と向き合っている戦っている

さいごに

この記事を書いていて思ったことが1つあります。
それは 技術的負債の解消が「プロダクト目標達成のためなのか」それとも「DXのためなのか」 があいまいだなぁ〜と思いました。
昔から受け継がれてきた業務、今の時代に合っていないユーザー体験、自動化されていないプロセス、大きな泥団子になっているレガシーシステムなど、これらを改善することは「プロダクト目標達成のためなのか」「DXのためなのか」があまり理解できていないです。
なので、もう少しDXの解釈と技術的負債の解像度を上げてから、また記事を書いてみたいと思います。

(プロダクトであるものとプロダクトではないものにおける境界も難しいw)

脚注
  1. 分散モノリスは多数のサービスを持つが、すべてを同時にデプロイしなければならないため、何かを行うにはチーム間の調整が数多く必要となる状態(What is 分散モノリス(Distributed Monolith)より) ↩︎

  2. 理解可能なアーキテクチャが欠けているソフトウェアシステムのこと(大きな泥だんごより) ↩︎

  3. DDDにおける戦略的設計を取り入れず、戦術的設計のみを取り入れること(軽量DDDでもやったほうがいい理由、けどやらない理由より) ↩︎

  4. システム上で何らかの異常が起こった際に、それを通知するだけでなく、どこで何が起こったのか、なぜ起こったのかを把握する能力を表す指標、あるいは仕組みを指します(オブザーバビリティとは?監視との違い、必要性について解説より) ↩︎

  5. 従来のリレーショナルデータベース(RDBMS)のトランザクション性と整合性を保持しつつ、分散型システムのスケーラビリティとパフォーマンスを兼ね備えた新しいデータベースシステム(NewSQLとは?概要や特長を解説より) ↩︎

レバテック開発部

Discussion