zoukankan      html  css  js  c++  java
  • 框架设计原则(梁飞)

    大纲

    1 模块分包原则
    2 框架扩展原则
    3 领域划分原则
    4 接口分离原则
    5 组件协作原则
    6 功能演进原则

    我将对每个原则进行自己的解读,如有不对,还请指教 :)


    1 模块分包原则

     

    说说我的理解。这里其实是从框架结构的解读来解读,这里的包指的是 Maven 的 module。

    复用度,指的是 maven 包的复用。可以理解为工具类。这个工具类不应该变化无常。

    稳定度:被依赖的包应该保持稳定,或者说,被依赖者应当比依赖者稳定,且不能成环状依赖。如果不稳定,将会影响其他的包。

    抽象度,越抽象,越稳定。越具体,越容易变化。

    同时,梁飞给出了一个公式,但是实践起来有点麻烦.......

    关于模块分包,可以参见更详细的博客。 以HTTL为例讲讲模块分包&领域模型&扩展框架


    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 中,使用行为进行传递,也就是会话域。

    4 关于功能演进,请遵循开闭原则,但前提通常是有一个好的内核。

    5 关于接口分离和模块分包,通常在后期重构能够达到更好的效果?

    好了,洋洋洒洒说了不少,读者如有更好的见解,请与我分享,毕竟现在关注这块的人不多了。:)期待和对此感兴趣的人一起讨论

  • 相关阅读:
    luogu 1865 数论 线性素数筛法
    洛谷 2921 记忆化搜索 tarjan 基环外向树
    洛谷 1052 dp 状态压缩
    洛谷 1156 dp
    洛谷 1063 dp 区间dp
    洛谷 2409 dp 月赛题目
    洛谷1199 简单博弈 贪心
    洛谷1417 烹调方案 dp 贪心
    洛谷1387 二维dp 不是特别简略的题解 智商题
    2016 10 28考试 dp 乱搞 树状数组
  • 原文地址:https://www.cnblogs.com/stateis0/p/9823450.html
Copyright © 2011-2022 走看看