ドメイン(問題領域)の知識が増えてくるとソフトウェアが複雑になる。
ビジネスルールを記述するため、if 文が増え、区分コードや状態フラグが増え、ひとつのメソッドに延々とコードがならぶ。
・メソッド内でインデント(段付け)が必要になる
・3行以上、空白行や {} の区切りがないコードが続く
・ && や || を使う
私のルールでは全部アンチパターンです。
void method()
{
input();
doSomething();
output();
}
このくらいがメソッドとしてちょうど良い感じ。これ以上複雑なメソッドは、リファクタリング(設計の改良)の候補です。
ファウラーの「リファクタリング」で、複雑になりはじめたコードを改良するパターンをいろいろ説明している。
メッソッドの抽出
コードをひとまとめにして、別のメソッドとして抽出する。
そのひとかたまりに名前(メソッド名)をつける。
データが並んだときと同じで、コードがならんだら、意味のある区切りに空白行を挿入する。 そのかたまりを別メソッドにする。
本の例では、2行の System.out.println() 文を まとめて printDetails() メソッドに抽出しています。
条件記述の分解
(リファクタリング前)
if( date.before(SUMMER_START) || date.after(SUMMER_END) )
{
charge = qauntity * _winterRate + _winterServiceCharge ;
}
else
{
charge = quantity * _summerRate ;
}
リファクタリング後
if( isSummer( date ) )
charge = summerCharge( quantity ) ;
else
charge = winterCharge( quantity ) ;
boolean isSummer( Date date ) { ; }
dobule summerCharge( int quantity ) { ; }
dobule winterCharge( int quantity ) { ; }
というように、評価式、計算式をそれぞれ別メッソドとして抽出する。 コードの意味がわかりやすくなったでしょう。
適切なメソッド名を使えば、コメント文での説明も不要。
ガード節で if-else の入れ子を置き換える
if( 条件A )
else
{
if( 条件B )
else
{
if( 条件C )
else
{
return normalResult ;
}
}
}
というようなコードを、
if( 条件A ) return getA() ;
if( 条件B ) return getB() ;
if( 条件C ) return getC() ;
return normalResult ;
というように return 文を使って、 else 文を無くす。
複雑な条件文が見違えるほど、わかりやすくなりますね。
メソッド名の変更
getinvcdtlmt()
↓
getInvoiceableCreditLimit()
ロジックをたくさんの小さなメソッドに分割した時、メソッドの名前をわかりやすくすることが大切。
わかりやすいメソッド名はそれだけで、メソッドの内容を説明する。コメントの補足は不要です。
問合せと更新の分離
Object getSomethingAndSetAnotherThing()
↓
Object getSomething();
void setSomething();
get と set を同時に行っているメソッドを見つけたら、とにかく分解しましょう。
改良した設計のコードはこんな感じになる。
・どのメソッドも短い (3行くらい)
・メソッドの名前がわかりやすい (名前は長め)
・if 文のネストが消える
・else 文が消える
あと、コレクションフレームワークやアプリケーションフレームワークを使えば、for 文も激減します。
for 文や if 文を駆使するより、 もっとシンプルに書きましょう。
そのほうが、読みやすく、安心して変更できるソフトウェアになりますね。
ビジネスルールを記述するため、if 文が増え、区分コードや状態フラグが増え、ひとつのメソッドに延々とコードがならぶ。
・メソッド内でインデント(段付け)が必要になる
・3行以上、空白行や {} の区切りがないコードが続く
・ && や || を使う
私のルールでは全部アンチパターンです。
void method()
{
input();
doSomething();
output();
}
このくらいがメソッドとしてちょうど良い感じ。これ以上複雑なメソッドは、リファクタリング(設計の改良)の候補です。
ファウラーの「リファクタリング」で、複雑になりはじめたコードを改良するパターンをいろいろ説明している。
メッソッドの抽出
コードをひとまとめにして、別のメソッドとして抽出する。
そのひとかたまりに名前(メソッド名)をつける。
データが並んだときと同じで、コードがならんだら、意味のある区切りに空白行を挿入する。 そのかたまりを別メソッドにする。
本の例では、2行の System.out.println() 文を まとめて printDetails() メソッドに抽出しています。
条件記述の分解
(リファクタリング前)
if( date.before(SUMMER_START) || date.after(SUMMER_END) )
{
charge = qauntity * _winterRate + _winterServiceCharge ;
}
else
{
charge = quantity * _summerRate ;
}
リファクタリング後
if( isSummer( date ) )
charge = summerCharge( quantity ) ;
else
charge = winterCharge( quantity ) ;
boolean isSummer( Date date ) { ; }
dobule summerCharge( int quantity ) { ; }
dobule winterCharge( int quantity ) { ; }
というように、評価式、計算式をそれぞれ別メッソドとして抽出する。 コードの意味がわかりやすくなったでしょう。
適切なメソッド名を使えば、コメント文での説明も不要。
ガード節で if-else の入れ子を置き換える
if( 条件A )
else
{
if( 条件B )
else
{
if( 条件C )
else
{
return normalResult ;
}
}
}
というようなコードを、
if( 条件A ) return getA() ;
if( 条件B ) return getB() ;
if( 条件C ) return getC() ;
return normalResult ;
というように return 文を使って、 else 文を無くす。
複雑な条件文が見違えるほど、わかりやすくなりますね。
メソッド名の変更
getinvcdtlmt()
↓
getInvoiceableCreditLimit()
ロジックをたくさんの小さなメソッドに分割した時、メソッドの名前をわかりやすくすることが大切。
わかりやすいメソッド名はそれだけで、メソッドの内容を説明する。コメントの補足は不要です。
問合せと更新の分離
Object getSomethingAndSetAnotherThing()
↓
Object getSomething();
void setSomething();
get と set を同時に行っているメソッドを見つけたら、とにかく分解しましょう。
改良した設計のコードはこんな感じになる。
・どのメソッドも短い (3行くらい)
・メソッドの名前がわかりやすい (名前は長め)
・if 文のネストが消える
・else 文が消える
あと、コレクションフレームワークやアプリケーションフレームワークを使えば、for 文も激減します。
for 文や if 文を駆使するより、 もっとシンプルに書きましょう。
そのほうが、読みやすく、安心して変更できるソフトウェアになりますね。