概要
privateなインスタンスメソッドをstatic(クラスメソッド)に変更することで、副作用が無いことを明示できるという方法小手先テクニックを紹介します。
どんな場合
例えばこんな感じの汚いインスタンスメソッドがあったとすると、
private void example(List hoge) {
String message;
if (hoge == null) {
message = "hoge is empty";
} else if (hoge.size() < 3) {
message = "hoge is small";
} else {
message = "hoge is big!";
}
// do something...
}
リファクタリングでこんな風にメソッド分割をすると思います。
private void example(List hoge) {
String message = messageFromHoge(hoge);
// do something...
}
private String messageFromHoge(List hoge) {
if (hoge == null) {
return "hoge is empty";
} else if (hoge.size() < 3) {
return "hoge is small";
} else {
return "hoge is big!";
}
}
別にこれでもいいんですが、もしこの分割されたメソッドが実は
public class Example {
private String fieldA;
private void example(List hoge) {
String message = messageFromHoge(hoge);
// do something...
}
private String messageFromHoge(List hoge) {
fieldA = null; // Oops!!
if (hoge == null) {
return "hoge is empty";
} else if (hoge.size() < 3) {
return "hoge is small";
} else {
return "hoge is big!";
}
}
}
このように、フィールド変数に余計なことをしてしまっているかもしれません。
考え過ぎかもしれません。でももっと複雑になっていけば、ついうっかりこんな感じのことをしてしまうかもしれません。
staticにして回避する
ではここで、インスタンスメソッド「messageFromHoge」をクラスメソッドとして定義し直します。
public class Example {
private String fieldA;
private void example(List hoge) {
String message = messageFromHoge(hoge);
// do something...
}
private static String messageFromHoge(List hoge) {
fieldA = null; // コンパイルエラー!!!!!!!!!
if (hoge == null) {
return "hoge is empty";
} else if (hoge.size() < 3) {
return "hoge is small";
} else {
return "hoge is big!";
}
}
}
そうすると、当然ながらフィールド変数へのアクセスはできず、コンパイルエラーになってくれます。
軽い解説
インスタンスメソッドはフィールド変数へアクセスできる可能性がありますが、クラスメソッドではそのようなことはありません。
privateなクラスメソッドは、引数にのみ依存し、外界へ副作用をもたらすことはありません。
つまり、privateメソッドを作成する際、フィールド変数に依存する処理はインスタンスメソッド、フィールド変数に依存しない処理をクラスメソッドとすることで、影響範囲や役割を明示することができます。