Skip to content

Instantly share code, notes, and snippets.

@mike-neck
Last active January 11, 2020 05:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mike-neck/0674f0f942295225275c349abbe06675 to your computer and use it in GitHub Desktop.
Save mike-neck/0674f0f942295225275c349abbe06675 to your computer and use it in GitHub Desktop.
『レガシーコードからの脱却』 随時更新予定

プラクティス1 - やり方より先に目的、理由、誰のためかを伝える

  • プロダクトオーナーがちゃんとプロダクトバックログを管理する
  • ストーリーは「誰が」「何をする」「なぜならば」を記述する
  • 受け入れテストを設定して、自動化する

プラクティス2 - 小さなバッチで作る

  • ストーリーは小さなタスク(4時間以内に終わる)に分割する
    • 複雑なストーリーは単純なストーリーに分解する
    • 既知のことと未知のことに分解する
  • フィードバックサイクルを短くする
    • コンパイルを頻繁に行う
    • ビルド時間を短くする
    • イテレーションを短くする
  • 計測する
    • コーディングに使った時間
    • リリースまでの時間
    • 機能ごとの顧客価値
      • 機能がない場合の価値
    • 欠陥密度
    • フィードバックループの効率

プラクティス3 - 継続的に統合する

  • 作業の完了 = 自分のマシンでビルド可能 + メインブランチに統合/ビルド + クリーンで保守可能(読みやすくリファクタリングされている)
  • 継続的にビルド/デプロイ可能にしておく
    • ビルドも自動化しておく
    • ビルドに必要なものはすべてバージョン管理する
    • 自動テストを書けるようなコードを書く
      • 自動テストに投資する
      • テストが難しいコードは設計の悪さの表象
    • 壊れたビルドはすぐに直す
  • 早期から頻繁に統合する
    • 常にリリース可能にでなければスクラムのプラクティスであってもウォーターフォール
    • 統合を先延ばしにするとより辛くなる
    • ブランチは避けてフィーチャーフラグを使う
  • 不明な技術などの調査は短時間で行い未知と既知を分離する(スパイク)
  • 頻繁に検証する/小さく作る
    • 価値の8割が2割の機能でできている場合、2割の機能をリリースする

プラクティス4 - 協力し合う

  • 個人プレーよりもチームプレー
    • IBM の事例 - 個室を与えられた社員よりも、大部屋にいる契約社員のほうが多くのことを成し遂げた
    • ケント・ベックのコンサルティング - オフィスのレイアウトを変更して大部屋にした
  • プログラミングは社会的な技術活動
    • ゴールの定義、「品質」の意味、「完成」の意味、「設計」のための共通言語、デザインパターン、リファクタリングなどのプラクティスなど、活動のための共有
  • ペアプログラミングのメリット
    • 名前付けの相談
    • アイデアの検証
    • お互いに学び合う
    • ペアで作業しているところに割り込みのタスクは発生しづらい
  • ストロングスタイルペアリングのルール
    • コンピューターにアイデアを伝えるまでに、他の人の手を経由しないといけない
  • バディプログラミング
    • ペアプログラミングへの導入
    • 1日の最後の1時間だけお互いの成果をレビューしあう
  • その他の協働のプラクティス
    • スパイク
      • 未知の課題解決のために複数の開発者が時間を限定して1つのタスクに取り組む
      • 図を書いてわかっていることを丸で囲うようにすると進捗がわかりやすい
    • スウォーミング
      • チーム全体 or 複数のメンバーで同一の問題に取り組む
    • モブ
  • コードレビュー
    • ペアプログラミングをしていても他のメンバーによるコードレビューは必要
    • 設計を採択した理由をレビューで議論する。チーム全体が設計を理解してトレードオフやアプローチについて語れるようにする
  • 学習し続ける
    • 常に誰かのメンターであれ、常に誰かのメンティーであれ
    • メンバーの知識を常に広げていくこと、自分の知識を常に広げていくことが安定して成し遂げるチームにつながる

プラクティス5 - CLEAN コードを作る

  • CLEAN コード
    • C - Cohesive 凝集性
      • それぞれの部品は 1 つのものだけを扱う
      • コードの理解が捗る
    • L - Loosely Coupled 疎結合
      • オブジェクト間の関係性(状態)を一定に保ち、利用者・提供者が間接的にしか依存しあわない
      • 結果として再利用・実装の入れ替え、機能の拡張が容易になる
    • E - Encapsulated カプセル化
      • 利用者の観点でインターフェースを設計することで、内部を秘匿する(名前も含まれる)
    • A - Assertive 断定的
      • 自分自身で自分の状態を管理する(オブジェクト指向入門におけるクラス不変表明のことと思われる)
      • 断定的でないコードは好奇心旺盛にも絶えず他のオブジェクトの状態を参照する(getter 呼び出しと思われる/別の言い方だとトランザクションスクリプト)
      • 振る舞い・処理のあるところにデータもある
    • N - Nonredundant 非冗長
      • 意図しない冗長性はコードの保守性を下げる
      • 複数の場所でやり方に関係なく同じことをしようとしているコードが冗長なコード
  • 明日のベロシティを上げるためには今日のコード品質をあげる
  • コード品質をあげる戦略
    • 品質の定義を明確にする
      • 機能 or 読みやすさ or メンテナンス性 or 拡張性
    • 品質のためのプラクティス共有
    • 良い名前をつける
    • 常にテスト可能に保つ
  • 保守しやすいコードを書く戦略
    • コードの共同所有概念
      • コードスタイル、ドメインモデル、開発プラクティス、設計概念
    • リファクタリングを常に行う
    • ペアプロ、モブプロ
    • コードの読み書きの練習を行う
      • スティーヴン・キング「作家になりたいなら…たくさん読み、たくさん書くことだ」
      • ヘニー・ヤングマン「練習、練習、また練習」

プラクティス6 - まずテストを書く

  • テストの種類
    • 受け入れテスト - 顧客テスト
      • ストーリーの振る舞いを明確にしたもの
      • どうなれば完成と言えるかの基準
      • Gherkin(Given/When/Then)で記述する
    • ユニットテスト - 開発者によるテスト
      • ストーリーより小さいユニットをテストする
    • QAテスト - その他のテスト
      • コンポーネント間の結合状態を確認する結合テスト
      • 機能テスト - E2E の振る舞いを検証するテスト
      • シナリオテスト - ユーザーがシステムと対話するテスト
      • パフォーマンステスト - 極限状態をテストする
      • セキュリティテスト - 脆弱性を検証
  • テスト駆動開発は QA の代わりではない
    • 開発を駆動する(これから〜〜の仕組みを作りますをサポートする)ためであって、品質保証のためではない
    • テスト駆動開発はテストと実装を行き来することによってフィードバックをもらいながら実装する方法
    • ユニットテストのユニットとは独立した検証可能なふるまいのことであり、メソッド、クラスと言った単位の意味ではない
      • 振る舞いがかわらないならばクラスを変更して良いし、そのことでテストは変更されない
    • テスト駆動開発はテスト可能なコードを書くための最も近道
  • テスト駆動開発のアンチパターン
    • IO も使おうとする - IO の抽象化、インターフェースを導入して、ユニットの振る舞いに注目する
  • ここまでの説明を読むと、ユニットと言っているのは、ユースケースのようなオブジェクトの相互作用を扱うレイヤーを指しているように思われる
  • ソフトウェア開発は何を作りたいか(インターフェース)を明らかにした後に、どうやって作るかを考えるようにするとテスト駆動開発が自然になる

プラクティス7 - テストでふるまいを明示する

  • 過去の仕事の手直しに開発者の時間の半分以上が費やされている
  • テスト駆動開発のテストは QA の目的を満たせるわけではない
    • QA は開発の段階で考えていないようなケースもカバー可能にすること
    • いったん QA のマインドセットは横においておく
    • ふるまいに基づいてテスト駆動開発のテストを書き、動くようになったら、 QA の考え方でテストを書き、他の問題がないか探す
    • QA テストはコードが機能するようになってから追加するほうが効率的
  • テスト駆動開発は設計方法論であり、テスト、メンテナンスしやすいコードに導く
  • ハードコードされたパラメーターは使わない(20 ではなく int age = 20 としてから age を使う)
  • バグから学習する
    • バグを修正した後、バグが入る要因となった設計とプロセスの問題点を修正する
  • テストはふるまいを文書化した仕様のようなもの

プラクティス8 - 設計は最後に行う

  • 変更が難しいコードの諸特徴
    • カプセル化の欠如
    • 継承の過度な利用
    • 抽象的でない実装
    • コピペコード
    • 互いの実装に依存し合うコード
    • オブジェクトの生成と利用が同一箇所にあるコード
  • 開発が持続可能なコードの諸特徴
    • 死んだコードがない
    • 名前が更新されている(プログラマーの学習によりコードの機能が少しずつ変わるため、その時々によって名称も変わる/過去のいきさつを名前に残さない)
    • 判断を集約する
    • すべての外部依存が抽象化されている
    • クラスが整理されている
  • ソフトウェアは書く回数より読む回数のほうが多い
  • 移譲できる処理は移譲して、抽象レベルの揃っているコードにする
  • 循環複雑度は減らす(if/switch/for/while/例外)
  • オブジェクトの生成と利用が同一だと、カプセル化が壊れる
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment