设计:需求在架构上的体现






4.16/5 (8投票s)
本文试图描绘架构、需求和设计这三者之间的关系。
摘要
本文试图描绘架构、需求和设计这三者之间的关系。
本文围绕“设计是需求在给定架构上的投影”这一概念展开。它尝试在拥有架构和相关需求的情况下,通过图形/数学方法来创建设计。
本文探讨了上述概念的几何表示,然后制定了代数技术来更详细地探讨这些概念。
给定一个诸如登录这样的需求,它接收用户名和密码,并有一个验证给定组合的操作 authenticate。该需求可以在一个具有 Web 界面的架构上实现,包括业务层、数据访问组件等。设计可以被派生为一种投影或阴影。这种投影机制构成了本文的基础。本文试图描述这种投影机制,并说明如何使用它从一组需求和设计中推导出架构。
本文首先定义了文章中使用的术语,然后详细介绍了设计投影的核心思想,这是本文的中心主题,并展示了其使用所带来的结果。随后将对该主题进行数学处理,使用集合和群。文章最后讨论了未探索的领域和潜在影响。
引言
软件开发由三个基石驱动:需求、架构和设计。
需求定义了问题的“是什么”。需求定义了应用程序需要做什么。应用程序的架构是蓝图;它定义了问题将如何总体上被解决以及有哪些参与的机构。架构是一个宏观结构,概括了需求将如何实现的机制。设计描述了一个特定需求将如何实现。它利用架构中描述的蓝图,并使用需求来创建参与的组件。
考虑一个例子,需要创建一个应用程序,该应用程序可以通过 ID、姓名或所属部门来搜索用户。这个需求有三个用例:
- 根据用户 ID 搜索用户
- 根据用户名搜索用户
- 根据部门搜索用户
在此示例中,我们假设将有一个基于 Web 的应用程序,包含 UI 层、实体层、业务层、数据访问层和一个数据库表。
每一层都有明确的任务和目标,例如,UI 层负责获取用户输入并将其转换为实体。它应该调用业务层的相关方法并显示返回的结果。这一层具有以下职责:
- 捕获用户输入
- 将用户输入转换为实体
- 执行业务结果
- 显示结果
其他层也将有类似的明确定义的职责。
一旦应用程序的需求和架构确定下来,只要有合适的建模方法,应用程序的设计就可以被认为是算法任务。
考虑使用“捕获用户输入”的架构来设计“根据用户 ID 搜索用户”的需求。这清楚地表明,用户 Web 前端应该能够通过网页捕获用户 ID。
在本文中,我们将讨论上述设计方法的图形化和非图形化形式化。
一些常用术语
在深入探讨设计投影机制之前,我们将回顾本文使用的一些常用表示和术语。
需求 – 在本文中,需求被定义为将在其上执行给定操作的一组变量。需求源自用例,本文将对其进行详细说明,直到创建实体变得微不足道。需求有两个维度:表示和操作。
考虑需求“用户可以保存到数据库”。这个需求可以分解为表示 user 和操作 Save。在本文接下来的部分,将详细介绍其数学表示。
架构 – 在本文的语境下,架构是分层架构方法。每一层都将有明确定义的职责。架构将有一个有序的执行控制流。
设计投影
现在我们深入探讨本文的核心,即理解设计是需求在架构上的投影。本节将通过图形方式展示这一概念,并进行任意的简化,以突出核心思想,同时忽略其他细节,例如架构应有多详细。这些话题将在文章的后续部分讨论。
让我们考虑一个非常简单的应用程序需求集:
- 将用户保存到数据库
首先,我们将在既定机制下详细说明需求,然后尝试以图形方式描绘它们。
- 需求 – 根据一些用户参数将用户保存到数据库
- 表示 – 用户:用户名、名、姓、密码
- 操作 – 保存
如图 1 所示,我们对此进行描绘。
现在,让我们为此使用一个简单的基于 Web 的应用程序架构,包含以下层:
- 用户界面
- 业务层
- 数据访问层
- 数据库
每一层为了获得可触及的组件所承担的责任如下。架构的可触及组件是可以用编程结构(如方法、类或数据库组件)直接解释的陈述。
- Web 层 – 这一层形成了用户界面。它提供了一个基于 Web 的 UI 来输入和输出数据。它将输入转换为业务实体。可触及的组件是:
- 一个 Web 表单
- 调用业务层的机制
- 业务层 – 这一层调用数据库层。可触及的组件是:
- 调用数据库层的机制
- 数据访问层 – 这一层调用数据库存储来保存或检索数据。
- 数据库访问逻辑
- 将实体转换为数据库可理解的结构
- 数据库 – 这是一个关系型数据库管理系统 (RDBMS),用于存储数据。它将具有以下可触及组件:
- 数据库表
- 实体 – 一种传输用户输入的机制,具有可触及组件:
- 传输实体
有人可能会认为,一旦定义了可触及组件并且可用了精确的需求定义,设计就可以被轻松创建。这种设计创建机制被称为投影,原因将在示例进行过程中变得清晰。
设计只是一组具体的、可触及的项。有些可触及项受表示的影响(如实体和数据库),而另一些则受操作或两者的影响。影响可触及项创建的部分也可以被定义为架构的一部分。
因此,设计是架构的图像,其中确切的功能细节的差距由需求填补。
应该注意的是,尽管出于良好的架构实践的考虑,有理由将可触及组件分层,但本文将这些决定视为任意的。
这种机制被称为投影,因为需求通过架构的可触及项被投影,从而形成设计。考虑一个类比:需求是给定颜色的光,架构是形状,设计然后形成显示器上的彩色投影,如图 3 所示。
让我们进一步探讨这个示例的一部分,其中用户保存需求被投影到 Web 层以形成设计可触及项。
如本更详细示例所示,设计是从一个提供指导方针的抽象架构中创建具体结果的过程。为了保存用户,我们需要满足捕获五个属性作为输入的那些需求。架构提供了一个通用指导方针,即应该有一个 Web 表单。设计侧重于这两个方面,并投影出应该存在的用于捕获这五个属性的 Web 表单。
到目前为止,在本文中,架构被定义为任意的。这样做是为了突出投影技术。我们将快速看一下分层架构的概念定义以及与本文的关联。
分层架构表示为一组层,每层都有明确定义的职责。层在执行流方面是部分排序的。职责是一个明确定义的、可触及的组件。这个可触及的组件是一个抽象的概念,它的存在会产生设计项。这些明确定义的可触及组件可以被投影,并在投影过程中受到需求表示和/或需求操作的影响。
投影代数
本讨论将现在把前面部分讨论的概念形式化为数学形式。讨论将从各种元素(如架构、需求和可触及项)的符号开始。然后将定义操作来成功建模投影操作。
到目前为止,我们已经讨论了两个基本概念:需求和架构。让我们用数学术语来形式化它们的表示。
表示 – 表示是物理属性。表示的例子有用户 (User)、雇员 (Employee) 和部门 (Department)。它们等同于实体。应该注意的是,在讨论中,一个表示是原子的(如年龄)还是复合的(如用户(姓名、年龄、性别))并不重要。在本文中,集合 E 将用于表示一组表示,表示的单个元素将用 e0、e1 等表示。
操作 – 操作是一个可计算的 P 函数,它需要表示作为参数。例如,Save 是一个操作,它需要一个 User 表示。在本讨论中,一组操作将用 O 表示。单个操作本身将表示为 o1、o2 等。应该注意的是,操作的定义可以被解释为封装表示,但是对于本讨论,表示将被分开处理。这样做是因为操作的目的是定义一个动词,即过程或要对表示执行的预期步骤。
需求 – 需求是由表示和操作的组合创建的元组集合。需求由 R 表示。需求是表示域和操作的元素的任意组合。
R ={(e,o) | e e E and o e O}
例如:{(User, Save), (User, Update)} 是一个需求集。
可触及项 – 可触及项被定义为一个原子任务,该任务可以作为执行所请求操作的一部分来执行。然而,可触及项缺乏确切的意图细节,因此只能有一个通用的算法来表示它。可触及项的例子包括使用 Web 表单接收用户输入、操作用户输入。本文用 T 表示一组可触及项。应该注意的是,在本次讨论中,可触及项与表示和操作的关系将不予考虑。
层 – 层是可触及项的偏序集,它定义了要执行的职责。层由可触及项的元组表示。层由 L 表示。例如:
WebLayer = (Accept user as input, validate user, call the save method)
分层架构 – 分层架构是层的偏序集,它描述了总体控制流。架构用 A 表示。例如:
Architecture = (WebLayer, BusinessLayer,DataAccessLayer,Database)
架构可以通过用可触及项的元组替换层的元组来表示。可触及项的元组可以表示为 A[l],其中 l 是层名,例如:
Architecture[WebLayer] = (Accept user as input, validate user, call the save method)
应该注意的是,分层架构可以被解释为可触及组件的偏序,并且任意层的存在只是为了方便对其进行分组。
设计项 – 设计是一个可触及项,其中意图的细节通过需求的析取来描述。设计本质上是填充在创建可触及项时所缺乏的确切问题描述细节周围的空白。
设计项是需求在层的可触及项上的投影操作。投影操作用 x 表示。投影操作会在给定层上产生多个设计项。
考虑以下内容
令 e 为表示,o 为操作,tl 为层 l 中的可触及项,则需求表示为 (e,o),投影项为 (e,o) x tl,并表示为 ((e,o),tl)。
这被解释为执行任务 t 对表示 e 进行操作 o 的设计项。设计项表示为 d。
例如,如果 e 是 User,o 是 Save,t 是 accept input,则设计项可以被解释为接受用户输入的 accept input 来保存。
设计 – 设计被定义为需求在架构上的投影。它是各个层中的设计项集合。
D = R x A
D = {((ei,oi),tlk) | (ei,oi) e R and tlk e A[l]}
应用
本文的其余部分将详细介绍上述结果的推论和可能的应用领域。这些是未探索的领域,只讨论了这些领域的初步方法。
设计 – 本文的研究成果主要与设计经验和作者的风格相关。这是一种我们成功设计了许多项目的技术。
设计自动化 – 本文提出的想法非常抽象。通过应用约束机制,可以创建设计自动化。例如,有人可能会认为只有 n 种可能的操作,如 Create、Update、Read、Delete、Sort 等,可以生成通用算法。设计表示也可以分解为基本类型。利用这些信息,可以提出一个产生设计的解决方案。然而,这需要对符号和表示进行形式化。它还将需要对可触及项进行更深入的探索。
估算 – 本文使用的一些定义可以用来估算编程结构的数量,例如:
- 类数量 = n(R) n(A)
- 方法数量 = n(E) n(O) n(A)
其他感兴趣的结果也可能可计算,例如什么可以定义一个 `static` 类等。
其他架构风格 – 本文主要关注分层架构,在其他风格中应用建议的技术是一个值得探索的领域。
结论
本文提出的想法尚处于萌芽阶段。它们是作者经验的形成和建模。人们坚信它们可能构成一种新的设计方法。
历史
- 2009 年 4 月 23 日:初次发布