コード設計の改善:関数呼び出しの簡略化(Making Method Calls Simpler)


ブログシリーズ


      1. コード設計の改善——関数の構成の最適化(Composing Methods)
      2. コード設計の改善-オブジェクト間の特性の最適化(Moving Features Between Objects)
      3. コード設計の改善-データの整理(Composing Data)
      4. コード設計の改善-条件式の簡略化(Simplifying Conditional Expressions)
      5. コード設計の改善:関数呼び出しの簡略化(Making Method Calls Simpler)
      6. コード設計の改善——要約関係の処理(Dealing with Generalization)

  1. Parameterize Method(関数にパラメータを持たせる)


説明:


「関数にパラメータを持たせる」というのは簡単に関数にパラメータを加えるわけではありません.関数にパラメータが必要な場合は、誰でも追加します.このようないくつかの関数を発見することができます:それらは似たようなことをしていますが、わずかな値のために関数のポリシーが異なるので、Parameterize Methodを使用して関数の重複コードを除去することができ、このパラメータで他の多くの変化を処理することができます.
以下に非常に簡単な例を示す.

衝動前:

   
   
   
   
public double FivePercentRaise()
{
_salary
*= 1.05 ;
return _salary;
}
public double TenPercentRaise()
{
_salary
*= 1.10 ;
return _salary;
}

衝動後:

   
   
   
   
public double Raise( int percent)
{
_salary
*= ( 1 + percent / 100 );
return _salary;
}

  2. パラメータの代わりに明確な関数を使用したReplace Parameter with Explicit Methods


説明:


Replace Parameter with Explicit MethodsはParameterize Methodとは逆の操作である.関数内で異なるパラメータに基づいて異なる挙動がなす場合、パラメータの代わりに明確な関数を用いることが考えられる.しかし、この1つはあまり使われず、次の例のようなゴミコードはめったに現れず、C#の属性を使うことをお勧めします.「衝動的」なコードでも、実際にはあまり見られません.

衝動前:

   
   
   
   
public void Set( string name, int value)
{
if (name.Equals( " height " ))
{
_height
= value;
return ;
}
if (name.Equals( " width " ))
{
_width
= value;
return ;
}
}

衝動後:

   
   
   
   
public void SetHeight( int height)
{
_height
= height;
}
public void SetWidth( int width)
{
_width
= width;
}

  3. Preserve Whole Object(オブジェクトを完全に保持)


説明:


あるアイテムからいくつかの値を取り出し、これらの値をパラメータとして関数に渡すと、なぜアイテム全体を渡すことを考えないのですか?もちろん具体的な状況を具体的に分析して、時にはあなたが元のようにする必要があります.

衝動前:

   
   
   
   
int height = rectangle.Height;
int width = rectangle.Width;

int area = CalculateArea(height, width);

衝動後:
   
   
   
   
int area = CalculateArea(rectangle);

  4. パラメータの代わりにReplace Parameter with Methods(関数)


説明:


関数のあるパラメータ値がメソッドによって直接得ることができる場合、この場合、関数はパラメータによってその値を取得すべきではなく、関数の中で直接メソッドによって必要な値を取得すべきである場合が多い.

衝動前:

   
   
   
   
double basePrice = basePrice * num;
double discount = GetDiscount();
double charge = DiscountPrice(basePrice, discount);

衝動後:

   
   
   
   
double basePrice = basePrice * num;
double charge = DiscountPrice(basePrice);

  5. Introduce Parameter Object(パラメータオブジェクトの導入)


説明:


いくつかのパラメータが常にいくつかの関数のパラメータリストに同時に表示されていることに気づきましたか?これらのパラメータには大きな悪名がある--データ泥団(Data Clump)、Introduce Parameter Objectはデータ泥団をオブジェクトにカプセル化し、元の関数が直接オブジェクト全体に伝わるようにし、後でこのオブジェクトを拡張することもできる.
私はすべてのデータの泥団に対してこのようにすることを主張しないで、たとえこのデータの泥団が何十回も何百回も現れたことがあっても、もしデータの泥団の各データの直接的なつながりがそんなに緊密ではないならば、それらは1つの物でそれらを大まかに含むことができなくて、このような状況の下で“パラメータの対象を導入します”はあまり適切ではないかもしれません.

  6. Remove Settings Method(設定関数の削除)


説明:


これは何も言うことはありません.もしあなたのクラスのある値ドメインがオブジェクトの初期化時に値を設定すべきであれば、クラスにはこの値ドメインに関する設定関数があるべきではありません.それらを削除する必要があります.

  7. Hide Method(関数を非表示)


説明:


これも何も言うことはありません.もしあなたのクラスの中の関数がクラス自体の関数呼び出しにしか使用できない場合、他のクラスは使ったことがありません.この関数のアクセス権をprivateに設定したほうがいいです.もちろん、このステップは慎重にしてください.今は他のクラスに呼び出されたことがありません.後でしないわけではありません.

  8. Replace Constructor with Factory Method(コンストラクション関数の代わりにファクトリ関数)


説明:


「コンストラクション関数をファクトリ関数に置き換える」ということは、オブジェクトを作成するときに単純な構造をするだけでなく、例えばEmployeeオブジェクトを構築する場合、Employeeはエンジニア、販売員、デザイナーである可能性があり、異なるカテゴリの従業員に基づいてEmployeeオブジェクトを作成する必要があることを思い出させます.

  9. Encapsulate Downcast(パッケージダウンシフト動作)


説明:


Encapsulate Downcastの再構築が必要な関数を見つけるのは難しくありません.もしあなたの関数がobjectタイプを返している場合は、別の場所でこの関数を呼び出してobjectを取得した後、変換(このobjectをintタイプに変換するなど)を行い、関数に変換の操作をカプセル化する必要があります.

衝動前:

   
   
   
   
public object LastPerson()
{
return _persons.LastElement();
}

衝動後:
   
   
   
   
public Person LastPerson()
{
return (Person)_persons.LastElement();
}

  10. Replace Error Code with Exception(エラーコードの異常置換)


説明:


あなたの関数はint型を返して、あなたは1を返すことを約束してこの関数が正常に運行して、–1を返してある地方の間違いを代表して、エラーコードはここの“1”と“-1”を指します.あなたの関数がエラーコードを返していることを考えてみてください.この関数を呼び出すとき、あなたが戻ってきたエラーコードを判断する必要がある可能性が高いです.もしあなたが受け取ったのは-1でプログラムの運行を停止して、本の中でこのようなやり方が面白いと形容しています.飛行機を逃して自殺したように、もし本当にそうすれば、私が猫であっても、私の9つの命はとっくに弁償しています.
C#の異常処理を忘れないでください.これは重要な概念で、それらを使う時です.

  11. Replace Exception with Test(異常の代わりにテスト)


説明:


「例外処理」は良い機能ですが、乱用しないでください.例外が発生しないコードブロックに対してtryに入れないでください.catch中
一定の条件でコードが異常を投げ出す場合は、Replace Exception with Testを使用することをお勧めします.異常を投げ出す可能性のあるコードの前に、正常な条件が満たされているかどうかをテストしてから実行することができます.満たされていない場合は、tryの代わりに別の実行案です.catchの使用

衝動前:

   
   
   
   
try
{
return _persons[index];
}
catch (IndexOutOfRangeException e)
{
// ...
}
// ...

衝動後:

   
   
   
   
if (index < _persons.Length)
return _persons[index];
// ...