なぜメソッド名がそんなに大事なのか
メソッド名は「このメソッドが何をするか」を一言で表すラベルです。
ここが雑だと、コードを読むたびに「これ何してるんだっけ?」と中身を開いて確認する羽目になります。
逆に、メソッド名がよくできていると
コードを上から流し読みしただけで処理の流れが頭に入る
中身を開かなくても、どこを呼べば何が起きるか想像できる
バグ調査や設計変更のときに「読む量」を減らせる
という、地味だけど大きな差が生まれます。
まずは、よくある「悪いメソッド名」と「良いメソッド名」を対比させながら、考え方を固めていきます。
悪いメソッド名の典型例とその問題点
何をしているか分からない「do / process / handle 系」
次のようなメソッド名、どこかで書いたことありませんか。
void doUser(User user) { ... }
void process(User user) { ... }
void handle(User user) { ... }
Javado も process も handle も、「何かする」以上の意味を持ちません。
このメソッドを呼ぶ側のコードは、こうなります。
userService.process(user);
Java日本語で読むと「ユーザを処理する」。
何の処理なのか、さっぱり分かりません。
例えば中身が「ユーザに確認メールを送る」処理だったとしたら、sendConfirmationMail(user) のほうが圧倒的に分かりやすいです。
悪いメソッド名の特徴は、「メソッド名だけ見ても、意図が全然伝わらない」ことです。
意味のない一文字・二文字の名前
メソッド名だけでなく、引数名も同じです。
int calc(int a, int b) { ... }
Javacalc は「計算する」、a と b は「何かの値」です。
例えば「税込金額を計算する」なら、実際にやっていることはこれです。
「単価と個数から税込み金額を計算する」
ならば
int calculateTotalPriceWithTax(int unitPrice, int quantity) { ... }
Javaと書くほうが、読む人には優しいです。
長く感じるかもしれませんが、「何の計算か」を毎回推理するコストに比べたら安いものです。
良いメソッド名の基本ルール(ここが一番重要)
「動詞+目的語」で“何をするか”をはっきり書く
メソッド名は、基本的に「動詞+目的語」の形にします。
例をイメージしやすく書くと
「ユーザを保存する」なら saveUser
「ユーザを登録する」なら registerUser
「カートに商品を追加する」なら addItemToCart
「送料を計算する」なら calculateShippingCost
といった感じです。
ポイントは、「何をするメソッドか」を日本語で言ってから英語にすることです。
最初から英単語をひねり出そうとすると、だいたい do や process に逃げがちです。
一度、心の中でこう言ってみてください。
「これは◯◯するメソッドだな」
その◯◯が「商品を追加する」「割引額を計算する」のように具体的なら、
そのまま英語にして addProduct や calculateDiscountAmount にできます。
「ユーザを処理する」みたいな説明しか出てこないなら、
そもそもメソッドの責務が曖昧か、やることが多すぎるサインです。
戻り値とメソッド名の関係を意識する
戻り値の型とメソッド名の相性も大事です。
例えば、何かを「問い合わせる」メソッドがあって、戻り値が真偽値なら
isActivehasEnoughPointcanCancel
といった「質問文(yes/no)」が自然です。
if (user.isActive()) { ... }
if (order.canCancel()) { ... }
Javaと書けると、コードがそのまま日本語の文章として読めます。
逆に、checkActive() のような名前にしてしまうと、
戻り値が boolean なのか
例外を投げるだけなのか
内部状態を変えるのか
が分かりにくくなります。
「戻り値を返すだけ」のメソッドか、「状態変更(副作用)」があるメソッドかで、
名前を変えると読みやすくなります。
例として
情報を取得するだけなら getTotalPrice()
内部状態を変えるなら addItem() や changeEmail()
のように分けておくと、呼び出し側が迷いません。
ドメイン(業務)の言葉をメソッド名にする
技術用語ではなく「業務の日本語」を英語化する
例えば、EC サイトの注文確定処理を作るとします。
業務的には「注文を確定する」「注文をキャンセルする」「出荷する」といった言い方をしますよね。
これをメソッドに落とすと
placeOrder()cancel()ship()
のようになります。
決して
execute()process()doOrder()
ではありません。
「仕様書に書いてある言葉」と「メソッド名」が直接つながっていると、
仕様変更のときもどこを見ればいいか分かりやすくなります。
ドメインの言葉をそのまま持ち込むことは、
読みやすさだけでなく「バグをビジネスの理解不足から防ぐ」意味でも大きいです。
クラスとメソッドを組み合わせたときに自然な文になるか
クラス名とメソッド名の組み合わせで読むと、さらに分かりやすさが変わります。
例えば Order クラスに
cancel()ship()calculateTotal()
というメソッドがあれば
order.cancel()order.ship()order.calculateTotal()
と書けます。
日本語にすると「注文をキャンセルする」「注文を出荷する」「注文の合計を計算する」。
かなり自然ですよね。
逆に
order.process()order.handle()
などは、「注文を処理する」「注文を扱う」。
結局何をするのか分からないままです。
メソッド名を付けるときには、
必ず「クラス名+メソッド名」で読んでみてください。
メソッド名が設計のおかしさを教えてくれる
名前がうまく付けられないメソッドは、責務が多すぎる
例えば、こんなメソッドを書こうとしているとします。
「ユーザ登録フォームから値を取ってきて、バリデーションして、ユーザを作って DB に保存して、確認メールを送る」
これをメソッド名にしようとすると
registerUserAndSendMail()handleUserRegistration()processUserForm()
みたいに、どう書いてもモヤモヤします。
これは「一つのメソッドでやっていることが多すぎる」サインです。
実際には
入力のバリデーション
User オブジェクトの生成
User の永続化
メール送信
という別々の責務があります。
それぞれを別メソッドに分ければ
validate()toUser()save()sendWelcomeMail()
のように、ずっと自然なメソッド名が付けられます。
「いい感じの名前がどうしても思いつかないメソッド」は、
だいたい設計のレベルで何かがおかしいので、分割を検討するチャンスです。
before / after でメソッド名の改善を体感する
例1:ポイント加算
悪い例を先に見ます。
public class UserService {
public void exec(User u, int p) {
u.point = u.point + p;
if (u.point > 10000) {
u.point = 10000;
}
}
}
Javaexec も u も p も意味不明です。
日本語で説明すると、「ユーザにポイントを加算する。ただし最大 10000 まで」です。
これを素直に名前にします。
public class User {
private int point;
public void addPoint(int addedPoint) {
if (addedPoint < 0) {
throw new IllegalArgumentException("マイナス加算は禁止");
}
point += addedPoint;
if (point > 10000) {
point = 10000;
}
}
public int point() {
return point;
}
}
Java呼び出し側はこう書けます。
user.addPoint(100);
Javaメソッド名だけで「ユーザにポイントを追加している」と分かります。
ここまで来ると、コメントすらほとんど要りません。
例2:合計金額計算
悪い例。
public int calc(List<Item> list) {
int s = 0;
for (Item i : list) {
s += i.price * i.quantity;
}
return s;
}
Javacalc、list、s。何の合計か分からないですね。
業務的には「カート内商品の合計金額」です。
ならば
public int calculateTotalAmount(List<Item> items) {
int totalAmount = 0;
for (Item item : items) {
totalAmount += item.price * item.quantity;
}
return totalAmount;
}
Javaと名前を付けるだけで、かなり読みやすくなります。
メソッド名を良くするための日常的なクセ
実装したあとに「これ日本語で読むとどうなる?」と考える
メソッドを書き終えたら、
呼び出しコードを頭の中で日本語に翻訳してみてください。
cart.addItem(product, 3);
「カートに商品を3つ追加する」
違和感ないですよね。
cart.process(product, 3);
「カートを3処理する…? 何それ?」
変な日本語になるなら、その時点でメソッド名を変えるべきです。
「短さ」より「意味の分かりやすさ」を優先する
初心者は「メソッド名は短くしなきゃ」と思いがちですが、
ほんとうに大事なのは「読む人が一瞬で意味をつかめるか」です。
calc() より calculateTotalPrice()do() より sendWelcomeMail()run() より executeMonthlyBilling()
のほうが情報量が多く、そのぶん他の人の理解コストが下がります。
長すぎて本当に読みにくくなっているなら、
それはメソッドがいろんなことをやりすぎている可能性のほうを疑ってください。
まとめ:メソッド名を付けるときの自分へのチェック質問
メソッド名を書いた瞬間、あるいは書いたあとに、
こんなことを自分に問いかけてみてください。
このメソッドは、日本語で言うと「何をどうする」メソッド?
その日本語を、そのまま英語にしたような名前になっているか?
クラス名と合わせて読んだとき、文章として自然か?
戻り値の有無とメソッド名のニュアンスは合っているか?do, process, handle, run, exec みたいな「意味の薄い動詞」でごまかしていないか?
どれか一つでも「うーん」と感じたら、今がリネームのチャンスです。
