LINEヤフー Tech Blog

LINEヤフー株式会社のサービスを支える、技術・開発文化を発信しています。

コード品質向上のテクニック: 第 15 回(文法は名を表す)

こんにちは。コミュニケーションアプリ「LINE」のモバイルクライアントを開発している石川です。

この記事は、毎週木曜の定期連載 “Weekly Report” 共有の第 15 回です。Weekly Report については、第 1 回の記事を参照してください。

文法は名を表す

以下の SettingRepository は、あるサービスのユーザ設定を取得・保存するためのクラスです。

class SettingRepository {

    fun getCurrentAccountModel(): QueryResult<AccountModel> {
        ...
    }

    fun deleteCurrentUserAccount(): QueryResult<Unit> {
        ...
    }

    ...
}

この設定の機能が徐々に拡張され、SettingRepository に含まれるメソッドも増えていったことを想定します。画面ごとに異なる設定項目を使うのであるならば、設定の種類ごとにクラスを分けたほうが好ましいこともあります。例えば、Account/Security/Notification/Language といった設定項目で分けることが考えられます。

分割されたクラスをどう命名するかについて、以下の 2 つの選択肢があるとします。一方は Account 等の修飾語を先頭に付ける命名で、もう一方は末尾に付ける命名です。

// As a prefix
class AccountSettingRepository { ... }
class SecuritySettingRepository { ... }
class NotificationSettingRepository { ... }
class LanguageSettingRepository { ... }
// As a postfix
class SettingRepositoryAccount { ... }
class SettingRepositorySecurity { ... }
class SettingRepositoryNotification { ... }
class SettingRepositoryLanguage { ... }

これらのうち、どちらのほうが好ましいでしょうか、また、それはなぜでしょうか。

表層に魅了されない

修飾語を末尾につけるほうが統一感があり、美しく見えるのですが、 先頭に修飾語をつける方が好ましい です。このクラスを使う側の視点に立った場合、表面的な一貫性よりも 文法 のほうがより重要になるためです。

修飾語を末尾につけたとしても、宣言や定義が十分に接近している場合は、名前で共通する部分が明確なため、これらのクラスが Repository であることはわかりやすいです。

class SettingRepositoryAccount { ... }
class SettingRepositorySecurity { ... }

しかし、このクラスを使う側では、常に複数の Repository を使うとは限りません。

class CallerClass(
    val environment: Environment,
    val settingRepositorySecurity: SettingRepositorySecurity,
    val dispatcher: Dispatcher
) { ... }

ある開発者が CallerClass のコードを読むとき、その開発者は Repository に関する知識を持っていないかもしれません。その場合、 SettingRepositorySecurity を英文法に従って訳すと、「SettingRepository のセキュリティモジュール」と誤解してしまうかもしれません。このような誤解は、コードを読む速度に重大な影響を与えます。

一方で、修飾語を先頭に付けた命名は文法的に正しくなり、誤解の可能性を低減することができます。

class CallerClass(
    val environment: Environment,
    val securitySettingRepository: SecuritySettingRepository,
    val dispatcher: Dispatcher
) { ... }

命名をするときは、「宣言・定義する側で美しく見えるか」よりも、「使う側で誤解される可能性が低いか」に焦点を当てる必要があります。

修飾語サンド

原則としては修飾語は前に置いたほうが良いのですが、いつもそれができるとは限りません。以下のような変数を作ることを仮定しましょう。

height of “send” button for portrait modeポートレートモードでの「送信」ボタンの高さ

この変数に portraitSendButtonHeightsendButtonPortraitHeight といった命名をすると誤解される可能性があります。例えば、 portraitSendButtonHeight は “height of button to send ‘portrait’” つまり「ポートレート画像を送信するボタンの高さ」とも読み取れてしまいます。

2 方向以上からの修飾が必要な場合、その修飾を末尾に置かざるを得ないこともあります。名詞で修飾を行う場合は、”of”/“for”/“at”/ “on”/ “in” といった前置詞を使い、最後の部分は修飾句であることを明示すべきです。前述の例ですと、sendButtonHeightForPortrait といった名前が候補になります。

前置詞については、2 つほど補足があります。

補足 1

前置詞を使って末尾に修飾句をつけることは、変数名などでは許容されることが多いですが、classstruct といった型の名前としては避けたほうが無難です。インスタンスの名前について、型の名前から最も重要な単語を抜き出して命名されることは一般的に行われるのですが、その際に「最後の単語を使う」ものと勘違いされやすいためです。

補足 2

プログラミング言語やプラットフォームによっては、誤解される可能性が低い場合に前置詞を省略することがあります。例えば、Java や Kotlin の標準 API では “current time in milliseconds” (ミリ秒での現在時刻) の In を省略して currentTimeMillis という名前が使われています。似たような関数や変数を作る場合、その言語やプラットフォームの標準的な命名規則に従うことが好ましいでしょう。


一言まとめ: 命名をするときは、宣言・定義側の一貫性よりも、使う側での誤解のされにくさに着目する。

キーワード: naming, grammar, attributive phrase