Hello, I'm Munetoshi Ishikawa, a mobile client developer for the LINE messaging app.
This article is the latest installment of our weekly series "Improving code quality". For more information about the Weekly Report, please see the first article.
Grammar represents names
The following SettingRepository
is a class for retrieving and saving user settings for a service.
class SettingRepository {
fun getCurrentAccountModel(): QueryResult<AccountModel> {
...
}
fun deleteCurrentUserAccount(): QueryResult<Unit> {
...
}
...
}
Assume that the functionality of this setting gradually expands, and the methods included in SettingRepository
increase. If different settings are used for each screen, it may be preferable to separate the classes by type of setting. For example, you could separate them into Account
, Security
, Notification
, and Language
settings.
There are two options for naming these split classes. One is to use the modifier like Account
at the beginning, and the other is to use it at the end.
// As a prefix
class AccountSettingRepository { ... }
class SecuritySettingRepository { ... }
class NotificationSettingRepository { ... }
class LanguageSettingRepository { ... }
// As a postfix
class SettingRepositoryAccount { ... }
class SettingRepositorySecurity { ... }
class SettingRepositoryNotification { ... }
class SettingRepositoryLanguage { ... }
Which of these is preferable, and why?
Not seduced by the surface
While placing the modifier at the end may look more consistent and aesthetically pleasing, it is preferable to place the modifier at the beginning. This is because, from the perspective of the user of this class, grammar is more important than superficial consistency.
Even if the modifier is placed at the end, if the declarations and definitions are sufficiently close, it is clear that these classes are Repository
from the common part of the name.
class SettingRepositoryAccount { ... }
class SettingRepositorySecurity { ... }
However, the user of this class may not always use multiple Repository
classes.
class CallerClass(
val environment: Environment,
val settingRepositorySecurity: SettingRepositorySecurity,
val dispatcher: Dispatcher
) { ... }
When a developer reads the code of CallerClass
, they may not have knowledge about Repository
. In that case, they might misunderstand SettingRepositorySecurity
as "the security module of SettingRepository
" if translated according to English grammar. Such misunderstandings can significantly impact the speed of reading the code.
On the other hand, naming with the modifier at the beginning is grammatically correct and reduces the possibility of misunderstanding.
class CallerClass(
val environment: Environment,
val securitySettingRepository: SecuritySettingRepository,
val dispatcher: Dispatcher
) { ... }
When naming, it is necessary to focus on "whether it is less likely to be misunderstood by the user" rather than "whether it looks beautiful on the declaration/definition side".
Modifier sandwich
As a principle, it is better to place the modifier at the beginning, but this is not always possible. Let's assume you create a variable like the following:
height of "send" button for portrait mode
If you name this variable portraitSendButtonHeight
or sendButtonPortraitHeight
, it can be misunderstood. For example, portraitSendButtonHeight
can be read as "height of button to send 'portrait'", meaning "the height of the button to send a portrait image".
When more than two modifiers are needed, you may have to place one of them at the end. When modifying with a noun, you should use prepositions like "of", "for", "at", "on", "in" to make it clear that the last part is a modifier phrase. In the previous example, a name like sendButtonHeightForPortrait
would be a candidate.
There are two additional points about prepositions.
Supplement 1
Using prepositions to attach modifier phrases at the end is often acceptable for variable names, but it is better to avoid it for type names like class
or struct
. It is common to name instances by extracting the most important word from the type name, but in doing so, it is easy to misunderstand that "the last word is used".
Supplement 2
Depending on the programming language or platform, prepositions may be omitted if there is a low possibility of misunderstanding. For example, in the standard API of Java or Kotlin, the In
is omitted in currentTimeMillis
for "current time in milliseconds". When creating similar functions or variables, it is preferable to follow the standard naming conventions of that language or platform.
Summary in a nutshell
When naming, focus on whether it is less likely to be misunderstood by the user rather than on the consistency of the declaration/definition side.