まずは前回の記事をお読みください
リファクタリング
最も思慮深く熟練したプログラマーであっても、ソフトウェア プロジェクトの微妙な点を予測することはできません。問題は常に予期せず発生し、要件が変更される可能性があり、その結果、コードが最適化、共有、置き換えられます。
リファクタリングは一般的な方法です。すべてのコードをチェックして、統合および簡素化できる共通または類似のものを見つけて、コードの保守と拡張を容易にします。リファクタリングには、特定の問題に設計パターンを適用できるかどうかを検討することも含まれます。これにより、解決策を簡素化することもできます。
リファクタリングとは、簡単に言えば、プロパティまたはメソッドの名前を変更すること、より複雑に言うと、既存のクラスを圧縮することです。 1 つ以上の設計パターンに準拠するようにコードを変更することも、別の種類のリファクタリングであり、この本を読んだ後に実装できる可能性があります。
リファクタリングを説明するのにサンプルほど適したものはありません。
CartLine と Cart という 2 つの単純なクラスを考えてみましょう。 CartLine は、ショッピング カート内の各商品の単価と数量を記録します。たとえば、CartLine は「赤いポロシャツ 4 枚、各 19.99 ドル」を記録する場合があります。 Cart は、1 つ以上の CartLine オブジェクトをロードし、ショッピング カート内の全アイテムの合計コストなどの関連計算を実行するために使用されるコンテナーです。
以下は CartLine と Cart の簡単な実装です:
// PHP5
class CartLine {
public $price = 0;
public $qty = 0;
}
class Cart {
protected $lines = array();
public function addLine($line) {
$this- >lines[] = $line;
}
public function calcTotal() {
$total = 0;
// 各行の合計を加算します
foreach($this->lines as $line) {
$total + = $line->price * $line->qty;
}
// 消費税を追加します
$total *= 1.07;
return $total;
}
}
リファクタリングの最初のステップは、すべてのコードをカバーするのに十分なテストを行う必要があります。これにより、変更したコードが元のコードと異なる結果を生成することがなくなります。ちなみに、要件 (コードの期待される結果) を変更するか、テスト インスタンスでバグを見つけない限り、テスト コードを変更することはできません。
以下は CartLine と Cart をテストする例です。これらはリファクタリング プロセス中に変更されません。
関数 TestCart() {
$line1 = 新しい CartLine;
$line1->価格 = 12; $line1->gt;数量 = 2;
$line2 = 新しい CartLine;
$line2->価格 = 7.5; line2->qty = 3;
$line3 = 新しいカートライン;
$line3->価格 = 8.25; $line3->qty = 1;
$cart = 新しいカート;
$cart->addLine($ line1);
$cart->addLine($line2);
$cart->addLine($line3);
$this->assertEqual(
(12*2 + 7.5*3 + 8.25) * 1.07,
$cart->calcTotal());
}
上記のコードを見ると、いくつかの「コードの匂い」があることがわかります。これらは奇妙で、問題のあるコードのように見えます。リファクタリング用。 (コードの匂いの詳細については、http://c2.com/cgi/wiki?codesmell を参照してください)。リファクタリングの最も当面の候補は、注釈と計算 (消費税などに関連する計算) の 2 つです。リファクタリングの一種: Extract メソッドは、この醜いコードを cart::calcTotal() から抽出し、適切なメソッドに置き換えて、コードをより簡潔にします。
たとえば、lineTotal() と calcSalesTax() という 2 つの計算メソッドを追加できます。
protected function lineTotal($line) {return $line->price * $line->qty;
}
protected function calcSalesTax($amount) {
return $amount * 0.07;
}
これで次のことができますcalcTotal() 関数を書き換えます:
public function calcTotal() {
$total = 0;
foreach($this->lines as $line) {
$total += $this->lineTotal($line);
}
$total + = $this->calcSalesTax($total);
return $total;
}
これまでの変更は (少なくともこの例のコンテキストでは) 意味があり、このコードを一時停止して再度実行することは意味があります。結果が依然として正しいことを確認するのに役立ちます。緑色の成功バーが表示されることに注意してください。 (翻訳者注: この章の冒頭で著者は次のように述べています: 緑色のバーはテストに合格したことを意味します。)
再度リファクタリングし、新しいメソッド total() を CartLine に追加して、注文内の各商品の長期価格を計算します。
public function total() {
return $this->price * $this->qty;
}
次に、Cart クラスからメソッド lineTotal() を削除し、新しい cartLine を使用するように calcTotal() メソッドを変更します。 ::Total() メソッド。テストを再実行しても、結果は緑色のバーで表示されます。
新しくリファクタリングされたコードは次のようになります:
class CartLine {
public $price = 0;
public $qty = 0;
public function total() {
return $this->price * $this->qty;
}
}
class Cart {
protected $lines = array();
public function addLine($line) {
$this->lines[] = $line;
}
public function calcTotal() {
$total = 0;
foreach($this ->lines as $line) {
$total += $line->total();
}
$total += $this->calcSalesTax($total);
return $total;
}
protected function calcSalesTax($amount) {
return $amount * 0.07;
}
}
コード自体が各行の機能をより適切に説明しているため、このコードでは各行のコメントが不要になりました。これらの新しいメソッドはコンピューティング機能をより適切にカプセル化し、将来の変更への適応を容易にします。 (たとえば、さまざまな消費税率を考慮してください)。さらに、これらのクラスはよりバランスが取れており、保守も容易です。
この例は明らかに簡単ですが、そこから推定して独自のコードをリファクタリングする方法を想像していただければ幸いです。
コーディングするときは、新しい機能を追加するかコードをリファクタリングするという 2 つのモードのいずれかになる必要があります。機能を追加するときは、テストを作成してコードを追加します。リファクタリングでは、元のコードを変更し、関連するすべてのテストが引き続き正しく実行されることを確認します。
リファクタリングに関する主な参考資料は、Martin Fowler の「Refactoring: Improving the Design of Existing Code」です。ファウラーの本をいくつかの簡潔なポイントで要約すると、再構築の手順は次のとおりです。
すべてのコードをカバーするテストを用意する
小さなステップで作業する
各ステップの後にテストを実行する。コーディングとテストは両方とも非常に反復的であり、コンパイル言語よりも PHP のようなインタープリタ言語を使用した方がはるかに簡単です。
リファクタリングを使用して、コードをより読みやすく、変更しやすくします。