写在前面
由于过去的工作经历基本都是在独立开发或者跟我同等级别的同事一起开发,且并没有针对我的code review等机制,因此导致我的代码质量一直不高.
来了理想以后在同组大佬们的纠正下还是偶尔会犯些低级错误,因此在智能云图书角选了一本“代码整洁之道”进行阅读,并且整理一下读书笔记以便查看回忆。
如果这篇笔记能让其他跟我差不多水平的同事们从中获益就更好了,后续我也会继续阅读K8s相关书籍并且整理读书笔记,将我这个级别的开发遇到的一些疑惑和思考记录下来。
代码整洁之道
得救之道,就在其中
第一章
没啥好说的
第二章 有意义的命名

  1. 如果不是特别简单的代码,尽量不要使用int d这种命名,因为不知道你的这个d代表什么
  2. 避免误导,比如我要返回一组用户账号,除非这组账号真的是List类型,否则尽量不要用accountList这种命名,因为在开发的眼里List基本都在说它是一个列表,用accountGroup或者accounts都会不错很多
  3. 做有意义的区分,a1 a2 a3这样的命名是绝对不允许的。UsernameString这样的命名也不可取,难道你的Name会是一个int或者bool类型吗?直接用Username就可以了
  4. 如果你的代码是针对一个用户账号进行操作,那么就选择createAccount而不是createUserAccount
  5. 避免使用编码,指的是不要将你的数据类型体现在命名中
  6. 类名或者对象名应该是名词或者名词短语
  7. 方法名应该是动词或者动词短语,比如createAccount
  8. 给每个抽象概念选一个词,如果你的代码里面用fetch来代表拉取操作,就不要用pull了
    个人觉得命名也应该遵循奥卡姆剃刀原则,如果删除命名中的某些单词不影响这个命名的能力,那就删掉

第三章 函数

  1. 函数要足够短小,小到不能再小那种(其实我不是很赞同)
  2. 只做一件事,一个函数只实现一个功能
  3. 自上而下的阅读,一个函数引用另一个函数功能,另一个函数只给这个函数使用,那么那个函数就放在这个函数下面
    第四章 注释

没啥好说的,个人觉得注释多点是好事,反正也不会太影响代码阅读体验,就算有些多余的注释也就是几十秒就可以看完,而且大部分人也不至于写出来有误导性的注释啥的
第五章 格式

  1. 作者说一个团队应该一致同意采用一套简单的格式规则,所有成员都要遵循这套规则。但我觉得太难了,而且有些付出回报不成比例的感觉,把小组成员全部调教到完全遵循固定的规则太难
  2. 作者在这一章提到的很多东西goland的format code都可以帮我们解决,比如缩进之类的
    第六章


第七章 错误处理

  1. 在一个项目中固定的错误码并且标明它的含义,将这些错误码抽出来作为常量放在常量文件中,即定义一个常规流程
  2. 不要传递和返回null值。但是在golang中与java的这个思想相反,golang的error经常返回nil值然后判断是不是nil
    第八章


第九章 单元测试

  1. TDD原则,先编写单测代码,再编写生产代码,就像测试人员会在开发之前就先把测试用例写出来一样
  • 在编写不能通过的单测之前,不能写生产代码
  • 算了,不重要,不写了...
  1. 测试代码和生产代码一样重要,命名注释啥的要按照生产代码来写。因为单测代码可以让你的代码变得可维护
  2. 每个测试函数都应有且只有一个断言
  3. 整洁的测试应该满足F.I.R.S.T,即
  • 快速FAST。你的测试用例要很快跑完,这样开发者才愿意频繁运行
  • 独立INDEPENDENT。测试互相独立,某个测试不应该为下一个测试设定条件
  • 可重复REPEATABLE。
  • 自主验证SELF-VALIDATING。
  • 及时TIMELY。测试应该及时编写
    第十章 类
  1. 类应该足够短小和符合单一权责原则
    本书中该章节的其他内容跟Java强相关,这里就不展开说了

第十一章 系统
这一章跟Java强相关,不做过多笔记。唯一的一点是建议多使用代码注入工具,比如Golang的wire。
第十二章 迭进

  1. 测试消除了对清理代码会破坏代码的恐惧
  2. 软件项目的主要成本在于长期的维护,为了在修改时尽量降低出现缺陷的可能性,就必须要理解系统是做什么,因此必须把代码写的清晰
    第十三章 并发编程
  3. 单一职责原则SRP认为,方法/类/组件应当只有一个修改的理由,因此建议分离并发相关代码和其他代码
  4. 限制数据作用域,其实就是在并发操作某个数据的时候加锁或者放入队列而已
  5. 使用数据副本,就是改数据的时候修改副本数据,然后把改的数据放在队列里
  6. 尽量让线程独立,不要与其他线程共享数据。这个有点难
  7. 因为加锁会带来延迟和额外开销,所以尽量不要用锁,也就是尽量少用临界区。这有点难
  8. 试试运行多于处理器数量的线程,这样会帮助你找到你的设计中的问题
  9. 在不同的环境上运行。但是这个感觉问题不大,我们的系统基本都是在linux上面的,centos或者ubuntu上面差别应该不会太大,不是像在linux和windows上面那样区别大
    第十四章 逐步改进

全是Java代码。。。看吐了,没啥好记录的
第十五章 JUnit内幕
全是Java代码。。。看吐了,没啥好记录的yet
第十六章 重构SerialData
全是Java代码。。。看吐了,没啥好记录的yet yet
第十七章 味道与启发

  1. 不恰当的注释、废弃的注释、冗余注释、注释掉的代码都给删掉。冗余注释的意思就是“ i++ // 让i自增”这种
  2. 函数输入的参数应该尽量少
  3. 函数的输出参数不应该是输入的参数,如果要改,那就改它的指针,反正输入的参数不能再作为输出参数返回回去
  4. 没被调用到的函数就删掉就行了,如果以后真的要用到的话就去看git记录
  5. 代码应该有正确的边界行为,也就是清楚你的某个函数在干嘛,不要做过多的事情,比如你的函数名是"年龄大于默认"这样的函数,那么这个函数就只判断年龄是不是大于默认的值,而不是如果大于默认值再改成默认值这种
  6. 不要用重复的代码,那种一眼就可以看出来复制粘贴且没有任何改动的代码绝对不要出现,如果出现了这种代码说明你的代码中还有内容可以抽象出来单独作为一个函数
  7. 与细节有关的常量变量之类的不能出现在基类里面,基类也不应该依赖于派生类。任何一个接口或者函数的功能都应该单一,不要有太多的信息
  8. 把逻辑依赖改为物理依赖,不应该对对依赖者的模块有假定(也就是不要有逻辑依赖)。使用多态来替换if/else,也就是函数的认知复杂度尽量要小
    写在后面

书中的关于整洁代码如何开发写的很清楚,但是对于我这样开发经验不多的人来说,很多东西还是得在实际开发中去踩坑。就我过去近一年的golang开发来说,我觉得以下几个点是必须需要注意的

  1. 函数名要非常清楚的表达这个函数的功能,就算函数名很长也没事。但是同时函数名也要遵循奥卡姆剃刀原则,比如你的函数在一个名为users.go的文件之中,那么你的createUserAccount就应该改为createAccount,毕竟肯定都知道你这个函数是在操作user的内容。当然,因为users可以分为admin或者visitor,那么函数名也可能会是createAdminAccount和createVisitorAccount
  2. 一个函数就只干一件事,比如判断一个人的分数是否达到了及格线,如果没有到及格线就默认将这个人的分数等级改为D-,但是你比较分数的那个函数只需要做比较分数的功能,而不是比较分数&修改等级
  3. 函数要尽量的简短,拆到不能继续拆分为止
  4. Golang-lint有个能力,判断函数的认知复杂度是否高于15,要善用这个能力
  5. 单测代码很重要,不仅仅是检测你的代码有没有问题,而且还可以让你在修改重构你的业务代码的时候不要有心理负担,因为改出bug的话单测代码可以帮你发现
  6. 以后想到了再加进来.... Todo
    写的差不多了(2023.7.18),接下来继续写programming kubernetes那本书的阅读笔记

在折腾了这么久以后,我终于还是暂时放弃了自己完全写一个博客网站的想法(主要是要搞论文和懒得写前端),而是选择了站在巨人的肩膀上,这只是我的博客网站的第一步,后续会修改模板和继续为我个人博客网站的github添砖加瓦。如果有兴趣加入我博客开发的朋友可以联系我,后端我在使用golang编写,我希望你是一个js大佬