Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

《Microsoft .NET企业级应用架构设计》——Dino Esposito、Andrea Saltarello #13

Open
thzt opened this issue Nov 10, 2016 · 0 comments

Comments

@thzt
Copy link
Owner

thzt commented Nov 10, 2016

完美的设计不是包罗万象无所不有,而是完整自洽不可精简。
软件工程的目的在于控制复杂度,而不是增加复杂度。
架构一词起源于建筑工程,现在已被用于描述规划、设计并实现软件密集型系统的艺术。
在软件领域中,架构就是指为客户构建系统。

UML类图可以用来表示类之间的关系,
用例图可以用来表示使用场景,
组件图可以用来说明系统中的可重用部分(即组件),并更易于看出它与二进制文件之间的对应关系。

墨菲定律根本内容是:如果事情有变坏的可能,不管这种可能性有多小,它总会发生。

所有的模型都不甚完备,有些模型却有些用处。
若想设计一个系统——任何领域中的任何系统,都需要首先对其进行抽象。
抽象就是指建立一个模型,对系统在视图、结构、行为、参与的实体和流程等方面提供概念上的描述。

UML基于一系列的图形化标记,特别适合在面向对象场景中建模。
不过若使用其他编程理念,例如,函数式或关系型等,UML或许不是最佳选择,
但UML的确非常适合描述面向对象系统。

UML图表:
活动图,类图,通信图,组件图,组合结构图,部署图,交互概述图,
对象图,包图,顺序图,状态机图,时间图,用例图

常用:用例图,类图,顺序图

用例是指系统和其中某个参与者之间的一次交互过程。
用例可以表示哪些参与者要做些什么。
参与者可以是一个用户,或者是外部系统等需要与系统产生交互的对象。
参与者无法被系统控制,参与者定义在系统之外。

类图用来表示系统的静态结构,静态结构是由类型及其关系构成的,
类图中的类型和接口自然由开发团队是实现。

顺序图能够给出实现了某个场景的一系列对象的交互顺序。
顺序图主要用来描述系统中某个流程的详细步骤。
有了顺序图,任何人都可以清楚的了解系统实现某个用例的方法。

UML是一种通用的语言,这意味着它适合描述任何领域,但仅限于大体上的描述,即UML并不能够精确的描述某个领域。
而在我们生活的这个非完美的现实世界中,却不存在通用的语言可以在同等代价下解决所有类型的问题。
而领域特定语言专门为特定的领域和场景设计,它是一种定制的、直击要害的专门语言。
领域特定语言中的元素来自于领域本身,而不是一些固定下来的元模型。

有经验的设计者显然知道一些缺乏经验的设计者不知道的事情。这些事情是什么呢?
写出可以正常工作的的代码是一回事,而写出可以正常工作的良好代码则是另一回事。
若目标是“写出可以正常工作的良好代码”,就需要用更加全面的眼光来看待系统。
一个设计精良的系统并不是一系列指令和修补的堆砌,里面还有很多与设计直接或间接相关的东西。

“写出可以正常工作的良好代码”需要我们更加重视代码的可维护性。
之所以选择这个特性,并不是因为其他特性(例如,可扩展性和可伸缩性)与可维护性相比不重要,
而是因为保持良好可维护的代价比较高,且容易让开发者忽视,最终造成严重后果。
一个良好的代码体系可以容易找到Bug所在,也可以轻易的修复Bug,还可以在任何时候进行任何程度的改进,包括可扩展性和可伸缩性。
考虑到这些,可维护性就成为了设计系统时最应该关注的问题。

从高处着眼,业界普遍认同的是两种软件模式:设计模式和架构模式。
在设计、编写代码时,我们会使用设计模式。
而在概括的规划系统的整体设计时,我们会使用架构模式。

若想设计出好的软件,普通的设计原则就够了。
你并不特别需要模式,不过若某个问题恰好可以由某个模式解决,那么该模式将成为解决问题的捷径。
时至今日,重复发明轮子绝对谈不上是什么好事。

模式并不一定是某个问题的终极解决方案,使用模式也不会让你的代码更好,或执行速度更快。
正确应用模式只能够保证解决问题,对待模式要有一颗平常心,不要花费很大的力气去让设计符合某个模式。

首先解决问题,随后编写代码。——John B. Johnson

若问题领域需要数百个实体来表示,数千个业务规则要满足,那么久需要一些规范来约束组件的设计。
这些规范分为两类:设计模式和架构模式。
设计模式就是针对某种重复出现的软件设计问题提供的通用解决方案。
而架构模式则是更大规模的模式,用来描述系统的组织结构,并制定每个子系统的职责。

从单纯的技术角度来看,很多号称复杂的系统实际上并没有遇到技术难题。
之所以给人复杂的感觉,是因为系统所处的领域天生就比较复杂。
通常难点在于为业务创建合适的软件模型,而不是具体的实现过程。
若有了良好设计的模型,那么基本上就可以随意的用合理的代价处理任何程度的复杂性。

业务逻辑通常是一系列的if-then-else语句,一把会手工映射到业务对象的方法上,
其产物通常叫做领域逻辑或业务逻辑。
一个真实系统中,我们经常会面对数以千计的业务规则映射到数百个业务对象上。

真正的敌人是重复,而不仅仅是代码重复。
一个良好设计的系统不会在多个地方(包括代码,文档,单元测试或用例)重复同一个功能。

实现领域模型的一个主要障碍是对象和关系模型数据库之前的不匹配。
领域模型是一个面向对象的设计,和数据库或其他应用程序的约束完全无关,
而今受限于其建模的业务流程,这意味着同样的领域建模可以重用于其他需要同样逻辑的任意场景中。
模型是和业务相关的,且仅和业务相关。
或早或晚,系统将要开始实现,数据也需要持久化,因此你需要将模型映射至一个活多个数据库系统中。
从应用程序角度来看,领域模型就是逻辑上的数据库(为各种数据存档),不过这个“数据库”仅仅是个对象模型,并没有提供关系型接口。
但创建这个关系型接口是必不可少的,且创建代价非常高。

业务逻辑是系统的核心,不过并不是整个系统。
每种做法都有其优势和劣势,各种模式的取舍并不像每个人都能看懂的菜谱或算法那样简单,这也正是架构师存在的意义。

在非技术的上下文中,我们将服务定义成一个业务相关的操作,应用程序中的每个客户都可以重复的执行,
这些客户包括用户、程序中的其他服务以及业务逻辑中的其他部分等。

高层次的思考,必须借助高层次的语言。——Aristophanes

分层系统中中间层的设计有两个选择,应用程序的数据可以通过强类型DataSet等表格状容器保存,也可以选用更加抽象的对象模型。
无论何种做法,最终都需要将数据持久化至关系型数据库中保存,也就难免造成阻抗失调情况。
领域驱动设计,随之而来的就是需要需要以更加概念的方式操作数据,数据库的角色也不可避免的降低成了一个持久化工具。
我们曾经使用多年的、作为存储过程简化封装的数据访问层很快过时并被替代,数据访问层正在不停的向着O/R映射层演化。

用户会嘲弄般的笑道:“太酷了,这跟我们以前说的一模一样,不过不是我们现在想要的。”
行为驱动开发让开发者关注于用户的真实需要,也能帮助用户更快的找到他们的真实需要。

设计软件有两种方式:一种是让其足够简单,从而避免错误。另一种是让其足够复杂,借此掩盖错误。——C.A.R. Hoare
悲观者抱怨风,乐观者期待风的结束,现实主义者却借风杨帆远航。——William Arthur Ward

继承是为了多态,而不是重用。
不要仅为了重用而使用继承,最好是编写一个新的类来满足需求,而不是继承某个原本不是完成此工作的现有类。

Donald Knuth曾说过,过早的优化是所有软件罪恶的根源。
我们将改说法更进一步——不要优化系统,而是让其尽可能的灵活面对改进和扩展,仅在系统完成之后,再关注纯粹的优化。

若你很在乎某个系统特性,那么在设计开始前就应考虑它,安全性和可测试性也是如此。

一些墨菲法则:
1.
为一个赶不上进度的软件项目增加人手,只能让其更加落后于进度。
程序的复杂性一直增加,直到负责维护的程序员力不从心为止。
若建筑师按照程序员写程序那样造房子,那么史上出现的第一只啄木鸟也许会毁掉整个文明。
2.
真正的程序员从不添加注释。若代码难以编写,那么也会难以阅读。
程序员90%的错误来自于其他程序员提供的数据。
编写符合需求的程序和在水面行走一样简单,前提是需求已确定,水面已结冰。
3.
软件可以正常工作的概率与其所需要的代码行数成反比。
Bug出现的几率与正在查看该软件的人数及这些人的重要程度成正比。
专家就是那些最后一刻赶到,陪众人一起挨骂的人。
4.
一个可以工作的复杂系统一定是始于一个可以工作的简单系统。
人们会一直增加软件的可靠性,直到提高的成本已经大于处理错误的代价为止。
在理论上,理论和实践之间没有差别;不过在实践中,二者截然不同。
5.
提供了接口说明文档的软件模块中仍有一些未在文档中提到的功能。
足够好并不是足够好,除非项目有明确的期限。
仅观察铁轨永远都不能告诉你火车行驶的方向。
6.
唯一完美确定的科学就是事后诸葛。
在将某事放在内存(记忆)中时,不要忘了存放的位置。
你永远没时间正确的做一件事,但总是有时间去重做。
7.
不怕用户没有想法,就怕用户的想法错误且不切实际。
若让软件处理了所有可能的愚蠢错误,那么也会同时造就出更加愚蠢的用户。
若想编写出一个连傻瓜都能用的软件,那么也就只有傻瓜才想使用了。

业务层:事务脚本模式,表模块模式,活动记录模式,领域模型模式
服务层:远程门面模式,数据迁移对象模式,适配器模式,面向服务架构
数据访问层:插件模式,控制反转模式
表现层:模型-视图-控制器模式,模型-视图-展示器模式,Presentation Model模式,选择用户界面模式

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant