- Published on
🔝🔝 IT人的职业素养-【置顶】
一、分享原因
我先说下我为什么认为这个很重要,因为自己工作也好多年了,也待过好几种不同风格的公司,里面多多少少都接触一些从大厂出来或者代码写的特别好的同事,深刻的体会到他们对代码的严谨和规范,而且自己也在这里吃过亏,踩过坑,特别的有感触。
然后自己在公司也待了一段时间,虽然不是很长,但是也接触了一些项目和代码,想和大家交流下代码方面的行为习惯,可能大家觉得这个讲的会比较没有意思,都想听关于底层和开源组件源码或者是架构方面的东西, 但是我个人感觉这个对于我们行业来说很重要,可能会为你以后有机会跳到大公司或者碰到一些对代码有洁癖的领导的时候有帮助,也可能会为你以后代码方面更精进,代码写的更容易维护和扩展做点铺垫。
二、什么专业程序员
世界级编程大师Robert C. Martin
下面这些是参考Bob大叔的对专业开发的描述:
- 设计模式。必须能描述GOF书中的全部24种模式,同时还要有 POSA 书中的多数模式的实战经验。
- 设计原则。必须了解 SOLID 原则,而且要深刻理解组件设计原则。
- 方法。必须理解XP、Scrum、精益、看板、瀑布、结构化分析及结构化设计等。
- 实践。必须掌握测试驱动开发、面向对象设计、结构化编程、持续集成和结对编程。
- 工件。必须了解如何使用UML 图、DFD图、结构图、Petri 网络图、状态迁移图表、流程图和决策表。
我个人简单的总结是:
- 每个团队都有一份统一的开发规范指引,所有开发都应该遵循基本规则;
- 自己写的代码必须能够正常工作;
- 必须理解当前要解决的是什么问题以及该如何解决;
- 代码尽量简洁,一个方法最好表达一种功能 ,方法不要太长,最好显示器能看完;
- 给类和方法写好注释,主要描述好方法的功能和为什么这么做;
- 方法的命明要有语意,别人看了大概明白,不用到处相都是list,add,update,不过取名字是个麻烦的事情,可以参考下:CODELF
- 多点考虑时间空间效率的问题,适当的了解一些数据结构和算法;
- 提醒自己是否满足设计原则,是否可以借鉴设计模式来调整代码结构;
- 业务操作是否可以异步,多线程并发操作。
- 什么都不是一蹴而就,重构,重构,在重构。
- 最后就是疲劳或者心烦意乱,千万不要编码,强而为之,最终只能再回头返工。
举个例子:
三、开发的行为和规范
暂无
四、设计原则和设计模式
下面大概对上面这些内容进行简单的描述:
- SRP 单一职责原则
该设计原则是基于康威定律( Conway Law) 的一个推论一一一个软件系 统的最佳结构高度依赖于开发这个系统的组织的内部结构。这样,每个软件模块都有且只有一个需要被改变的理由。
- OCP 开闭原则
该设计原则是由 Bertrand Meyer 20 世纪 80 年代大力推广的,其核心要素 如果软件系统想要更容易被改变,那么其设计就必须允许新增代码来修 改系统行为,而非只能靠修改原来的代码。
- LSP 里氏替换原则
该设计原则是 Barbara Liskov 1988 年提出的一个著名的子类型定义。简单来说,这项原则的意思是如果想用可替换的组件来构建软件系统,那么这 些组件就必须遵守同个约定,以便让这些组件可以相互替换。
- ISP 接口隔离原则
这项设计原则主要告诫软件设计师应该在设计中避免不必要的依赖。
- DIP 依赖反转原则
应在代码中多使用抽接口,避免使用那些多变的具体实现类。不要在具体实现类上创建衍生类。应避免在代码中写入与任何具体实现相关的名字 或者是其他容易变动的事物的名字。
- Iterator 迭代器模式
一般都是在集合编程中使用,尤其是如果要对集合元素遍历过程中做插入删除操作,那就用iterator,如果要对某个类中的集合进行遍历,由那个集合类返回一个iterator回来,我们统一面向iterator迭代器接口来编程遍历,提高系统整体的可维护性,可扩展性。
- Adapter 适配器模式
这个模式一般是在系统不断升级的过程中使用,对已经写好的老的类,写一套适配器来适配老类,但是提供新的接口。
一种情况,是对于已有的第三方类库,比如redis的客户端,或者是elasticsearch的客户端,他们提供了一套API,但是我们这里的要求是需要面向我们这里的DAO接口来进行编程,此时可以写一个适配器,将比如redis客户端的接口适配到我们的接口。
我们手头有有一套系统v1.0版本的 老代码,现在要在这个基础之上构建v1.0的新代码。然后有了一个新的接口,需要让别人面向新接口开发,此时就只能开发适配器,适配v1.0版本的类,但是实现的是v2.0的接口。
- Template 适配器模式
这个模式一定要多用用,尤其是对于有多种不同实现的一些场景,比如说,不同的折扣类型,不同的优惠券类型,不同的商品类型,那肯定涉及到不同的处理逻辑。但是可以将他们共同的基础逻辑抽取到父类中,然后将要子类实现的逻辑留空,交给子类去实现。
- Factory 适配器模式
工厂模式的核心思想,其实就是不要自己在代码里手动new一个实现类对象出来,因为那样的话,调用方就不是面向接口编程了。,spring的容器其实本质上就是个大工厂的概念,这个工厂里什么对象都有,你需要什么,自己去找spring要就好了,非常方便。
- Singleton 适配器模式
单例模式,在系统里,你要判断一下,如果有一些类,只需要一个实例对象就可以了,那就给那个类做成单例的模式。比如说,你自定义了一个框架,自定义了一份xml格式的一个配置文件,你要读取这个配置文件,这个配置文件中的数据,读取到类中,这个类的实例,只要保存一份就可以。那么此时可以使用单例模式,将这个类做成他的实例只能有一个,在这个实例中保存了配置文件中的数据。
- Facade 门面模式
假设我们有一个系统A吧,自己内部有多个代码组件,每个代码组件都可以实现一些功能。此时如果别的系统B要调用系统A实现某个功能,此时一种方法是,系统B调用系统A的多个代码组件的方法,最终实现一个功能。另外一个选择,就是系统A里提供一个Facade类,系统B不需要关心系统A内部有多少个代码组件,直接调用系统A的一个facade类的一个方法即可。
- Prototype 原型模式
场景就是一个对象,我们希望拷贝一个这个对象,就是弄出来这个类的另外一个实例,实例的属性跟之前的实例是一模一样的,我们要用原型模式,以某一个对象为原型,然后对这个对象进行拷贝,得到拷贝后的另外一个对象,经常使用就是我们的dto 拷贝。
- Builder 构造器模式
常见于在构建一个复杂的对象,或者是构建一个复杂的表达式的时候,在开源框架中有大量广泛的运用,Mockito框架中,when().thenReturn()之类的,其实就是构造器模式的一种,通过多个连续的方法完成一个模拟对象的构建。
- Mediator 中介者模式
这个模式,担心的就是系统中各个子系统之前互相之间调用,乱成一团。所以就将系统之间互相调用的逻辑给放到一个所谓的中介者里面去。每个系统如果要通知别的系统干个什么事儿,直接就是调用中介者,中介者负责去调用别的系统。主要是各个系统之间彻底解耦,比如MQ。
- Proxy 代理模式
常用场景,懒加载:hibernate、mybatis,都可以实现懒加载,这个大家应该都知道了,其实也是基于动态代理思想实现的,对刚查询出来的对象做一个代理。然后去调用getX()方法的时候,再实际执行sql查询出来关联的数据。常用的RPC操作,Fegin的请求。
- Observer 观察者模式
比如我们有一个目标对象,一旦这个目标对象的状态改变了,然后的话就去通知相关的对象,我的状态改变了,数据也变化了。还有就是基于zookeeper进行分布式系统之间的协调工作。
- Command 命令者模式
这个模式一般就是说,你可能会执行一些操作,这些操作都实现一个接口,但是有不同的命令实现,然后命令的执行类就是同一个,你需要执行哪个命令就封装那个命令后发送给执行类即可。比如在实际中有这种场景,读请求和写请求,封装成command,然后发送给一个异步处理线程,执行即可,逻辑都封装在命令的内部。
- Composite 组合者模式
组合模式非常适用于有较多父子层级关系的那种场景,比如部门树的递归删除,或者是文件树的递归删除之类的场景。就是删除一个父权限,就要级联递归删除所有的子权限。
- Strategy 策略者模式
最最高频使用的一种设计模式,他的常见应用场景,就是替换掉那一大坨复杂难懂的if else if else。对于那种过于复杂的选择判断逻辑,完全可以将选择哪种策略的过程放到工厂里去。所以也会和工厂模式组合起来。
- State 状态模式
其实状态模式,就是维护多种不同的状态,每种状态下可以去执行一些特殊的逻辑。然后由一个Context类负责根据请求参数调用,来维护这些状态之间的切换,形成一个状态机的概念。
比如销售出库单,状态需要从新建、待审批、已审批、已完成,四个状态之间流转,流转到每个状态的时候,都需要执行那个状态对应的一个逻辑。
- Memento 备忘录模式
比如一个类计算出来一份中间数据,这个类,之后需要基于这份中间数据再执行另外两次操作,每次操作都要基于这份中间数据去执行,第一次基于中间数据操作过后,会对中间数据做出修改,要求是第二次再执行操作的时候,需要基于未修改之前的中间数据来执行。
- Flyweight 享元模 式
从最基本的角度来说,其实就是维护固定数量的对象实例,不同的对象实例,只有一个,然后保存在内部的一个map中。见使用场景,其实就是jvm内缓存实现,如果我们不想引入ehcache之类缓存框架,就想简单一点,通过自己实现的一个map来缓存对应的一些数据,比如说每个权限的数据,或者每个员工的数据,在内存里自己维护一个缓存工厂,就是基于享元模式的思想来实现的。
- Decorator 装饰器模式
主要是基于已有的类的功能基础之上,再增强一些功能,可以做装饰。一些经典的实现比如java的io体系,可以一层包装一层,一层包装一层,外面的一层,都会对立面的一层进行功能的增强。还有就是spring的aop,aop这块可以基于动态代理的理念,装饰我们的目标对象,然后加入事务控制,日志打印之类的功能。
- Chain of responsibility 责任链模式
责任链模式,那也是经常会使用到的,对于那种复杂的业务流程,一种方案是采取面向对象的设计,将不同的业务逻辑封装到不同的类里去,然后通通过方法中的调用来控制业务流向;另外一种就是采用责任链模式,将业务逻辑封装到不同的handler里面去,形成链条式调用。常见的网关spring zuul,Spring gateway。
- Bridge 桥接模式
所谓的桥接,就是搭建一个桥,让两个组件之间互相调用,可以通过桥来执行。因为有了桥,两个代码组件无论怎么修改,都互相没有影响。这个桥,实际上就是一个接口。所以说,java中,无处不桥接,只要你是面向接口编程,基本就是在桥接。
- Vistor 访问者模式
使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定 义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
五、最后
最后希望大家能在编码过程中好好体会。
最后,最后,很推荐大家有时间去看下Bob大叔的两本经典之书,虽然都是很多年前的书的,但是可以慢慢细品。