LINEヤフー Advent Calendar 2023の21日目の記事です。
こんにちは。コミュニケーションアプリ「LINE」のモバイルクライアントを開発している石川です。
この記事は、毎週木曜の定期連載 "Weekly Report" 共有の第 7 回です。Weekly Report については、第 1 回の記 事を参照してください。
新事成語
「ユーザ」を示す以下のようなモデルクラスがあるとします。
class UserData(
val id: UserId,
val name: String,
val profileImageUri: String,
...
)
この name
というプロパティは、ユーザの「ログイン名」を示しているものとします。ここで、ログイン名を他のユーザに公開したくないという要望を実現するために、公開用の別名として「ニックネーム」を登録できるように仕様を変えることを想定します。実装の結果として、UserData
は以下のように変更されたとしましょう。(ニックネーム未登録時に null
を使うことは合意が取れていて、問題がないものとします。)
class UserData(
val id: UserId,
val name: String,
val profileImageUri: String,
...
/**
* ...
* もし `nickname` が明示的に `null` の場合は、ニックネームが登録されていないことを意味する。
*/
val nickname: String?
)
さらに、「ユーザ名」を表示する UI は以下のように実装されたとします。
userNameView.text = userData.nickname
?: userData.name
これらのコードについて問題点はありますか?
新しきを以って古きを変える
新しいプロパティやメソッドを足しただけでも、既存のプロパティやメソッドの名前の変更が必要になる ことがあります。上記のコードでは、UserData.name
のプロパテ ィ名を変更するべきでした。
仮にログイン名を表示させず、ニックネームだけを表示させる UI nicknameView
を以下のように実装したとします。このコードには「ニックネームではなくログイン名を使ってしまっている」というバグがあるのですが、一見しただけではそれに気が付きにくいです。
val nickname = userData.name
nicknameView.isVisible = nickname.isNotEmpty()
nicknameView.text = nickname
一目でバグに気が付きにくいのは、「"nickname" (ニックネーム) は "name" (名前) の一種である」ということに起因します。実際の UserData.name
と UserData.nickname
の値に包含関係はないものの、プロパティ名としては包含関係があるように見えてしまうのです。このような混乱を避けるためにも、UserData.nickname
が追加されるときに UserData.name
の名前を変更するべきでしょう。以下のコードでは name
というプロパティ名を loginName
に変えています。
class UserData(
val id: UserId,
/** ... */
val loginName: String,
/** ... */
val nickname: String?,
val profileImageUri: String,
...
) {
// Also, we may put property selection logic
/** ... */
val displayName: String
get() = nickName ?: loginName
}
このようにして、loginName
と nickname
の違いを明確にすることができます。このコードではさらに、「表示名 displayName
ではニックネームを優先し、なければ ログイン名にフォールバックする」ことが明示的になっています。
類似例
似たような状況は、様々なケースで発生しえます。
Case 1
- 既存の要素: ローカルに保存されたデータ
fooData
- 新しい要素: ネットワークを介して取得するデータ
fooRemoteData
- リネーム案:
fooData
->fooLocalData
Case 2
- 既存の要素: 作成時のタイムスタンプ
timestamp
- 新しい要素: 最終更新のタイムスタンプ
lastUpdateTimestamp
- リネーム案:
timestamp
->creationTimestamp
Case 3
- 既存の要素: ユーザのプロフィールに追加可能な外部リンク
url
- 新しい要素: ユーザのプロフィール画像のリンク
profileImageUrl
- リネーム案:
url
->externalLinkUrl
一言まとめ
新しい要素を追加したときは、既存コードの名前の変更を検討する。
キーワード: naming
, new element
, inclusive relation