レガシーコード改善ガイド 第7章...

Preview:

Citation preview

第7章 いつまでたっても 変更作業が終わりません

Takahiro Okada

レガシーコード改善ガイド読書会

変更は

素早く行えるほどよいという話

そもそも、

変更の理由とは?

•変更の理由

–バグ修正

–機能追加

–仕様変更

–リファクタリング

•変更の理由

–バグ修正

–機能追加

–仕様変更

–リファクタリング

日々の業務

われわれの

日々の業務は、

コードの変更である。

仕事を速く行うには?

仕事を速く行うには?

→ 変更を速く行う。

変更は

素早く行えるほどよい

小休止 (ここまでOK?)

変更は

素早く行えるほどよい

現実には…

「いつまでたっても

変更作業が

終わりません」

なぜ?

他にあるかな・・・?

なぜ?

1. コードの内容が

理解出来ない。

2. 変更を行なってから、

結果を得るまでに時間がかかる。

1. コードの内容が

理解出来ない。

1. コードの内容が理解出来ない

• 変更方法を調査するのに時間がかかる。

–ある程度はしかたないこと。

–ただし、整理されたコードのほうが時間は短い。

• 変更自体に時間がかかる。

–レガシーコード特有の問題

1. コードの内容が理解出来ない

• 変更方法を調査するのに時間がかかる。

–ある程度はしかたないこと。

–ただし、整理されたコードのほうが時間は短い。

• 変更自体に時間がかかる。

–レガシーコード特有の問題

→「小さく、理解しやすく、適切なパーツに分割されたシステム」

1. コードの内容が理解出来ない

• 変更方法を調査するのに時間がかかる。

–ある程度はしかたないこと。

–ただし、整理されたコードのほうが時間は短い。

• 変更自体に時間がかかる。

–レガシーコード特有の問題

→「小さく、理解しやすく、適切なパーツに分割されたシステム」

→どうすればいい?

詳細は後日

→第16章「変更できるほど十分に私はコードを理解していません」

→第17章「私のアプリケーションには構造がありません」

今日はこっちが本題

2. 変更作業を行なってから、結果を得るまでに時間がかかる

2. 変更作業を行なってから、結果を得るまでに時間がかかる

変更できた!

コンパイル

リンク

パッケージング

インストール

テスト

2. 変更作業を行なってから、結果を得るまでに時間がかかる

変更できた!

コンパイル

リンク

パッケージング

インストール

テスト

フルビルドして 40分

2. 変更作業を行なってから、結果を得るまでに時間がかかる

変更できた!

コンパイル

リンク

パッケージング

インストール

テスト

フルビルドして

Flash image作って 10分

40分

2. 変更作業を行なってから、結果を得るまでに時間がかかる

変更できた!

コンパイル

リンク

パッケージング

インストール

テスト

フルビルドして

Flash image作って

Boardに焼いて

10分

40分

10分

2. 変更作業を行なってから、結果を得るまでに時間がかかる

変更できた!

コンパイル

リンク

パッケージング

インストール

テスト

フルビルドして

Flash image作って

Boardに焼いて

Manual testして

10分

40分

10分

30分

2. 変更作業を行なってから、結果を得るまでに時間がかかる

変更できた!

コンパイル

リンク

パッケージング

インストール

テスト

フルビルドして

Flash image作って

Boardに焼いて

Manual testして

やっぱりダメだった!

10分

40分

10分

30分

2. 変更作業を行なってから、結果を得るまでに時間がかかる

変更できた!

コンパイル

リンク

パッケージング

インストール

テスト

10秒以内に!

でも、どうやって?

小休止 (ここまでOK?)

どうやって 確認作業を早くする?

どうやって 確認作業を早くする?

依存関係を排除する

コンパイル・リンク範囲の減少 差分パッケージング/インストール

テスト範囲の減少 テストハーネスの使用

依存関係を排除する

コンパイル・リンク範囲の減少 差分パッケージング/インストール

テスト範囲の減少 テストハーネスの使用

速い

速い

依存関係を排除する

まとめると

依存関係を排除する 1

テストにおける

依存関係を排除する。

テスト時の依存関係を排除する

• テストハーネスで必要なクラスのインスタンス化を試みる。

• すなわち、テストに必要な周辺のクラスはすべて、テストハーネスで作成する。

テストハーネスで必要なクラスの インスタンス化を試みる。

• 速度向上ポイント1

– コンパイル・リンクの速度が向上する。

• 速度向上ポイント2

–テストの速度が向上する。

–外部リソース(DB / Network / HW etc)の呼び出し時間を短縮できる。

テストハーネスで必要なクラスの インスタンス化を試みる。

インスタンス化できない?

テストハーネスで必要なクラスの インスタンス化を試みる。

インスタンス化できない? →第9章

「このクラスをテストハーネスに入れることができません」 →第10章 「このメソッドをテストハーネスで動かすことができません」

依存関係を排除する 2

ビルドにおける

依存関係を排除する。

そのまえに、小休止 (ここまでOK?)

依存関係を排除する 2

ビルドにおける

依存関係を排除する。

ビルド時の依存関係を排除する

インターフェースを

抽出する。

インタフェースの抽出(1/3)

Before

インタフェースの抽出(2/3)

After

インタフェースの抽出(3/3)

1. 適切な名前のインターフェースを作成する。

2. 抽出対象のクラスで、インタフェースを実装する

3. 変更対象オブジェクトの使用箇所を変更して、クラスの代わりにインターフェースを呼び出すようにする。

4. コンパイルする。コンパイルで出たエラーを取り除く。

ビルド時の依存関係を排除する

実装を

抽出する。

名前を変えたくない場合など

実装の抽出(1/2)

Before

インタフェースの抽出(2/2)

After

小休止 (次はちょっと長い)

実践してみよう

こいつをビルドしたいだけなのに

こいつをビルドしたいだけなのに

依存しているこいつもビルドしないと

こいつをビルドしたいだけなのに

依存しているこいつもビルドしないと しかも、テストの際にDB接続必要?

こいつをビルドしたいだけなのに

依存しているこいつもビルドしないと しかも、テストの際にDB接続必要? さらに、こいつが別クラスに 依存してて・・・

これは遅い。

実装を抽出する。

ココ

これで、ビルドが速くなった

ちなみに、Implっていう名前はどうなの?

これで、 これで、テストも速くなった

ココ

もっとやりたい?

ココ

やりすぎはほどほどに。

コンパイラのファイアウォール

コンパイラの ファイアウォール

コンパイラの ファイアウォール

素早く変更し放題

コンパイラの ファイアウォール

素早く変更し放題

これでおわり?

よく見ると まだ依存が。

依存を取り除く

小休止 (ここまでOK?)

ひとことででまとめると

具象クラスに 依存するよりも インタフェースや 抽象クラスに 依存すべし

いいかえると

変更の少ないものに依存すべし

確かに

全体をビルドする時間は増えるかもしれない

けど、部分を ビルド/テストする時間は

大幅に減るはず

構造が見えにくく なるかもしれないが

妥当なオーバーヘッド である。

ほんとかな

パッケージ間の インターフェースを すべて抽象型に

すると、何が起こるだろう?

おわり

しかし、この本、 章と章の間の依存が強すぎて、

読むのがちょっと辛い。

Recommended