それゆえ、ある人たちにとっては、次のことが理解できない。 リファクタリング は実はプログラミングの一分野であり、プログラマーの仕事の中でも非常に重要な部分でもある。コードは常に進化しており、新しい機能を追加できる可能性がある限り、修正される。しかし、新しい機能を効果的に追加することができなくなり、プログラム全体を書き直した方が簡単になるような形になることもある。
リファクタリングとは何か?
通常、あなたが耳にする答えは、コードの観察可能な動作に影響を与えることなく、一連のリファクタリング変換を適用することによってコードの構造を変更するというものだ。これは正しい。最近、私は マーティン・ファウラー 彼の著書の中で "既存コードの設計改善" そこで彼は次のように語っている。 リファクタリング 小さなステップで大きな変化を起こす "と。彼は次のように述べている。 リファクタリング しかし、彼はそれをスモールステップで行わなければならないと強調する。
本書はまた、次のように提唱している。 リファクタリング がコードの動作に影響を与えることはなく、いつでもテストに合格することに何の影響も与えないことを指摘している。本書では、以下のことを安全に実行する方法を順を追って説明している。 リファクタリング.彼の本が気に入ったのは、日常の仕事で使える簡単なトリックが書かれているからだ。
なぜリファクタリングが必要なのか?
多くの場合、新しい機能を導入したいが、現在のバージョンのコードではそれができないか、コードを変更しないと難しい場合に必要になる。また、より多くの機能を追加することが時間的に不利な場合、つまりゼロからコードを書き直した方が早い場合にも便利です。時々、次のことが忘れられているように思う。 リファクタリング はコードをよりクリーンで読みやすくすることができる。マーティンは著書の中で、コードに不快な臭いを感じたときにリファクタリングを行う方法を書いている、 "それは常に、より良いもののための余地を残す".そして彼はここで、リファクタリングを日常的なコード作業の一要素として捉え、私を驚かせた。私にとって、コードはしばしば理解不能であり、コードを読むことはちょっとした経験である。
よく設計されたプログラムの特徴は、次の点にある。 モジュール性そのおかげで、コードのほんの一部を知っているだけで、ほとんどの変更を導入することができる。また、モジュール化されていることで、新しい人が入りやすくなり、効率的に作業を開始することができる。このモジュール性を実現するには、関連するプログラム要素をグループ化し、そのつながりを理解しやすく、見つけやすくする必要がある。どのようにすればよいのか、唯一の経験則はない。コードがどのように機能するか、よりよく理解できるようになれば、要素をグループ化することができる。
におけるリファクタリングのルールのひとつは ヤグニこれは「You Aren't Gonna Need It」の頭文字をとったもので、次の言葉に由来する。 エクストリーム・プログラミング(XP) 主に アジャイル ソフトウェア開発 チーム.話が長くなった、 ヤグニ は、最新のものだけを行うべきだと言っている。これは基本的に、将来必要になるかもしれないものであっても、今すぐはやるべきではないということだ。 しかし、私たちはさらなる拡張をつぶすこともできず、ここでモジュール性が重要になる。
について話すとき リファクタリングしかし、最も重要な要素のひとつであるテストについては言及しなければならない。それは リファクタリングというのも、そのコードがまだ機能していることを知る必要があるからだ。 リファクタリング は、動作方法を変えるのではなく、構造を変えるので、すべてのテストに合格しなければならない。そのため、すべてのテストに合格する必要がある。小さな変更を行うたびに、作業中のコード部分に対してテストを実行するのがベストである。そうすることで、すべてが思い通りに動くことを確認できるし、作業全体の時間も短縮できる。これはマーティンが彼の本で語っていることだが、できるだけ頻繁にテストを実行することで、一歩下がって何かを壊した変換を探す無駄な時間を省くことができる。
コードのリファクタリング テストなしは面倒だし、何かがうまくいかない可能性が大きい。もし可能であれば、少なくとも基本的なテストを追加して、コードが機能することを少し安心できるようにするのがベストだろう。
以下に挙げる変形はほんの一例に過ぎないが、日々のプログラム作りに大いに役立つ:
- 関数の抽出と変数の抽出-関数が長すぎる場合、抽出可能なマイナー関数がないかチェックする。長い行も同様だ。これらの変換は、コード内の重複を見つけるのに役立ちます。スモール・ファンクションのおかげで、コードはより明確で理解しやすくなります、
- 関数と変数の名前の変更 - 正しい命名規則を使用することは、優れたプログラミングに不可欠です。変数名は、適切に選択された場合、コードについて多くのことを伝えることができます、
- 関数を1つのクラスにグループ化する - この変更は、2つのクラスが同じようなオペレーションを行う場合、クラスの長さを短くすることができるので便利です、
- ネストされたステートメントをオーバーライドする - 条件が特殊なケースでチェックアウトされた場合、条件が発生したときにreturnステートメントを発行する。この種のテストは、しばしばガード節と呼ばれる。ネストされた条件文を終了文に置き換えると、コードの重点が変わります。if-else構文は、両方の変形に等しい重みを割り当てます。コードを読む人にとっては、それぞれが等しく可能性があり、重要であるというメッセージです、
- 特殊ケースの導入 - コード内で何度も使用する条件がある場合、そのために別の構造を作成する価値があるかもしれません。その結果、ほとんどの特殊ケースのチェックは単純な関数呼び出しで置き換えることができる。多くの場合、特別な処理を必要とする一般的な値はnullです。そのため、このパターンはよくゼロ・オブジェクトと呼ばれます。しかし、このアプローチはどのような特殊なケースでも使うことができます、
- 条件付き命令ポリモーフィズムの置き換え。
例
に関する記事である。 リファクタリング そしてその例が必要である。以下に、簡単なリファクタリングのサンプルを示したい。 ネストされたステートメントのオーバーライド そして 条件付き命令ポリモーフィズムの置き換え.例えば、実際の植物の水やり方法に関する情報をハッシュで返すプログラム関数があるとしよう。そのような情報はおそらくモデルの中にあるはずだが、この例では関数の中にある。
def watering_info(plant)
result = {}とする。
if plant.is_a?Suculent || plant.is_a?サボテン
result = { water_amount:"A little bit " , how_to:"底から", watering_duration:"2週間" }.
elsif plant.is_a?アロカシア || plant.is_a?マランタ
result = { water_amount:"Big amount", how_to:"As you prefer", watering_duration:"5日間" }.
elsif plant.is_a?ペペロミア
result = { water_amount:"お好みの量"、
how_to:"下から!葉に水がかかるのを嫌がる"、
watering_duration:「1週間}
else
result = { water_amount:"適量"、
how_to:「お好みで
watering_duration:"1週間"
}
終了
結果を返す
終了
戻るのであれば、変えることだ:
if plant.isa?Suculent || plant.isa?サボテン
result = { 水の量:"少し" , howto:「下から
へ
return { water_amount:"少し" , how_to:"底から",watering_duration:"2 weeks" } if plant.is_a?多肉植物 || plant.is_a?サボテン
水量:「少し」、どのようにに:「下から」、散水期間:"2週間" } if plant.isa?多肉植物|plant.is_a?サボテン
そして、このような関数にたどり着くまで、あらゆることを続ける:
def watering_info(plant)
return result = { 水の量:"A little bit " , howto:"下から", wateringduration:"2 weeks" } if plant.isa?Suculent || plant.is_a?サボテン
return result = { wateramount:"Big amount", howto:"As you prefer", wateringduration:"5 days" } if plant.isa?アロカシア || plant.is_a?マランタ
return result = { water_amount:「ディセント量
ハウツー"下から!葉に水がかかるのを嫌がる"、
wateringduration:"1週間" } if plant.is_a?ペペロミア
return result = { water_amount:「ディセント量"、
how_to:「お好みで
水やりの期間"1週間"
}
終了
最後の最後には、すでに結果が戻ってきた。そして良い習慣は、これを一歩一歩実行し、すべての変更をテストすることである。このifブロックをswitch caseに置き換えれば、すぐに見栄えがよくなるし、すべてのifを毎回チェックする必要もなくなる。このようになる:
def watering_info(plant)
swich plant.class.to_string
ケース Suculent, Cactus
{ wateramount:"少し" , howto:"from the bottom", watering_duration:"2週間"}
ケース アロカシア、マランタ
{ wateramount:"多めに", やり方"お好みで", watering_duration:「5日間}
ケース ペペロミア
{ water_amount:「ディセント量
how_to:「下から!葉に水がかかるのを嫌がる」、
watering_duration:「1 週間" }.
その他
{ water_amount:「ディセント量
how_to:「お好みで
watering_duration:「1週間}
終了
終了
そして 条件付き命令ポリモーフィズムの置き換え.これは、正しい値を返す関数を持つクラスを作成し、それらを適切な場所に切り替えるためである。
粘液質クラス
...
def watering_info()
return { 水量:"少し" , howto:"底から", watering_duration:"2週間" }.
終了
終了
クラス Cactus
...
def watering_info()
return { 水量:"少し" , howto:"底から", watering_duration:"2週間" }.
終了
終了
クラス Alocasia
...
def watering_info
return { wateramount:"Big amount", howto:"お好みで", watering_duration:"5日間" }。
終了
終了
クラス Maranta
...
def watering_info
return { wateramount:"Big amount", howto:"お好みで", watering_duration:"5日間" }。
終了
終了
クラス Peperomia
...
def watering_info
return { water_amount:「ディセント量"、
how_to:"下から!葉に水がかかるのを嫌がる"、
watering_duration:「1 週間" }.
終了
終了
クラス Plant
...
def watering_info
return { water_amount:「ディセント量"、
how_to:「お好みで
watering_duration:「1週間}
終了
終了
そしてメインのwatering_infofunctionでは、コードは次のようになる:
def watering_info(plant)
plant.map(&:watering_info)
終了
もちろん、この関数を削除してその内容に置き換えることもできる。この例で、私は一般的な リファクタリングのパターン.
概要
リファクタリング は大きなトピックだ。この記事が続きを読むきっかけになれば幸いだ。以上 リファクタリング技能 バグをキャッチし、クリーンコードのワークショップを向上させるのに役立つ。マーティンの本(Improving the Design of Existing Code)を読むことをお勧めする。 リファクタリング.著者は、様々な変身をステップ・バイ・ステップで示し、十分な説明とモチベーションを与え、失敗を避けるためのヒントを示している。 リファクタリング.その多用途性から、フロントエンドと. バックエンド開発者.
続きを読む