このイベントの登壇資料です 『ミノ駆動さんと語るエンジニア怪談〜技術的負債の呪いにどう立ち向かうのかLT〜』 https://forkwell.connpass.com/event/291332/
技術的負債の怨霊と除霊方法2023年8月24日株式会社スタメンミノ駆動
View Slide
こんばんは霊能力者ミノ駆動です
ミノ駆動エンゲージメント向上サービスを手掛ける株式会社スタメンで働いていますアプリケーションアーキテクトとして以下設計全般に取り組んでおります● 技術的負債の解消● アーキテクチャの再設計● 拡張性向上設計● エンジニアへの設計サポート(助言、提案など)@MinoDriven
著作紹介『良いコード/悪いコードで学ぶ設計入門』技術的負債を作り込まない変更容易性の高い設計を学ぶ初級〜中級向け入門書新卒エンジニアに最適です輪読会も多数開催されております発売14ヶ月で10刷重版発行部数 3万部 超え3万部記念で帯が付きました
ITエンジニア本大賞2023 大賞受賞
登壇及び受賞多数● Developers Summit 2021 Summer ベストスピーカー賞3位● Developers Summit 2023 話題賞1位● Developers Summit 2023 ベストスピーカー賞3位● Developers Summit 2023 ベストスピーカー賞5位● 昨年だけでも16回以上の講演依頼● 今年は毎月講演やインタビュー etc...
おしながき- 恐怖1 既存クラスに…- 恐怖2 使えそうなロジックに…- 恐怖3 リファクタリングに挑むものの…- 技術的負債の本質的な問題とは何か
【注意】技術的負債は霊のシワザであって人は悪くありません貶める意図はないのであしからず
恐怖1既存クラスに…
Aさん:既存の◯◯Managerクラスに新機能のロジック書いておきました。ぼく:ち、ちょっと。新機能なのにクラス追加しないんですか!?Bさん:え…クラス追加ですか? クラスって追加していいもんなんですか?Cさん:新しくクラスって要る? 動くもの書けてるんだからそれでいいじゃん。Dさん:クラス分けると一気に読み流せなくなるから俺はやらない(ドヤ顔
おわかりいただけただろうか
クラス追加拒絶霊
クラス追加拒絶霊- クラス追加を拒んだり、恐れたりする霊。- 霊の性格はさまざま。以下は各性格。- 既存クラスへのロジック追加を何とも思わない。- クラスを追加することに、何かよく分からない不安感や罪悪感を覚える。- 追加すること自体が悪だと考えているケースもある。- あまりにも先鋭化するとメソッド追加や変数追加すら拒むケースもある。
カプセル化 とは- データとそのデータに強く関与するロジックをひとまとめにして秘匿し、外部には正しい操作手段(メソッド)のみを公開すること。- なぜひとまとめにするのか:低凝集に陥り関連ロジックの追跡が困難になる、つまり影響範囲の調査工数が増大する。- なぜ秘匿し正しい操作手段のみ公開するのか:秘匿せず露出したままだと、不正な変更や意図しない変更を加えられ、バグになる可能性がある。- カプセル化の発想なき実装は、こうした弊害を作り込んでいることと同じ。- クラスはカプセル化の手段のひとつ。
クラス追加拒絶霊は神クラスを生み出す- 神クラスの正体はカプセル化が崩壊した世界。- クラスは、自身のメンバ(インスタンス変数、メソッド)を知っているし触れる。- 神クラスは自身のスコープが巨大すぎるために、自身のメンバがグローバルな性質を帯びる、つまりグローバル変数、グローバルメソッドめいてくる。- 秘匿されておらずありとあらゆる要素にアクセス可能な構造。カプセル化しない場合の弊害がさまざまな箇所で発生しやすい構造。
- カプセル化の意義も含め、メンバーの設計スキル向上が肝要。- 設計スキル向上には実際に手を動かして訓練する必要がある(本の読み合わせだけでは困難)。- プロダクションコードを用い、例えば★ミノ駆動本★記載の手法でコードを整理してみる、といった勉強会がオススメ。- 基本的にカプセル化を軸に除霊を試みる。クラス追加拒絶霊を除霊するには
「カプセル化」で通じなければ「セキュア設計」- カプセル化せずフルアクセス、フルコントロール可能な構造はWebサービスで全くセキュリティ対策せず、重要情報を誰でも触れて変更できるのと同じこと。- 自社のプロダクションコードをGitHubのパブリックリポジトリに置いておきますか?- 家の玄関や窓を全開にして外出できますか?- カプセル化で秘匿し正しい操作手段(メソッド)のみ公開するのは、玄関を施錠し、ドアホンで来客者を確認することと同じ。招かれざる客(不正操作)を排除する。- クラス=家に例えても良い。クラス作成はセキュアな家をひとつひとつ建築していくことに似ている。
- t_wadaさん「品質とトレードオフになっているのは学習コストなのではないか」- 厄介なのは成長する気のない人。まことに残念ながら一定数存在する。この場合せっかく学習コストをかけても徒労に終わる。除霊不能だが、封じることはできる(後述)。それでも除霊できない場合もある
恐怖2使えそうなロジックに…
Aさん:この追加仕様、どうやって実装する?Bさん:どれどれ。あー、それは(既存の)この◯◯メソッド内でフラグ生やして分岐で切り替えるだけでいけるっしょ。Cさん:あと、流用できそうなメソッド見つけたよ。仕様通りに動くように呼び出してパパっと実装終わらせようぜ。
流用霊
流用霊- ありあわせのロジックの流用や改造で動くものを作る霊。- 既存ロジックにフラグと条件分岐を埋め込むことを非常に好む。- 「流用する」「応用する」「再利用する」という言葉を好んで話す。- 使えそうなロジックをgrepする能力に異常に長けている。- grep能力がさらに先鋭化すると、ネット上で使えそうなサンプルコードを見つけ、サンプルのコピペと継ぎ接ぎで動くものを作ってしまう「コピペ霊」に変化するケースも。
通常割引価格割引率5% 夏季割引価格わたくしと同じ5%割引ですわ〜おDRY原則に基づいて再利用しますわ〜
通常割引価格割引率3% 夏季割引価格3%割引に仕様変更しますわ〜きゃあああああ!!!!!5%割引の仕様を満たせなくなりましたわよ!?!??- 割引率が多目的に使われてしまっており一方の仕様変更が別目的の仕様に影響を及ぼしてしまう- DRY原則とはコードの重複を許さないのではなく意図や目的の重複を許さない原則- 典型的な単一責任原則違反
通常割引価格割引率5%夏季割引価格割引率5%- 同じように見えるロジックでも目的の異なるものを共通化してはならない- こうすることで目的の異なるもの同士の仕様変更が影響しなくなる- 各クラスは多目的にならないよう単一の目的を達成する手段として設計する- 単一責任原則とは単一目的原則
再利用性は基本的に共通基盤開発のみ共通基盤(フレームワーク)固有アプリA固有アプリB固有アプリC再利用性を追いかけていいのは共通基盤のみ● DRY原則に則ると固有アプリのロジックは基本的に目的特化型● 再利用可能なものはほぼ皆無● 共通化可能なのは目的が同じロジックのみ
流用霊を除霊するには- 「流用しよう」「応用させてみよう」「再利用しよう」「共通化しよう」この手の声が聞こえたら要注意。流用霊の声である可能性が高い。- DRY原則の意義である「意図や目的の重複を許さない」に照らし合わせ、対象ロジックの意図や目的を確認すること。- 既存ロジックを意図や目的の違うものに流用、応用しないこと。- 意図や目的の違うロジック同士を共通化しないこと。- 開発対象がアプリケーションならば、基本的に再利用性を追いかけてはならない。- 開発対象がフレームワークならば、再利用性を追いかけて良い。
恐怖3リファクタリングに挑むものの…
Aさん:デザインパターンとか、書籍『リファクタリング』に書いてある方法でリファクタしてみたんだけど……Bさん:どうした?Aさん:なんか逆に余計に複雑になっちゃった感じでさ。やった意味があったのか疑問で。Bさん:偉い人が書いた本かもしれないけど、実務に使えないことはよくあるからね。うちらの開発には合わないんだよ。Aさん:そっか、そうだよね。やめた方がいいかも。
挫折霊
挫折霊- 設計やリファクタリングに興味を持ち始め、取り組んではみたものの、上手くいかず挫折してしまう霊。- または「どうせ上手くいかない」「うちらには合わない」と囁き、挫折させてしまう霊。
- 設計やリファクタリングのゴールを設定できていないことが原因。- 技術的負債は変更容易性と深い関係がある。- 変更容易性とはソフトウェア品質特性のひとつで、バグを埋め込まず、どれだけ素早く正確に変更できるかを示す度合い。- 技術的負債とは変更容易性が低い状態を指す。- つまり、変更容易性が高い構造がリファクタリングのゴール。
変更容易性このギャップが技術的負債変更容易性の高い構造を知らないと負債もゴールも認知不能これが挫折霊の正体
挫折霊を除霊するには- 変更容易性の高い構造を設計できるスキルが必要。- この設計スキルが手薄なまま書籍『リファクタリング』に記載のテクニックを表面的に真似てもあまり上手くいかない。- 凝集度、結合度、複雑度の他、SOLID原則やドメイン駆動設計など、さまざまな設計知見を深めることでリファクタリングの精度が向上していく。- 特に、次に紹介する方法の除霊効果が高くオススメ。
手段に対応する目的がたったひとつになるよう設計する
【目的】髪を乾かしたい【目的】目的地に早く移動したい【手段】【手段】手段たるシステムは目的のためにあり、作り出される目的はひとつだけ
【目的】食べ物を温めたい【手段】【目的】濡れた猫を乾かしたい食べ物を温める目的で作らたものであって猫を乾かすために作られたものではない
しかしソフトウェアの世界ではこうしたカオスを容易に作り出せてしまう
【目的】商品を売買したい
【大目的】商品を売買したい【中目的】商品審査したい【中目的】在庫管理したい【中目的】注文したい【中目的】配送したい大目的は中目的から構成される
在庫管理 配送注文商品審査ECサイト商品モデル多目的に対応するよう作れられた商品モデルは巨大化複雑化し品質上様々な弊害をもたらす
商品原材料構成部品匂い味審査品目品目分類審査所見審査結果サイズ重量抽出在庫品発注金額在庫量安全在庫量配送品サイズ重量注文品取扱開始日売値在庫量取扱開始日売値在庫量抽出抽出品目分類審査所見審査結果抽出発注金額在庫量安全在庫量原価予約開始日製造メーカー賞味期限目的ごとにそれぞれ必要な解決要素を抽出
在庫管理 配送注文商品審査ECサイト審査品目品目分類審査所見審査結果在庫品発注金額在庫量安全在庫量注文品取扱開始日売値在庫量配送品サイズ重量各目的に1:1で対応する特化モデルになる
【目的】商品審査したい【手段】商品モデル【目的】在庫管理したい【目的】注文したい【目的】配送したい
【目的】商品審査したい【目的】在庫管理したい【目的】注文したい【目的】配送したい【手段】審査品目【手段】在庫品【手段】注文品【手段】配送品手段に対応する目的はそれぞれたったひとつリファクタリングもこの考えをベースにゴール設定する
技術的負債の怨霊つまり本質的な問題とは何か
怨霊の正体は学習コスト- 負債が積み上がることがマズいのではなく、解消されない、解消する環境を作り出せないことが問題。- t_wada御大が仰るように、設計に関する学習コストが原因の根本にあると考える。- ゆえに、負債解消には学習コストを軸に開発戦略を組み立てる必要がある。- コアドメインなど、クリティカルな品質が求められる箇所には、単純な話、設計の学習コストが低い人、つまり積極的に設計を学ぶ人をアサインする。- 学習コストが高い人、つまり消極的な人は、クリティカルな品質が求められるスコープとは別の箇所にアサインする。また、多少品質の悪いコードが書かれても重要スコープに影響が生じないよう、アーキテクチャレベルで分離設計することも有効な手段。
ご清聴ありがとうございました