整洁架构--纸上谈兵03

一个架构设计的理念如下图:

整洁架构--纸上谈兵03

外层依赖内层,内层不应该依赖外层。

名词解释:

  1. 业务实体 

     就是操作关键数据的业务逻辑(不一定非得是类,也可以是模块),只包含业务逻辑,不包含其他东西,可以在任何其他系统中提供本业务逻辑所描述的功能。

整洁架构--纸上谈兵03

     上图中的Client客户类就是一个业务实体,其中包含了关键数据(rate, money等),以及关键的业务逻辑(save_money()等)

  2. 用例

    特定情景下的业务逻辑(不是上面业务实体的逻辑,下面会举例解释),这些特定的情景控制了与业务实体的交互。

    现在给出一个用例的描述:

       输入:名字,地址等

       输出:显示所有输入信息确认,并且包括信用值

       主要步骤:

          1、接受并校验名字  

          2、校验地址等信息

          3、获取信用值

          4、如果信用值小于500,则跳转到拒绝页

          5、否则,创建客户对象,并且跳转到还款预估页

 

    1-5步骤描述的就是特定情景下的业务逻辑,而最终控制了与业务对象(第五步的客户对象)的交互。而客户对象中是包含了真正的系统级的业务逻辑的(借钱,还钱等),用例中的业务逻辑是描述业务实体应用情景的。

 

  3. 接口适配器

    最主要的作用是数据转换器,负责将外部格式的数据转换成用例和业务实体可接受的数据类型。

    比如,这一层是数据库最深入的一层,不能再让与数据库有关的代码进入用例甚至是业务实体。不然用例就要依赖某个数据库了。如果用的是SQL数据库,那么所有的SQL语句都要被限制在这一层中。

    例如:这一层通过调用数据库对象(框架与驱动程序层,下面会讲)的查询语句,当然是接口调用,不然就成了内层依赖外层了(DIP原则),使用SQL查询语句,通过数据库对象来获取到数据后,转换为用例层可接受的数据。

  假定数据库对象查询返回的是Resource对象,不能直接传到用例(会造成用例对这个对象,也就是该数据库的依赖),所以可以在接口适配层,取出该对象中的数据,再以参数的形式,传入用例层。

   int arg1 = Resource.name;

   int arg2 = Resource.age;

   use_case(arg1, arg2);  /* 没有对Resource产生依赖 */

 

  4. 框架与驱动程序

     一般是由工具,数据库,Web框架等组成,这些都是实现细节,以插件的方式嵌入系统,更随意更换。

    在这一层,我们通常只需要编写一些与内部沟通的代码即可(如上面说的数据库对应的数据库操作对象(MySQLHelper等 ))。

 

 

数据库只是实现细节

  数据库只是存储数据的手段之一,说白了就是一个存储数据的工具(文件系统也可以存储数据),而使用什么工具不是做架构时应该考虑的问题,我们应该让数据库成为系统的插件,可以方便地更换数据库,而不是在架构时就把数据库确定起来,那样就成了针对某数据库而进行的设计,不可避免地整个系统会对该数据库产生依赖,如果以后有变更数据库的需求,会很棘手。

  但是不是说数据的模型,数据组织结构不重要,只是怎么存放数据不是架构应该关心的重点。

Web只是实现细节

  Web是GUI的一种,只是一种IO设备,也是细节问题,如果让IO成为系统的插件,那么系统很容易更改为向客户端界面,甚至是命令行界面来输出。这些只是一种输出方式,而架构不应该关心我们的数据如何呈现给用户。

框架只是实现细节

  不过尽早地选择使用框架,尽可能地将框架长时间地留存架构边界之外,可能不需要使用框架就可以完成功能。

   如果使用了框架,也就不得不接受它的依赖,比如框架后期添加的功能,对我们的系统来说不必要,但是我们还是要*升级。甚至以后更换框架,都会很困难。

  

  不要让细节玷污了架构。

 

参考:《Clean Architecture》

以上为书中内容及个人理解,会有错误,欢迎指正。