[TOC] SOLID原则包括单一职责,开闭原则,里氏替换原则,接口隔离原则,依赖倒置原则。 单一职责原则(SRP) SRP: Single Responsibility Principle A class or module should have a single reponsilibility.一个类或者模块只负责完成一个职责(或者功能) 一个类只负责完成一个职责或功能, 也就是说, 不要设计大而全的类, 要设计粒度小, 功能单一的类. 换个角度来讲就是. 一个类包含了两个或两个以上业务不相干的功能, 我们就说它的职责不够单一, 应该将它拆分成多个功能更加单一, 粒度更细的类. 如何判断类是否单一 类中的代码行数,函数或者属性过多. 类依赖的其它类过多, 或者依赖类的其它类过多, 不符合高内聚, 低耦合的设计思想. 私有方法过多 比较难给类起一个合适的名字 类中大量的方法都是集中操作类中的某几个属性. 如何设计单一类 技巧: 持续重构. 没有一尘不变的设计 单一职责原则通过避免设计大而全的类, 避免将不相关的功能耦合在一起, 来提高类的内聚性. 同时类职责单一, 类依赖和被依赖的其它类也会变少, 减少了代码的耦合性, 以此来实现代码的高内聚, 低耦合. 但是, 如果拆分得过细, 实际上会适得其反, 反倒会降低内聚性, 也会影响代码的可维护性. 开闭原则(OCP) OCP: Open Closed Priciple Software entities (modules, classes, functions, etc.) should be open for extension, but closed for modification.
很早前写过一篇关于Golang持续集成服务之Travis教程, 今天再写写关于 github 上常见的徽章是如何制作的. 让你的开源项目更高大上, 让你的代码也更健壮. 徽章的含意 当你浏览一个开源项目时,看到各种徽章, 有些徽章是直接反应这个开源库的质量和完整性等等. 如上图所示 第一个徽章即 Github 自带的 workflow 提供的持续集成(CI)和持续部署(CD), 官方称之为 Actions, 图示显示为 CI, CD 是否通过 第二个徽章即 Codecov 是一个测试结果分析工具, 图标显示测试覆盖率. 第三个徽章即 shields.io 一个可以自定义徽章的网站 第四个徽章即 goreportcard 是一个项目综合评分网站 第五个徽章即 gitter 自定义讨论组的网站 CI&CD 徽章 github 于2018. 10月推荐 GitHub Actions 持续集成服务, 在此之前大家都是使用 https://travis-ci.org/ 持续集成服务, 之前我也写过相关文章. Golang持续集成服务之Travis教程. 持续集成和持续部署目前 github 官方自带支持, 官方称之为 GitHub Actions. 只要你在 github 上创建一个开源项目仓库就自带 Actions 功能, 支持各种语言. 还可以自动发布 GitHub Pages 等功能, 十分强大. 如何使用可以参考阮一峰写的GitHub Actions 入门教程 关于GO的持续集成服务模板参考: 使用 GitHub Actions 后会在你的项目里自带生成一个.
Golang tracks stack error package. 优雅追踪堆栈错误包 安装(Install) go get github.com/yezihack/e 介绍(Introduction) github.com/yezihack/e 项目是一个优雅地追踪你的堆栈信息.方便存储日志里. 而且还扩展了error包,自定义 code,msg 信息. 特色(Features) 优雅地追踪堆栈错误信息 基于github.com/pkg/errors包进行封装 支持 code, msg 自定义错误码和错误信息 方便存储日志json文件 堆栈信息以人性化展示 文档(Documentation) https://godoc.org/github.com/yezihack/e 简单使用(Use) package main import ( "github.com/yezihack/e" "log" ) func foo() error { return e.New("foo") } func main() { err := foo() if err != nil { // 需要判断是否是自定义error, 否则无法输出堆栈信息. if e.Assert(err) { log.Println(e.Convert(err).ToStr()) // 输出字符串形式 log.Println(e.Convert(err).ToArr()) // 输出数组形式 } else { log.Println(err) // 系统的 error } } } 与原堆栈信息对比 github.
充血模式即领域驱动设计(Domain Driven Design, 简称 DDD) 贫血模式 在之前我们写一篇关于贫血模式的文章, 点击查看. 贫血模式是目前主流的一种开发模式, 基于MVC结构的开发模式. MVC三层架构中 M 表示 Model 即数据层 V 表示 View 即展示层 C 表示 Controller 即逻辑层 做为后端开发MVC有所调整 1. Model 层 负责数据访问 2. Service层 负责业务逻辑 3. Controller层 负责暴露接口
让.皮亚杰 瑞士人,近代最有名的发展心理学家,他的认知发展学成为了这个学科的典范。 20世纪最伟大的心理学家. 与弗洛伊德称为心理学史上两位巨人。 主要贡献是对儿童的心理发展做了全面的解释, 不同于成熟论与外铄论, 这些理论都不足以让人信服, 直到让.皮亚杰提出认识发展理论提出.也称之为建构主义. 皮亚杰认为孩子的认知不是被动的,而是个体与环境相互交互的时候形成的, 孩子们都是天生的科学家与哲学家. 他们有一套非常神奇的认识外界的方法. 就象小树苗一样是有所选择的接受外界的营养. 理论 图式理论 认知发展的核心理论. 孩子从婴儿时期什么也不懂, 只知道喝奶, 这叫遗传图式, 而有一个人总是给他喂奶, 建立起妈妈的概念, 妈妈就是总喂奶的那个人. 就这样通过外界不断刺激下建构成自己的一个一个的图式. 图式主要是通过外界对自身的刺激在自己的大脑里形成一个个概念, 即是建构图式 Tip: 图式具有对客体信息进行整理,归类.改造和创造功能,以使主体有效地适应环境. 同化理论 同化过程是对图式量的提升 同化是指遇到外界刺激后他们尝试着使用自己的这个图式去理解外界, 希望把外界纳入到原有的图式之中. 这个过程称之为同化 例: 如对狗的认识, 如吉娃娃狗的图式概念, 知道他长着四条脚, 一个尾巴, 会旺旺的叫, 下次遇到哈士奇, 就会使用这个图式解释他,也就是说他会把这个图式进行同化成为之前图式的一部分, 图式也得到的发展与巩固. 但是遇到一只猫时, 他使用同样的方式解释时, 妈妈告诉他这不是一条狗, 是一只猫. 这个时候孩子就混乱啦, 然后旁边的妈妈解释给他听, 猫的嘴巴上有长长的胡须, 还会喵喵的叫, 这个叫猫. 此时孩子会在大脑中重新构建新的图式概念, 这个过程是一种顺应. 同化是一个非常重要的概念, 只有对一个图式不断的同化,得到量的积累, 才会得以建立更加完善, 更加巩固. 成年人学习一个新知识也是一样, 需要不断的同化过程, 也就是需要做相关练习, 多加应用, 得到更多的同化过程, 你的知识图式才会更加牢固完美. 同化过程是对图式量的提升 Tip: 中国俗语称: 熟能生巧. 顺应理论 构建新图式的过程 外界的刺激不可能永远可以用同样的图式去解释,顺应是指同化失败后, 产生混乱时重新构建新的图式的一个过程. 如上面所说的猫的认识过程.
朴实定律 程序应该熟悉的常用定律法则 二八定律 二八定律是指在任何一组东西中, 最重要的只占其中一小部分, 约20%. 其余80%尽管是多数, 却是次要的. 如世界上的财富分配也属于二八定律, 20%人的撑握着世界80%的财富. 工程定律 海恩法则 是德国飞机涡轮机的发明者德国人帕布斯.海恩提出的一个在航空界关于飞行安全的法则. 海恩法则: 指任务不安全事故都是可以预防的. 海恩法则强调两点: 一是事故的发生是量的积累的结果 二是再好的技术, 再完美的规章, 在实际操作层面, 也无法取代人自身的素质和责任心. Tip: 软件行业也是如些, 生产上的程序出现故障, 也符合海恩法则. 墨菲定律 事情往往会向你所想到的不好的方向发展.只要有这个可能性. 比如你衣袋里有两把钥匙, 一把是房间的, 一把是车的, 如果你现在想拿车钥匙, 会发生什么呢?是的, 你往往是拿错了房间钥匙. Tip: 如果做某项工作有多种方法, 而其中一种方法将导致事故, 那么一定有人会按这种方法去做. 康威定律 设计系统的架构受制于产生这些设计的组织的沟通结构 — M.Conway 即系统设计本质上反映了企业的组织机构. 系统各个模块间的接口也反映了企业各个部门之间的信息流动和合作方式. Tip: 系统设计的结构必定反映其团队的组织结构 管理定律 SMART 原则 Smart 原则是目标管理中的一种方法. 由五个字母组成 S (Specific) 明确性: 指目标必须是明确的, 具体的.不能笼统. M (Measurable) 可衡量: 目标可以量化, 有计划的, 数据支撑. A (Achievable) 可达成: 付出努力的情况下可以实现你的目标, 避免设立过高或过低的目标. R (Relevant) 相关性: 指目标与那些还有关联, 需要配合, 辅助你完成目标.
技术书籍 推荐参考: «豆瓣编程图书TOP10» 程序员修炼之道(第2版) 豆瓣分:9.0 原英文名«The Pragmatic Programmer» 直译为: 务实的程序员, 即靠谱的程序员. 这是一本如同航海的指南般的书, 被一代代开发者奉为圭臬. 已经出版20年啦, 当之无愧的"道", 可惜在国内出现各种修炼之道相关的书籍, 内容干货少之又少, 实在汗颜. 深入理解计算机系统(第2版) 豆瓣分: 9.7 原英文名Computer Systems: A programmer’s Perpective 工程师人人必读之书, 没有之一. 本书最大的优点是从程序员的视角详细阐述计算机系统的本质概念. 主要包括: 1. 信息的表示和处理 2. 程序的机器级表示 3. 处理器体系结构 4. 优化程序性能 5. 存储器层次结构 6. 链接 7. 异常控制流 8. 虚拟存储器 9. 系统级I/O 10. 网络编程 11. 并发编程 Tip: 书比较厚, 读之前做好心理准备, 打硬仗. 代码大全(第2版) 豆瓣分: 9.3 原英文名称«Code Complete» 完成代码, 是一种教你如何一步一步完成开发. 这本书覆盖了软件全过程, 从需求分析, 系统架构,设计到具体编码规范, 编码技巧, 整个项目的生命周期. 是一部软件构建的百科全书. 重构:改善即有代码的设计(第2版) 豆瓣分:9.
有一种非常经典的设计原则: 组合优于继承, 多用组合少用继承 为什么少用继承 继承是面向对象的四大特性之一, 表示类之间的 is-a 关系. 支持多态特性, 可以解决代码复用问题. 如果继承层次过深, 过复杂, 会影响到代码的可维护性, 可读性. 如上面, 继承带来的后果就是代码变得复杂, 因为层次过深, 继承关系过于复杂, 影响到代码的可读性与可维护性. 组合的优势 可以利用组合(composition), 接口(interface), 委托(delegation) 三个技术手段解决继承的问题.(如上面的问题) 利用接口实现多态特性 利用组合和委托实现代码复用问题 通过组合, 接口, 委托三个技术手段完全可以替换掉继承. Tip: 在项目中不用或少用继承关系, 特别是一些复杂的继承关系 . 什么时候使用继承还是组合 一个技术的出现, 一定是有他的用武之地, 并非一无是处. 当类之间的继承结构稳定, 继承层次比较浅(最多有两层继承关系), 我们可以大胆使用继承. 当类之间的继承结构不稳定, 复杂, 继承层次又深,我们尽量考虑使用组合来替代继承 哪些设计模式使用了继承? 装饰者模式(decorator pattern) 策略模式(strategy pattern) 组合模式(composite pattern) 哪些设计模式使用了组合? 模板模式(template pattern)
何为"接口"编程 基于接口而非实现编程. 英文: Program to an interface, not an implementation 这条原则是一条比较抽象,泛化的设计思想. 接口的本质: 接口就是一组协议或者约定, 是功能提供者给使用者的一个"功能列表" 接口编程 这条原则能非常有效地提高代码质量. 接口编程是将接口与实现相分离, 封装不稳定的实现, 暴露稳定的接口. 上游系统面向接口而非实现编程, 不依赖不稳定的实现细节. 当实现发生变化的时候, 上游系统基于上不需要做改动, 以些来降低耦合性,提高扩展性. 在软件开发中, 最大的挑战之一就是需求的不断变化, 这也是考验代码设计的好坏的一个标准. 越抽象, 越顶层,越脱离具体某一实现的设计, 越能提高代码的灵活性, 越能应对未来的需求变化. 好的代码设计, 不仅能应对当下的需求, 而且在将来需求发生变化的时候,仍然能够在不破坏原有代码设计性况下奶灵活应对. 而抽象就是提高代码扩展性, 灵活性, 可维护性最有效的手段之一 接口编程要点 函数的命名不能暴露任何实现细节 封装具体的实现细节 为实现类定义抽象接口. Tip: 做开发的时候, 一定要有抽象意识, 封装意识, 接口意识. 在定义接口的时候, 不要暴露任何实现细节. 接口的定义只表明做什么, 而不是怎么做. 什么时候使用接口 任何事物都有两面, 一味使用接口编程会导致不必要的开发负担.具体要搞清楚我们为了解决什么问题. 如果业务场景中, 某个功能只有一种实现方式, 未来也不可能被其它实现方式替换,则我们没必要设计接口.也没必须基于接口编程.直接使用类即可. 如果业务场景中, 某个功能可能被两种以上, 不
贫血开发模式 传统的MVC结构分为: Model 层, Controller 层, View层. 而做为前后端分离的MVC变为后端被分为: Controller, Service, Model 层. Controller 层负责暴露接口给前端调用. Service 层负责核心业务逻辑 Model 层负责数据读写 以上为典型的面向过程的编程风格.也称为分血模式的开发模式 这也是我们现在非常常用的一个 Web项目的开发模式. Tip: 与之相对是充血开发模式即DDD, 也称领域驱动设计 面向过程VS面向对象 面向过程编程风格是一种符合我们人脑思维方式. 如同在生活中, 你去完成一个任务: 先做什么 后做什么 最后完成整个任务 面向对象编程风格是一种自底向上的思维方式, 它不是先去按照执行流程来分解任务: 先将任务翻译成一个一个小的模块(也就是类) 然后设计类之间的交互 最后按照流程将类组装起来 完成整个任务 面向过程与面向对象是互相协作完成整个项目的 面向过程编程是面向对象编程的基础 面向对象编程离不开基础的面向过程编程. 如一个方法的实现逻辑即是一个面向过程的逻辑. Tip: 我们编程最终的目的是写出易维护, 易读, 易复用, 易扩展的高质量代码. 面向对象编程常见的坑 面向对象的封装特性的本质就是通过设置访问权限隐藏代码 随意设置 Public 权限 解决方法: 慎重使用 Public , 使用之前询问自己 为什么要开放 开放会带来哪些后果. 滥用全局变量和全局方法 从分配内存空间: 全局变量, 静态局部变量, 静态全局变量都在静态存储区分配空间, 而局部变量在栈分配空间. 从作用域来看: 破坏边界, 不利后续调试等. 常用的面向过程场景 编写Shell 脚本. 数据处理 算法为主, 数据为辅.