《实现领域驱动设计》摘抄

我记得当时第一次看这本书的时候是在去西安旅行的飞机上和等待途中,当时我记得一下子就被这本书的语言个风格所吸引,但是当时只是一边旅行一边看书,所以还是没有完全看完这本书。今天我又再次拿起来准备阅读的,想想前些天阅读的,《深入立即Java虚拟机》,完全是不同的感受,那本书和Java编程思想有的一拼,全是 纯文字的,看起来相当地吃力,有很多的概念也是完全不好理解和记忆的,然而我也是不喜欢记忆的一个人,所以我还是有足够的信心可以好好阅读和吸收这本书的精华的。我也顺便把这本书的原版英文书打开了看了一下,发现有2点。第一滕云的翻译能力和对语言的理解能力真得很令我欣赏。第2点就是我阅读英文书的能力还是有待提高,理解使用英语写的文字是一个值得我坚持的习惯,同时我也是需要对比着学习别人的翻译能力。

第一章 DDD入门,我简单的总结一下,也可以说是记录一下经典的话。(3/17)

  • 领域驱动设计(DDD)作为 软件开发方法,它可以帮助我们设计高质量的软件模型。高质量软件模型至少可以提现在可测试、可伸缩、组织良好。
  • DDD首先并不是关于技术的,而是关于讨论、聆听、理解、发现和业务价值的,这些都是为了将知识集中起来。
  • 开发过程中,最大的鸿沟之一便存在于领域专家和开发者之间。通常来说,领域专家将关注点放在交付业务价值上,而开发者则将注意力放在技术实现上。DDD可以帮助团队成功地交付真正的业务价值。
  • 通用语言和界限上下文同时构成了DDD的两大支柱,并且它们是相辅相成的。
  • 通用语言是团队共享的、会随着时间推移而不断演化改变的。团队交流和代码是对通用语言的持续表达。
  • DDD强调将精力花在对业务最有价值的东西上。
  • DDD并不是画模型图,而是将领域专家的思维模型转化成有用的业务模型。DDD不是创建一个真实世界的模型,而是模仿现实。
  • 使用DDD最大的挑战之一便是:我们需要花费大量的时间和精力来思考业务领域,研究概念和术语,并且和领域专家交流,以发现、捕捉和改进通用语言。
  • 我们希望对对象行为的命名能够传达准确的业务含义,也即反映通用语言。
  • 使用DDD开发可以结合测试驱动和敏捷开发的方法。
  • 最后一点,实现DDD需要团队同心协力。

第二章 领域、子域和界限上下文.我也简单总结一下。(3/18)

  • 领域(Domain)即是一个组织所有的事情以及其中所包含的一切。每个组织都有它自己的业务范围和做事方式。这个业务范围以及其中所进行的活动便是领域。
  • 领域既可以表示整个业务系统,也可以表示其中的某个核心域或者支撑子域。
  • 在DDD中,一个领域被分为若干个子域,领域模型在界限上下文中完成开发。事实上,在开发一个领域模型时,我们关注的通常只是这个业务系统的某个方面。
  • 通过使用DDD战略设计工具,我们可以按照实际功能将这些交织的模型划分成逻辑上相互分离的子域,从而在一定程度上减少系统的复杂性。
  • 子域并不是一定要做得很大,并且包含很多功能。有时,子域可以简单到只包含一套算法。
  • 如果这样的界限上下文对应着业务的某些重要方面,但却不是核心,那么它便是一个支撑子域。创建支撑子域的原因在于它们专注于业务的某个方面,否者,如果一个子域被用于整个业务系统,那么这个子域便是通用子域。
  • 领域中还同时存在问题空间和解决方案空间。在问题空间中,我们思考的是业务所面临的挑战,而在解决方案空间中,我们思考如何实现软件以解决这些业务挑战。
  • 解决方案空间在很大程度上受到现有系统和技术的影响。
  • 界限上下文是一个显式的边界,领域模型便存在这个边界之内。限界上下文主要是一个语义上的边界,我们应该通过这一点来衡量对一个限界上下文的使用正确与否。
  • 界限上下文主要用来封装通用语言和领域对象,但同时它也包含了那些为领域模型提供交互手段和辅助功能的内容。
  • 使用隔离内核的时机是当你有一个非常重要的界限上下文,但是其中模型的关键部分却被大量的起辅助作用的功能所掩盖了。
  • 采用额外的战略模式,可以将可重用的模型分离到单独的界限上下文中,并在不同的界限上下文之间进行合适的集成。

第三章 上下文映射图。简单总结一下。(3/18)

  • 项目的上下文映射图可以通过两种方式表示,一种是一个简单的框图,另一种就是通过界限上下文集成的源代码实现来表示。
  • 上下文映射图主要帮助我们从解决方案空间的角度看待问题。
  • 上下文映射图表现的是项目当前的状态,如果项目在将来发生变化,上下文映射图可以做相应的更新。
  • 界限上下文之间的关系有:合作关系、共享内核,客户方-供应方开发、遵奉者、防腐层、开放主机服务、发布语言、另谋他路、大泥球。
  • 在迭代过程中,思考和讨论可以帮助我们改进上下文映射图,比如对集成点进行改进,这将有助于描述界限上下文之间的关系。
  • 我们应该将有助于团队交流的高层次元素加入上下文映射图中,而不是龙凤冗繁的细节,保持简单性和敏捷性,这样创建的上下文映射图将对项目起推动作用,而不是阻碍作用。

第四章 架构。(3/21)

  • DDD的一大好处便是它不需要特定的架构。
  • 分层架构的一个重要原则是:每层只能与位于其下方的层发生耦合。
  • 依赖倒置原则:高层模块不应该依赖于低层模块,两者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。
  • 六边形架构具有对称性特征。
  • 面向服务架构精神所在:业务价值高于技术策略,战略目标高于项目利益。
  • Rest作为一种架构风格,它将不同架构实现所共有的东西抽象出来,使得我们在谈及架构时不至于陷入技术细节中。
  • DDD和RESTful HTTP结合起来的两种方法:(1)为系统接口层单独创建一个界限上下文,再在此上下文中通过适当的策略访问实际的核心模型。(2)用于需要使用标准媒体类型的时候。如果某种媒体类型并不用于支持单个系统接口,而是用于一组相似的客户端-服务器交互场景,此时我们可以创建一个领域模型来处理每一种媒体类型。
  • CQRS:一个方法要么是执行某种动作的命令,要么是返回数据的查询,而不能两者皆是。CQRS旨在解决数据显示复杂性问题。
  • EDA事件驱动架构是一种用于处理事件的生成、发现和处理等任务的软件架构。
  • 在一个长时处理过程(Saga)中,可能存在许多彼此分离的业务处理过程同时运行。采用长时处理过程可以感受到分布式和并行处理带来的优雅,也有助于开发高可伸缩性、高可用性的业务系统。
  • 事件源:对于某个聚合上的每次命令操作,都有至少一个领域事件发布出去。该领域事件描述了操作的执行结果。
  • 数据网织的一个好处是它对领域模型提供了自然的支持,几乎消除了所有的阻抗失配。
  • 数据网织可以很好地支持事件驱动架构风格,因为它能确保对事件的投递。它还可以在所有复制缓存范围内完成分布式处理,然后将处理结果聚合到一起发给客户端。

第五章 实体。(3/22)

  • 当我们需要考虑一个对象的个性特征,或者需要区分不同的对象时,我们引入实体这个领域概念。一个实体是一个唯一的东西,并且可以在相当长的一段时间内持续地变化。
  • 唯一的身份标识和可变性特征将实体对象和值对象区分开来。
  • 一共有4中方式生成唯一标识:用户提供、应用程序生成、持久化机制生成、另一个界限上下文提供。
  • 实体唯一标识的生成既可以发生在对象创建的时候,也可以发生在持久化对象的时候。
  • 委派标识通常是为了满足ORM机制所产生的。
  • 有时一个实体维护了一个或者多个不变条件。不变条件即是在整个实体生命周期中都必须保持事务一致性的一种状态。
  • 验证的主要目的在于检查模型的正确性,检查的对象可以是某个属性,也可以是整个对象,甚至是多个对象的组合。
  • 跟踪变化最实用的方法是领域事件和事件存储。

第六章 值对象。(3/26)

  • 我们应该尽量使用值对象来建模而不是实体,即便一个领域概念必须建模成实体,在设计时也应该更偏向将其作为值对象容器,而不是实体容器。
  • 值对象特征:度量或描述、不变性、概念整体、可替换性、值对象相等性、无副作用行为。
  • 值对象还可以实现最小化集成,即可以最小化下游模型中用于管理职责的属性数目,使用值对象可以使我们做更少的职责假设。
  • 用值对象表示标准类型。标准类型是用于表示事物类型的描述对象。系统中既有表示事物的实体和描述实体的值对象,同时还存在标准类型来区分不同的类型。
  • Java中枚举是实现标准类型的一种简单方法。枚举提供了一组数量有限的值对象,它是非常轻量的,而且无副作用。
  • 在设计领域模型时,从客户端的角度思考有助于捕获关键的领域概念。否则,我们便是在从自己的角度设计模型,而不是从业务的角度。
  • 持久化值对象是通过一种非范式的方式完成的,即所有的属性和实体对象都保存在相同的数据库表中。这样可以优化对值对象的保存和读取,并且可以防止持久化逻辑泄漏到模型中。
  • ORM可以将单个值对象持久化到表中的列,也可以将多个值对象序列化到单个列中。使用数据库实体保存多个值对象,还可以使用联合表保存多个值对象。
  • 持久化Java枚举的一种简单方式是保存枚举所对应的文本展现。

《程序员修炼之道——从小工到专家》经典语录

注重实效的程序员之快速参考指南

1.关心你的技艺
Care About Your Craft
如果你不在乎能否漂亮地开发出软件,你又为何要耗费生命去开发软件呢?

2.思考!你的工作
Think! About Your Work
关掉自动驾驶仪,接管操作。不断地批评和评估你的工作。

3.提供各种选择,不要找蹩脚的借口
Provide Options, Don’t Make Lame Excuses
要提供各种选择,而不是借口。不要说事情做不到;说明能够做什么。

4.不要容忍破窗户
Don’t Live with Broken Windows
当你看到糟糕的设计、错误的决策和糟糕的代码时,修正他们。

5.做变化的催化剂
Be a Catalyst for Change
你不能强迫人们改变。相反,要向他们展示未来可能会怎样,并帮助他们参与对未来的创造。

6.记住大图景
Remember the Big Picture
不要太过专注于细节,以致忘了查看你周围正在发生什么。

7.使质量成为需求问题
Make Quality a Requirements Issue
让你的用户参与确定项目真正的需求。

8.定期为你的知识资产投资
Invest Regularly in Your Knowledge Portfolio
让学习成为习惯

9.批判的分析你读到的和听到的
Critically Analyze What You Read and Hear
不要被供应商、媒体炒作、或教条左右。要依照你自己的看法和你的项目的情况去对信息进行分析。

10.你说什么和你怎么说同样重要
It’s Both What You Say and the Way You Say It
如果你不能有效地向他人传递你的了不起的想法,这些想法就毫无用处。

11.不要重复你自己
DRY – Don’t Repeat Yourself
系统中的每一项知识都必须具有单一、无歧异、权威的表示。

12.让复用变得容易
Make It Easy to Reuse
如果复用很容易,人们就会去复用。创造一个支持复用的环境。

13.消除无关事务之间的影响
Eliminate Effects Between Unrelated Things
设计自足、独立、并具有单一、良好定义的目的的组件。

14.不存在最终决策
There Are No Final Decisions
没有决策是浇铸在石头上的。相反,要把每项决策都视为写在沙滩上的,并为变化作好计划。

15.用曳光弹找到目标
Use Tracer Bullets to Find the Target
曳光弹能通过试验各种事物并检查他们离目标有多远来让你追踪目标。

16.为了学习而制作原型
Prototype to Learn
原型制作是一种学习经验。其价值并不在于所产生的代码,而在于所学到的经验教训。

17.靠近问题领域编程
Program Close to the Problem domain
用你的用户的语言进行设计和编码。

18.估算,以避免发生意外
Estimate to Avoid Surprises
在着手之前先进行估算。你将提前发现潜在的问题。

19.通过代码对进度表进行迭代
Iterate the Schedule with the Code
用你在进行实现时获得的经验提炼项目的时间标度。

20.以纯文本保存知识
Keep Knowledge in Plain Text
纯文本不会过时。它能够帮助你有效利用你的工作,并简化调试和测试。

21.利用命令shell的力量
Use the Power of Command Shells
当图形用户界面无能为力时使用shell

22.用好一种编辑器
Use a Single Editor Well
编辑器应该是你的手的延伸;确保你的编辑器是可配置、可扩展和可编程的。

23.总是使用源码控制
Always Use Source Code Control
源码控制是你的工作时间的机器—-你能够回到过去。

24.要修正问题,而不是发出指责
Fix the Problem, Not the Blame
Bug是你的过错还是别人的过错,并不是真的很有关系—-他仍然是你的问题,他仍然需要修正。

25.调试时不要恐慌
Don’t Panic When Debugging
做一次深呼吸,思考什么可能是bug的原因。

26.“Select”没有问题
“Select” Isn’t Broken
在 OS或编译器、甚至或是第三方产品或库中很少发现bug。Bug很可能在应用中。

27.不要假定,要证明
Don’t Assume It-Prove It
在实际环境中—-使用真正的数据和边界条件—-证明你的假定。

28.学习一种文本操纵语言
Learn a Text Manipulation Language
你们每天的很大一部分时间处理文本,为什么不让计算机替你完成部分工作呢?

29.编写能写代码的代码
Write Code That Writes Code
代码生成器能提高你的生产效率,并有助于避免重复。

30.你不可能写出完美的软件
You Can’t Write Perfect Software
软件不可能完美。保护你的代码和用户,使它(他)们免于能够预见的错误。

31.通过合约进行设计
Design with Contracts
使用合约建立文档,并检查代码所做的事情正好是他声明要做的。

32.早崩溃
Crash Early
死程序造成的危害通常比有问题的程序要小的多。

33.如果它不可能发生,用断言确保它不会发生
If It Can’t Happen, Use Assertions to Ensure That It Won’t
断言验证你的各种假定。在一个不确定的世界里,用断言保护你的代码。

34.将异常用于异常问题
Use Exceptions for Exceptional Problems
异常可能会遭受经典的意大利面条式代码的所有可读性和可维护性问题的折磨。将异常保留给异常的事物。

35.要有始有终
Finish What You Start
只要可能,分配某资源的例程或对象也应该负责解除其分配。

36.将模块之间的耦合减至最少
Minimize Coupling Between Modules
通过编写 “羞怯的”代码并应用得墨忒耳法则来避免耦合。

37.要配置,不要集成
Configure, Don’t Integrate
要将应用的各种技术选择实现为配置选项,而不是通过集成或工程方法实现。

38.将抽象放进代码,细节放进元数据
Put Abstractions in Code, Details in Metadata
为一般情况编程,将细节放在被编译的代码库之外。

39.分析工作流,以改善并发性
Analyze Workflow to Improve Concurrency
利用你的用户的工作流中的并发性。

40.用服务进行设计
Design Using Services
根据服务—-独立的、在良好定义、一致的接口之后的并发对象—-进行设计。

41.总是为并发进行设计
Always Design for Concurrency
容许并发,你将会设计出更整洁、具有更少假定的接口。

42.视图与模型分离
Separate Views Form Models
要根据模型和视图设计你的应用,从而以低廉的代码获取灵活性。

43.用黑板协调工作流
Use Blackboards to Coordinate Workflow
用黑板协调完成不同的事实和因素,同时又使各参与方保持独立和隔离。

44.不要靠巧合编程
Don’t Program by Coincidence
只依靠可靠的事物。注意偶发的复杂性,不要把幸运的巧合与有目的的计划混为一谈。

45.估计你的算法的阶
Estimate the Order of Your Algorithms
在你编写代码之前,先大致估算事情需要多长时间

46.测试你的估计
Test your Estimates
对算法的数学分析并不会告诉你每一件事情。在你的代码的目标环境中测定他的速度。

47.早重构,常重构
Refactor Early, Refactor Often
就和你会在花园里除草、并重新布置一样,在需要时对代码进行重写、重做和重新架构。要铲除问题的根
源。

48.为测试而设计
Design to Test
在你还没有编写代码时就还是思考测试问题。

49.测试你的软件,否则你的用户就得测试
Test Your Software, or Your Users Will
无情地测试。不要让你的用户为你查找bug。

50.不要使用你不理解的向导代码
Don’t Use Wizard Code You Don’t Understand
向导代码可以生成大量代码。在你把它们合并进你的项目之前,确保你理解全部这些代码。

51.不要搜集需求—-挖掘它们
Don’t Gather Requirements – Dig for Them
需求很少存在于表面上。它们深深地埋藏在层层假定、误解和政治手段下面。

52.与用户一同工作,像用户一样思考
Work with a User to Think Like a User
要了解系统实际上将如何被使用,这是最好的方法。

53.抽象比细节活得更长久
Abstractions Live Longer than Details
“投资”于抽象,而不是现实。抽象能在来自不同的现实和新技术的变化的”攻击”之下存活下去。

54.使用项目词汇表
Use a Project Glossary
创建并维护项目中使用的专用术语和词汇的单一信息源。

55.不要在盒子外面思考—-要找到盒子
Don’t Think Outside the Box – Find the Box
在遇到不可能解决的问题时,要确定真正的约束。问问你自己:”它必须以这种方式完成吗?它真的必须完
成吗?”

56.等你准备好再开始
Start When You’re Ready
你的一生都在积累经验。不要忽视反复出现的疑虑。

57.对有些事情”做”胜于”描述”
Some Things Are Better Done than Described
不要掉进规范的旋涡—-在某个时刻,你需要开始编码。

58.不要做形式方法的奴隶
Don’t Be a Slave to Formal Methods
如果你没有把某项技术放进你的开发实践和能力的语境中,不要盲目地采用它。

59.昂贵的工具不一定能制作出更好的设计
Costly Tools Don’t produce Better Designs
小心供应商的炒作,行业教条、以及价格标签的诱惑。要根据工具的价值判断它们。

60.围绕功能组织团队
Organize Teams Around Functionality
不要把设计师与编码员分开,也不要把测试员与数据建模员分开。按照你构建代码的方式构建团队。

61.不要使用手工流程
Don’t Use Manual Procedures
Shell脚本或批文件会一次次地以同一顺序执行同样的指令。

62.早测试,常测试,自动测试
Test Early. Test Often. Test Automatically
与呆在书架上的测试计划相比,每次构建时运行的测试要有效的多。

63.要通过全部测试,编码才算完成
Coding didn’t Done Until All the Tests Run
就是这样。

64.通过”蓄意破坏”测试你的测试
Use Saboteurs to Test Your Testing
在单独的软件副本上故意引用 bug,以检验测试能够抓住它们。

65.测试状态覆盖,而不是代码覆盖
Test State Coverage, Not Code Coverage
确定并测试重要的程序状态。只是测试代码行是不够的。

66.一个bug只抓一次
Find Bugs Once
一旦测试员找到一个bug,这应该是测试员最后一次找到它。此后自动测试应该对应其进行检查。

67.英语就是一种编程语言
English is Just a Programming Language
像你编写代码一样编写文档:遵守DRY原则、使用原数据、MVC、自动生成,等等。

68.把文档建在里面,不要拴在外面
Build Documentation In, Don’t Bolt It On
与代码分离的文档不太可能被修整和更新。

69.温和地超出用户的期望
Gently Exceed Your Users’ Expectations
要理解你的用户的期望,然后给他们的东西要多那么一点。

70.在你的作品上签名
Sign Your Work
过去时代的手工艺人为能在他们的作品上签名而自豪。你也应该如此。

检查清单

71.要学习的语言
厌倦了C、C++和JAVA?试试CLOS、Dylan、Eiffel、Objective C、Prolog、Smalltalk或TOM。他们每一种都有不同的能力和不同的”风味”。用其中的一种或多种语言在家里开发一个小项目。

72.WISDOM 离合诗
What do you want them to learn? 你想让他们学到什么?
What is their interest in what you’ve got to say? 他们对你讲的什么感兴趣?
How sophisticated are they? 他们有多富有经验?
How much detail do they want? 他们想要多少细节?
Whom do you want to own the information? 你想要让谁拥有这些信息?
How can you Motivate them to listen to you? 你如何使他们听你说话?

73.怎样维持正交性
设计独立、良好定义的组建 
使你的代码保持解藕 
避免使用全局数据 
重构相似的函数

74.应制作原型的事物
架构 
已有系统中的新功能 
外部数据的结构或内容 
第三方工具或组建 
性能问题 
用户界面设计

75.架构问题 
责任是否得到了良好定义? 
写作是否得到了良好定义? 
耦合是否得以最小化? 
你能否确定潜在的重复? 
接口定义和各项约束是否可以接受? 
模块能否在需要时访问所需数据?

76.调试检查清单
正在报告的问题是底层bug的直接结果,还是只是症状?
Bug 真的在编译器里?在OS里?或者是在你的代码里?
如果你向同事详细解释这个问题,你会说什么?
如果可以代码通过了单元测试,测试是否足够完整?如果你用该数据单元测试,会发生什么?
造成这个bug的条件是否存在于系统的其他任何地方?

77.函数的得墨忒耳法则
某个对象的方法应该值调用属于以下情形的方法: 
它自身 
传入的任何参数 
它创建的对象 
组件对象

78.怎样深思熟虑地编程
总是意识到你在做什么 
不要盲目地编程 
按照计划行事 
依靠可靠的事物 
为你的假定建立文档 
不要只是测试你的代码,还要测试你的假定 
为你的工作划分优先级 
不要做历史的奴隶

79.何时进行重构
你发现了对DRY原则的违反 
你发现事物可以更为正交 
你的知识扩展了 
需求演变了 
你需要改善性能

80.劈开戈尔迪斯结
在解决不可能解决的问题时,问问自己: 
有更容易的方法吗? 
我是在解决正确的问题吗? 
这件事情为什么是一个问题? 
是什么使它如此难以解决? 
它必须以这种方式完成吗? 
它真的必须完成吗?

81测试的各个方面
单元测试 
集成测试 
验证和校验 
资源耗尽、错误及恢复 
性能测试 
可用性测试 
对测试自身进行测试