| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
jopen
10年前发布

敏捷架构应用

原文  http://www.infoq.com/cn/articles/agile-architecture-applied


敏捷有适应性。什么时候以及如何应用架构取决于环境。本文首先解释了为什么是这样,然后说明了在敏捷环境中怎么样才能仍然给予架构足够的重视。适应性和对话是基本要素。

敏捷宣言十年前就已经问世,它的出现是对当时作为标准的计划驱动方法的一种响应。在计划驱动方法中,计划工作和开展工作是单独的步骤。编写好的计 划需要一个稳定的基础:明确的需求。因此,确保需求稳定是一个明确的要求。基于那些稳定的需求,可以创建一个同样稳定的架构,并随后实现。

事实上,这是相当困难的,因为人类天生就不是那样的。你们是否曾经参与过一个这样的项目,它开始的时候有一个定义良好的、完整的需求说明书,你们 带着它回到团队,可能在国外,并制定了一个刚好十八个月的计划,然后无需进一步的工作就可以开始满足客户需求?我们没有。客户会逐渐发现他们想要什么,开 发团队会发现如何创建它,而与此同时,环境往往也在变化。

因此,敏捷有一种不同的计划方法,它拥抱所有会为客户增加价值的变化。该方法没有提供构建“大设计(big design)”的基础,也让我们没有意愿构建这样一个设计,因为那样的设计很脆弱。这不是说架构不再重要,不过,它必须健壮,能够适应未来的变化。那究 竟上意味着什么?得看情况。还要提前做多少工作?够用就好。

敏捷架构应用

你是不是已经知道这些答案?在敏捷宣言宣告敏捷十年后的今天,你是不是希望我们现在可以更具体一点?是的,我们也是如此!而且现在就挺好,因为我 们的客户——我们组织内的业务方——期望值越来越高。成功不再是根据计划交付,而是要交付能够影响实际业务的软件。像“影响地图(Impact Mapping)”、“功能注入(Feature Injection)”、“用户故事映射(User Story Mapping)”等技术迅速普及;它们中的每一个方法都能帮助我们构建适当的产品。而为了构建适当的产品,具有有效架构的方法不能停止不前。由于架构是 一个涉及面很广的话题,所以为了讲得更清楚,我们将接下来要重点探讨的架构定义为软件架构:单个应用程序的架构。

架构?我们采用测试驱动开发,并编写整洁的代码。

采用测试驱动开发对代码设计非常有益。我们发现,它在我们由外向内工作时尤其有用,就像 TDD伦敦学校 所倡导的那样从验收测试向内。由外向内工作减少了增加各种if判断代码的趋势。而且,你测试类的交互方式,测试并不是在以最严格的方式应用单元测试时创建的。根据我们的经验,这些就是那些实际上可以为重构提供支持的测试,而不是障碍。

现在,如果你也编写漂亮整洁、可以与读者清晰沟通的代码,那么几乎可以肯定,你在细节上有一些非常好的东西。但整体上怎么样呢?你如何用文档记录通过代码不容易看出来的总体设计的方方面面?你如何讨论它们,并达成一致?有一些容易理解的“ 架构草图 ”是不是有好处呢?

敏捷架构应用

你可能不止一次绘制过草图,不同于我们在项目中所绘制的。那我们可以问一下,谁在场吗?架构师,领导,管理人员,还是你的整个团队?后续在哪里重新审视和修改这些草图?如果是这样,那对项目有价值吗?如果不是,什么妨碍了你?

在我看来,作为一个团队,创建并维护这样的资料是架构的基本组成部分。通过草绘架构并与所有参与编码的人进行讨论,可以将应用程序层面的关注点与 繁琐的细节联系起来。TDD提供了一种做详细设计决策的框架,但是架构活动才能帮助你创建健壮的软件。虽然几乎任何东西在白板上看起来都不错,但缺陷还是 会在代码中形成,告诉你架构模型还不够完善,或者不再完善了。

“层创(Emergence)”

有一个常见的误解,就是敏捷不需要特别关注架构;于是,它先期就同定义架构的文档一起被扔掉了。“ 敏捷宣言原则 ”中提到的层创概念被解释为自然出现。一个更好的解释是:我们一起逐步地做那件事。架构是一种团队活动和共同的理解,而不是一个从象牙塔中传递给团队的文档。

最好的架构、需求和设计源于自组织团队。

——敏捷宣言原则#11

层创属性(emergent property) ”的特点是,它不能脱离派生它的系统部分而存在。我们无法由它追溯到一个特定的部分,但它影响着系统的每一部分。例如,当你去除了分子,水就没有了流动 性。单个分子是不流动的,但水作为一个整体是流动的。类似地,没有应用程序和团队,也就没有(层创)架构。你无法指出一个决定架构是什么的架构师。但共享 的概念框架影响着团队的行为以及应用程序的样子。传统的流程中没有这种说法。在这里,我们再一次看到,敏捷真地带来了观念的改变,专注于人与交互。

那么还有专职的架构师吗?也许有,虽然与以前的角色不同。当与多个团队一起开发一个应用(或者是姊妹应用)时,有其他人关注全局问题有助于团队集中精力。 这样,架构师就将架构作为一个基本关注点,但他致力于服务团队,而不是向团队发号施令,或者比团队超前工作。他知道,如果他使团队等待一个完美计划的话, 他就没有价值了,而且他们可以通过实现架构来帮助他证明架构的合理性。他会实验和验证,通过“ 峰值(spikes) ”以及定期与团队成员一起编码。在架构会议上,他会不断地问团队,他们讨论的内容是否会与他们将来实际编写的代码一致。

可选项有价值

对变化有较好健壮性的架构是,在任何需要的时候都确实很容易变化的架构。这样的架构不会没必要地限制你的可选项。每当你做架构决策的时候,尤其是以后变化 会很难的决策,你就限制了你处理变化的能力。只有在知道为什么做那样的决策的那个特定时刻,你才能作难以变化的决策,并且要本着负责任的态度不断的寻找机 会延期决策。这就像在你的个人生活中:你会立即买一张音乐会的票,因为你估计很快就会卖光。但晚上与几个朋友在酒吧里聚会可能是最后一分钟才做出的安排。 此外,这意味着:循序渐进。不要让应用程序处理(尚且)不必要的事情,但要确保后续容易添加。换句话说,通过使架构具有可扩展性,减少变化需求。将“ 开放—封闭原则 ”应用到架构。在接下来的两节中,我们将更具体的进行描述。

简单——使未完成的工作最大化的艺术——是根本。

敏捷宣言原则#10

简单

循序渐进还意味着追求简单,简化到再进一步简化就会去掉重要的价值。这是说积极删除几乎没有价值的功能。它同样也关乎应用本身的结构。从清晰的架 构图到整洁的代码实现,在任何层面上都是越简单越容易理解。要把大量注意力放在组件布局上,并简化组件本身。简单的软件是有适应性的软件!

如何将应用划分成组件?正当你打开开发环境的时候,应用程序告诉了你什么?我希望是它所提供的功能,而技术和框架不是它十分关注的。Alistair Cockburn 几年前就建议 ,以同心圆方式分解比层叠方式更自然。使用这种分解方式的 架构模型 最近引起了人们的注意,并达到了有望成为新标准的程度。

敏捷架构应用

如果愿意,这样一种设计的内核可以始于应用程序提供的功能、应用程序特性或者用例,如购买旅行卡、更换旅行卡、取消旅行卡。遗憾的是,虽然这些特 性是客户所需要、应用程序所需提供的,但在许多应用程序中,要找出它们非常困难。我们希望将它们与它们所操纵的业务域实体区分开来。这样,我们就围绕业务 域把它们创建成一个单独的层。你会发现,内核周围有连接外部世界的接口。不只是连接用户界面,还包括连接数据库以及与其它系统互连的接口。你立马就会发 现,最有可能变化的东西容易调整了:新增一个数据库、一个移动用户界面、提供一个服务接口等等。

无一例外,所有的依赖都是指向中央的。借助 依赖注入 ,每一层都完全独立于其它层。外圈中的各种接口组件也不知道彼此的存在。

“有界上下文(Bounded contexts)”

我们就像上面这段时间刚刚讨论过的那样设计架构。我们已经体验到了许多好处,不过有时候还是不满意。随着应用程序的扩展和时间的推移,内核的体量 往往会开始成为我们的沉重负担。该模型基于这样一种假设,由于实体代表了业务规则——最好是企业范围内有效——所以它们很少会变化。正是这种稳定性使它可 以作为其它所有一切的基础。但仅仅是逐步实现业务规则,随着我们迭代增加特性,我们已经破坏了那种稳定性。企业的各个部门以及他们的系统通常也没有统一稳 定的业务实体定义;它们取决于环境,也会随着时间发展变化。

在某些时候,我们应该放弃一个统一内核的概念,转而采用来自领域驱动设计的概念“ 有界上下文 ”。一个将两个有界上下文分成两个独立模型的著名例子是“命令查询职责分离(Command Query Responsibility Segregation,缩写为 CQRS )。应用程序可以用多个类似的独立模型服务于不同的业务上下文。这些上下文是为了允许模型针对不同的——通常是组织方面的——原因以不同的速度变化。方便起见,我们必须打破它们之间的“二进制依赖(binary dependencies)”。

敏捷架构应用

Russ Miles建议我们那样做并转而采用简单事件进行组件间通信。一个人能够获得的自由非常有用,但它也是权衡的开始。例如,你是只想轻度解耦,还是准备好完全放弃利用交换强类型对象的优点,从而换取可提供的灵活性?

假如与主机的接口每年更新两次,而且日期完全无法预测。同时,企业几乎每个周都想更改他们提供的保险产品的业务规则,以便与市场机遇保持一致。你 大概会希望在不同的组件中处理这两个问题,它们之间不存在任何方向上的二进制依赖。但是,这两个组件是否可以同时依赖于介于它们之间的一个强类型接口,或 者只是通过一个没有明确模式的、非常松散的数据结构进行交互,以便提供你所需要的灵活性?你可以拥有灵活性,但那会使两个组件都更复杂,而且为了确保只将 兼容的组件投入生产环境,你需要进行更多的处理。

你发现自己在平衡灵活性和复杂性,而这种平衡很可能会随着时间变化。这使得将功能明智地分组成组件很重要,而且每当新需求出现时,要重新审视分组,保持对架构的持续关注。因此,在Russ看来,这既是一个模型,也是一个 过程工具 。他将其称为救生圈。

边做边学

当运用了我们讨论的技术,你的应用程序会是什么样子呢?我们不熟悉你的项目,也不相信象牙塔架构,所以我们不打算告诉你。它或许会反映你所面对的组织和约束。 Conway定律 有类似的描述,或许,那其实是件好事。

设计系统的组织……受到限制,产生的设计是对这些组织的沟通结构的复制

——M. Conway

因此,这就是我们送你上路的地方。从已知的规则入手:分割问题,寻求有限数量的、强内聚少依赖的组件。加上我们描述的敏捷原则:对变化持开放态度、团队精神、协作、层创、简单,最重要的是可用的软件。

让它成为你的思维方式,并且行动起来,不只是作为指定的架构师要如此,作为开发人员也要如此。沿着这条道路边做边学至关重要。问下自己,现在预先完成的工作有哪些部分团队已经可以不做,什么状况可以显示团队已经找到了更高效的满足需求的方式。祝你好运!

关于作者

敏捷架构应用 Wim Heemskerk 为团队实践敏捷提供帮助。他是一名敏捷人士、软件工匠和Stoosian。作为一名富有经验的变革推动者,他增加流程、技术和组织工作的一致性。Wim将 互补模型及其原则串联起来转化为日常行动。他致力于创建可持续的变革,就是人们常说自己创建和想要的那种。他还为其他探索敏捷、领导力、优秀软件和真正有 效的测试自动化的人提供支持。他的推ter账号是 @WimHeemskerk

敏捷架构应用 Minze Tolsma 是一名软件工匠,他对人们的工作和思考方式有浓厚兴趣。他愿意接受一切可以增加客户价值的方式。他坚信“身后一步(from one step behind)”的领导方式:保持灵活性,作为一名工匠,要设法完全了解所服务的企业,然后利用所有配备的工具行动起来。Minze为iPROFS(荷兰 哈勒姆)工作,是一名软件架构师和知识管理人员。你可以在 推terLinkedIn 上找到他。

查看英文原文:Agile Architecture Applied

</div>

 本文由用户 jopen 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
 转载本站原创文章,请注明出处,并保留原始链接、图片水印。
 本站是一个以用户分享为主的开源技术平台,欢迎各类分享!
 本文地址:https://www.open-open.com/lib/view/open1428625317500.html
敏捷 敏捷开发