「リファクタリング」の完全読破。その6、第6章後半。
前回は「第6章 メソッドの構成」から『総論と「メソッドの抽出(P110) 」「説明用変数の導入(P124)」』について書いたので、今回は残りの項目を。
大きなものは「メソッドオブジェクトによるメソッドの置き換え」くらいで、あとは項目名のとおりという印象。
(※下記のコード片は、本書の例を元に短縮等を行ったもの。)
第6章 メソッドの構成
「メソッドのインライン化(P117)」
不要な間接化、つまり委譲のみ行っているようにみえたら行う。単純な場合にのみ行い、複雑な場合は避ける。
return (moreThanFive()) ? 10 : 0; boolean moreThanFive(){ return _preAmount > 5; } ↓ return (_preAmount >5) ? 10 : 0;
「一時変数のインライン化(P119)」「問い合わせによる一時変数の置き換え(P120)」
「一時変数のインライン化(P119)」は、よく「問い合わせによる一時変数の置き換え(P120)」の一部として使う。
先に変数をfinalにしてみるのがコツ。エラーがなければ一度しか代入されていないことがわかる。
これらも、一度だけ代入されるか副作用がない場合に行う。
複数回代入されるなら「一時変数の分離(P128) 」、副作用があるなら「問い合わせと更新の分離(P279)」を適用することを考える。
//一時変数のインライン化 double todayPrice = anOrder.getTodayPrice(); return (todayPrice > 1000); ↓ return (anOrder.getTodayPrice() > 1000); //問い合わせによる一時変数の置き換え double basePrice = _quantity * _itemPrice; return basePrice * 3; ↓ return basePrice() *3; private double basePrice() { return nowPrice * quantity; }
「一時変数の分離(P128)」
複数回代入される一時変数は、代入ごとに別の一時変数に分ける。
複数回設定されるのは、複数の責任を担っていることを示す。 複数の責任を担う変数は、コードを読む人を混乱させる。
double temp = 2 * (_height + _width); System.out.println(temp); temp = _height * _width; ↓ final double perimeter = 2 * (_height + _width); System.out.println(perimeter); final double area = _height * _width;
「パラメータへの代入の除去(P131)」
int discount(int inputVal) if(inputval > 50) inputVal -= 2; ↓ int discount(int inputVal) int result = inputval; if(inputval > 50) result -= 2; //代入が悪いだけで、メソッドの使用はなんら悪いことではない。 void aMehod(Object foo) foo.modifyInSomeWay(); //OK foo.setBar(); //OK foo = anotherObject; //NG
この項目で重要なのは、上記の例よりも ”Javaは、厳密にはすべて値渡しを使っている””本質的に、オブジェクトへの参照は値渡し”ということ。
「メソッドオブジェクトによるメソッドの置き換え(P135)」
メソッドの分解を困難にするのはローカル変数である。Method Objectパターンを使う。
ちょっとこれは大きいので、無意識に出来るようになるまで何度か本書を読み直した方が良さそう。
class Account int gamma(int a, int b, int c){ int value1 = (a * b ) + delta(); int value2 = (a * c) +100; if ( (c - value1) >100 ) value2 -=20; int value3 = value2 *7; return value3 - 2 * value1; } ↓ class Account int gamma(int a, int b, int c){ return new Gamma(this, a, b, c,).compute(); }
TDDの調子で、抽出したGammaクラスとcomputeメソッドを書く。
これでリファクタリングの対象はGamma.compute()になる。というテクニック。
「アルゴリズムの取り替え(P139)」
文字通り、よりよいアルゴリズムに変更する。項目として必要なのはわかるんだけど、内容はタイトル以上のものでもないので割愛。
以上で第6章は終了。
「リファクタリング」の完全読破。その5
今回からカタログに入る。第6章は内容が多いので2回にわけて。
今回は、総論と「メソッドの抽出(P110) 」「説明用変数の導入(P124)」をしっかりと。
第6章 メソッドの構成
総論
下記の通り重要な章。いくつかの項目を除けばクラス階層の変更が不要なので、やりやすいという面もある。
(経験上、クラスを作ったり消したりすると面倒になる職場が多い。悲しいことに。)
P109 メソッドを、適切にパッケージ化されたコードとして構成することが、本書のリファクタリングの大部分です。 問題を起こすのは、ほとんどの場合、長すぎるメソッドなのです。 メソッドを分解すると、その動作がより深く理解できます。そして、そのアルゴリズムがもっとわかりやすくできることに気づくかもしれません。
さて、いったいどこまでメソッドを小さくするといいのだろうか。
私はここに書いてある通りと考える。
P110 メソッド名とメソッド本体の間の意味的な距離が重要なのです。コードを抽出することで明快さが向上するなら、そうすればよいのです。 抽出されるコードよりも名前のほうが長いとしてもです。
ファウラーは、現実的、実務的な人だという印象が強い。(これは他の著書でも強く感じる。UMLでは顕著に。)
ここでも、見た目や体裁より如何に実際の作業で効果が上がるか、ということが書かれている。
本章の構成
本章では「メソッドの抽出(P110)」がメインとなり、それをいくつかのリファクタリングが支えている。
例えば、「問い合わせによる一時変数の置き換え(P120)」で一時変数を取り除く。
困難な場合は先に「一時変数の分離(P128)」を行う。
それでもダメなら「メソッドオブジェクトによるメソッドの置き換え(P135)」を適用する。
パラメータの場合は「パラメータの除去(P131)」を行う。
また「アルゴリズムの取替(P139)」を検討する。
などなど。(これらは次回取り上げる。)
知っての通り、今では簡単なリファクタリングは自分で書く必要はない。
例えば「メソッドの抽出」なら、Eclipse上で括って右クリックし「リファクタリング」「メソッドの抽出」を選択、そしてメソッド名を入力すると自動で変換される。
しかし、もちろんリファクタリングはそんな簡単なものばかりではない。
効果的なリファクタリングは、プログラマが意図的に書かなければならないものが多いので、しっかり学ばなければならない。
「メソッドの抽出(P110) 」と「説明用変数の導入(P124)」
「メソッドの抽出」は本章のメインとなるリファクタリングである。
「説明用変数の導入」は適用したくなる場面が多いが、ファウラーはその場合も「メソッドの抽出」を適用することを推奨している。
ここでは、両者を比較することで理解を深めようと思う。(本書でもそうしている。)
まずは修正前のコード。こういうコードをよく見る人も多いのでは。(下記のコード群は全てP125〜P127を元にしたもの。)
double price(){ //価格は、基本価格ー数量割引+送料 return _quantity * _itemprice - //基本価格 Math.max(0, _quantity - 500) * _itemPrice * 0.05 + //数量割引 Math.min(_quantity * _itemPrice * 0.1, 100.0); //送料 }
まず、_quantity * _itempriceが複数回書かれており、意味もコメントの通りなのでbasePriceとして抽出する。
そして、Math.maxの行と、Math.minの行もコメントの通りに「説明用変数」として抽出する。
それだけで「説明用変数の導入」は完了する。
ここで重要な点は「コメントを取り除ける」ということ。修正後のコードは、コード以上のことを何も表現していないからだ。
(とはいえ、それでも書けというプロジェクトはいくらでもありそう。ご愁傷さまです。)
double price(){ final double basePrice = _quantity * _itemPrice; final double quantityDiscount = Math.max(0, _quantity - 500) * _itemPrice * 0.05; final double shipping = Math.min(basePrice * 0.1, 100.0); return basePrice - quantityDiscount + shipping; }
十分わかりやすいが、ファウラーは上記のとおり「メソッドの抽出」を推奨している。
それを適用するとこうなる。
double price(){ return basePrice() - quantityDiscount() + shipping(); } private double basePrice() { return _quantity * _itemprice; } private double quantityDiscount() { return Math.max(0, _quantity - 500) * _itemPrice * 0.05; } private double shipping() { return Math.min(basePrice() * 0.1, 100.0); }
読みやすさとしては同じようなものだと思う。
メソッドにする利点は「他の部分からも使える」ことが大きく、必要に応じてprivateの解除を行って良い。
できる限り「メソッドの抽出」を行い、「説明用変数の導入」 を使うのは「メソッドの抽出」では手間がかかる場合だとファウラーは書いている。
今回書いたリファクタリングは、頭の硬い上司(やそれに準じる体制)がいてもできるのではないかと思う。
次回は、これを支えるリファクタリングについて記載する。
続く。
「リファクタリング」の完全読破。その4
今回は第4章と第5章。この次から、いよいよカタログに入る。
第4章 テストの構築
多分ここが、古いということで一番割を食ってる箇所。
JUnitの説明などは、今は他の本を読んだ良いと思う。
所々出てくる、今読んでも色褪せないなと思う部分だけ引用する。
(古い古いと書いているが、未だにJUnitすら使っていないシステム開発現場はあるし、むしろ経験上そっちの方が多い。)
P89 リファクタリングに限らず、よいテストを書くとプログラミングが加速するようです。 P90 テストを完全に自動化して、その結果もテストにチェックさせること。 P94 テストを頻繁に実行せよ。コンパイル時にはテストを局所化して、1日に最低1度はすべてのテストを実行せよ。 P97 バグレポートを受け取ったら、まずそのバグを明らかにするための単体テストを書け。 P98 不完全なテストでも、書いて実行するほうが、実行できない完全なテストよりもましだ。 P99 失敗の恐れのある境界条件を考えて、そこを集中的にテストせよ。 P100 失敗すると予測されるときに、例外が上がることをテストし忘れないこと。 P101 テストですべてのバグが見つからないからと入って、テストを書くのをやめてはならない。ほとんどのバグはテストで補足される。
テストのやめ時について、いくつか補足する。
カバレッジを100にする意味があるときと、あまり無いときがある。
まずはテストにおける収益低減点を考えること。
適当な時間で大部分のバグを補足するほうが良い。
継承とポリモーフィズムを踏まえるとテストの組み合わせはどんどん増えていくが、全部の組み合わせを試す必要はない。
ふと見ると、Kent Beckの「テスト駆動開発入門」も、相当に古い本だった。
私が持っているのは2008年の第3刷だけど、日本語の初版は2003年。
リファクタリングもTDDも、思想と技術は確実に身になってるんだけど、職場では強制されないし、逆に強制できないというのが少しもどかしい。
第5章 リファクタリング・カタログに向けて
こちらはタイトルのとおり、カタログ(第6章〜第12章)の記述方針等の説明。
注意点として、リファクタリングの説明に集中するために、金額をdoubleとしたり本来はまずしないような書き方もしているということ。
(それを踏まえると、Javaのバージョンが古いということも、ある程度は受け入れられるかな。)
また、GoFには「デザインパターンはリファクタリングの目標を提供する」と書かれており、リファクタリングを使うとき、デザインパターンはその出発点であることを心に留めるようにと書かれている。
・過去記事。
「リファクタリング」の完全読破。その1 - holyppの日記
「リファクタリング」の完全読破。その2 - holyppの日記
「リファクタリング」の完全読破。その3 - holyppの日記
「リファクタリング」の完全読破。その3
帰省などで間があきましたが、今回は第3章。8月中の読破を目標に。
第3章「コードの不吉な匂い」
テーマは、いつリファクタリングを始めていつ終えるか。
(P76) ここではリファクタリングの必要を示す不吉な兆候について説明していきます。 インスタンス変数はいくつ以上になれば多過ぎであり、メソッドは何行以上で長過ぎるかなどの感覚は、自ら養っていかねばなりません。
他に「経験で磨かれた人間の直感には、メトリックスをいくら集めてもかなわない」とも書かれており、経験の重要さが強調されている。
各項目はそれぞれ半ページから2ページで文量は少ないが、引用されている手法を確認しながら読むとかなり時間がかかる。
本エントリは後から見直せるように、見出しと簡単な説明を書いていく。
重複したコード
同一クラス内の複数メソッドに同じ式がある場合。
完全に同じでなく似通っている場合は、共通に使える部分とそうでない部分を分離し、TemplateMethodの形成(P345)を検討する。
複数のメソッドが、同じ処理を違うアルゴリズムで実装していた場合は、アルゴリズムの取り替え(P139)を適用する。
関係の無い二つのクラス間で、重複したコードがある場合は、クラスの抽出(P149)を行い処理を委譲する。
長すぎるメソッド
メソッドが長くて、ソースを追わないと何をしているかわからない場合。
メソッドの分割時に問題になるのは引数や一時変数が多いメソッドで、先に以下の手法を使ってスリム化を行う。
「問い合わせによる一時変数の置き換え(P120)」
「引数オブジェクトの導入(P295)」
「オブジェクトそのものの受け渡し(P288)」
「メソッドオブジェクトによるメソッドの置き換え(P135)」
条件分岐やループも「条件記述の分解(P238)」を使って抽出を検討する。
巨大なクラス
インスタンス変数を持ち過ぎたクラス、コード量の多いクラスは「重複したコード」の温床。
多すぎる引数
オブジェクトをそのまま渡し、メソッドがさまざまなデータをそこから取り出せば良い。
変更の発散、変更の分散、パラレル継承
設計は、一つの変更要求(DBの変更や商品追加など)に対して、1つのクラスの1箇所が常に修正対象となるようにする。
以下のような状態になったらリファクタリングを行うべき。
変更の発散:一つの変更に対して同一クラス内の複数のメソッドを少しずつ修正しなければならない。
変更の分散:一つの変更に対して複数のクラスを何度も修正しなければならない。
パラレル継承:一つの変更に対して複数の継承木にそれぞれサブクラスを作らなければならない。
属性、操作の横恋慕
見出しの翻訳が良いなと思う。
あるメソッドが他のオブジェクトのgetメソッドを何度も何度も呼び出している場合、メソッドの位置が悪い。
ただし、StrategyパターンとVisitorパターン(と、Self Delegationパターン)など例外はある。
上記のパターンは変更に必要な部分(この場合は振る舞い)を1か所にしているので、パターンを優先する。
データの群れ
「数個のデータがグループとなって」属性やシグニチャに頻繁に現れる場合は、オブジェクトとしてまとめてみる。
基本データ型への執着
基本データ型ではなくオブジェクトを使う。
例えば「電話番号」を最初に文字列で定義し、後から頻繁にフォーマット変更などの振る舞いが必要になった場合、オブジェクトにすると良い。
スイッチ文
スイッチ文を見たらポリモーフィズムを使って解決できないか考える。
1章で行った「State/Strategyによるタイプコードの置き換え(P227)」や、null値で分岐している場合の「ヌルオブジェクトの導入(P260)」など。
怠け者クラス
十分な仕事をしないクラスは排除する。「階層の平坦化(P344)」、「クラスのインライン化(P154)」など。
疑わしき一般化
「いつかこの機能が必要になるさ」と凝った仕掛けを作った場合。例えば、あるクラスやメソッドがテストケースでのみ利用されている場合など。
一時的属性
インスタンス変数の値が特定の状況でしか設定されない場合。クラスとして切り出すか、ヌルオブジェクトを使う。
メッセージの連鎖
クライアントがオブジェクトにメッセージを送り、そのオブジェクトが更に別のオブジェクトにメッセージを送り、更に……という場合。
getHoge()のような呼び出しが長い行となって連なっていたり、一時変数が非常にたくさん定義されているとあやしい。
仲介人
メソッドの大半が別のオブジェクトに委譲しているだけのクラスは除去する。
不適切な関係
これも翻訳が良い。見出しも本文↓も。
仲の良すぎるクラスは、いにしえの恋人たちのように、遠くに離してあげねばなりません。
この場合は「双方向関連の単方向への変更(P200)」、「以上による継承の置き換え(P352)」を検討する。
クラスのインタフェース不一致
処理が同じでシグニチャのみが異なるメソッドは「メソッド名の変更」を行う。
(見出しと説明文を読んでも、イマイチ何が言いたいのか理解できない。どういう場合?)
未熟なクラスライブラリ
再利用はオブジェクト指向の目的とよく言われるが、万能なクラスライブラリというのは非常に難しいもの。
既存のクラスライブラリに追加したいメソッドがある場合は「外部メソッドの導入(P162)」、「局所的拡張の導入(P164)」を行う。
データクラス
get,setメソッド以外に何も持たないクラスに、利用しているクラスから振る舞いを移せないか検討してみる。
接続拒否
サブクラスが親の属性と操作の一部しか利用していない場合、継承階層が間違っているというのが伝統的な見方になる。
兄弟となるクラスを新たに作成し、「メソッドの引き下げ(P328)」、「フィールドの引き下げ(P329)」を行う。
サブクラスが「振る舞いは継承するけどインタフェースは必要無い」場合は「委譲による継承の置き換え(P352)」を行う。
コメント
コメントは良いものだが、それが「わかりにくいコードを補うため」だとしたら修正する必要がある。「表明の導入(P267)」など。
はてなブックマークでRSSリーダーにいれるべき、たった一つのタグ
これ、入れてみてはどうか。
タグ「インタビュー」を検索 - はてなブックマーク
何年か、いろいろと見てるけど、私が安定して面白いと思うのはこれだけ。
実に3割くらいは面白い記事で、それはすごい高い確率だと思う。野球の打率と同じだね。
他に、Ruby、Vim、お役立ち、ガジェットなどをはじめ、いろいろと入れてるけど、それらの記事はやっぱりピンキリで、そこから自分のフィルターが必要になってしまう。
それらの本文は、総合すると1割も見ないので、かなり弾く必要がある。
インタビューというのはすなわち、あるテーマにそった成功者の言葉だ。
ほとんどは、私のような凡人が考えられないくらいストイックな思想をもとにしているし、そうでなくても、自分では考えつかないような面白い(新しい)視点のものが多い。
手塚治虫は
「一流のマンガ家になりたいのなら、一流のものを読んで、一流のものを観て、一流のものを聴きなさい。」
と言っていたが、それは真理だと思う。
「はてブはあんまりなぁ」という人も多いと思うけど、「インタビュー」タグは一ヶ月くらいチェックしても、悪いことは無いと思うよ。
「リファクタリング」の完全読破。その2
ソフトウェアシステムはほぼ間違いなく、汚く滅茶苦茶になってしまうことに気づいたからです。 最初はプログラマの心のなかでけがれのない水晶のように輝いていた設計が、時間が経つことで劣化し、悪くなった肉のように腐敗していきます。 1年前に構築した、こぢんまりした出来の良いシステムが、翌年には関数や変数が絡まり合ったひどい泥沼に変わります。 いったい何が起きているのでしょう。 「レガシーコード改善ガイド」まえがき
大きなシステムに携わったことがあるなら、痛いほど気持ちがわかると思う。
私はこの問題を、プログラマのレベルが低いプロジェクトにのみ起こる現象だと思っていたが、どうやらそうではないらしい。
そんな簡単な問題では無かった。
第2章 リファクタリングの原則
ここではリファクタリングの定義にはじまり、行う理由、いつ行うべきか、などが示される。
中でも、私はこの文が気に入っている。これは冒頭の問題への回答でもある。
(P55) リファクタリングなしでは、プログラムの設計は徐々に劣化していきます。 リファクタリングを定期的に行うことで、コードの状態をしっかりと保つことが出来ます。
つまり、システムが劣化していく、汚れていく、泥沼になる、というのは避けがたいことで、それを浄化するのがリファクタリングである。
汚れた泥沼というのはリファクタリングをしなかったシステムということだ。
リファクタリングの定義
ここで、リファクタリングの定義を引用する。
(P53,54) リファクタリング(名詞):外部から見たときの振る舞いを保ちつつ、理解や修正が簡単になるように、ソフトウェアの内部構造を変化させること。 リファクタリングする(動詞):一連のリファクタリングを行って、外部から見た振る舞いの変更なしに、ソフトウェアを再構築すること
定義に続けて2点強調されている。
・ソフトウェアの外部的振る舞いを保つこと。
・ソフトウェアを理解しやすく、変更を容易にするために行うこと。
つまり、機能追加はリファクタリングでは無い。
リファクタリングをするときは「機能追加をしない」ことを意識するように書かれている。
いつリファクタリングをすべきか
明確な答えは無いが、いくつかのガイドラインがある。
・3回重複したコードを書いたとき/無駄なことをしていると思ったとき。2回なら我慢する。
・設計が原因で、機能追加が困難なとき。
・バグフィックスでコードが不明確なとき。
・コードレビューのとき。例えば二人一組レビューを行い、そこでリファクタリングを行う。
別の節で、Ward Cunnninghamは未着手のリファクタリングを借金に喩えている。
P66 借金に利子があるように、あまりに複雑化したコードは、維持と拡張のコストがかかります。 利子もある程度ならば払うことができますが、あまりに高くなると、自分の首を絞めることになってきます。 借入金は適切に保たねばなりません。ときどきリファクタリングを行って負担を軽減していくことが重要です。
管理者を説得するには
品質を気にする管理者は説得することができる、と方法が書かれているが、やはり面白いのは次の箇所だろう。
品質よりもスケジュールを気にするマネージャの場合はどうするか。これは引用しておきたい。
P61 いささか問題発言的なアドバイスをしておきましょう。彼らにはだまってリファクタリングするのです。 これはマネージャたちに対する反乱でしょうか。私はそうは思いません。 ソフトウェア開発者はプロとしての誇りを持っています。 (中略) スケジュールを気にするマネージャであれば、開発者が最も速い方法を選択するのを望むでしょう。 ただし、どのような手段で実施するかは、マネージャの知るところではありません。 最も速い方法はリファクタリングです。だからリファクタリングをするのです。
プロとしての誇りを持つソフトウェア開発者が、最も速い方法で開発する。そこには何の問題も無い。
まとめ
他にもいくつかの節があるが、読み通すことで思想が理解できる体験談・エッセイなので、要約のようなことは難しい。
それでも、最後に一つ紹介するならばこれ。
P57 ここで、Kent Beckが自らを語ったセリフを思い出しました。 「僕は、偉大なプログラマなんかじゃない。偉大な習慣を身につけたプログラマなんだ」。 リファクタリングによって、堅牢なコードがずっと効率よく書けるようになるでしょう。
ファウラー自身も、バグ探しは得意ではないと言っている。
ただし、リファクタリングできればコードに立ち向かえるようになると。
私もいろいろな場面で「自分は偉大なプログラマじゃないからこれができないんだ」とよく感じる。
しかし、それも偉大な習慣を身につけることで少しずつ変わっていくのかなと。
そして、偉大な習慣を身につける第一歩は、本書をマスターすることかなと理解して、進んでいる。
「リファクタリング」の完全読破。その1
ファウラーの言わずと知れた名著だけど、私は15章構成のうちカタログ部分(第5章〜第12章)を今まで読んでいなかった。
理由としては、やはり古いこと、そんなに難しい内容では無いこと、リファクタリングの思想という意味では理解していたこと。
ホントに古い本なので、もういいかなと思っていたんだけど、少し読み直したらやっぱり一度は全部書くべきだった。
リファクタリングの思想と同じくらい、カタログにある各種技術は重要だった。
それに「おすすめの本は?」と聞かれたときに、とりあえずこれを挙げることは多くて、そのくせ完読してないのは質が悪いというのもある。
ということで、今回は「はじめに」と「第1章」
はじめに
ここでは本書の説明と、リファクタリングについての話が少し。
・リファクタリングはリスクが高いのでやみくもに行ってはいけないこと。
・手順を守り、体系的に行うこと。
・具体的には「1度に1ステップずつ」行うこと。
それに、ファウラーとKent Beckが以前にした仕事の話がある。さらっと読む。
第1章 リファクタリングー最初の例
大まかには、3つのクラスからなるシステムをリファクタリングしていくという流れ。
最初の状態では、class Customerが、巨大なstatement()メソッドを持っており、明らかに悪い設計となっている。
まずは、Eclipseを起動してこの悪いコードを書き、本書の通りにリファクタリングをしていく。
内容は「1度に1ステップずつ」の思想を守っているので、非常に簡単。
頭を使うのは最後のポリモーフィズムだけ。
まず最初にテストの重要さが書かれる。
(P7~8) 最初にすることは常に同じです。対象となるコードについてきちんとしたテスト群を作りあげることです。 リファクタリングの成功は、良いテストを用意できるかで決まります。
とあるが、本書にはテストコードはないので、JUnitを使って自分で書く。
そしてリファクタリングをはじめる。
ほとんどが基本的なことだけど、改めて読むと勉強になる。
メソッドの抽出(P110)
switch文をメソッドにする。
ローカルなスコープを持つ変数は、新規メソッドの引数か一時変数にならないか検討する。変更されない変数はメソッドの引数として渡すことができる。
変数名を変更する
コンパイラが理解できるだけではなく、人間にとって解りやすいコードにする。
メソッドの移動(P142)
使用するデータを持つオブジェクトにメソッドは定義されるべき。
問い合わせによる一時変数の置き換え(P120)
代入した後に変更されない一時変数は、問い合わせメソッドにする。
一時変数は長くて複雑なルーチンの原因となるので、できるだけ減らす。
thisAmountやtotalAmountのようなそれっぽい変数があやしい。
P34 料金計算の条件文をポリモーフィズムに置き換える
ここだけ、ちょっと大きい。
「他のオブジェクトの属性を調べるswitch文を書くことは、常に間違いです。他のオブジェクトではなく自分自身について行うべきなのです。」
とあり、それを実現する。そのために以下の手順が必要。
State/Strategyによるタイプコードの置き換え(P227)
自己カプセル化フィールド(P171)
メソッドの移動(P142)
ポリモーフィズムによる条件記述の置き換え(P225)
まとめ
P52 (リファクタリングは)クラスの責任を分割させ、保守しやすいコードを書くのに役立ちます。 手続き的なコードとはかなり様子が異なるので、慣れるのには時間がかかるかもしれません。 しかし、いったん慣れてしまえば、もう手続き的プログラミングには戻れないものです。
「はじめに」でファウラーが言及したプロジェクトも汚いコードだったらしい。
その例も含め、リファクタリングの工数を見積もれるプロジェクトというのはほとんど無い。
本書を読んでもその事実は変わらず、これを読んだからって工数がもらえるわけではない。
ただ、そんな中でも本書のカタログにある技術を習得するのは大事。リファクタリング云々の前に、コードの質が良くなる。
ホントに古い本なので「今風の書き方」という意味では参考にならないけど、技術としてはその一歩手前の「設計」が学べる。
例えば上記の引用の通り「Javaで書いた手続き型のコード」があったら、それをスマートに修正できるようになる。
並行で他にもいろいろと読んでいるけど、8月中には「リファクタリング」を終えたい。