本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 HelloWorld杰少 即可关注。

如何看待程序员不写注释?

“几个月前,我写的代码只有我和上帝知道”

“现在,只有上帝知道了”

最近在知乎上看到了这个话题:怎样看待程序员不写注释? 看了下浏览量居然有 30+w 次,看来大家讨论的挺热闹,我浏览了大部分的回答,发现大家的观点可以归纳为以下几点:

  1. 不写注释就是害人害己,别人看不懂,过几天连自己也看不懂
  2. 好的代码就是最好的注释,我的代码可读性很好,没必要写注释
  3. 只要有完善的文档,代码本身就是注释
  4. 自己写代码时:“我自己写的代码还要写注释?” 看别人的代码时:“卧槽这人居然不写注释?”

对于程序员群体,有位知乎网友的总结非常到位:程序员最讨厌的四件事:1. 写注释 2. 别人不写注释 3. 写文档 4. 别人不写文档,不得不说我们程序员群体真是个可爱而又敢于自黑的群体。

说实话,我第一次看到这个话题的时候,我愣了一下,心想谁会提出这么沙雕的问题,在我看来写代码不写注释,那不就跟耍流氓一样嚒!在我第一天开始写代码的时候,我的老师就告诉我注释的重要性,就好比渴了要喝水,饿了要吃饭一样,这是编码的习惯。

我们写代码不仅仅是只给编译器看,还要给自己身边的同事看,假如有一天休假,你把工作交接给了你的同事社会王,你正吃着火锅唱着歌呢,社会王因为帮你解决 Bug 而又看不懂你的代码,给你来个夺命连环 Call,你还有什么心思度假。有人也会说:“我自己写的代码只要我自己看的懂就行”,可事实上不写注释,时间一久,等需要重新拾起来的时候你就会发现:“卧槽,这是啥?这为啥报错”。所以给代码添加合格的注释不仅能够让别人更快速的接手你的代码,也能更快的让拾起自己的代码。

迷惑行为

在正式的给大家讲解如何写出合格的注释之前,先给大家看下各种脑洞大开的代码注释:

斗图型

吐槽型

炫耀型

这是学生时期的谢尔盖·布林,后来 Google 的联合创始人之一,这位小伙子当时“低调”地把自己的待遇需求写在了注释里。翻译成中文大概意思就是“钱多事少大办公室,经常免费去好玩的地方旅行,好耶!

雷军 23 年前写的代码

/* * You may think you know what the following code does. * But you dont. Trust me. * Fiddle with it, and youll spend many a sleepless * night cursing the moment you thought youd be clever * enough to "optimize" the code below. * Now close this file and go play with something else. */

中文:你可能相信你能看懂以下代码,但是其实绝对不可能,相信我。一旦你调试了,你绝对会后悔装聪明去尝试优化这段代码。最好的方式是关闭文件,去玩点儿你喜欢的东西吧

菜鸡型

// I am not sure if we need this, but too scared to delete. ... ...

中文:个人不确认是不是需要,但是实在不敢删除

// I am not responsible of this code. // They made me write it, against my will.

中文:个人不负责这块的质量,因为他们逼迫我违心的写了这段代码

//This code sucks, you know it and I know it. //Move on and call me an idiot later.

中文:这段代码的确很挫,我知道你也知道,先不要骂我蠢,请先接着往下看.

看到上面这些灵魂极其有趣的程序员们各种脑洞大开,整起了各种类型的花活,我就只想问你们一下,你们的经理是不是不 review 你们的代码?

如何优雅的为程序写注释?

“好的代码不需要注释”不等于“没有注释就是好的代码”,好的代码不需要注释的前提是后面阅读你代码的人水平不能比你差太多,要写出那种新人都能看懂的代码,实在是太难了。

说到这里想必大家也知道了注释的重要性,注释可以帮助开发者在没有阅读代码的情况下快速了解该接口的功能和用法,如果注释写的好,你的代码也就更受人欢迎。

既然注释有这么多好处,那还不来学习一下一名合格的程序员该如何写注释。

以下注释遵循 C++ 和 Swift 规范, 注释选自开源项目:Kingfisher 和 Alamofire

利用好注释模板

注释模板为注释写作提供了极大的便利,我们常用的开发工具如 VS Code,Xcode 都对注释模板有很好的支持;例如 Xcode, 只要在需要注释的代码的上一行按下快捷键:opt + cmd + / 就可以添加注释模板。

示例如下:

注释风格

// 或者 /// 或 /* */ 都可以; 但 // 更 常用, 要在如何注释及注释风格上确保统一。

文件注释

文件注释描述了该文件的内容,每个文件注释都要包含以下内容:文件内容的简要描述,作者信息,日期,版权信息声明

文件注释的顺序应该如下:

  1. 文件内容的简要描述
  2. 作者信息
  3. 日期
  4. 版权信息声明,例如:Copyright 2008 Google Inc。 必要的话还可以加上许可证样板,例如:Apache 2.0, BSD, LGPL, GPL

示例如下:

//
//  Kingfisher.swift
//  Kingfisher
//
//  Created by Wei Wang on 16/9/14.
//
//  Copyright (c) 2019 Wei Wang <onevcat@gmail.com>
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.

类注释

类注释应该要为读者提供使用该类的足够信息, 同时应当提醒读者在使用此类时要注意的事项。

示例如下:

import Foundation/// `Session` creates and manages Alamofire's `Request` types during their lifetimes. It also provides common
/// functionality for all `Request`s, including queuing, interception, trust management, redirect handling, and response
/// cache handling.
open class Session {...}

函数注释

我们要在每个函数的声明处前加上注释, 描述该函数的功能和用途. 只有在函数的功能通俗易懂时才可以省略这些注释 (例如, 简单的取值和设值函数).。

示例如下:

/// Creates a `DataRequest` from a `URLRequest` created using the passed components and a `RequestInterceptor`.////// - Parameters:///   - convertible:     `URLConvertible` value to be used as the `URLRequest`'s `URL`.///   - method:          `HTTPMethod` for the `URLRequest`. `.get` by default.///   - parameters:      `Parameters` (a.k.a. `[String: Any]`) value to be encoded into the `URLRequest`. `nil` by///                      default.///   - encoding:        `ParameterEncoding` to be used to encode the `parameters` value into the `URLRequest`.///                      `URLEncoding.default` by default.///   - headers:         `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.///   - interceptor:     `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.///   - requestModifier: `RequestModifier` which will be applied to the `URLRequest` created from the provided///                      parameters. `nil` by default.////// - Returns:       The created `DataRequest`.open func request(_ convertible: URLConvertible,method: HTTPMethod = .get,parameters: Parameters? = nil,encoding: ParameterEncoding = URLEncoding.default,headers: HTTPHeaders? = nil,interceptor: RequestInterceptor? = nil,requestModifier: RequestModifier? = nil) -> DataRequest {let convertible = RequestConvertible(url: convertible,method: method,parameters: parameters,encoding: encoding,headers: headers,requestModifier: requestModifier)return request(convertible, interceptor: interceptor)}

变量注释

通常我们取变量名称的时候已经将其意义说明了。但是在逻辑复杂的情况下, 还是需要添加一些注释说明来做特别说明。

示例如下:

/// Underlying `URLSession` used to create `URLSessionTasks` for this instance, and for which this instance's/// `delegate` handles `URLSessionDelegate` callbacks.////// - Note: This instance should **NOT** be used to interact with the underlying `URLSessionTask`s. Doing so will///         break internal Alamofire logic that tracks those tasks.///public let session: URLSession

TODO 注释

对那些临时的, 短期的解决方案, 使用 TODO 注释。

示例如下:

// TODO(kl@gmail.com): Use a "*" here for concatenation operator.
// TODO(Zeke) change this to use relations.
// TODO(bug 12345): remove the "Last visitors" feature

弃用注释

通过注释(DEPRECATED comments)来标记接口已弃用,并要说明后续的替代方案。

示例如下:

/// Gets an image deserialized from provided data.////// - Parameters:///   - data: The data from which an image should be deserialized.///   - options: Options for deserialization./// - Returns: An image deserialized or `nil` when no valid image///            could be deserialized./// - Note:/// This method is deprecated. Please implement the version with/// `KingfisherParsedOptionsInfo` as parameter instead.@available(*, deprecated,message: "Deprecated. Implement the method with same name but with `KingfisherParsedOptionsInfo` instead.")func image(with data: Data, options: KingfisherOptionsInfo?) -> KFCrossPlatformImage?

最后

注释虽然写起来很痛苦, 但对保证代码可读性至关重要。 总而言之,学会写好代码注释,是每一个程序员的必备技术,也是一种良好的编程习惯,不仅仅是为了开发团队中的小伙伴,也是为了面对将来的自己。

参考资料:

  1. https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/comments/
  2. https://bbs.huaweicloud.com/blogs/176194
  3. https://github.com/onevcat/Kingfisher
  4. https://github.com/Alamofire/Alamofire
  5. https://www.zhihu.com/question/27246926/answer/1214585389

相关阅读:

Codable发布这么久我就不学,摸鱼爽歪歪,哎~就是玩儿

iOS 优雅的处理网络数据,你真的会吗?不如看看这篇

UICollectionView 自定义布局!看这篇就够了

Swift 探索 UICollectionView 之 SupplementaryView 和 Decoration View

UICollectionView 自定义布局实现瀑布流视图

使用 UICollectionView 实现分页滑动效果

使用 UICollectionView 实现首页卡片轮播效果

请你喝杯 ☕️ 点赞 + 关注哦~

  1. 阅读完记得给我点个赞哦,有

    代码要写注释吗?写你就输了相关推荐

    1. 程序员写代码要写注释吗?写你就输了

      前言:在职业发展道路上,需要不断提升自己,需要学习资源的,一起学习交流的欢迎加群[443128517],小编准备了学习视频,学习线路,自学书籍,职业发展视频.也可以加美女老师七七的微信.二维码放在下面 ...

    2. Java代码中的注释详解

      2019独角兽企业重金招聘Python工程师标准>>> java注释详解 声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责 ...

    3. 我的代码和注释都写的像坨屎,那又怎么样?

      一周前,我的朋友圈被一篇 #百度某新员工发飙:前人代码写得像一坨屎,颠覆了对大厂的认知# 的文章刷屏了,评论区也非常热闹. 但让我惊讶的是,几乎所有的声音里都充满着嘲笑与讥讽,有的剑指百度的价值观,那 ...

    4. 自解释的代码根本不存在,老老实实写注释吧

      作者 | Sven Gregori 译者 | 薛命灯 有什么比花时间写注释更令人感到兴奋的事情吗?如果我没有猜错,你可能会说:"不好意思,所有事情都比写注释更令人感到兴奋".如果有 ...

    5. 反思代码能力提升点:foreach循环层数;命名契合;分块写;写注释;分步骤;多沟通

      1.foreach循环 最好不要超过四层  超过四层之后  之后再看容易看晕 分开写循环   尽可能的简化  扩展性也好一些 2.命名一定要考虑好  还是很重要的  最好名字的意思与其他的变量能够立马 ...

    6. 代码自解释不是不写注释的理由

      有什么比花时间写注释更令人感到兴奋的事情吗?如果我没有猜错,你可能会说:"不好意思,所有事情都比写注释更令人感到兴奋".如果有人要你给代码加上注释,对你来说就像是一种侮辱.你的代码 ...

    7. 设计代码说明什么是多态性?如何实现多态?(代码中要写注释解释)_狗屎一样的代码!快,重构我...

      关注后你就是我的人了 重构不止是代码整理,它提供了一种高效且受控的代码整理技术. (一)重构原则 1.何谓重构 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修 ...

    8. 设计代码说明什么是多态性?如何实现多态?(代码中要写注释解释)_狗屎一样的代码!快,重构我!...

      狗屎一样的代码如何重构? 重构不止是代码整理,它提供了一种高效且受控的代码整理技术. (一)重构原则 1.何谓重构 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低 ...

    9. 给代码写注释时有哪些讲究?

      如果领导给你一个项目的源码让你阅读,并理解重构代码,但里面一句注释都没有,我想这肯定是之前同事"删库跑路"了. 看一份源码什么很重要?除了各种代码规范之外,还有一个比较重要的就是注 ...

    10. “穷X”事件程序员致歉:以后老实写代码,正紧写注释

      (点击上方公众号,可快速关注) 转自:新浪科技 tech.sina.com.cn/i/2017-11-20/doc-ifynwnty5776053.shtml 新浪科技讯  19日晚间,技术论坛出现了 ...

    最新文章

    1. linux网络编程常用函数详解与实例(socket--bind--listen--accept)
    2. 复杂网络社区结构划分方法
    3. angularjs -- 页面模板清除
    4. python鸡兔同笼编程运行结果_Python解决鸡兔同笼问题的方法
    5. 固态硬盘测试软件有哪些,手把手教你测试固态硬盘!硬盘测试软件大汇总
    6. 2021FME博客大赛 —— FME在道路实景建模中的应用研究
    7. SAP-简单的OALV演示练习
    8. 小程序开发视频教程免费下载
    9. Android逆向不可不知的smali语言
    10. php 统计uv,简单网站统计功能的实现 PV IP 真实访客数(UV) | 学步园
    11. 这是一个转型AI的励志故事,从非科班到拿下竞赛一等奖
    12. python期货程序化交易高手_Python版商品期货跨期对冲策略 (教学)
    13. 江苏计算机小高考2016,2016江苏小高考成绩揭晓 生物化学4A不易
    14. Java HotSpot(TM) 64-Bit Server VM warning:
    15. 【Python】import class/import module
    16. JAVA设计模式之调停者模式
    17. ({}+{}).length
    18. total uninstall 7(卸载清除工具) v7.00
    19. Echarts折线图的平移假动画
    20. java 调用 mahout_(转)Mahout使用入门

    热门文章

    1. 阿里面试题:设计相关的系统对外提供商品实时价格获取功能
    2. 苹果鼠标怎么连接_用手机连接鼠标和键盘的方法(安卓和苹果都可以)
    3. bootstrap网站模板10例精选欣赏
    4. Code3Kingdom - Tech Support
    5. ps污点修复画笔用法和案例:去除脸上痘痘
    6. java实现ftp文件上传失败_用java+ftp实现文件上传的问题?
    7. STM32学习之红外遥控
    8. Vue中的Ajax(26th)
    9. 从西洋跳棋开始机器学习
    10. photoshop cs4 注册