编写可读代码的艺术

96
且把金针度与人
0.2 2019.06.18 18:09 字数 1622

"阅读本文大约需要 5 分钟"

很多程序员在学习一门新的编程语言时,会先学习基础的语法和自带的基础库,稍加熟练后便会在实际工作中使用,在实践中再继续提升。

但是在这里,我们需要明确一个概念,就是熟练掌握某种编程语言,并不意味着所写出的代码的可读性,可维护性是好的。同样的,功能正确,性能良好的代码也不一定是易懂,易维护的,在某种程度而言上面这些特性是正交的,彼此并没有特定的联系。

在工作 2,3 年后,把功能代码写对不是什么太大的问题,但是和一些能力较强的程序员的代码,或是优秀的开源框架的代码相比,抛开架构层面的优劣不谈,在最基础的代码层面,你隐隐的发现总是有些区别,但是可能你很难用具体的语言表达出这差的到底是什么。

我把这些差异很大部分归因于代码的可读性问题,而可读性体现在代码的方方面面,小到一个变量的命名,大到如何编写循环,组织函数和类的层次结构。正是由于这些细微的问题,积少成多,会在总体上让你的代码和优秀的代码从看到的第一眼开始就分了高低。

市面上从不缺少教授各种编程语言和框架的书籍,也有很多介绍系统架构的书,但是真正告诉你如何写出「漂亮」,易懂,专业代码书却很少。之前推荐过的 <<重构>> 算一本,而今天推荐的 <<编写可读代码的艺术>> (后文简称艺术) 也是一本讲述如何「写好」代码的书。这本书虽然很薄,200 页都不到,周末两天一定能看完,但是其中内容却非常的实用。本书的两位作者都来自 Google,因此编码的经验和技能毋庸置疑,但是你也不用担心无法理解书里讲解的技巧和思想。作者/译者实用的语言风趣浅显,配上幽默的漫画,要想不懂才是难事。

<<艺术>> 从 4 个方面来阐述如何提升代码的可读性,从最基础的变量,函数如何命名,到如何编写注释,如何简化循环和逻辑,直到重新组织代码,可谓囊括了日常编码和设计技巧中最为实用的几个部分。下面是一些我个人印象比较深也觉得对大部分编程语言也适用的技巧。

[first, last] 和 [begin, end]

有时候你会编写一些与范围相关的代码,比如时间范围,数字范围。而牵涉到范围的逻辑一般都会有开闭区间的问题,如果是你,你怎么编写清晰的代码来告诉使用者理解这些范围逻辑呢?书中给出了大部分框架和类库中约定俗成的建议,即实用 first, last 来表示两个闭区间的变量,而使用 begin, end 来表示前闭后开的区间逻辑。使用这样的命名方法是不是让自己的代码一下子有些专业的感觉呢?

代码的段落

其实写代码和写文章一样,也讲究段落分明,这样才能让读者更清晰的了解代码的意图,不信?看一下下面两段内容一样的代码,是不是给你带来不同的感觉?

# Import the user's email contacts, and match them to users in our system.
# Then display a list of those users that he/she isn't already friends with.
def suggest_new_friends(user, email_password):
  friends = user.friends()
  friend_emails = set(f.email for f in friends)
  contacts = import_contacts(user.email, email_password)
  contact_emails = set(c.email for c in contacts)
  non_friend_emails = contact_emails - friend_emails
  suggested_friends = User.objects.select(email__in=non_friend_emails)
  display['user'] = user
  display['friends'] = friends
  display['suggested_friends'] = suggested_friends
  return render("suggested_friends.html", display)
def suggest_new_friends(user, email_password):
  # Get the user's friends' email-addresses.
  friends = user.friends()
  friend_emails = set(f.email for f in friends)

  # Import all email address from this user's email acount.
  contacts = import_contacts(user.email, email_password)
  contact_emails = set(c.email for c in contacts)

  # Find matching users that they aren't already friends with.
  non_friend_emails = contact_emails - friend_emails
  suggested_friends = User.objects.select(email__in=non_friend_emails)

  # Display these lists on the page.
  display['user'] = user
  display['friends'] = friends
  display['suggested_friends'] = suggested_friends

  return render("suggested_friends.html", display)

两段相同内容的 python 代码,这是第二段合理的使用了空行这样简单的技巧,将函数内不同部分的逻辑在视觉上进行分割,就大大提升了代码的可读性,这样的技巧是不是简单易学,但是效果明显?

控制流程

在日常编程中,if...else 语句一定是出现频率最高的语句之一。但是往往 if 这种逻辑分支又是在理解代码过程只能够较为耗费脑力的部分,如何提升这种语句的可读性呢?不妨看看 <<艺术>> 给出的建议。

  • if 语句中首先处理「正逻辑」部分,即第一个分支处理分支条件为 true 的分支,因为一般在理解正相逻辑时较为简单
  • 尽量使用 return 提早从分支结构中返回,并减少 else 的使用,参考下面的示例:
public boolean Contains(String str, String substr) {
  if (str == null || substr == null) return false;
  if (substr.equals("")) return true;
  ...
}
  • 较少 if...else 语句中嵌套的层数,最好没有嵌套。看看下面嵌套的 if...else 逻辑是不是挺难理解的?
if (user_result == SUCCESS {
  if (permission_result != SUCCESS) {
    reply.WriteErrors("error reading permissions");
    reply.Done();
    return;
  }
  reply.WriteErrors("");
} else {
  reply.WriteErrors(user_result);
}
reply.Done();

那到底怎么改呢?你不妨自己先试一下,然后去书中寻找答案,看看是不是与作者想的一样呢?

书中还介绍了很多类似我提到的技巧和最佳实践,我个人读到这本书的时候有些相见恨晚的感觉。因为其中有些技巧是我自己慢慢摸索的,也有些是其他同事教给我的,假如我能早些读到这本书会节约我大量的时间。想写出易读,「漂亮」,专业代码的你,不妨找一个周末,静下心来,仔细的阅读这本 <<编写可读代码的艺术>>,我想结果不会令你失望。不积硅步无以至千里,想当架构师,先把代码写好吧!

如果你想学习某些计算机相关的知识,缺不知道要去看哪些经典的书籍,不妨后台联系我吧,我一定会推荐你最适合你的好书,帮你事半功倍,飞速成长!


13688092-1d0f5f4dcf0ba004.png
好书推荐