编程范式
- 结构化编程
C语言(if/else结构) - 面向对象编程(OOP)
JAVA语言(将程序组织为类与类之间的交互) - 函数式编程(FP)
没有典型的语言,AI中常用python的FP特性来进行数据处理,但python同时也能支持OOP。python用于数据处理的方便之处在于语法简单,数据处理的第三方库丰富。
设计原则
目前最被广泛接受的是SOLID原则:
- Single Responsibility Principle(单一职责原则)
类或函数的功能要尽量单一,从而保证各模块尽量正交,引起每个模块的变动的来源更加地少; - Open-Closed Principle(开闭原则)
对扩展开放,对修改关闭 - Liskov Substitution Principle(里氏替换原则)
做继承设计时,要从父类角度思考,设计行为一致的子类,子类和父类是is-A的关系 - Integerface Segregation Principle(接口隔离原则)
类似SRP,ISP表达了接口设计时应遵循职责尽量单一的原则,只不过SRP是从代码维护者的角度,而ISP是从使用者的角度 - Dependency Reversion(依赖倒置原则)
实现应该依赖于抽象
常用的设计模式
- 创建型:简单工厂、工厂方法、抽象工厂:
简单工厂是通过一个简单工厂类根据不同的输入,实现不同的处理方式(一般通过if-else实现);工厂方法是针对不同的实现方式抽象出一个工厂方法接口,然后不同的处理方式去实现这个接口得到不同的工厂,这种方式更符合开闭原则;抽象工厂是当不同的工厂类需要实现不止一个工厂方法接口时,在抽象的工厂类中新增更多的工厂方法接口,然后不同的工厂都去实现这些接口,抽象工厂用的比较少,一般这种情况就会用抽象类来代替了,因为可能还有公共的属性。 - 结构型:代理模式、装饰器模式、适配器:
代理模式,如Spring AOP就是典型的动态代理设计模式,核心目的是在屏蔽用户感知的情况下,控制对象的访问,通常应用在日志、埋点、监控、鉴权、事务等;
装饰器模式,本质是要解决类继承深度过深,然后通过组合的方式,实现多重装饰进行嵌套,从而避免继承问题;
适配器模式,本质是将不同的实现统一成相同的接口,比如Slf4j日志框架,通过统一日志接口定义,然后为不同的日志框架实现如log4j和logback构造对应的适配器,适配器来实现统一的接口,从而形成了接口和实现的解耦。 - 行为型:观察者模式、模版模式、职责链模式:
观察者模式,例如google的eventbus就是基于该模式进行的设计,所有观察者可以注册到需要监听的event上,event发送时触发调用相应观察者进行处理。总体来说分为异步和同步两种,异步一般就是通过新起线程来实现。
模版模式,通过抽象出子类公共的功能,增加代码复用,同时对流程中需要有不同实现的环节预留扩展点。典型的应用就是callBack。
职责链模式,应用于需要将一个业务流程各环节进行拆分,每个环节分配给一个对应的职责类来处理,如流水线上不同工位可以看作不同的职责类,整个流水线就应用类职责链模式。
设计扩展性的思考
基于开闭原则,我们平时在技术设计时要预留足够的扩展性,同时也注意不要过度设计。
扩展性设计主要体现在下面几个方面:
- 数据库扩展性
设计数据库时,要确认好产品的功能全景和发展方向,针对有较大可能的功能预留扩展字段;预估业务体量,考虑是否应用分库分表; - 代码扩展性
厘清业务迭代方向,形成产品全景,通过功能抽象,应用设计模式保证代码满足SOLID特性。