《A Philosophy of Software Design》心得 3 — 写程式时该写注解 (comments) 吗?如果要的话该怎么写?
2023年1月15日
每当提到在程式中写注解(comments),你大概会在网路上看到两派人马,有人觉得应该要写注解;又有另一群人觉得代码应该要写得够清楚,如果有注解就代表写不够清楚,应该要重构而不是加注解。当然除了这极端的两派人马外,多数人都是在中间,部分的代码写注解,但不会全部都写。
关于写注解这件事,在 《A Philosophy of Software Design》 书当中也有谈及。 John Ousterhout 教授的观点是,如果注解写得好,将有效改善整体的系统设计。假如你是反注解派的人,或许可以一起来读读他为什么这么认为。
程式本身写得够清楚,就不用注解吗?
「程式本身写得够清楚,就不用注解」是很多人认为不该写注解的第一大理由。然而程式本身或许可以清楚表达该代码做的事,但不能解释「为什么」要这样写,也不能解释在什么情境可能比较适合某个方法。对于这些相对后设 (meta) 的内容,注解就是很好的帮手。
更进一步说,好的软件设计,应该要把复杂度藏起来,要藏起复杂度,我们需要抽象化,让其他使用该段代码的开发者,可以不用去管背后的细节。因此,如果一个开发者,还要去读程式的细节才能懂如何用该函式或方法,那就失去抽象化的意义。写注解可以让其他开发者,不用去读程式里头的细节也知道如何用该函式或方法,这才能达到抽象化的意义。因此不论程式本身写的清楚与否,好的抽象化搭配好的注解,都是对整个程式库的维护有帮助的。
别说你没时间写注解
在开发时,很多开发者会认为写注解的优先顺序比较低,因此会想把时间花在写新功能,而不是为已经开发好的功能写注解。然而在软件开发中,永远有写不完的功能,如过说因为要开发新功能而没时间写注解,就永远不会有注解。从长远的角度来看,这样的代价是程式库的可维护性会降低。如果从效益与成本的角度来看,写注解的时间,会远比其他开发者花在弄懂没注解的程式所花的时间要少很多。
不要找其他不写注解的理由
很多开发者也会找其他理由不写注解。例如认为注解如果没随着程式更新,反而会误导人;或者是因为过去读过别人写的注解觉得没用,就认为注解没有用。这些都是外部因素,无法证成注解本身没有效益。此外这些都是可以透过好的流程而解决的,所以作者认为不要找这些理由不写注解,而是要去打造更好的流程来改善这些问题。
写注解的好处
上面谈了这么多,大概可以看出 John Ousterhout 教授有强烈的观点认为要写注解。不过回过头来说,写注解有什么好处呢? 他认为最大的好处在于注解可以捕捉到代码没办法传达的资讯,这能够让未来要维护这段代码的开发者,能够更快速地上手。特别对于团队中加入的新成员,代码中的注解可以大幅降低读程式的认知负担 (cognitive load),以及减少未知。
如果没有记录下这些脉络与原因,未来的开发者就不会知道为什么当初是这样写,这变得只能猜测原作者的意图。这不仅更耗时,也可能会因为理解错原本的意图,导致在维护该段代码时出错。很多时候,未来要维护代码的是自己,许多人在写完某段代码几个月后,可能忘了自己当初为什么这样写,所以写注解不仅是帮助其他开发者,也很可能是在帮助未来的自己。
注解该写什么?
虽说 John Ousterhout 教授的观点是认为写注解对软件设计有帮助,但他也同意不是什么都该写成注解。他认为只有在代码中不显而易见的才该写注解 (comments should describe things that aren’t obvious from the code)。
在软件设计中最重要的抽象化,即是提供一个更简易的思考方式,让开发者可以不用深入过于细节的部分。即使开发者可以透过细读代码来了解其如何运作,但这样做太花时间。 John Ousterhout 教授的观点认为开发者应该要不读代码内容,即可理解模组提供的抽象化,而注解是能够协助做到这样的方法。
不要重复代码本身
前面提到,注解应该要讲「为什么」这样写,而不是讲代码在做什么。毕竟代码本身就代表代码在做的事,如果注解在写一次,会是多此一举。下面是书中提到的负面教材,基本上注解就是把代码做的事情。
ptr_copy = get_copy(obj) # Get pointer copy
if is_unlocked(ptr_copy): # Is obj free?
return obj # return current obj
if is_copy(ptr_copy): # Already a copy?
return obj # return obj
thread_id = get_thread_id(ptr_copy)
if thread_id == ctx.thread_id: # Locked by current ctx
return ptr_copy # Return copy
要怎么判断你写的这段注解是不是跟代码本身一样? 书中提到,在你写完注解后可以问问自己「如果某个之前没读过这段代码的人,能不能看着这段注解写出代码?」如果可以的话,就代表注解只是在描述代码,而不是在解释为什么这样写该段代码。因此,在写完注解后,可以再比对一下代码与注解,如果你的注解像是下面那长梗图一样(代码本身是 Stop Sign,然后注解写着「这是一个 Stop Sign」) ,这种状况下注解就真的没有额外价值,不推荐写。
从读者的角度出发
最后 John Ousterhout 教授提到,写注解要从代码读者的角度出发,要思考有哪些关键资讯是读者不知道的。特别是在代码审查(code review) 时,如果你写的某段代码让别人说很难懂,或者某个资讯让别人说并不显而易见,这时候不要去跟对方争,而是去想为什么对方会有困惑,以及你可以如何靠注解让代码更好被理解。
(文末备注:这个章节本身有很多范例,但为了避免笔记变太长,就仅有放其中一个。有兴趣透过案例更具体了解作者的观点的话,推荐直接买这本书来读)。
《A Philosophy of Software Design》心得系列文
- 《A Philosophy of Software Design》心得 1 — 写出复杂度低的软件
- [《A Philosophy of Software Design》心得 2 — 透过模组设计降低软件复杂度,从介面开始](https://www.explainthis.io/zh-hans/swe/a-philosophy-of-software- design/part2)
- 《A Philosophy of Software Design》心得 3 — 写程式时该写注解 (comments) 吗? 如果要的话该怎么写?