1.书籍信息
封面 | ![]() |
---|---|
书名 | 企业应用架构模式 |
作者 | martin fowler |
状态 | 未读 正在读 已读完 未读完-暂时放一放 |
简介 | 本书作者是当今面向对象软件开发的权威,他在一组专家级合作者的帮助下,将40多种经常出现的解决方案转化成模式,最终写成这本能够应用于任何一种企业应用平台的、关于解决方案的、不可或缺的手册。本书获得了2003年度美国软件开发杂志图书类的生产效率奖和读者选择奖。本书分为两大部分。第一部分是关于如何开发企业应用的简单介绍。第二部分是本书的主体,是关于模式的详细参考手册,每个模式都给出使用方法和实现信息,并配以详细的Java代码或C#代码示例。此外,整本书中还用了大量UML图来进一步阐明有关概念。 |
资源 | |
评价(满6颗) | 给 5 颗是因为这本书是十几年前的了,有点旧,但真的是好 ⭐⭐⭐⭐⭐ |
一句话说出本书最核心的东西【尽可能遵循原作】 | 开发企业级应用可能会用到的各种成功的可复制的模式。 |
一句话说出对自己最有启发的【主观上】 | 刷新了我对 DDD 的认知,很多源头都在这里能够找到类似的。 |
2.阅读书摘 & 想法
引用一段话,写几句自己的感受想法,按照时间顺序记录
2022-11-03 记
很多人都试图给“架构”下定义,而这些定义本身却很难统一。能够统一的内容有两点:一点是“最高层次的系统分解”;另一点是“系统中不易改变的决定”。越来越多的人发现:表述一个系统架构的方法不止一种;一个系统中也可能有很多种不同的架构,而且,对于什么在架构上意义重大的看法也会随着系统的生命周期变化。
每个人都有不同的看法,是一个很主观的东西。
能够统一的地方就是不变的地方。
系统最高层次的分解是什么?不变的地方我理解
顶层上看有哪些块?
中间因为大家站的层次不同非常容易有歧义。
第三个例子是一家小型公司使用的简单的“开支跟踪系统”。这个系统的用户很少,功能简单,通过HTML表现方式可以很容易实现,涉及的数据源表项也不多。尽管如此,开发这样的系统也不是没有挑战。一方面你必须快速地开发出它,另一方面你又必须为它以后可能的发展考虑:也许以后会为它增加赔偿检验的功能,也许它会被集成到工资系统中,也许还要增加关于税务的功能,也许要为公司的CFO生成汇总报表,也许会被集成到一个航空订票Web Service中,等等。如果在这个系统的开发中,也试图使用前面两个例子中的一些架构,可能会影响开发进度。如果一个系统会带来业务效益(如所有的企业应用应该的那样),则系统进度延误同样也是开销。如果现在不做决策又有可能会影响系统未来的发展。但是,如果现在就考虑了这些灵活性但是考虑不得当,额外的复杂性又可能会影响到系统的发展,进一步延误系统部署,减少系统的效益。虽然这类系统很小,但是一个企业中往往有很多这样的系统,这些系统的架构不良性累积起来,后果将会非常可怕。
这个例子可以说是非常贴切了
对于一个目前还算小的系统设计时可能会出现的问题
设计过多现在复杂度过高,影响开发效率
设计过少,将来扩展的时候,就很痛苦
那怎么平衡他们呢?
这是门艺术啊!
2022-11-05 记
分层架构中最困难的问题是决定建立哪些层次以及每一层的职责是什么。
对,很难。
在客户/服务器方式逐渐大众化的同时,面向对象方式开始崛起。面向对象为领域逻辑的问题找到了答案:转到三层架构的系统。在这种方式下,在表现层实现用户界面,在领域层实现领域逻辑,在数据源层存取数据。这种方式使你可以将复杂的领域逻辑从界面代码中抽取出来,单独放到中间层,用对象加以建模和组织。
尽管有这些优势,但一开始面向对象的进展并不大。当时的实际情况是:大多数系统并不特别复杂,或者至少在构建之初没有那么复杂。因此,当系统比较简单时,相对于三层架构的优势,强有力的客户/服务器工具的竞争力非常大。但客户/服务器工具很难甚至无法应用于三层架构系统的配置。
我认为真正巨大的冲击来自Web的兴起。人们忽然想在Web浏览器上部署这些客户/服务器应用。然而,如果所有的领域逻辑都是写在“胖”客户中,则所有这些都必须在Web界面中重写。对于设计良好的三层系统来说,只需要增加一个新的表现层,就可以了。另外,Java的出现使得面向对象语言无所顾忌地向当时的主流技术发起冲击。用于构建Web页面的工具对SQL的绑定也没有那么紧密了,这也使得它们比较容易适应三层结构。
很好的解释了为什么会由两层转到三层,驱动力是什么:web 的兴起。
当人们讨论分层时,常常不容易区分layer和tier。这两个词汇经常被用作同义词,但是很多人还是认为tier意味着物理上的分离。客户/服务器系统常常被称为“two-tier system”,其分离是物理上的分离:客户端是一台台式机,而服务器端是一台服务器。我使用layer,旨在强调无需把不同的层次放在不同的计算机上运行。独立出来的领域逻辑层,既可以运行在台式计算机上,也可以运行在数据库服务器上。在这种情形下,有两个节点,但是有三个层次。如果数据库也在本地,还可以在一台笔记本电脑上运行三层软件,当然,仍旧存在三个截然不同的层次。
很好的解释了我的疑问:b-s 是几层架构,c-s 是几层。
有两个不同的维度:分层和物理节点。
使用领域逻辑时,其中一个最困难的部分就是区分什么是领域逻辑,什么是其他逻辑。一种不太正规的测试办法就是:假想向系统中增加一个完全不同的新层,例如为Web应用增加一个命令行界面层。如果在这个过程中,发现需要重复实现某些功能,则说明可能有一些本应该在领域层实现的逻辑,现在在表现层实现了。类似地,你也可以假想一下,将后台数据库更换成XML文件格式,看看情况又会如何?
好办法。
领域逻辑的组织可以分为三种主要的模式:事务脚本、领域模型以及表模块
所以这里提出了这三种说法,后续大家都引用的是这里。
我看着书越看越觉得这不就是领域驱动设计嘛
额不,领域驱动设计有点造词
也不是
国内的人造词?
在对象技术出现的早期,许多人意识到在对象和关系之间有一个“阻抗不匹配”的问题,因此随之掀起了一股面向对象数据库的研究热潮,从本质上来说,面向对象数据库是将面向对象的理论体系带到了磁盘存储领域。使用面向对象数据库时,无需担心映射的问题。
现在的 json 就是吧,基本是可以直接映射。
2022-11-09 记
可以这样理解工作单元,它是一个对象,充当数据库映射的控制器。在没有工作单元的情况下,一般都是由领域层充当控制器,决定何时读写数据库。工作单元就是来源于把数据库映射控制器的行为分解到它自己的对象中。
领域驱动设计里叫做仓储
cola 里叫做网关
如果使用了领域模型,就必须合理安排,使得关联的对象一起加载,例如,在读取一个订单对象的同时,把与之相关联的客户对象也一同加载进来。然而,如果许多对象都是连接在一起的,则读取任何对象都会从数据库中带出大批的对象。为了避免这种低效,必须设法减少带出来的东西,当然,还需要保持接口以便在以后需要的时候再来取。延迟加载的主要思想是拥有一个对象引用的占位符。可以采用几种方法,但它们的共同点都是拥有被修改对象的对象引用,它指向的是一个占位符而不是实际的对象。当且仅当想要通过链接访问的时候,才会真的去数据库中读取实际的对象。适当使用延迟加载能使每次数据库调用取得刚好够用的数据。
好熟悉,方法也好熟悉。
这是领域驱动设计里面的,所以他是从这里来的。
2022-11-10 记
标识域用来把对象间引用变为外键,但并不是所有的对象关系都需要用这种方法持久化。一些小的值对象(比如日期范围和钱)显然不应该描述成数据库中它们自己的表。取而代之的是,取出值对象中所有的域,并以嵌入值方式把它们嵌入到关联对象中。由于值对象含有值的语义,可以在每次执行读操作的时候创建它们,而无需担心标识映射的问题。把它们写到外面也非常容易,仅仅需要解除对象引用,并且把它的域写到它自己的表中即可。
值对象,不是领域驱动设计中第一次提出。
每次都是站在前人肩膀上。
2022-11-11 记
所以我以后不能光提问题,说正确而无用的废话。
要提有建设性的意见。
不建议只抛问题,只抛原则,不解决。
应该还有原则的实践。
在设计的的时候应该考虑领域模型与数据库模型的差异度。
从业务的表达上,当然是领域模型越有表达力约好。
但是从成本和性能来看,不得不兼容一些数据模型,做一些取舍。
在本书中,我绝大部分的例子都采用手写的代码。利用简单和重复性映射,这样会导致代码简单和重复,而重复代码是设计上有问题的一个标志。可以通过委托和继承分解出通用行为,但还有一种更成熟的方法是使用元数据映射。
元数据映射基于把映射浓缩到元数据文件的方法。元数据文件详细描述数据库中的列如何映射到对象的域。这里的关键在于:一旦有了元数据,就可以通过代码生成或者反射编程来避免重复性代码。
使用元数据使我们可以用少量元数据表达很多含义。一行元数据可以像这样传递某些信息:
忽然懂了映射框架干的事情有什么好处了。
以前知道能省事,但是没有这么清晰。
节省的是映射代码。
业务事务和系统事务
这个区分好,系统事务一般由技术组建为我们实现,业务事务需我们自己写代码来实现。
通常不能把领域对象本身直接发送过去,因为它们绑定到一个由细粒度的本地对象间引用组成的网络中。所以应该将客户端需要的所有数据打包在一个特定对象中以便于传输——就成了所谓的数据传输对象(很多企业级Java开发人员称之为值对象,这与本书中所说的值对象有些混淆)。传输双方都用到了数据传输对象,很重要的一点是要保证它们不能引用网络间任何非共享的事物。事实上,一个数据传输对象一般只引用其他的数据传输对象和一些如字符串等原始类型的对象。
叫法稍微有点混乱啊!不过是类似的
2022-11-12 记
即便如此,类和方法的面向对象接口也很有用。将所有的传输数据转化成XML结构和字符串给远程调用增加了可观的开销。因此,使用远程过程调用比使用基于XML的接口要高效许多。如果系统间的二进制编码机制相同,基于XML的接口只是一堆花哨的东西。因此,如果两个系统是用相同的平台构建的,最好使用系统自己的远程调用机制。Web Service在不同平台相互交互时能提供便利。我建议只有在无法使用更直接的方式时,才使用基于XML的Web Service。
方便的同时也带来了开销,需要权衡。
2022-11-14 记
Brown模型的分层方式,它在[Brown et al.]中详细介绍(见表8-1)。该模型包含五个层次:表现层、控制层/中介层、领域层、数据映射层和数据源层。从本质上看,它在三层模型的基础上增加了两个中介层。控制层/中介层在表现层和领域层之间起中介作用,数据映射层在领域层和数据源层之间起中介作用。
我发现,中介层在一些时候很有用,但并非所有时候都如此,所以我用模式描述它们。应用控制器(模式)是表现层与领域层之间的中介层;而数据映射器则是数据源层与领域层之间的中介层。
这就是 cola 的分层哈。
基础设施层包含了数据映射和数据源。
J2EE另一个很好的分层方案出现在“CoreJ2EE patterns”[Alur et al.]中(见表8-2)[插图]。这里,分为如下几个层次:客户层、表现层、业务层、集成层和资源层。业务层和集成层存在简单的对应关系,资源层包含了集成层需要连接到的外部服务。主要区别在于它将表现层分成了客户端部分(客户层)和服务器端部分(表现层)。这是非常有用的分隔方法,但同样,这种分层方式并不是任何时候都需要。
把客户端分了一下子。
Microsoft的DNA架构[Kirtland]定义了三个层次:表现层、业务层和数据访问层。这和本书使用的三层结构能够很好地对应(见表8-3)。最主要的区别在于数据从数据访问层向上层传递的方式。在Microsoft DNA中,所有层都操作在数据访问层通过SQL查询访问数据库产生的记录集上。这就带来一个耦合的问题——无论是业务层还是表现层,都必须了解数据库。
看起来像是我们现在用的三层架构。
区别在于表现层不能操作数据层的东西。
[Marinescu]中使用的是五层结构(见表8-4)。表现层被分为两部分,主要反映了应用控制器的分离。领域层也被分为两部分,实际上是在领域模型上构建了服务层。这是一种通用的方法
将服务层从领域层中剥离出来的原因,源于将工作流逻辑从纯粹领域逻辑中的剥离。服务层所包含的逻辑一般都特定于某个用例,并与其他一些基础设施相互通信,如消息机制。是否将服务层与领域层分离还存在一些争论。我个人认为,这种分离偶尔是有用的,而在一般情况下没有意义,但是,也有不少我所尊敬的设计者持不同意见
表现层是 controller task consumer
应用层是 appService
服务层是 domainService
领域层是领域对象
持久层是各种 maopper rpc
[Nilsson]中使用了一种较复杂的分层模型(见表8-5)。映射到这种模型有点复杂,这是因为Nilsson太广泛地使用存储过程,并且为了性能原因而鼓励在存储过程中使用领域逻辑。我不赞成将领域逻辑放到存储过程中去,因为这样会增加维护开销。当然,在不多的情况下,这也是一种优化技术。Nilsson的存储过程层包含了数据源和领域逻辑。
像[Marinescu]一样,Nilsson来用单独的应用层和领域层来表示领域逻辑。他建议对于小型系统来说,可以不使用领域层,这和我的观点类似——领域模型对于小型系统来说意义不大。
这玩意真实够复杂的,这么多层。
这个肯定得避免,存储过程与数据库厂商绑定,可读性非常差。
3.读后感 & 点评
为什么读?
大名鼎鼎的经典书,值得读。
读了什么,有什么用 ?
全书把开发企业级应用可能用到的模式非常全的梳理了一遍,对实际开发时特别具有指导意义。
有和感受,想法?
语言很精简,用很少的话就说清楚了一种模式,特别佩服,后续反复读。
4.其他
4.1 微信读书划线笔记
微信读书导出的笔记