是否应该在编写应用程序代码之前设计数据库?

Tho*_*ger 57 database-design

设计数据库的最简单和最有效的方法是什么?从我的角度来看,应用程序的数据存储设计有几个选项:

  1. 在编写任何应用程序代码之前,尽可能最好地设计数据库。这为您提供了使用基本数据结构的优势。在我看来,这样做的缺点是您将有很多更改作为应用程序细节,这些更改会影响整个应用程序开发周期中数据更改的内容/位置/方式。
  2. 在应用程序实现时设计数据库。当您在编写应用程序时需要一些数据库对象时,您可以与应用程序并行(按时间顺序)开发数据库。在我看来,优点是对数据库结构的更改较少。缺点是应用程序代码和数据库开发之间的时间和开发工作的划分。

根据您的经验,您认为最有成效和最有效的方法是什么?

gbn*_*gbn 43

除了其他答案...

首先捕获您的概念模型应该定义范围和要求。由此,您可以推导出逻辑和物理数据模型。

一旦这大部分是静态的,那么您就有了一个稳定的数据库来构建您的应用程序。这与您的第一个选择相反。

你的第二点将以一个凌乱、无法维护的泥球结束。数据模型永远不会被修复:如果你没有预先设计它,你将没有时间在发货前修复它。你会忙着一起破解事情。

对模式的细微更改、合并或拆分表、更改关系等都会发生,但在本地化的“孤岛”中,您的模型 + 基本设计将保持不变。

  • 稳定性很重要,因为表和视图名称、列名称、存储过程名称等都是数据库的公共接口。(迟早会有许多应用程序共享该界面。) (6认同)

Mar*_*ith 27

您将很难找到任何不运行某些敏捷变体的现代软件部门。相比之下,DBA 被困在黑暗时代,@RobPaller 的答案包含的那种想法仍然很常见。

修改数据库架构从来没有像修改代码那么容易,这就是为什么人们不愿意采用敏捷方法来开发和维护数据库。既然我们拥有以与开发人员类似的方式操作的工具和技术,我们绝对应该这样做。仅仅因为改变架构并不容易,并不意味着你不能也不应该。

我不是在提倡一种随意的数据库设计方法(见评论),只是一种更接近敏捷开发团队的方法。如果您是敏捷项目的一部分,您将不会对将来可能(或可能不会)发生的工作提出要求,因此设计您知道需要的东西,而不是可能需要的东西。

我想这让我投票支持您的选项 2,我怀疑我可能会发现自己对这个选项感到冷淡!

  • 敏捷和数据库确实伴随着警告。敏捷是 VLDB 的边界:可能没有足够的时间来验证和测试可交付成果之间对 10 亿行表的更改。由于缺乏远见,“敏捷开发”与“批发变更”不同 (4认同)
  • +1 对于您的答案的总体看法,但“修改数据库架构从未像修改代码那样简单”实际上取决于您拥有多少代码(以及它有多旧)。IMO 恰恰相反 (4认同)
  • 我将问题读作“尚无数据库的新应用程序”,而不是“需要更改数据库的现有应用程序” (3认同)
  • 不能同意更多:缺乏远见,但我认为这与问题无关。这不是关于您是否应该随意地进行设计,而是您的数据模型是否应该随着应用程序的发展而发展。VLDB 问题需要进行编辑,我将添加。 (2认同)

Rob*_*ler 12

您的逻辑数据模型应该有效地捕获应用程序的业务需求。您的物理数据库设计应该基于逻辑数据模型,并结合您作为 DBA 认为最大化 RDBMS 效率所需的必要更改。

如果您发现在应用程序的整个软件开发生命周期中必须对底层数据库设计进行大量更改,这表明两件事:

  1. 范围蔓延- 您允许在不适当的时间引入新需求。
  2. 业务需求不足- 您的数据建模师(或系统分析师)没有充分转换业务分析师的需求。这导致了不完整或不正确的数据模型来支持您的应用程序的要求。

话虽如此,一旦应用程序转入生产环境,必须返回并对数据模型进行迭代更改以支持应用程序或底层业务流程的自然演进并不少见。

希望这可以帮助。

  • 在项目过程中添加大量新需求并非“不合适”。这是你的开发方法应该支持和鼓励的东西 www.agilemanifesto.org/principles.html (7认同)

Eri*_*ikE 12

我有幸设计了几个中等复杂度的数据库,所有数据库都用于企业,具有各种前端,包括 Web、Access 和 C#。

通常,我已经坐下来提前制定了数据库模式。这对我来说总是最有意义的。但是,没有一个案例是我最终没有做出更改、添加新表或忍受困扰我并且基本上来不及修复的方面。

我不认为解决方法是先编写代码。而且我不认为问题是“业务需求不足”,或者至少不是一个本来可以完全解决的问题。用户不知道他们需要什么,我也没有能力让他们更努力地思考、变得更聪明、更有意识或更好地回答我的问题。或者他们争论,我被命令以某种方式做某事。

我构建的系统通常位于以前没有人涉足的新领域。我没有来自组织的支持、资源或工具来完成顶级设计专业人士的开发团队所能完成的工作,他们作为一个团队的报酬是我在其中构建东西的十倍两倍的时间。

我擅长我的工作。但是只有我一个人在“不做开发”的环境中做这件事。

综上所述,我越来越善于发现业务规则。我看到了第三种选择:

在设计数据库和编写任何代码之前,绘制粗略的屏幕以显示应用程序将如何工作。它们必须是手绘的,以防止任何人评论字体、大小或尺寸——您只需要功能。

使用透明胶片和纸片,您可以换入和换出,一个人是计算机,两个是非技术主题专家用户(两个是他们大声说话),一个人在那里做笔记和绘图的协调员让用户了解他们的思维过程和困惑。用户“点击”并拖拽写在盒子里,“电脑”更新屏幕,每个人都可以体验设计。您将学到在深入开发过程之前无法通过其他方式学到的东西。

也许我自相矛盾——也许这是更好的需求发现。但这个想法是先设计应用程序,而不是编写任何代码。我已经开始小规模地做这件事了,它正在奏效!尽管我的环境存在问题,但它帮助我从一开始就更好地设计了数据库。我了解到一列必须移动到新的父表中,因为有多种类型。我了解到工作清单必须具有并非来自集成订单系统的长期订单。我学到了各种各样的东西!

在我看来,这是一个巨大的胜利。


nvo*_*gel 10

大多数情况下,我会选择选项 2:与其他组件并行构建数据库。尽可能采用迭代方法并在构建每个部分时提供端到端功能。

这确实需要一定数量的项目纪律。每次更改数据库时都严格应用归一化(Boyce-Codd / 第五范式),以保持质量并且不会以临时和不一致的模型结束。尽可能积极地处理业务规则和伴随的数据库约束。如果有疑问,最好尽早强制执行约束 - 您可以随时将其取消。了解实现架构组件的顺序,以最大限度地减少技术债务。拥有一套所有开发团队都接受的良好的数据库设计指南。

当然,所有这些都需要与其他良好的开发工程实践齐头并进:持续集成、测试自动化以及至关重要的从数据库的角度来看,创建测试数据。应在每次迭代中完成实际大小数据的测试数据创建。

  • 您是否认为定义概念模型不需要一些预先思考? (2认同)

Rol*_*DBA 9

在建筑界,“形式追随功能”这个词是创造出来的,后来在建造高层建筑时坚持使用。这同样适用于数据库基础设施和应用程序开发。

想象一下编写一个应用程序,即时决定你需要一张桌子,那里一张桌子。当您的应用程序完成后,您将有大量表被视为数组。并排查看所有表格,这些表格肯定会显得没有韵律或理由。

不幸的是,一些开发人员商店会选择像 memcached 这样的东西,在 RAM 中加载数据(因此将其视为数据管道),并拥有一个数据库,如 MySQL 或 PostgreSQL,仅作为数据存储单元运行。

使用数据库的动机应该是正确看待它:作为 RDBMS。是的,关系数据库管理系统。当您使用 RDBMS 时,您的目标不仅应该是建立用于存储的表,还应该是用于检索。表之间的关系应该根据您想要查看的数据及其呈现方式进行建模。这应该基于数据的内聚性和完整性以及已知的业务规则。这些业务规则可以在您的应用程序(Perl、Python、Ruby、Java 等)或数据库中编码。

结论

我肯定会选择选项 1。它需要适当的规划、数据建模和持续的数据分析。然而,从长远来看,这应该最大限度地减少数据库更改。

  • @dportas:并非所有数据库更改,只有 RADICAL 更改。微小的变化是软件业务的一部分。但是在工作过程中必须将数据拆分到 2 个不同的数据库中是设计和捕获业务规则的失败。(这真的发生在我身上。 (3认同)
  • +1 表示“将 RDBMS 用作关系数据库而不是数组的位桶”-无论您采用哪种方法 (2认同)
  • @dportas:虽然这是真的(业务规则改变),但设计良好的数据库不会在迭代(或冲刺或其他)和另一个迭代之间发生根本性的变化,因为它反映了工作流程的所有相关数据结构。如果发生这种情况(根本性变化),则意味着捕获活动的业务规则失败。 (2认同)

Fab*_*ujo 9

我记住了以下规则:“您只能从数据库中获取您有数据要生成的信息”。所以,我先设计数据库,后设计代码。

为什么?无论我使用什么方法/语言/工具集,如果所有相关数据都经过精心设计并存储在数据库中,我可以检索它。无论是在 C#/Delphi/FORTRAN/COBOL/Assembly/VBA 还是 Crystal Reports 中;面向对象设计或事件/数据/任何驱动;敏捷或瀑布。如果数据在那里,如果我使用的工具可以连接到数据库,我就可以检索它。如果我可以选择本季度收入的订单,我就可以创建销售报告——即使我必须在 Assembly 上逐字节地编写它。

如果相关数据不存在,或者即使它存在但(非)结构化,我无法检索我需要的信息 - 如何对其进行编码?


Joe*_*Joe 9

我认为它应该在应用程序的任何实际代码之前完成,而不是在应用程序设计之前完成。

如果单独工作,我的典型工作流程是:

  1. 确定应用程序需要做什么
  2. 查看是否有任何任务可以分解为可重用组件
  3. 确定每个任务需要如何与数据存储交互——他们将询问数据什么样的问题,他们多久写一次,等等。
  4. 设计数据库,使其能够回答我们需要向它提出的所有问题,并且对于最常见的任务应该表现良好。
  5. 编写应用程序。

由于我经常作为团队的一员工作,而且我们在地理上分散(并且跨时区),因此我们倾向于召开初始启动会议:

  1. 确定应用程序需要做什么。
  2. 确定将应用程序分解为独立组件的优点
  3. 确定每个组件需要如何与其他组件交互。
  4. 就每个交互的 API 达成一致。

然后,我们回家,编写我们的部分,如果一个组件需要自己的本地存储,只要该部分的维护者保持其模块的 API 一致。主数据存储作为一个模块处理,有自己的 API,人们应该写入它。(在 DB 速度至关重要的情况下,API 是表定义,如果进行了更改,我们会使用视图或其他某种机制来呈现旧版本,直到所有模块都可以更新为止)


A-K*_*A-K 7

通常,这取决于;)

例如,假设我们有一个用 Python 开发并使用平面文件的小型工作原型,并且用户对原型的功能感到满意,那么我们需要做的就是将其生产化,使用 RDBMS 作为其后端. 在这种情况下,期望第一次就做对是合理的——问题很小而且定义明确。在这种情况下,预先设计是可行的。

另一方面,当我们在敏捷环境中发现需求时,我们需要几次迭代才能更好地理解它们。在这种情况下,数据库会随着应用程序的其余部分而发展。这就是我们通常所做的。因为我们可以在没有任何停机时间和低风险的情况下重构实时 OLTP 表,所以我们对数据库重构的可能性感到满意。