写Scala代码时,很多人只关注函数式的高阶用法,比如map、flatMap、for推导这些,却忽略了命名这个看似简单实则影响深远的细节。其实,好的命名能让同事快速理解你的意图,也能让自己三个月后回看代码不至于一头雾水。
变量名:小写开头,见名知意
在函数式编程中,变量通常是不可变的,所以用val很常见。命名时推荐使用小写字母开头,多个词用驼峰命名法。比如处理用户数据时,别写成data1或tempList这种模糊名字,而是像这样:
val userList = List(User("Alice", 28), User("Bob", 32))
val filteredAdults = userList.filter(_.age >= 18)
一眼就能看出filteredAdults是筛选后的成年人列表,不需要再翻逻辑。
函数命名:动词优先,表达行为
函数是用来做事情的,所以名字最好以动词开头。比如你写一个判断用户是否能登录的函数,别叫checkLogin,虽然也说得通,但更自然的是canLogin或isValidUser:
def canLogin(user: User, attempts: Int): Boolean =
user.isActive && attempts < 3
这样的命名方式在for推导里尤其舒服,读起来像自然语言:
for {
u <- users if canLogin(u, u.loginAttempts)
} yield u.email
避免缩写,除非约定俗成
有些人为了省几个字母,把configuration写成cfg,把accumulator写成acc。除了像acc这种在fold里几乎成了标配的缩写,其他尽量写全。毕竟敲代码的时间远少于读代码的时间。
比如你在写一个累加积分的fold操作,可以接受:
points.foldLeft(0)((acc, p) => acc + p.value)
但如果自己定义一个类叫CustInfo而不是CustomerInfo,就容易让人多想一层。
类型别名要清晰,别为了简洁牺牲可读性
Scala支持type关键字做类型别名,在处理复杂函数签名时很有用。但别滥用,比如:
type Processor = List[String] => Option[Int]
这个名字太泛了,到底处理什么?改成LineCountProcessor或者LogEntryToInt会更明确。别人一看就知道这玩意儿是用来从日志行算出一个可选整数结果的。
私有函数和局部值:可以稍微随意,但别太过
在方法内部定义的辅助函数,作用域很小,命名可以稍微简化。比如在某个大函数里临时用一下:
def calculateScore(entries: List[Entry]): Double = {
def scoreOf(e: Entry) = e.weight * e.value
entries.map(scoreOf).sum / entries.size
}
这里scoreOf虽然短,但在上下文中足够清楚。但如果逻辑变复杂,还是建议写成computeEntryScore这类更完整的名称。
布尔值相关命名:加上is、has、can等前缀
返回Boolean的函数或val,最好通过名字直接体现真假含义。比如:
val isActive = user.status == "active"
val hasPermission = permissions.contains("write")
def canProcess(task: Task) = task.ready && !isLocked
这样在条件判断里读起来非常顺:
if (user.hasPermission && canProcess(task)) { ... }
像是在读一句话,而不是解析符号。