演化架构和紧急设计:利用可重用代码,第1部分

简介:识别出代码中的惯用模式后,下一步是积累和使用它们。理解设计与代码之间的关系有利于发 现可重用的代码。本期的 演化架构与紧急设计 探索代码与设计的关系,使用表达性强的语言的重要性, 以及重新考虑抽象风格的潜在价值。

通过本 系列 的前几期,您已经知道,我的观点是软件的每个部分都包括可重用的代码块。例如,公 司处理安全性的方式在整个应用程序甚至多个应用程序中可能都是一致的。这就是我所说的 惯用模式 的 实例。这些模式代表对构建软件特定部分时遇到的问题的常用解决方案。惯用模式有两种类型:

技术模式 —— 包括事务、安全性和其他基础结构元素。

域模式 —— 包括单个应用程序内或跨多个应用程序的业务问题的解决方案。

在前几期中,我将大部分注意力放在如何发现这些模式上面。但是,发现模式之后,必须能够将它们 作为可重用代码加以利用。在本文中,我将研究设计与代码之间的关系,特别是表达性强的代码如何使模 式的累积变得更容易。您将看到,有时候通过改变抽象风格,可以解决一些看似难以解决的设计问题,并 且可以简化代码。

设计即代码

早在 1992 年,Jack Reeves 写了一篇题为 “What is Software Design?” 的思维敏锐的论文。在 此文中,他将传统的工程(例如硬件工程和结构工程)与软件 “工程” 作了比较,目的是为软件开发人 员拿掉工程这个词上的引号。这篇论文得出一些有趣的结论。

Reeves 首先观察到,一项工程最终交付的成果是 “某种类型的文档”。设计桥梁的结构工程师不会 交付真正的桥。其最终成果是一座桥的设计。然后,这份设计被传到一个建筑团队手上,由他们来建造真 正的桥梁。对于软件而言,类似的设计文档是什么呢?是餐巾纸上的涂鸦、白板上的草图、UML 图、时序 图还是其他类似的工件?这些都是设计的一部分,它们合起来仍不足以让制造团队做出实际的东西来。在 软件中,制造团队是编译器和部署机制,这意味着完整的设计是源代码 — 完整的 源代码。其他工件只 能为创建代码提供帮助,但是最终的设计成果还是源代码本身,这意味着软件中的设计不能脱离源代码。

Reeves 接下来的观点是关于制造成本的,制造成本通常不算工程的一部分,但是是工件的总体成本估 计的一部分。构建物理实体较为昂贵,这通常是整个生产流程中最昂贵的部分。相反,正如 Reeves 所说 的:

“...软件构建起来很便宜。它廉价得简直就像是免费。”

记住,说这句 话的时候,他正在经历 C++ 编译和链接阶段,这可是非常消耗时间的。现在,在 Java 领域,每 时每刻都有团队冒出来实现您的设计!软件构建现在是如此的廉价,以至于几乎可以忽略。相对于传统的 工程师,我们有着巨大的优势。传统工程师肯定也很希望能够免费地建造他们的设计,并进行假设分析的 游戏。您能想象吗?如果桥梁工程师能够实时地试验他们的设计,而且还是免费,那么造出来的桥梁将会 是多么的精致。

制造是如此容易,这就解释了为什么在软件开发中没有那么高的数学严密性。为 了取得可预测性,传统工程师开发了一些数学模型和其他尖端技术。而软件开发人员不需要那种级别的严 密分析。构建设计并对其进行测试,比为其行为构建形式化的证明要来得容易。测试就是软件开发的工程 严谨度(engineering rigor)。这也导致了 Reeves 的论文中的一个最有趣的结论:

如果软件 设计相当容易被证实,并且基本上可以免费构建,那么毫不奇怪,软件设计必将变得极其庞大而复杂。

实际上,我认为软件设计是人类有史以来尝试过的最复杂的事情,尤其是在我们所构建的软件的 复杂性不断攀升的背景下。考虑到软件开发成为主流也才大约 50 年的光景,通常的企业软件的复杂性已 经令人瞠目。

时间: 2024-10-15 05:18:54

演化架构和紧急设计:利用可重用代码,第1部分的相关文章

演化架构和紧急设计: 利用可重用代码,第2部分

简介:在使用 演化架构和紧急设计 前几期描述的技术发现 代码中的紧急设计之后,下一步您需要一 种获取和利用这些设计元素的方法.本文介绍了两种用于获取惯用模式的方法:将模式作为 APIs 进行捕 捉:使用元程序设计方法. 本 系列 的前几期主要关注紧急设计中显而易见的第一步:发现 惯用模式.发现惯用模式之后,您要 用它做什么?该问题的答案就是本期重点,本文属于由多个部分组成的系列文章的第二部分.第 1 部分 -代码与设计的关系探讨- 介绍了一种观点的理论基础,这种观点就是软件中的设计真正是指解决方

演化架构与紧急设计: 积累惯用模式

简介: 本期将之前的 演化架构与紧急设计 文章中的紧急设计概念与一个案例研究相结合,展示如何 发现.积累和利用代码中意料之外的设计元素.一旦理解了如何识别设计元素,便可以使用该知识改进代 码的设计.紧急设计使您可以发现代码中意料之外但是已成为代码库重要部分的那些方面. 在本系列第一期 "研究架构和设计" 中,我曾断言每个较大的项目都包括超出所有人意料的设计元 素.详细考虑一个问题时,常常会发现有些本以为困难的事情实际上却更容易,有些本以为容易的事情实 际上却更困难.随后的几期则演示了发

演化架构与紧急设计:研究架构和设计

演化架构(evolutionary architecture)和紧急设计(emergent design)都是将 重要的决策推迟到最后责任时刻(Last Responsible Moment)的敏捷技术.在本 系列的第一期文章中,系列作者 Neal Ford 将定义架构和设计,然后指明了一些 关于整个系列的基本概念. 软件架构和设计一直都没有一个明确的定义,因为软件开发作为一门学科,尚 未完全理解其中的复杂度和内涵.但是要发表关于这些主题的论述,您必须从某 个位置开始.本系列涉及演化架构和紧急设

演化架构与紧急设计:对设计进行重构

在 "测试驱动设计,第 1 部分" 和 "测试驱动设计,第 2 部分" 中,我 介绍了测试如何为新的项目实现更好的设计.在 "组合方法和 SLAP" 中,我讨 论了两种关键模式 - 组合方法(composed method)和单一抽象层原理 - 为您 的代码结构提供了整体目标.需要牢记这些模式.一旦拥有了一个现有软件项目 ,那么发现和利用设计元素的主要方法就是进行重构.在 Martin Fowler 的经典 著作 Refactoring 中,他将

演化架构和紧急设计: 演化架构

简介: 这一期的 演化架构和紧急设计 将会解决演化架构相关的各种主题,包括设计和架构之间的重 要区别(以及如何区分两者),您在创建企业级架构时遇到的某些问题,以及面向服务的架构中静态类型 和动态类型的区别. 在 本系列的第一期 中,我推荐了软件世界中的一些架构定义.无论如何,如果您已经阅读过本系列 ,您会注意到我花费了大部分时间在设计上.我之所以这么做是基于以下几个原因:首先,在当前紧急设 计尚未被广泛关注时,软件世界里存在很多架构定义(良莠不齐):其次,在设计方面很多问题都有具体 的.不受环境

演化架构与紧急设计: 通过指标进行紧急设计

简介: 软件指标可以帮助您寻找代码中隐藏的设计元素,让它们能够成为惯用模式. 演化架构与紧急设计 的这一期讲解如何使用指标和可视化发现被复杂性掩盖的重要代码元素. 紧急设计的难题之一是寻找隐藏在代码中的惯用模式和其他设计元素.指标和可视化有助于识别代码的重要部分,从而提取出一些设计元素.本文主要讨论两个指标,圈复杂度(cyclomatic complexity) 和传入耦合(afferent coupling).圈复杂度度量方法的相对复杂度.传入耦合表示有多少个其他类使用当前类.本文要介绍显示和

演化架构和紧急设计: 使用 DSL

简介:至今, 演化构架和紧急设计 主要关注技术模式的紧急设计,本期将介绍使用特定领域语言 (DSL)捕获 领域惯用模式.系列作者 Neal Ford 用一个例子说明了该方法,显示了这种获取惯用模式 的抽象样式的优势. 惯用模式可以是 技术也可以是 领域.技术模式为常用的技术软件问题指出解决方案,例如在应用程 序(或应用程序套件)中怎样处理验证.安全和事务数据.前几期主要关注获取技术惯用模式所用的技术 ,例如元程序设计.域模式关注的是如何抽象常见业务问题.而技术模式几乎出现在所有的软件中,域模 式

演化架构与紧急设计: 组合方法和 SLAP

简介:如何在陈旧的代码库中找出隐藏的设计?本文讨论两种对于代码结构很重要的模式:组合方法 和单一抽象层.对代码应用这些原则有助于找到以前隐藏的可重用资产,有助于把现有的代码抽象为成熟的框架. 在这个 系列 的前两期中,我讨论了如何使用测试驱动开发 (TDD) 帮助您逐步发现设计.如果从头开始一个新项目,这种方法的效果非常 好.但是,更常见的情况是您手中已经有许多并不完善的代码,在这种情况下应该怎么办呢?如何在陈旧的代码库中找出可重用的资产和隐藏 的设计? 本文讨论两个很成熟的模式,它们可以帮助您

演化架构与紧急设计: 语言、表达性与设计

简介:发现和积累惯用模式的能力对于紧急设计至关重要.对于设计而言同样十分重要的是代码的表 达性.在本系列文章的第 2 部分中,Neal Ford 将继续讨论表达性和模式的交集,通过惯用模式和正式 设计模式阐释这些概念.他用动态语言为 JVM 重构了一些经典的四人组(Gang of Four)模式,以说明 表达性更好的语言如何使您看到被透明度不佳的语言遮挡的设计元素. 本文是本系列文章的第 2 部分,旨在演示计算机语言的表达性(允许您专注于本质,而不是形式)对 于紧急设计的重要作用.意图(inte