机器人论坛
登录
直播中
王平
7年用户
1339经验值
私信
关注
[问答]
General的要点思想
开启该帖子的消息推送
General
这是一本被前辈称赞, 另一个马丁的知名著作, 被赋予学习如何写出漂亮代码的教皇级手册, 最近(再)浏览, 有诸多感受.
总结一下就是如果你是新手, 可能看优秀的open source学习更好; 如果你是老手, 可能他说的东西要么你会觉得太啰嗦, 要么你会觉得例子太细节, 太教条, 无法举一反三.
不过一些General的要点思想我摘录了出来, 有些还包括个人的观点, 记录在此, 以备查阅.
回帖
(1)
h1654155275.5764
2020-11-4 11:43:15
勒布朗(LeBlanc)法则, Later equals never
代码如果烂了就会越来越烂, 所谓破窗原理, 以前老是也提过叫代码腐化
命名
命名应该合理, 成员变量不用加前缀, 靠高亮就很好
接口加前缀I也不太好, 不如实现加Imp
方法命名最好使用动词或动词短语
多使用计算机领域的词汇
有时候命名在语境里才有意义, 有时候变量命名也不需要重复语境
函数
函数短小一些比较易懂, 20行内最佳
if/else/while代码块封装函数, 只有一行最好 (有点激进?)
一个函数只干一件事情
复杂的switch试图用多态取代, 然后封装在抽象工厂里
同一类型函数命名风格应该一致, 使用描述性的语句描述比难懂的短词更好
一元函数最普遍, 标识函数(参数为boolean)的不如分成两个函数, 二元函数尽可能转换成一元函数
参数太多可能需要封装类了
好名字的函数一般是动词, 或者动词+关键字
函数一般要么做事, 要么回答事, 不可兼得 (其实也不一定, 比如很多返回boolean状态的函数)
推荐使用异常代替错误代码
最好将try/catch单独抽入一个函数 (如Android代码会对RemoteService调用进行类似封装, 吃掉exception)
使用枚举表示错误码会让改动变得繁琐 (重新导入或者编译部署), 大家都依赖这个枚举, 应该用异常与继承取代
不要重复, 偶尔可以考虑AOP这类的方法解决
注释
注释少要比注释多有用, 注释多说明代码糟糕 (其实分情况吧)
有目的性的注释还是有用的, 比如阐述, 放大, 警告, 定期维护的TODO等
如果代码不用, 不要注释掉, 直接删掉
格式
横向, 竖向对齐, 间隔, 缩进等. 其实目前formater已经很强大了, 养成良好的format习惯, 渐渐的写出来的代码就会像直接format后一样
对象与数据结构
面向过程与面向对象对立, 前者容易加函数, 不容易加对象, 后者容易加对象, 而不容易加函数
理想情况下, Law of Demeter认为, 类不应该操作对象内部的东西, 如不应该操作函数返回对象的方法. 目的只是为了降低复杂度, 认为这样将私有变量公开化, 增加了重构的难度, 如添加新函数, 方法等, 将数据结构与对象逻辑耦合在一起.
针对于上面的问题, 原则应该是对象暴露行为, 隐藏数据, 数据结构暴露数据
错误处理
Java特色的受控异常(Checked Exception), 必须得被catch, 对受控异常的修改会引起上层所有调用方法的改动, 尽量不要使用, 其他语言只有RuntimeException
可以包装第三方逻辑, 封装自己的异常类, 简化为只catch一种异常
简化使用也可以将异常处理完全封装进去, 返回特例即可
轻易不要返回null, 传入null
代码的坚固与干净不冲突, 所以添加一些check, throw相应的Exception也合理
边界
所谓边界就是自己可以控制到的程序与第三方的边界, 通常需要通过封装的办法来划清边界, 限制那些无法控制的第三方, 如直接Wrapper或者Adapter模式等
单元测试
测试需要整洁, 需要跟随代码一起更新, 测试的最大用途是保证你后续的修改有信心
测试的整洁主要讲的是可读性, 即分为三个环节, build->operate->check, 可以把繁杂的准备封装起来
测试API是渐渐重构演进过来的, 也不可能是起初就设计出来
有人建议每个测试一个assert, 但是这样会有很多重复的代码, 不过可以利用Template Method来解决. 不过也不一定必须一个, 做到最小化就可以了
整洁还有五条规则, Fast, Independent, Repeatable, Self-Validation, Timely
这里讲到TDD的好处, 主要是帮助你覆盖更多的测试, 如果写完再测, 发现测不了, 就不写了.
类
类应该短小, 权责应该足够单一, 内聚性应该高
如果期望抽走一部分逻辑, 最好连相关函数参数也抽走
简化类的过程应该小步, 每一步都运行测试一下
类的精简是为了更好的体现开闭原则, 整体结构为修改而设计
类应依赖于接口, 不依赖实现, 可以隔离修改, 符合依赖倒置原则, 类似策略模式
系统
构造与使用分开, 通过依赖注入等
通过AOP, Proxy的方式, 无侵入性的插入逻辑
系统如果充分模块化, 领域之间相互直接松耦合, 最为理想, 就可以通过测试来驱动
DSL的使用可以平衡领域与技术
迭代
代码是在不断迭代中进步的, 比如通过抽函数, 运用设计模式等
并发
应该尽可能分离并发代码与其他代码
尽可能让线程之间独立, 不要有共享
线程模型有典型的生产者与消费者, 读者与作者, 宴席哲学家模型, 分别用来说明互斥, 读写, 竞争死锁等特例
锁定代码块应该尽可能小
线程最好可插拔, 遵循单一权责, 分离线程与其他代码, 测试先保证除线程之外的逻辑
最后一张通过实例来介绍并发代码如何重构的比较清晰
逐步改进
这片使用了一个例子, 先采用蛮干进行重构发现越来越难, 后来采用逐步的办法, 还写的很细节, 但是比较Tricky的地方是, 这里提出的每步改动都通过测试来印证, 然后保证测试通过, 或者补充一个测试, 让代码通过, 但是所谓TDD部分只有思想, 老代码既然写的不好, 测试是如何出来的, 如何做到Cover全的. 如果假设在一个有比较好测试覆盖的基础上重构, 我感觉即便蛮力也不会太差...
JUnit
比较神奇的一章, 感觉更像是用一个算法类的重构来说明如何把代码改简单, 但是开头先介绍了100%覆盖的Junit测试长什么样子... 感觉作者是想说以前的人做的还不错, 都用JUnit给覆盖全了, 还是可以重构的更漂亮的, 所以感觉标题不太好
重构SerialDate
跟上一个对比, 这个测试覆盖不全, 所以在补测试的过程中进行重构, 还发现了缺陷, 又最终把代码改清晰了. 不过同样由于太过细节, 一些重构理论也很教条, 如果想通过看别人重构的例子来学习如果写简洁的代码, 不如直接看优秀的代码是怎么写的
味道
里面类比了很多Bad Smell, 同样是很细节, 比如太多, 太死, 太复杂, 重复, 不一致, 耦合, 测试不足等, 提供的Tips大多的中心思想就是抽, 封装, 单一职责, 命名清晰
提到使用*来避免过长import, 不过这个与现在流行的lint检测违背, 可以因为以前都是手动, 通配符简单吧.
不要通过继承来使用常量, 还提到不要用静态常量, 用枚举, 这个也与当前的思想有出入, 现在经常将Java的enum太冗余, 不必要时可以用常量
勒布朗(LeBlanc)法则, Later equals never
代码如果烂了就会越来越烂, 所谓破窗原理, 以前老是也提过叫代码腐化
命名
命名应该合理, 成员变量不用加前缀, 靠高亮就很好
接口加前缀I也不太好, 不如实现加Imp
方法命名最好使用动词或动词短语
多使用计算机领域的词汇
有时候命名在语境里才有意义, 有时候变量命名也不需要重复语境
函数
函数短小一些比较易懂, 20行内最佳
if/else/while代码块封装函数, 只有一行最好 (有点激进?)
一个函数只干一件事情
复杂的switch试图用多态取代, 然后封装在抽象工厂里
同一类型函数命名风格应该一致, 使用描述性的语句描述比难懂的短词更好
一元函数最普遍, 标识函数(参数为boolean)的不如分成两个函数, 二元函数尽可能转换成一元函数
参数太多可能需要封装类了
好名字的函数一般是动词, 或者动词+关键字
函数一般要么做事, 要么回答事, 不可兼得 (其实也不一定, 比如很多返回boolean状态的函数)
推荐使用异常代替错误代码
最好将try/catch单独抽入一个函数 (如Android代码会对RemoteService调用进行类似封装, 吃掉exception)
使用枚举表示错误码会让改动变得繁琐 (重新导入或者编译部署), 大家都依赖这个枚举, 应该用异常与继承取代
不要重复, 偶尔可以考虑AOP这类的方法解决
注释
注释少要比注释多有用, 注释多说明代码糟糕 (其实分情况吧)
有目的性的注释还是有用的, 比如阐述, 放大, 警告, 定期维护的TODO等
如果代码不用, 不要注释掉, 直接删掉
格式
横向, 竖向对齐, 间隔, 缩进等. 其实目前formater已经很强大了, 养成良好的format习惯, 渐渐的写出来的代码就会像直接format后一样
对象与数据结构
面向过程与面向对象对立, 前者容易加函数, 不容易加对象, 后者容易加对象, 而不容易加函数
理想情况下, Law of Demeter认为, 类不应该操作对象内部的东西, 如不应该操作函数返回对象的方法. 目的只是为了降低复杂度, 认为这样将私有变量公开化, 增加了重构的难度, 如添加新函数, 方法等, 将数据结构与对象逻辑耦合在一起.
针对于上面的问题, 原则应该是对象暴露行为, 隐藏数据, 数据结构暴露数据
错误处理
Java特色的受控异常(Checked Exception), 必须得被catch, 对受控异常的修改会引起上层所有调用方法的改动, 尽量不要使用, 其他语言只有RuntimeException
可以包装第三方逻辑, 封装自己的异常类, 简化为只catch一种异常
简化使用也可以将异常处理完全封装进去, 返回特例即可
轻易不要返回null, 传入null
代码的坚固与干净不冲突, 所以添加一些check, throw相应的Exception也合理
边界
所谓边界就是自己可以控制到的程序与第三方的边界, 通常需要通过封装的办法来划清边界, 限制那些无法控制的第三方, 如直接Wrapper或者Adapter模式等
单元测试
测试需要整洁, 需要跟随代码一起更新, 测试的最大用途是保证你后续的修改有信心
测试的整洁主要讲的是可读性, 即分为三个环节, build->operate->check, 可以把繁杂的准备封装起来
测试API是渐渐重构演进过来的, 也不可能是起初就设计出来
有人建议每个测试一个assert, 但是这样会有很多重复的代码, 不过可以利用Template Method来解决. 不过也不一定必须一个, 做到最小化就可以了
整洁还有五条规则, Fast, Independent, Repeatable, Self-Validation, Timely
这里讲到TDD的好处, 主要是帮助你覆盖更多的测试, 如果写完再测, 发现测不了, 就不写了.
类
类应该短小, 权责应该足够单一, 内聚性应该高
如果期望抽走一部分逻辑, 最好连相关函数参数也抽走
简化类的过程应该小步, 每一步都运行测试一下
类的精简是为了更好的体现开闭原则, 整体结构为修改而设计
类应依赖于接口, 不依赖实现, 可以隔离修改, 符合依赖倒置原则, 类似策略模式
系统
构造与使用分开, 通过依赖注入等
通过AOP, Proxy的方式, 无侵入性的插入逻辑
系统如果充分模块化, 领域之间相互直接松耦合, 最为理想, 就可以通过测试来驱动
DSL的使用可以平衡领域与技术
迭代
代码是在不断迭代中进步的, 比如通过抽函数, 运用设计模式等
并发
应该尽可能分离并发代码与其他代码
尽可能让线程之间独立, 不要有共享
线程模型有典型的生产者与消费者, 读者与作者, 宴席哲学家模型, 分别用来说明互斥, 读写, 竞争死锁等特例
锁定代码块应该尽可能小
线程最好可插拔, 遵循单一权责, 分离线程与其他代码, 测试先保证除线程之外的逻辑
最后一张通过实例来介绍并发代码如何重构的比较清晰
逐步改进
这片使用了一个例子, 先采用蛮干进行重构发现越来越难, 后来采用逐步的办法, 还写的很细节, 但是比较Tricky的地方是, 这里提出的每步改动都通过测试来印证, 然后保证测试通过, 或者补充一个测试, 让代码通过, 但是所谓TDD部分只有思想, 老代码既然写的不好, 测试是如何出来的, 如何做到Cover全的. 如果假设在一个有比较好测试覆盖的基础上重构, 我感觉即便蛮力也不会太差...
JUnit
比较神奇的一章, 感觉更像是用一个算法类的重构来说明如何把代码改简单, 但是开头先介绍了100%覆盖的Junit测试长什么样子... 感觉作者是想说以前的人做的还不错, 都用JUnit给覆盖全了, 还是可以重构的更漂亮的, 所以感觉标题不太好
重构SerialDate
跟上一个对比, 这个测试覆盖不全, 所以在补测试的过程中进行重构, 还发现了缺陷, 又最终把代码改清晰了. 不过同样由于太过细节, 一些重构理论也很教条, 如果想通过看别人重构的例子来学习如果写简洁的代码, 不如直接看优秀的代码是怎么写的
味道
里面类比了很多Bad Smell, 同样是很细节, 比如太多, 太死, 太复杂, 重复, 不一致, 耦合, 测试不足等, 提供的Tips大多的中心思想就是抽, 封装, 单一职责, 命名清晰
提到使用*来避免过长import, 不过这个与现在流行的lint检测违背, 可以因为以前都是手动, 通配符简单吧.
不要通过继承来使用常量, 还提到不要用静态常量, 用枚举, 这个也与当前的思想有出入, 现在经常将Java的enum太冗余, 不必要时可以用常量
举报
更多回帖
rotate(-90deg);
回复
相关问答
General
PCB设计
要点
2021-02-25
1543
请问学习51、STM32以及更高性能单片机需要注意什么?
2019-11-06
1827
SPI配置的
要点
都有哪些呢
2022-01-25
830
电机驱动选型
要点
是什么?
2021-10-20
1873
单片机程序设计中的“分层
思想
”是什么意思?
2021-02-22
734
在高速电路中电阻的应用
要点
都有哪些?
2023-06-19
253
什么是数学?对
思想
和方法的基本研究有哪些?
2021-06-21
1062
单片机分层屏蔽的设计
思想
2021-02-26
2018
_
general
_exception_handler()不会执行
2018-12-19
1994
做嵌入式开发必须掌握的设计
思想
?
2021-03-09
1118
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分