1. 从 CR 谈开发编码分析、设计与质量
1.1. 质量不高的代码原因
- 缺乏系统的编码基础学习
- 缺乏整体架构设计意识,导致复杂度提升
- 缺乏编码设计方法论
- OOA、OOD、OOP
- DDD
- BDD、TDD
- 固有编程方式,不能接受变化
1.2. 面向对象
- 面向对象特性:封装、继承、多态、抽象
- 抽象类和接口的区别(基础、多态)
- 多用组合,少用继承(代码维护性)
- 基于接口而非实现编程(契约)
- 贫血模型 vs 充血模型(合理分层)
1.3. 设计原则
- SOLID 原则
- SRP:单一职责(design by simple )
- 感知:代码行数、类属性方法过多、难给类取名、方法过于臃肿
- 实施:遵循高内聚、低耦合,避免大而全,减少耦合,也不要拆分得过细,会降低内聚性
- OCP:开闭原则(对扩展开放,对修改关闭)
- 感知:维护修改扩展时候考虑,时刻具备扩展、封装、抽象意识)
- 实施:多态、依赖注入、面向接口编程
- 模式:装饰器、策略、模板、责任链
- 目标:未来需求变更,做到最小代码的变动
- LSP:里氏替换原则(design by contract)
- 感知:和多态的差异,多态 OOP 特性,LSP 是设计原则
- 实施:按协议约定来设计
- 约定:对输入、输出、异常的约定
- ISP:接口隔离原则(design by need)
- 感知:不要提供我不需要的内容(API 臃肿、类方法臃肿)
- 实施:侧重接口设计,通过识别接口是否符合单一职责,是否存在接口难命名等情况
- DIP:依赖倒置原则
- 控制反转:指导框架设计,程序的流程由框架接管
- 依赖注入:编码技巧,通过构成方法、函数参数,将外部创建好的对象,注入到框架内来使用;通过注入后,实现
- 依赖反转:指导框架设计,高层模块不依赖底层模块,而是依赖接口抽象
- SRP:单一职责(design by simple )
- KISS 原则
- 少即使多,言简意赅
- 复杂事情,采用分治思想,拆分成简单事项处理
- 适度、不重复、不过渡优化
- DRY 原则(Don’t Repeat Youself)
- 感知:事不过三
- 实施:逻辑重复(mss 对接 18 家平台)、功能重复(多处写 curl)、代码执行重复(复用意识)
- 不要面向
copy c,copy v
编程
- YAGIN 原则(You Ain’t Gonna Need It)
- 感知:不要做过度设计
- 实施:当前不需要做的内容,就不要画蛇添足
- 反原则:只看当下,局部视野
- LOD/LKP 原则(Law of Demeter, 迪米特法则)
- 可以无依赖的类之间,不要有依赖
- 有依赖的类之间,考虑采用依赖接口,解耦依赖关系
1.4. 重构
软件之熵
1.4.1. 重构概述
- WHY? 为何要重构?
- 代码腐化、个人成长
- 痛点问题太多(效率、质量、难扩展、难维护、问题难排查)
- WHAT?
- 大重构:代码分层、模块化、解耦,架构梳理调整
- 小重构:类、函数、命名、编码规划遵循
- WEHN?
- 持续重构意识,现在开始
- 严重影响效率
- HOW
- 小重构:日常迭代,马上开始
- 大重构:有目的、有计划,分批分块进行(分治思想)
1.4.2. 单元测试
- TDD 驱动,加速业务熟悉,减少边界问题(前期投入较大,长期收益非常明显)
- 代码可测试性的反模式:
- 滥用全局变量
- 滥用静态方法
- 使用复杂的继承关系
- 高度耦合的代码
- 函数代码内部中断,非返回退出
1.4.3. 解耦的理解
- 时刻记得高内聚、松耦合
- 大系统分分层、模块设计
- 大系统微服务
- 长流程,遵循职责来抽离方法(遵循 KISS 原则)
1.5. 编码规范提升
- https://time.geekbang.org/column/article/188622
- https://time.geekbang.org/column/article/188857
- https://time.geekbang.org/column/article/188882
1.5.1. 命名与注释
译事三难: 信、达、雅 – 信(准确,不偏离,不遗漏)、达(不拘泥于原文)、雅(翻译得体,简明优雅)
- 词达意,缩写优先采用通用缩写,不要采用拼音,不要太长或太短
- 可读、可搜索,不要用生僻词
- 长短命名变量:变量范围越大,考虑命名越具体,反之作用域越小,用短变量
- 结合类名、包名上下文,避免口吃效果
- 统一约定抽象类名前缀
Abstract
、接口名前缀Impl
- 注释:
- 说清楚 3W(WHY, WHAT, HOW),即函数或类实现了什么功能、做了什么,怎么做,复杂使用时候,提供适当示例
- 注释不是越长越好,考虑言简意赅
1.5.2. 代码风格
团队规约,采用统一风格
line
,一行多长,写多少代码一个函数多长合适?尽量控制在一屏幕左右
{
,括号放的位置,推荐放在同行末尾tab
,空格缩进缩进对齐
命名方式,采用驼峰命名
空行分隔代码逻辑
成员可见性
1.5.3. 编程技巧
- 代码分割成效的单元块,通过合适的空行和注释增加可读性
- 函数遵循 SRP、KISS 原则
- 函数参数过多(函数没有遵循 SRP 原则、函数封装成对象)
- 实施:拆分成多个职责明确的函数、拆分成单独的类
- 不要使用参数做控制逻辑(违背单一职责、违背接口隔离)
- 移除过深的嵌套 if-else 层次(可读性差)
- 逻辑合并,去掉过多的 if-else
- continue\break\return 提前退出
- 基于异常,提前退出(if… return)
- 嵌套的内容,封装成函数
- 使用解释性变量
- 替换魔法数值
- 替换复杂表达式
1.5.4. CR
https://mp.weixin.qq.com/s/3M9-I1gS_Niuv4yGoX3vqA
在 cr 时,请务必确保:
- 代码经过完善的设计
- 功能性对于使用者们是好的
- 对于任何 UI 改动要合理且好看
- 任何并行编程的实现是安全
- 代码不应该复杂超过原本所必须的
- 开发者不该实现一个现在不用而未来可能需要的功能
- 代码有适当的单元测试
- 测试经过完善的设计
- 开发者对于每样东西有使用清晰、明了的命名
- 注释要清楚且有用,并只用来解释 why 而非 what
- 代码有适当的写下文件(一般在 g3doc)
- 代码风格符合 style guide
- 确保你查看被要求 review 的每一行代码、确认上下文、确保你正在改善代码质量,并赞扬开发人员所做的好事与优点吧!
在 cr 中要看些什么:
- CL 的总体设计
- 功能验证,功能性对于使用者们是好的,对于任何 UI 改动要合理且好看
- 是不是很复杂,有没有过度设计
- 代码有适当的单元测试
- 测试经过完善的设计
- 规范命名,看见名字就知道是什么
- 合适的注释,注释应该是 why 而不是 what
- 代码风格遵循 style guide,如果需要改代码风格应该在另一个 CL 解决
- CL 更改了构建、测试、交互、发布的时候,也要更新文档
- 仔细 review 每一行代码(除了资源文件、生成的代码、大型数据结构)。如果比较复杂得让开发者解释
- 安全性、并发性、可访问性、国际化等复杂问题时需要更合适的人来 review
- 以整个系统的角度出发来思考 CL
- review 的时候,与其告诉开发者做错什么,还不如告诉他们做对了什么
1.6. 设计模式
- 创建类型
- 组合类型
- 行为类型
2. Go 语言
互联网时代的 C 语言,许世伟 - 2012-03-01
- 多少人了解 Go,多少人用过 Go?
3. 微服务
- 对微服务的了解?
- 多少人具体
3.1. 微服务和单体
3.2. 微服务有哪些前置内容
3.3. 为什么说微服务复杂
4. 云原生
- 什么是云原生?
- 未来架构思考?
5. 结语
Go 语言最终会取代 Java 居于编程榜之首!
本周我打算分享一个《谈谈基于 Go 的应用设计与开发》,时间的话还待定。 分享主要大纲内容:
- 从 CR 出发,谈谈对编码分析设计、研发质量的看法
- Go 语言
- 单体与微服务
- 云原生