框架设计原则(梁飞)
⼤纲
1 模块分包原则
2 框架扩展原则
3 领域划分原则
4 接⼝分离原则
5 组件协作原则
6 功能演进原则
我将对每个原则进⾏⾃⼰的解读,如有不对,还请指教:)
1 模块分包原则
说说我的理解。这⾥其实是从框架结构的解读来解读,这⾥的包指的是 Maven 的 module。
复⽤度,指的是 maven 包的复⽤。可以理解为⼯具类。这个⼯具类不应该变化⽆常。
稳定度:被依赖的包应该保持稳定,或者说,被依赖者应当⽐依赖者稳定,且不能成环状依赖。如果不稳定,将会影响其他的包。
抽象度,越抽象,越稳定。越具体,越容易变化。
同时,梁飞给出了⼀个公式,但是实践起来有点⿇烦.......
关于模块分包,可以参见更详细的博客。
2 框架扩展原则
这是其实是说的⽐较多的东西了。
什么是微核⼼ + 插件?按照作者的说法,核⼼只负责装配插件。这样,⽆论是作者⾃⼰的功能,还是第三⽅的功能,都是平等的,再多的插件也不会影响软件架构,因为没有硬编码,且都是可以卸载的。甚⾄微核也是可以扩展的。:)
同时,插件的组装规则是统⼀的。说到这⾥,你应该想到了 IDEA,Maven,Eclipse 等等。
然后说外置⽣命周期。这个其实我是有⼀点不理解的。按照作者的说法,其实是说,框架只负责管理对象,对象的出⽣和死亡不由框架负责。即,⽤户应将实例注册到框架中。
但 Spring 似乎不是这么做的。同时,如果使⽤注册机制,那么就需要硬编码。或者说,Spring 本⾝就是管理 Bean ⽣命周期的框架,⽽
Dubbo 的职责不在于此?
最少化概念模型,这个其实是⼀种优化。
⼀致化数据模型:例如 URL 这种对象,就是⼀致化数据模型,拒绝使⽤ String 拼接,解析。
3 领域划分原则
这是在框架设计中,是⾮常重要的。
PPT 中已经说的⾮常清楚,我就不再说明。其中,Invocation ⼀定要轻量。否则,对 GC 来说,将是很⼤的压⼒(使⽤对象池?性能不好。)
说说他的好处:
1. 结构清晰,这个不必讲吧。
2. 充⾎模型......这个怎么理解?
3. 可变和不可变状态分离,可变状态集中。通常实体域都是只读的,即不变状态。会话域都是可变状态。
4. 所有领域模型线程安全。⽆锁编程(lock-free ⾮常重要)。
关于他们的线程安全性:
1. 服务域⽆状态,天⽣线程安全。
2. 实体域属性只读,线程安全。
3. 会话域⼯作在栈中,线程安全。
所以,需要保证他们是这么设计的,才能实现⽆锁编程。
4 接⼝分离原则
关于接⼝分离,我认为是单⼀职责的⼀种实现。
其中提到 API 和 SPI,API ⾯向⽤户,SPI ⾯向开发者。两者必须分离。
声明式 API 和过程式 SPI ,没看懂,看懂的说⼀下。:)
API 可配置,⼀定可编程,这个不⽤说吧。
区分命令和查询,例如,不应该有 updateAndGet 这个⽅法(不包括原⼦类),应该分成 2 个⽅法,保
证 get ⽅法幂等。
对称性接⼝:很简单,有 get ⽅法,就应该有 set ⽅法,有 add 就由 remove,称之为对称性和完备性。这样⽤户能⾃⾏推导出接⼝。
兼容性:如果接⼝加⽅法,应该是增加⼦接⼝的⽅式。其他的没看明⽩.......
5 组件协作原则
这个就⽐较爽了,我们知道 Dubbo 是管道式设计。⼀个 Invoker 贯通整个流程,事实上,web 服务器都是这么设计的。例如 Tomcat ,Netty。
关于派发,还记得 Spring 的 dispatchServlet 吗?
关于状态的共享:
分布是什么?即通过⾏为传递(适合交互性系统)。
共享是什么?通过⼀个固定的点获取,称之为仓库(适合管理状态的系统)。
主过程拦截,还记得 Mybatis 留给我们的插件吗?还记得 Spring 留给我们的吗?框架要在关键节点留出拦截点供⽤户扩展。
事件派发:观察者模式,Reactor 模式,另外提到 Proactor 模式,查了⼀下,通常在 GNU 编程中,由 OS ⽀持。
Dubbo 暴露、引⽤、调⽤事件,都预留了。
关键路径,即在管道使⽤职责连模式进⾏拦截,保证每个职责单⼀。
⾮关键路径,需要有监听机制,不能影响主流程运⾏。
关于协作防御,我理解为防御性编程。
1. 分离可靠操作和不可靠操作。不可靠操作尽量范围要⼩。
2. 状态分离,尽量⽆状态。状态要尽可能⼩。
3. 对状态要尽早验证,因为如果失败,通常⽆⼈回滚。前后断⾔验证状态正确性。
4. 异常防御,应该是预见性的异常,异常包含环境信息。
5. 降低修改成本,防⽌埋雷:不要根据异常类型做分⽀判断。保持 null 和 empty ⼀致。
6 功能演进原则
第⼀就是开闭原则,微核⼼加插件机制能够⽀持。
软件质量的下降,来源于修改。
加功能的姿势:应该是增量式,⽽不是扩充式,即不在原有基础上修改,⽽是新增加功能。
关于⾼阶:顶层接⼝尽量抽象,且不能依赖底层实现。这样,当底层实现变化时,⾼层⽆需变化。
例如 Dubbo 泛化,在顶层就⾜够抽象,底层实现⽅式不影响⾼层。
总结
以上是梁飞总结。
今天说的框架设计和现在⼤部分⼈喜欢说的架构设计有所不同,现在似乎只需要再 processon 上放⼏个阿⾥云组件,再连⼏条线,就是架构设计了:)
我个⼈认为,框架设计更能考验⼀个程序员对程序的抽象和管理能⼒(也许措辞不当?)
然后,再说说我的总结:关于⼀个系统的设计,这⾥应该指的是框架的设计,⾸先要知道⽤户需求(废话)。根据需求抽象出模型,再变成代码,且是可扩展,可复⽤的代码。
这⾥提到的 6 个原则,应该算是⽐较成熟的原则了。
1 微核 + 插件,⾮常理想化,例如 SOFA,也有⾃⼰的扩展机制。
2 关于领域模型设计,这
3 个模型的职责⼀定要划分清楚,同时实现⽆锁编程,这个对于系统的性能⾮常重要。
3 关于组件协作,⼀个系统有多个组件,通常需要进⾏状态的共享,在 Dubbo 中,使⽤⾏为进⾏传递,也就是会话域。
reactor模式和观察者模式4 关于功能演进,请遵循开闭原则,但前提通常是有⼀个好的内核。
5 关于接⼝分离和模块分包,通常在后期重构能够达到更好的效果?
好了,洋洋洒洒说了不少,读者如有更好的见解,请与我分享,毕竟现在关注这块的⼈不多了。:)期
待和对此感兴趣的⼈⼀起讨论

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。