2018-02-24 项目/教程中使用母语命名的"问题"

时间:2021-07-18 12:43:50

早先试图找使用中文命名代码的项目, 但所获寥寥: 索引: 用中文编写代码的实用开源项目 · Issue #6 · program-in-chinese/overview. 更不用说教程了: 索引: 用中文代码作示例的编程教程 · Issue #5 · program-in-chinese/overview

前几天有幸看到Quora不久前的一个回复: Has any serious project been written in a non-English-based programming language?

得知西门子和爱立信内部都有使用母语命名的C/C++代码(德语/瑞典语). 原文如下:

At both Siemens (German) and Ericsson (Swedish), I have seen programs written in C, and C++ where the only English words are the keywords. So if, new, else, for and the standard libraries like std::vector<>

Everything else was in German or Swedish.

...

另外, 答者还提到在布拉格碰到过一本Java编程书, 也是用非英语进行命名写的示例代码.

以母语命名可读性强的优势, 照理说编程教程应该是非常适合这一实践的. 那么来试试:

enum 发薪日 {
周一, 周二, 周三, 周四, 周五, 周六, 周日; private static final int 每班分钟数 = 8 * 60; int 发薪(int 工作分钟数, int 每分钟薪水) {
int 底薪 = 工作分钟数 * 每分钟薪水;
int 加班费;
switch (this) {
case 周六:
case 周日: // 周末
加班费 = 底薪 / 2;
break;
default: // 周中
加班费 = 工作分钟数 <= 每班分钟数 ? 0 : (工作分钟数 - 每班分钟数) * 每分钟薪水 / 2;
}
return 底薪 + 加班费;
}
}

观感如何? 个人觉得是非常一目了然, 但自带不少槽点.

下面看看原版(Effective Java第三版, Item 34的例程):

enum PayrollDay {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; private static final int MINS_PER_SHIFT = 8 * 60; int pay(int minutesWorked, int payRate) {
int basePay = minutesWorked * payRate;
int overtimePay;
switch (this) {
case SATURDAY:
case SUNDAY: // Weekend
overtimePay = basePay / 2;
break;
default: // Weekday
overtimePay = minutesWorked <= MINS_PER_SHIFT ? 0 : (minutesWorked - MINS_PER_SHIFT) * payRate / 2;
}
return basePay + overtimePay;
}
}

意思一样, 但是不是看上去有了些"距离感", 槽点似乎就没那么明显了, 尤其不会有太多代入感. 可以想见, 在翻译英文原著时, 译者对代码本身的命名进行中文化也许会吃力却讨不到多少好.

翻了也许会有其他麻烦的还有这种(同一本书, Item 68):

if (car.speed() > 2 * SPEED_LIMIT)
generateAudibleAlert("Watch out for cops!");

还有这种(Item 4):

String s = "bikini";

至于下面这个例子(Item 34), 问题是想翻译都只能找到音译词, 也许还不如不翻. 而且, 在示例代码里用"桔子", "苹果"之类在外文编程书籍中屡见不鲜, 但如果真用在中文代码中, 似乎第一感觉就有点幼稚.

public enum Apple  { FUJI, PIPPIN, GRANNY_SMITH }
public enum Orange { NAVEL, TEMPLE, BLOOD }

还有一种问题比如(Programming in Scala 第三版, 7.5节):

    val firstArg = if (args.length > 0) args(0) else ""
firstArg match {
case "salt" => println("pepper")
case "chips" => println("salsa")
case "eggs" => println("bacon")
case _ => println("huh?")
}

直译过来是:

    val 参数1 = if (参数.length > 0) 参数(0) else ""
参数1 match {
case "盐" => println("胡椒")
case "玉米薄片" => println("萨尔萨辣酱")
case "鸡蛋" => println("培根")
case _ => println("啥?")
}

这几个词对于不大了解西方饮食习惯的读者来说, 读起来完全没有感觉. 与其费口舌在注解里普及西方文化, 也许改成这样更自然:

    val 参数1 = if (参数.length > 0) 参数(0) else ""
参数1 match {
case "牛奶" => println("面包")
case "烧饼" => println("油条")
case "煎饼果子" => println("薄脆")
case _ => println("啥?")
}

但这比起翻译本身来, 又多了不少工作量, 估计还很难获得原作者的同意. 当然, 如果是自编文献, 就没有原作的限制了, 但就像之前的例子所示, 恐怕选材和尺度都会比用英文代码更加敏感.

类似的, 在项目中使用中文命名也比英文命名更需要推敲. 随手写个奇怪的英文名看起来也许不那么显眼, 但用了中文, 就会非常扎眼. 所谓"文如其人", 也许语文的实用性会随着中文编程的推广而逐渐回归.