3 ポイント 投稿者 GN⁺ 2024-10-01 | 1件のコメント | WhatsAppで共有
  • Riot Gamesは技術的負債を、将来の開発者がコストを支払うことになるコードやデータと捉え、League of Legendsの開発事例を通じて負債を判断するための共通言語を整理している
  • 評価基準は影響度、修正コスト、伝染性の3つで、とくに伝染性は負債が時間の経過とともにほかのシステム・データ・開発慣行へ広がる度合いを指す
  • 負債の種類は、内部実装に閉じたLocal Debt、2つのシステムを一時的につないだMacGyver Debt、深い前提が構造に埋め込まれたFoundational Debt、欠陥の上にコンテンツが積み上がったData Debtに分かれる
  • JarvanのCataclysm、std::stringとAStringの併用、BlockBuilderでのLua利用、block parameter naming bugが各タイプの具体例として使われる
  • 伝染性の低い負債は長く残しておいても問題ない場合があるが、伝染性の高い負債は時間がたつほど修正コストと影響が大きくなるため、早期に拡散経路を断つ必要がある

技術的負債を判断する3つの軸

  • 技術的負債とは「将来の開発者がコストを支払うことになるコードやデータ」である
  • ある負債を今直すべきか、後で直すべきか、現実的にそのまま残すべきかを判断するには、共通の測定基準が必要になる
  • Riotは技術的負債を3つの軸で評価する
    • impact: プレイヤーと開発者に与える影響
    • fix cost: 修正に必要な時間とデプロイのリスク
    • contagion: 放置したときに問題がどれだけ広がるか
  • impact: プレイヤーと開発者に表れるコスト

    • プレイヤーにはバグ、欠けた機能、予想外の挙動として現れる
    • 開発者には実装の遅延、ワークフローの妨げ、覚えておかなければならない不要な細部として蓄積する
    • ここでいう開発者にはエンジニアだけでなく、デザイナー、VFXアーティストなどゲーム制作に関わる職種も含まれる
    • ある負債はエンジニアの新規コード作成を妨げ、別の負債はデザイナーの新しいスクリプト作成やVFXアーティストの新しいパーティクル制作を妨げる
  • fix cost: 実装時間とデプロイのリスク

    • 修正コストには実際の開発時間だけでなく、変更をデプロイするときに生じるリスクも含まれる
    • 単一関数の単純な誤りなら数分で直せるが、ゲーム全体のコード行に影響する深い前提は数週間から数か月かかることもある
    • 「間違った」システムであっても、すでに優れたゲームを作るための道具として使われている可能性があり、直した瞬間に既存コンテンツが壊れることがある
    • たとえばスクリプトエンジンのエラー処理方式や、パーティクル生成時間の計算方法を変えると、140体以上のチャンピオンの500以上のスキルに影響する可能性がある
  • contagion: 時間とともに広がる度合い

    • contagionとは、技術的負債を放置した場合に、それがほかのシステム・データ・開発手法へどれだけ伝播するかを意味する
    • 伝播は、問題のあるシステムとのインターフェース、その上に積み上がったデータのコピー&ペースト、新機能の実装方法の変化によって起こる
    • 十分に隔離された負債は、後で直しても今直す場合とコスト差が大きくない
    • 伝染性の高い負債は時間がたつほど修正が難しくなり、より多くのシステムが中核的な妥協に感染するほど影響も大きくなる

Local Debt: 内部だけが雑然としたブラックボックス

  • Local Debtは古典的なブラックボックス型プログラミングモデルに近い
  • 外から見ればシステムは安定して動作するが、内部実装はひどかったり混乱していたりすることがある
    • 例: スキル、ネットワーク層、スクリプトエンジン
  • 周辺システムを開発する際に内部の負債を意識する必要がないなら、伝染性は低いほうである
  • 現実世界のたとえ: 人間の目

    • 人間の目は構造上、画像を上下逆に受け取り、網膜神経は各眼の中央付近に盲点を作る
    • 脳の視覚中枢がデータを反転し、盲点を埋めることで、脳のほかの部分が「正しい」画像と相互作用できるようにしている
    • この特異性は目と視神経のシステムに局所化されており、ほかのシステムが簡単に回避できるため、「十分に良い」状態といえる
  • Leagueの事例: JarvanのCataclysm

    • JarvanのCataclysmは現在に至るまでminionとして作られている
    • デザイナーは、特定の位置や位置の集合にゲームプレイ効果を付与するとき、「invisible minion」を生成するツールを使える
    • RiotXypherousはRedditのコメントで、ここでいう“minion”を説明している
    • こうしたゲームオブジェクトは、スクリプトロジックを追跡して実行するための安定した、よく理解された方法である
    • Jarvanの壁は、プレイヤーが抜け出せないようにするには正確に24体のminionが必要である
    • 以前は12体だったが、プレイヤーがときどき壁の間をすり抜けてしまうため、Riot Exgeniarが24体に増やした
    • 代替案は、Cataclysmのpathabilityを制御する単一のロジック片であるring-terrain構造で、ロジックを整理し、計算コストをわずかに下げられる可能性がある
  • Cataclysmの評価

    • impact: 1/5
      • 壁がminionで作られているという事実は、新コンテンツを作るほかの開発者にはほとんど影響しない
      • 「Jarvan Ult Hitch」は、この負債と、欠落したauto-attack定義を読み込もうとしたローディングバグが組み合わさった結果だった
    • fix cost: 2/5
      • 現在は、新しいコードなしに合成図形でカスタムジオメトリを作ることはできない
      • ring形状の「area trigger」を作るには、ringの衝突計算用の専用数学コードが必要になる
      • Riotは別目的でConstructive Solid Geometryを調査しており、これによって修正コストを大きく下げられる可能性がある
    • contagion: 1/5
      • 機能開発時にJarvanの壁の実装を考慮する必要がなく、よく隔離されている
      • 伝染リスクは、ほかのデザイナーがこの実装を新チャンピオンへコピー&ペーストする場合で、実際にときどき起きていた
      • 実装上の問題として、Cataclysmの潜在的な拡散は低く、よく理解されている
  • Local Debtへの対処法

    • Local Debtの典型的な特徴は、contagionスコアが低いことである
    • impactがfix costより高ければ、善良な市民のように振る舞う開発者は長く放置される前に修正する傾向がある
    • 本当に伝染性がないなら、必要なだけ長く残しておいても安全である
    • エンジニアの完璧主義を刺激する一方で、十分に広い影響を持たないLocal Debtに即座に飛びつくのは、大きな誤りのひとつである
    • 変更範囲が局所的なため、修正確認とリグレッションテストはたいてい容易である
    • 最近修正された例には、inhibitor関連のバグ、Janna’s Monsoon、Tear of the Goddessが含まれる
      • 特定の状況でinhibitorがチャンピオンを0,0,0座標へpathingさせてしまうバグ
      • Janna’s Monsoonがspell shieldを無視していた問題
      • Tear of the Goddessがマナのない詠唱でもスタックしていた問題

MacGyver Debt: 2つのシステムをダクトテープでつないだ状態

  • MacGyver Debt は、1980年代半ばのテレビ番組 MacGyver にちなんで名付けられた類型
  • 技術的負債の文脈では、衝突する2つのシステムがコードベース全体のインターフェース箇所で「ダクトテープ」でつながれている状態を指す
  • 現実世界の比喩: Seattle

    • Seattle には、かつてそれぞれ独自の区画グリッドを持つ2つの競合する入植地があった
    • その2つの入植地が現代の Emerald City へと成長する中で、少し異なるグリッドが結合され、いびつな形の街区や建物、非効率な空間利用が生まれた
  • League の事例: std::string と AString

    • League のコードベースには、C++ の std::string と Riot 独自の AString クラスが共存している
    • どちらも文字列を保存、変更、受け渡しするための方法である
    • Riot は、std::string が多くの「隠れた」メモリアロケーションと性能コストを引き起こし、好ましくないコードを書きやすくすると考えている
    • AString は、慎重なメモリ管理を念頭に設計されている
    • 代替戦略は、2つのシステムを併存させたまま .c_str().Get() を通じて相互変換できるようにする方式だった
    • AString には使い勝手を高める改善が追加され、エンジニアがコードを変更する際に自発的に std::string を置き換えるよう促された
    • この方法により、std::string はゆっくり段階的に姿を消し、2つのシステム間の「ダクトテープ」インターフェースもコード整理とともに減っていく
  • std::string vs AString の評価

    • impact: 2/5
      • std::string で発生していた高影響のアロケーションの大半は、profiling を通じてすでに取り除かれている
      • 現在の主なコストは、片方のシステムからもう片方へ変換するときに生じる小さな認知的切り替えコストである
    • fix cost: 3/5
      • AString への移行は単純な find-and-replace ではない
      • AString には、stack メモリに初期割り当てする AStackString、static string 参照用の ARefString、heap 割り当てベースの AString など、用途別の派生がある
      • 正しい置き換えには、人が各箇所を直接見て判断する必要があり、既存システムを段階的に除去する過程は長く遅いものになるだろう
    • contagion: -2/5
      • AString を std::string より使いやすくすることで、contagion を有利な方向へ反転させた
      • エンジニアがゲームコードの変更をチェックインするたびに、AString がさらに広がる可能性が生まれる
  • MacGyver Debt を解消する方法

    • MacGyver Debt の大きなコストは、境界をまたぐたびにモードを切り替えなければならない 知的コスト であることが多い
    • バグや機能が「wrong」 system 側にあって行き詰まる場合、目標地点を「right」 system 側へ移す作業はおおむね直接的である
    • 新システムと既存システムの相対的な contagion が重要な指標となる
    • 新システム側がより伝播しやすくなるようにバランスを反転させれば、より優れたシステムが最終的に勝つ
    • グローバルに優れたシステムが、ローカルなレベルでもより魅力的に見えるようにしなければならない
    • 時間に追われるエンジニアが日常業務の中で貪欲な最適化を行いながらも、望ましい最終状態の側を選ぶなら、それは良い方向に進んでいるということだ
    • もう1つのアプローチは大規模な brute-force リファクタリングであり、システム同士がどれほど近くマッピングできるかによっては、巧妙な regex で一部または全部を修正できる場合もある

Foundational Debt: 深い前提が全体構造に埋め込まれた状態

  • Foundational Debt とは、システムの深い部分にある何らかの前提が、全体の動作方式に焼き付いてしまっている状態を指す
  • システムの経験豊富な利用者はこれを「ただそういうもの」と見なすため、気づきにくいことがある
  • 現実世界のたとえ: United States Customary Units

    • アメリカで育った人は、1マイルが5,280フィート、1クォートが2パイント、1ガロンが4クォートといった換算を覚えることになる
    • アメリカ政府はメートル法への移行を何度も検討してきたが、今なお Système International を公式な計量体系として採用していない7か国の1つである
    • この負債は、道路標識、レシピ、小学校、人々の頭の中にまで焼き付いている
  • League の事例: BlockBuilder と Lua

    • Riot が扱ってきた大きな Foundational Debt の事例としては、Determinism in League of LegendsGame Data Server がある
    • League における Lua scripting language の使用も、Foundational Debt の一例である
    • League のデザイナーは BlockBuilder というツールで機能ブロックをつなぎ合わせ、複雑な動作を作る
    • 機能ブロックには、点間距離の計算、minion の生成、damage の処理、さまざまな script flow control が含まれる
    • デザイナーが選べる演算の集合は多様ではあるが制限されており、各演算のパラメータにも制約がある
    • League of Legends の初期には、ブロックとパラメータをデータに適した単純で制約のある形式で保存するのではなく、強力ではあるもののこの目的には過剰に複雑な Lua 言語の arrays と tables で保存することが決定された
    • その後およそ10年にわたるゲーム開発がその基盤の上で進み、Lua object の操作はエンジン内で最も一般的な作業の1つになった
  • BlockBuilder Lua の評価

    • impact: 4/5
      • Lua とその問題領域の不一致は、多くのコストを生んでいる
      • BlockBuilder ロジックの各 frame ごとに、callstack はおよそ6つの marshalling stack frame によって汚染される
      • marshalling の作業は、server CPU 使用量の観点で安価ではない
      • script の変更 diff を読む作業が不必要に難しい
      • 機能を把握するために script file を parsing/searching するには、Lua 言語についてかなり深い理解が必要になる
    • fix cost: 4/5
      • Lua はエンジンに深く埋め込まれているため、取り除くのが難しい
      • 現在提案されている案の1つは、Lua object のように振る舞うが内部的にははるかに単純な struct である wrapper class を作り、scripting の内部をより適した形へと徐々に変えていくことだ
      • どのようなアプローチを取るにしても、慎重かつ思慮深く進める必要がある
    • contagion: 4/5
      • システムが scripting と接するたび、そのシステムは Lua backend の演算と要件によって形作られる
      • scripting は LoL の中核となる logic の単位である
      • Riot は平均して約3〜4日ごとに新しい Building Block を追加しており、各 Building Block は Lua object を直接操作する
      • Lua の置き換えを先延ばしにすればするほど、Lua を置き換えることはさらに難しくなる
  • Foundational Debt を減らす方法

    • Foundational Debt は、impact、fix cost、contagion の3軸すべてで高いスコアを示す傾向がある
    • fix cost が高いと、不完全なシステムを使い続けることになり、ときにはそれが正しい選択であることもある
    • しかし、impact と contagion も高いため、深刻な Foundational Debt を修正できれば大きな見返りが得られる可能性がある
    • Riot で観察された最も一般的な修正戦略は、新しいシステムを既存システムの横に構築することだ
    • 可能であれば、既存の foundational debt を MacGyver Debt に変え、conversion operation を通じて新旧システムを行き来しながら徐々にポーティングする
    • この方法なら、特定領域で利点を得始めながら、リスクへの露出を抑えられる
    • このような移行が不可能な場合は、compile time switch、可能であれば loading time switch を作り、新しいシステムへの信頼を築けるようにする
    • compile time switch の方式は GDS 移行 で使われている
    • loading time switch の方式は Determinism で効果があった

Data Debt: 欠陥の上に大量のコンテンツが積み上がった状態

  • Data Debt は、他のカテゴリの技術的負債の上に多くのコンテンツが積み上がると発生する
  • 出発点は、scripting system のバグ、item に適していない file format、互いにうまくかみ合わない 2 つのシステムなどでありうる
  • そのコード欠陥の上に、art、scripts、sounds のような大量のコンテンツが作られると、初期の技術的負債を直すことが非常に危険になる
  • 時間がたつほど、何が壊れるのか把握するのが苦痛なほど難しくなる
  • 現実世界の比喩: DNA

    • 生物の genome は、数百万年にわたって mutation、transcription error、evolutionary pressure を通じてゆっくり積み重なってきた
    • ある複製エラーは役に立たないが無害であり、あるエラーは有害であり、またあるエラーは強力な利点をもたらす
    • DNA 断片が実際に何をしているのかを突き止めるのは非常に難しい
    • base pair が何を意味するのか、base pair の集合が protein construction のための amino acid にどう翻訳されるのかについては、完全に理解している
    • DNA の一部の non-encoding role についても、より多くのことが分かり始めている
    • しかし、人間の genome にある 30 億個以上の base pair には、いまだほとんど理解できていない部分が多い
    • Radiolab の CRISPR エピソード は、最近解かれたそうしたパズルの 1 つを扱っている
  • League の事例: block parameter naming bug

    • League of Legends の Data Debt は、もともとは些細な修正で済んだはずのことを骨の折れる作業に変えてしまうときに最も大きな影響を及ぼす
    • game engineer たちは、ゲームシステムの実装方式について深い知識を蓄積し、どのコード変更がどのデータを壊すかを予測することに熟練している
    • Data Debt は、LoL engine を変更する際の最重要考慮事項の 1 つである
    • 数年前に修正された Data Debt の事例は、BlockBuilder scripting language の block parameter に関するバグだった
    • toy example では、Owner の armor を変数と定数で増やそうとすると、期待値は変数 Delta 20 と定数 5 を足した 25 bonus armor になる
    • 変数名が parameter 名と同じだと、以前は結果が 40 になっていた
    • なぜ 45 にならなかったのかは、筆者にも分からないという
  • 実際の修正プロセス

    • Champions team のエンジニア NoopMoney がこの挙動を直そうとしたとき、実際のコード修正は 4 行削除 だけだった
    • しかし、伝染性の高い負債は、小さな変更であっても徹底した計画を必要とした
    • LoL の 400,000 行の script のどこかにある numerical parameter が、このバグによって 2 倍になっている可能性があった
    • さらに大きな問題は、ゲームがその潜在的に 2 倍になった値に合わせて balance と tuning されていたため、それらの script が“correctly”動作していたことだった
    • NoopMoney は、予期しないバグに備えて、fix を Live で toggle 可能にしておく必要があった
    • どの script がこのバグに依存しているかを特定するために、広範な regex searching と QA sweep を実施した
    • 最終的に、修正による問題は比較的小さく、少数の champion script だけが変更を必要とした
    • Data Debt のため、結果の予測は難しかった
  • Parameter Naming Bug の評価

    • impact: 2/5
      • 発生時の影響は小さかった
      • 渡された値を 2 倍にし、定数を無視する可能性があった
      • これを知ったデザイナーやエンジニアが覚えておかなければならない、もう 1 つの無用な tribal knowledge になった
      • developer mindshare は、このように浪費するには価値の高い資源である
    • fix cost: 2/5
      • 全体として、修正自体は直接的だった
      • live feature toggle を作ることで、fix の安全性への確信を高めることができた
      • 最もコストが高かった部分は、テスト対象を決めるために問題範囲を評価する初期 screening だった
    • contagion: 4/5
      • このバグが不運だったのは、非常に論理的な行動を狙い撃ちしていた点だった
      • unit に damage を与えるなら、値を “Damage” という変数に保存するのは完全に理にかなっている
      • ApplyDamage block が同名の parameter で amount を受け取ることで、バグが発動した
      • 別の人が似た spell を作るためにその block を copy/paste すると、バグはさらに広がる
  • Data Debt の伝染性が高い理由

    • Data Debt は変更の影響評価を難しくするため、一般に修正コストが高く見積もられる
    • さらに懸念されるのは、data の性質上、ほぼ常に非常に高い伝染性を持つことだ
    • 既存の data を copy/paste して新しい data を作るやり方が、一般的に許容されている
    • 新しい skillshot spell を作るとき、Ezreal’s Mystic Shot から始めれば大幅な時間短縮になるが、既存 data の問題もその子孫 data に伝播する
    • data は code review に相当する技術レビューをほとんど受けないため、悪い慣行が広く知られていても、その拡散に気づいて止めるのは難しい
    • data の問題を直すには、通常、目と頭脳を持つ人が直接検証しなければならず、compiler と formal logic だけでは不十分である
  • Data Debt を直す 2 つのアプローチ

    • 1 つ目のアプローチは do it right checkbox である
      • data creator のために、既存の “broken” behavior と新しい “fixed” behavior の間で toggle を作る方式である
      • 理想的には fixed version をデフォルトにし、old content には broken version を使わせる
      • その後は MacGyver Debt のように、ゆっくりと着実な replacement によって新バージョンへ移行できる
      • 欠点は、editing UI に不要な要素を次々と追加してしまう恒久的なコストが発生する点である
    • 2 つ目のアプローチは just fix the damn thing である
      • NoopMoney が parameter naming bug に使った方式である
      • バグを修正した後、意味のある影響を受けるすべての data を直そうとする
      • より怖くなくするための手法としては、theoretical impact を理解するための大量の grep と regex searching、targeted testing、ship 後により深刻な見落としが見つかった場合に備えて従来の挙動へ戻す toggle の用意がある
      • Determinism は、変更前後でサーバーが同じ結果を生成するか確認できるため、この種の変更テストに大いに役立つ

まとめ: 伝染性をコスト評価に含めるべき

  • 技術的負債の測定指標は impactfix costcontagion である
    • impact は顧客と開発者への影響である
    • fix cost は時間とリスクである
    • contagion は問題の伝播度合いである
  • ほとんどの開発者は impact と fix cost を定期的に考慮するが、contagion の議論は比較的少ない
  • contagion は、問題が深く入り込み、ますます取り除きにくくなるとき、開発者にとって最悪の敵になりうる
  • 逆に、fix のほうを問題よりも高い伝染性にできれば、contagion を武器に変えられる
  • League で見られた技術的負債の大半は、4 つのカテゴリのいずれかに整理できる
    • Local Debt: 中身が散らかった black box のような負債
    • MacGyver Debt: conversion function で 2 つ以上のシステムがダクトテープのようにつなぎ合わされている負債
    • Foundational Debt: 全体構造が不幸な前提の上に作られた負債
    • Data Debt: 他タイプの負債の上に膨大な data が積み上がり、修正が危険で時間もかかる負債

1件のコメント

 
GN⁺ 2024-10-01
Hacker News のコメント
  • 伝染性こそ、インターフェースが設計における最重要要素の一つであり、十分に考え抜くべき理由そのもの
    美しいインターフェースに最適ではない実装が付いているなら、時間ができたときに簡単に整理できるが、その逆はほとんど成り立たない

    • 同意するが、きちんと設計しようとすると、たいてい次のどちらかが欠けている。設計する時間、そして今日と1年後に正確に何をすべきかについての知識
      ときには両方ともない
      こういう場合、小さなモジュールと単一責任を組み合わせとして強制すると、伝染がひどくなりすぎるのを防げる。未来の知識や多くの時間は必要なく、複数の振る舞いのバリエーションをパラメータで制御する、ロシア人形のような表面積の広いインターフェースを避ければよい。設定、パース、振る舞いの決定はロジックの端へ移し、下位モデル全体に染み込ませないほうがよい
    • 同意するが、堅牢で将来に強いインターフェースを設計することは、ソフトウェア開発で最も難しい問題の一つだった
      技術的負債を何としても避けようと意識して始めても、正しくやるのは難しく、単なる技術的自信やアーキテクチャのビジョン以上のものが必要になる。実際には未来予測の領域に入る
    • 良いインターフェースを表に出すには、良い内部実装がどのようなものかを理解している必要がある
      愚かな実装をインターフェースに暗黙のうちに焼き込んでしまうと、実装だけを変えても直せなくなりがちだ。思い浮かぶ例はソートとページネーションの挙動だ。ジュニア開発者や、今ではもっと分かっているべき多くのシニアでさえ、limit/offset系のパラメータを使うリクエストから始めることが多く、これはひどい性能問題や異常な挙動につながる。ページネーションが効率的に動く方法と、性能よくサポートできるソートオプションは、データの形とデータストアの選択に本質的に結び付いている。低い層でこの過程を経験していない人は、実装を先に十分掘り下げない限り、上位インターフェースをまともに作れる可能性は低い
    • だから OCaml や Ada のように、インターフェースを非常に明示的にする言語が好きだ
      ほとんどの場合、実装は見たくなく、きちんと文書化されたインターフェースだけを見たい。インターフェースの挙動を簡単な言葉で説明できないなら、何かが間違っている
    • 歴史には反例がかなり多いように見える
      QWERTY は最適な物理インターフェースではないことで有名だし、ハンドルも似た例になり得る。コンピュータの世界では、x86 が表面的には最適でないインターフェースの代表例だ
  • この記事をエンジニアリングマネージャーが書いたというのはかなり驚きだ
    一緒に働いたマネージャーの中で、私たちのコードベースをここまで技術的に細かいレベルで語れる人はいなかった。以前エンジニアだった人たちも同じだった
    ただ公平に言えば、社内昇進のマネージャーがおらず、私を含め社内の人間はエンジニアリングを辞めたがらないので、外部からマネージャーを採る悪い習慣がある

  • 私が見てきた最も一般的な負債の種類が抜けている気がする。創業者負債
    創業者たちが、速く価値ある技術を出すために作った負債だ。低く垂れた果実に見えたものが、システム全体の土台になってしまうケース
    多くの国の建国文書もこの範疇に入る lol(ただし USA! USA! USA! は違う)
    マクガイバー負債と基盤負債が最も近いが、どちらもこの現象を正確には捉えていない

  • 技術的な観点から見て素晴らしい記事だ
    ただ、これは「分類体系」というより命名法に近いと思う。意図的に網羅的でも相互排他的でもないからだが、私が間違っているかもしれない。各項目の物理的な例は特に良く、考えるきっかけになる
    いつものように、哲学的には些細に引っかかる部分がある。冒頭の「三つの軸」は、伝統的な ROI のリターンと投資に、特定の未来志向・条件付きリターンの下位カテゴリを加えたもののように見える。この判断は実際にはうまく機能したのだろうと思うし、ビデオゲーム開発の慣行が絶対的に科学的である必要はないが、哲学的な確かさがもう少しあっても悪くはない

  • 当時も議論されていた。
    A Taxonomy of Technical Debt - https://news.ycombinator.com/item?id=16810092 - 2018年4月(コメント113件)
    そしてこちらもある。
    A Taxonomy of Tech Debt (2018) - https://news.ycombinator.com/item?id=39782923 - 2024年3月(コメント1件)

  • 「技術的負債を、将来の開発者がコストを支払うことになるコードやデータとして定義する」という説明は、私が見た中でも最高に近い
    あらゆる負債と同じく、負債を負うときには、差し迫った必要性と将来コストのバランスを取るしきい値を適用すべきだ。ほとんどの人は、開発者に限らず、差し迫った必要性を過大評価し、将来コストを過小評価すると感じる
    個人的には、どんな種類の負債もほとんど病的なほど嫌っている。将来役に立つかもしれないものを切り出すのに、さらに1日使うこともある。当たるのはだいたい50%くらいだが、そういう作業をするたびに習慣が強化され、基本的な作業フローも速くなる

  • これまで「スタートアップ」3社で働いたが、いずれも普通に近い給与を払えるだけの売上が出た後に参加した
    最もよく見たのは、複数の創業者が自分が思いついたアイデア、実際に作られたもの、実装された部分のうち実際に動くものを、ぼんやり混同して理解していることだ

  • この記事を初めて読んで以来、技術的負債を説明するときに伝染性という言葉を使ってきたが、かなりしっくり来る

  • 「局所的負債」を普通の状況で技術的負債と呼べるのか、よく分からない
    現実的には、どこかには常に汚い部分があり、それをカプセル化して誰も傷つかないように隠しておくのは普通のことだ。要件が変わらない限りほとんど変更する必要がなく、変わればどんな実装でも修正が必要になるなら、それでよい
    例にある24個のミニオンインスタンスが単に洗練されていない程度ではなく実際の問題だとすれば、「ミニオン」が最も単純な基本単位になってしまっていて、もっと軽い何かがあり得たという点で、むしろ基盤負債に近いように見える

    • 記事でも少し触れているが、コストは実際に作業しなければならないときにそれを理解するための認知コストであり、そこにツールを同じ状態に保つコストも加えたい
      開発者に、古く成熟していて触る必要のないモジュールまで含めて変更するよう促せば、これが問題になるほど積み上がらないようにする良い方法になる
  • 重要な側面の一つは、短期的な利益を得るために意識的に技術的負債を負う場合だ
    そうなると、その利益も一緒に天秤にかけるべき別の軸になる

    • 実際の借金とまったく同じだ
      15年後に資本ができるまで待たず、今すぐ新しい建物を建てて仕事を終わらせたいなら?借金すればよい
      負債は道具だが、強力で危険な道具だ。使っていることを認め、敬意を払わなければ怪我をする。あるいは、あなたから手榴弾を受け取った誰かが怪我をする。実際の借金と同じように
    • こういうものを「技術的負債」ではなく戦術的負債と呼ぶのを聞いたことがある
    • たいていはスピードのためだ