可塑软件和系统设计






2.60/5 (2投票s)
实施敏捷软件开发
"简洁是极致的优雅。"
Leonardo da Vinci
引言
关于敏捷软件开发的好处以及如何使其奏效的讨论一直很多。这些都是很好的流程和组织方面的讨论,但没有人真正讨论如何实际设计敏捷软件。我将介绍一种我称之为“可塑性系统架构”(MSA)的架构,它为系统架构师和开发人员提供了一个基于敏捷软件开发概念构建的物理框架。与构建业务应用程序的其他框架相比,MSA框架具有许多优势。其中一些优势包括:
- 使系统能够快速轻松地适应不断变化的业务需求
- 最大程度的代码复用,最小化浪费
- 降低系统复杂性
- 减少数据冗余
- 降低开发时间和成本
- 提高质量,减少bug,缩短测试时间
- 提高性能、可伸缩性、可靠性和健壮性
这些都是很棒的优点,对吧?但它们是如何实现的呢?这一切都始于一些基本的设计原则。
设计原则
可塑性软件架构的核心是指导系统物理设计的底层原则。我将讨论这些原则以及如何利用它们来构建典型的MSA系统。
关键概念
- 代码与内容分离
- 将流程从代码中剥离
- 追求简洁和高效
- 确保数据完整性
- 创建表驱动设计
- 了解你的数据(哪些是静态的,哪些是动态的)
- 定义高效的数据访问方法和标准
内容与代码分离
将代码与内容分离的基本思想是将业务与编程分开;区分“什么”和“如何”。解耦工具与任务。例如,不要仅仅构建一个每日发送发票传真的解决方案。构建一个可以每日运行的批量发送文档的方式要好得多。细微的区别在于,第一个方法只发送发票,而第二个方法可以发送任何文档或报告,其中自然包括发票。在这个例子中,“代码”是发送文档的能力。“内容”是实际的发票。通过审慎地区分工具或功能与业务内容,可以更容易地重用技术,也更容易进行更改,因为你不再受限于特定的实现或流程。
这个概念也可以扩展到数据的持久化。在这个类比中,数据是代码。内容是数据供用户或其他系统消费的格式。将数据存储为已格式化的形式通常是个坏主意,因为它会给将其“取消格式化”以用于不同系统带来麻烦,而且格式化数据通常占用更多存储空间。
如果格式包含在数据中,为其他系统准备格式化数据将是一个两步过程。首先,你必须去除格式,然后根据特定应用程序重新格式化。如果数据以未格式化的方式存储,不仅占用的存储空间更少,而且为不同系统格式化也只需一个步骤,因为不必先去除格式。一个例子是电话号码。存储格式化的电话号码可能看起来像 (905) 555-1212,而仅存储数据则只包含数字 9055551212。下面在“简洁性”部分将更详细地讨论这一点。
将流程从代码中剥离
计算机擅长将数据处理成信息、存储和检索信息,但却不擅长解决问题。人类擅长解决问题,但不擅长计算数字。我们的大脑计算机在数据存储和检索方面也可能不一致。设计你的计算机系统来做它们最擅长的事情,并将解决问题留给人类。
当千年虫危机迫近时,这对我来说意义重大。人们都在谈论电梯失灵、街道上污水倒灌、大面积停电和蝗灾。过去十年我一直在构建计算机系统,我知道这些担忧可能有些道理。我的妻子,她不太懂电脑,对所有这些担忧都有一个简单的答案。她说:“这就是为什么有人的存在。”人控制机器,而不是反过来(我们活过了1997年8月29日)。
人通常是灵活的;计算机和软件本质上不是。让人来控制流程。计算机、软件和系统只是帮助人们完成工作的工具。我们都见过将流程内置到系统中,结果在实施之前就已过时的情况。通常,用户对新流程的第一反应是想办法绕过它们。不要指望你的用户会按照你的意愿使用系统,他们通常比这更有办法。
与其将流程内置到系统中,不如专注于构建数据完整性,让用户控制适合他们的流程。尽可能移除业务规则,以保持系统的简单性和灵活性。设计系统是为了赋能用户,而不是限制他们。不要依赖流程来确保数据的良好。在数据库层面使用数据完整性,以防止由于不奏效的流程导致坏数据进入系统。
追求简洁和高效
讽刺的是,构建更复杂的解决方案通常比构建更简单的解决方案更容易。几乎总是,更简单的解决方案是更好的。更简单的设计需要维护的组件更少,代码行数更少,bug来源也更少。为了创建更简单的设计,需求会被提炼成实际需要的东西,从而构建出更灵活、更易于重用的组件。设计一个简单的解决方案可能需要更长的时间,但从长远来看,在实施、维护和重用代码方面,你将节省时间和金钱。
当一个解决方案正在演进时,我喜欢做我称之为“收敛测试”。如果解决方案在开发过程中变得越来越复杂,并且解决问题的修复次数不断增加,那么该解决方案正在发散。这是麻烦的迹象。复杂性正在滋生更多的复杂性,你离最佳解决方案越来越远。是时候采取不同的方法了。如果解决方案正在消除复杂性以及潜在的问题,那么该解决方案正在向最佳答案收敛。
例如,考虑一个简单的电话号码。大多数系统将数据存储在一个大约20个字符的字符字段中。因此,只有特定范围的字符是有效的(0到9,括号,连字符)。其他字符需要被阻止存入电话号码字段,否则有人会利用它来存储他们客户狗的名字,如果他们有机会的话。电话号码不仅有一组有限的有效字符,而且字符的位置也很重要。
一种解决方案是假设数据库只接收有效号码。每个数据访问点都必须确保数据是正确的。在面向服务架构的世界里,这可能是一个挑战。数据可以来自许多不同的来源。遗留数据转储、Web应用程序、Web服务和Windows应用程序都可以混合在一起,每种方法和服务都需要有自己复杂的验证方法;这是一个编码维护和测试的噩梦。这也不是一个好的解决方案,因为数据库在设计上不应该允许坏数据进入,而且它会暴露于其他系统提供的任何逻辑。
一个更好的解决方案是将一些数据接受代码放在数据库触发器上,用于插入和更新,以消除或拒绝坏字符和格式。这将保护数据库免受坏数据的影响,并提供一个单一的逻辑点来解析电话号码。这会起作用,但对于不同的电话号码长度(只有分机号,没有区号等),数据库触发器的逻辑可能会变得复杂。在SQL Server的世界里,TSQL编程对于字符串解析和验证来说可能很麻烦。SQL Server 2005提供了使用用你选择的语言编写并在Visual Studio中编译的自定义函数的能力。这效果出奇地好,但还有一个更好、更“收敛”的解决方案。
数字就是数字
电话号码就是这样,数字加上特定的格式。北美电话号码看起来像 (412) 555-1212。这实际上是数字 4125551212 应用了格式。通过将代码或数据(4125551212)与内容((412) 555-1212)分离,我们得到了数字和格式。格式对于十位数字是固定的,所以我们不必存储它。数字仍然可以根据需要应用格式来呈现给用户,但没有必要存储格式化的数字。它不包含任何价值或额外信息。格式化数字只是为了让它更容易阅读。
如果我们将在数字类型字段中存储电话号码,所有有效的字符存储问题都将消失,因为数字字段本身只能接受数字数据类型范围内的数字。如果你真的想确保数据有效,你可以检查数字范围(大于零,小于9999999999)作为电话数据字段的约束。另一个很大的好处是,数字类型的数据存储需求可以比基于字符的存储小得多,甚至可能只有三分之一。(有关更详细的信息,请参阅我的另一篇文章“SQL Server 2005 中的电话号码”。)
电话号码存储解决方案正在收敛。我们消除了每个服务的复杂数据验证例程和复杂的服务器端解析来接受数据。我们将数据存储需求减少了三分之一。这是一个优雅、简单的解决方案。
在《可塑性软件与系统设计 - 第二部分》(即将推出!)中,我将继续讨论设计原则。
历史
- 2007年10月30日:初次发布