Showing 84 Result(s)

レガシーコードからの脱却 まとめ – 12.9 – 12.9.1

12.9 実践しよう 12.9.1 創発設計をマスターする7つの戦略 内容 創発設計のための効果的な戦略を7つ紹介。 戦略 説明 オブジェクト指向を理解する オブジェクト指向言語を使っているからと言って、オブジェクト指向を理解していると思うな。うまくカプセル化したエンティティを作り、解決する問題を正確にモデル化すべし。 デザインパターンを理解する デザインパターンはふるまいを分離するのに有効。創発設計の中でパターンが明らかになってくる。 テスト駆動開発を理解する テスト駆動開発は、修正した際のセーフティネットであり、創発設計をサポートする。 リファクタリングを理解する リファクタリングは創発設計に大きく関係している。コードを整理していく中でパターンが見つけられるためだ。 コードの品質にフォーカスする コードは「CLEAN」(高凝集、疎結合、カプセル化、断定的、非冗長)に保たなければ、すぐに保守不可能になる。 情けはかけない 必要に応じて設計を変える勇気を持て。思い入れた設計を捨てる勇気を持て。 良い開発プラクティスを習慣にする スクラム、XPのようなアジャイルプラクティスは、創発設計をサポートする有効なツールだ。が、アジャイルプラクティスが設計してくれるわけではない。良い設計は、プラクティスの背景にある原則を理解した上でプラクティスのサポートを受けるべきだ。 学び 12章の総集編 学びを活かすアイディア・行動 テストコードの目的の事前知識整理 コーディング規約づくり

レガシーコードからの脱却 まとめ – 12.7

12.7 生成と利用を分離する 内容 生成と利用を分離することで、利用する側のコンポーネントが独立し、テストをしやすくなる。 オブジェクト指向言語では、オブジェクトを生成してからオブジェクトを利用する。生成のみ行うオブジェクト群と利用のみ行うオブジェクト群に分け、生成と利用のフェーズを分けることには意味がある。 ファクトリーオブジェクト生成するオブジェクトをファクトリーと呼び、newをカプセル化する。 ポリモーフィズム利用するオブジェクトは、ポリモーフィズムというテクニックを使って、実装の中身を意識せず、目的の得たい結果だけを意識して利用する。インターフェースだけに依存しインターフェースを実装した具体的なサブクラスとの依存を切り離すテクニック。これにより、インターフェースを実装したサブクラスに依存しない独立したコンポーネントにすることができる。サブクラスとの依存がなくなると、インターフェースのモックを用意すればよいだけになりテストがしやすくなる。(さまざまなサブクラスを考慮したテストにならなくて済む。) 学び 生成と利用を分離することで、利用する側のコンポーネントが独立し、テストをしやすくなる。 このあたりってモジュールのあり方を考えるための設計原則が関係していて、デザインパターンの理解のために必要な知識だと思う。完全に理解した状態からチョットワカル状態になっていくための必要な考え方だなぁとフと思った。 学びを活かすアイディア・行動 現場のコーディング規約づくり。どのクラス群が生成を担い、どのクラス群が利用を担うのか。

レガシーコードからの脱却 まとめ – 12.6

12.6 循環複雑度を減らす 内容 循環複雑度はコードの実行経路の数。 条件分岐がなければ、循環複雑度は1。条件分岐が1つの場合、異なる2つの経路があるので循環複雑度は2。2つの場合は4、3つの場合は8。。。 循環複雑度は幾何級数的に大きくなる。大きければ大きいほど条件パターンが増え、注意が行き届かなくなる場合があり、バグの発生率が高くなる。 なので少ないに越したことはない。 しかし、常に1にすることはできない。条件分岐を使わないことは実質ありえないからだ。循環複雑度を減らすテクニックとして、インスタンスの生成やメソッドの利用にポリモーフィズムを使う。そうすることで、プログラム上の条件分岐がなくなる。 学び 循環複雑度はバグの原因になるからなるべく減らそう。ポリモーフィズムを使っても減らすことができる。 循環複雑度は常に1にはできないよ。 学びを活かすアイディア・行動 現場のコーディング規約づくり。

レガシーコードからの脱却 まとめ – 12.5 – 12.6

12.5 意図によるプログラミング 内容 API、メソッド、サービスなどを外部に公開するとき、メソッドの中に実装を入れることはしない。実装は別のメソッドに移譲する。こうすれば、コードが読みやすくなる。 このテクニックを「意図によるプログラミング」と呼んでいる。(へー、そうなんだ) なぜ読みやすくなるのか?抽象レベルと具象レベルで観点が切り分けられ、観点に一貫性が出るから。抽象レベルでは「目的」を、具象レベルでは「やり方」を見ることができる。 抽象レベルを読み進めることで、プログラムの大枠の文脈を読むことができる。必要に応じて具象レベルの具体的な方法を読めば良い。 12.6 循環複雑度を減らす 循環複雑度はコードの実行経路の数。 条件分岐がなければ、循環複雑度は1。条件分岐が1つの場合、異なる2つの経路があるので循環複雑度は2。2つの場合は4、3つの場合は8。。。 循環複雑度は幾何級数的に大きくなる。大きければ大きいほど条件パターンが増え、注意が行き届かなくなる場合があり、バグの発生率が高くなる。 なので少ないに越したことはない。 しかし、常に1にすることはできない。条件分岐を使わないことは実質ありえないからだ。循環複雑度を減らすテクニックとして、インスタンスの生成やメソッドの利用にポリモーフィズムを使う。そうすることで、プログラム上の条件分岐がなくなる。 学び パブリックにするものは抽象レベルで定義すると、大きな文脈で読むことができるプログラムになりやすい。 「意図によるプログラミング」というワードでググってもわかりやすい情報は出てこない。。 循環複雑度はバグの原因になるからなるべく減らそう。ポリモーフィズムを使っても減らすことができる。 循環複雑度は常に1にはできないよ。 学びを活かすアイディア・行動 現場のコーディング規約づくり。抽象レベルの切り分けルール。 現場のコーディング規約づくり。

レガシーコードからの脱却 まとめ – 12.3 – 12.4

12.3 コーディング対クリーニング 内容 コーディング・・・特定のタスクの解決方法を探す作業。テストを通すことに集中する。 クリーニング・・・動くコードを保守可能にする作業。扱いやすくすることに集中する。 それぞれ、別のタスクとして捉えて進めたほうが効率が良い。 技術的負債は短期的にも長期的にも返済を続ること。短期的には、テストファースト開発のリファクタリングステップにて。長期的には、チームの学習をコードに取り込むための定期的なリファクタリング作業の中で。 それでも技術的負債が溜まり続けてしまう場合もある。新しい機能を実装するために設計変更が必要だったり、単にもっと良いやり方を思いついたりする場合だ。その場合、通常数か月ごとに、大規模なリファクタリングを行い、技術的負債の返済作業を行う。この場合でも、ユニットテストが助けとなる。 12.4 ソフトウェアは書かれる回数より読まれる回数のほうが多い 平均してコードは書かれる回数の10倍読まれる。効率性、拡張性のために読みやすくなければならない。コードは自分のためではなく読み手のために書け。 コメントの注意点1わかりやすくするためにコメントを書くことがある。注意点として、コードが「そうなっている理由」を書くのは良いが、「やっていること」を書くのは良くない。「やっていること」はコードで表すべきだ。まず、冗長である。そしてコメントの運用の手間が二重になり、コメントの修正漏れによりコードとの差分が生まれる可能性が発生する。どちらが本来正しいのかがわからなくなる。 コメントの注意点2「わかりにくい理由」を書く前に、一度わかりやすく出来ないか設計を考えよう。 学び 技術的負債のタイミングは、以下3つ。 テストファースト開発のりファクタリングステップ、 チームの学習をコードに取り込む定期的なリファクタリング、 それでも溜まってしまう技術的負債を解消するための大規模なりファクタリング コードは平均して、書かれる回数の10倍読まれる。読めるように書こう。 学びを活かすアイディア・行動 大規模なリファクタリング計画と実施 現場のコーディング規約づくり

レガシーコードからの脱却 まとめ – 12.1 -12.2

12.1 変更しやすさへの障害 内容 変更しにくくする要因としてアンチコーディングパターンを紹介。これを知ることは、変更しやすくする原則を実践することと同じくらい重要。 障害 説明 カプセル化の欠如 知るべきでない内容を知ると、そこに依存性が生まれ、影響範囲が増える。そして後に、意図しない改修しにくさにつながる。 継承の過度な利用 間違った継承は無関係な機能の依存を作り、影響範囲を広げる。 具体的すぎる凝り固まった実装 意味が限定的すぎると、修正箇所が特定しづらくなる。 インラインコード コードをコピペすると冗長になるので、メソッド化してメソッドに良い名前をつけなさい。 依存性 カプセル化の問題と同じ。依存の方向に気をつけること。 作ったオブジェクトを使うか、使うオブジェクトを作るか サブタイプのインスタンス化を行ってしまうと、具体的な依存関係が発生しカプセル化が壊れる。一番やっていはいけない。 12.2 持続可能な開発 12.1と比べて、持続可能にするためのコードの保守性を高くするプラクティスを紹介。 プラクティス 説明 死んだコードを消す コメントアウト化されたコード、未使用なコードは不要に開発者の注意を奪う。消すべし。コメントアウトはバージョン管理システムで行うこと。 名前を更新する 開発が進むにつれてコードに変更が入り、当初の意味から変わる可能性がある。そういうときは名前のリファクタリングも忘れずに。 判断を集約する ? 抽象化 すべての外部依存性には抽象によって行う。そうすれば限定的な依存関係でなくなるため、テストが簡単になる。 クラスを整頓する モデルからエンティティが抜け漏れることがあり、辻褄があわないときがある。どこに追加するべきか整理して進めよう。 学び ソフトウェアは、リリースされてからも比較的簡単に修正ができる。そのため、ハードウェア業界と比べると間違うことが許されている。しかし、小さなほころびは、積もり積もると大きなコストになり、改修が難しかくなる。修正ができるからと言って、間違って良いということではない。良いものを作るための緊張感は忘れてはいけない。 カプセル化、抽象化はかなり重要で、名前変更やクラス整頓はリファクタリングしながら進める。 学びを活かすアイディア・行動 現場のコーディング規約づくり

レガシーコードからの脱却 まとめ – 12, 12.8

12章 プラクティス8 設計は最後に行う 内容 ソフトウェア開発では、保守性の設計は最後にしたほうが良い傾向がある。プロジェクトの終盤の方が、システムの全体に対して理解が深くなっており、適用させるデザインパターンの判断もしやすくなる。実現の手段として、ユニットテストのサポートを受けながら、再設計とリファクタリングを行う。 反復開発は設計を創発する。創発とは、最初の設計よりも開発が進むに連れ、もっと良い設計が見えてくることを指す。 12.8 創発する設計 原則として、テストファースト開発を行いながら、理解容易性、テスト容易性に注意を配りながら開発していけば、修正しやすいプログラムになり、あとから生まれた設計を取り込むことも、テストがサポートしてくれる。 創発した設計を取り込むことができないということは、修正がしづらいことを意味し、それを続けているといずれ保守可能でないシステムになり、システムはビジネスの拡張についていけなくなるし、エンジニアたちも苦しむことになる。 学び 保守性を加味した設計とリファクタリングは、テストが書かれている前提であれば、プロダクトの全体像が見えるプロジェクトの後半が適している。 テストファースト開発は創発した設計を取り込むことができる。 最初に設計しきるのは現実的ではない。だから、創発した設計を取り込めるプロセスを作ることが重要だ。 学びを活かすアイディア・行動 まずは実践し、メンバーに手法として展開する テストコードの目的の事前知識整理

レガシーコードからの脱却 まとめ – 11.12.2

11.12.2 バグを修正する7つの戦略 内容 バグ修正は大きなコストとなる。そのための7つの戦略の紹介。 戦略 説明 そもそもバグを作らない そのまま。ツールを駆使してヒューマンエラーを減らそう。 できるだけ早くバグを見つける 自動回帰テスト環境を作ってフィードバックを早くし、バグ発見を早くしよう。 バグを見つけられるように設計する カプセル化されていれば、バグは特定しやすくなる 正しい質問をする まず何が正しいのかを明確にする。その次にどこにギャップが有るのかを明確にする。 バグをテストの不足とみなす バグを見つけたら修正する前に失敗するテストを書き、その後にコードを修正する。バグは誤った想定のもと起きるので、まず何が誤った想定なのかを把握し、ユニットテストで具体化する。そうすることで二度と再現しなくなる。 欠陥をもとにプロセスを修正する バグが見つかったら、なぜそのバグが発生したかを、開発プロセスの観点で確認する。開発プロセスに原因があるのであれば、ツールでヒューマンエラーを防げないか検討する。 失敗から学ぶ ↑に似ている。バグを教訓に設計、プロセスを修正する方法を探す。 学び バグが起きたら再発防止フローを徹底する。なぜ起きたのか、どんな種類のバグなのか、ツールで防ぐことができないか、開発プロセスが原因ではないか。 学びを活かすアイディア・行動 現場にレトロスペクティブの観点として展開できる。

レガシーコードからの脱却 まとめ 11.12 – 11.12.1

11.12 実践しよう 11.12.1 テストを仕様として使うための7つの戦略 内容 テストを文書のようにすることで生きた仕様になる。そのための7つの戦略を紹介する。 戦略 説明 テストを文書のように扱えるようにする テストのコードも、マジックナンバーをハードコードせずに意味がわかる変数名にする 意図がはっきりわかるヘルパーメソッドを使う セットアップの処理や、そのほかの機能を独自のヘルパーメソッドでラッピングすることで、個々のテストの重複を排除しつつも、異なるセットアップオプションを用意できるようになる 何が重要なのかを明らかにする 1と似ている。マジックナンバーをハードコードせずに変数で読めるようにして、意図するところをわかるようにする 実装ではなくふるまいをテストする 具体的な実装に合わせてテストするのではなく、テストメソッド名を表すことをテストする。悪い例:testConstructor 。単純すぎる。良い例:testRetrievingValueAfterConstruction 。何をテストしたいのかがわかる。 モックを使ってワークフローをテストする アサーションは値やふるまいをテストできるが、ワークフローやオブジェクト間の相互作用はテストできない。これはモックを使ってテストする。 書きすぎない 微細に記載することは簡単だが、意味が同じテストは重複である。例えば、境界値とその間の値の場合、その間の値のパターンは無尽蔵にあるが、実施するのは1つでよい。それ以外は実施した1つのテストと意味が同じだ。重複したテストは削除する。 正確な例を使う 実際の使われ方を実行することによって、コーディングを開始する前に、矛盾や設計上の問題が明らかになり、早期に対処できる 学び プログラマでない人でも読めるように書くべし 重複は省くべし 相互関係のテストはモックを使うべし ふるまいを明確にテストすべし 学びを活かすアイディア・行動 現場のユニットテストのコーディング規約づくり

レガシーコードからの脱却 まとめ – 11.10 – 11.11

11.10 モックを使ったワークフローテスト 内容 ユニットテストは一連の順序を検証したり、似たようなほかのシナリオを検証することは出来ない。こういう場合は、ワークフローテストを行う。 ワークフローテストは実際のオブジェクトを使うのではなくモックを使う。 モックは外部との依存関係とどのように相互作用するかを検証するために使う。 テストとしては、モックが正しいパラメータで呼び出されたかを検証する。 11.11 セーフティネットを作る テスト駆動開発はソフトウェアを作るためのリズムや、開発者が安全にコードを書くためのセーフティネットを提供してくれる。 アクロバットをする人にとってのセーフティネットは命を守るものだが、開発者にとってのセーフティネットは、心理的な保証だ。 テストファースト開発を行う最大の利点は、ソフトウェア開発者がテストしやすいコードを書くようになり、維持するコストも抑えられること。 開発者は設計から始めるように教えられるが、プロジェクトの後半のほうが正しい設計についてはるかに多くのことがわかるため、最後に設計をするのが良い。最後に設計する説明は次の章。 学び 外部との依存関係と相関関係をテストするのはワークフローテストと呼ぶこと ワークフローテストもモックを使って行うこと テストファースト開発は開発者に心理的安全を保証してくれて、結果的にコストを抑えることができる。心理的安全は、心に余裕を生み、焦って汚いコードになることを防ぎ、保守性、テスト容易性を保つことができ、結果的に拡張コストを少なくすることができる。 学びを活かすアイディア・行動 テスコードの目的のための事前知識整理