反对或支持将应用程序逻辑置于数据库层的论据是什么?

Phi*_*llo 78 database-design

NOTE程序员.se和dba.se的受众不同,会有不同的观点,所以在这个例子中我认为复制什么是反对或支持将应用程序逻辑放在数据库层的论据是什么?在程序员.se上。

我已经找不到关于 dba 的讨论了,原帖已经说明了一切,所以:

大多数软件开发人员都希望将应用程序逻辑保留在应用程序层中,我们将它保留在这里可能感觉很自然。数据库开发人员似乎希望将应用程序逻辑放在数据库层,作为触发器和存储过程。

就我个人而言,我更愿意在应用层中保留尽可能多的内容,以便更容易调试并保持各层的职责分离。

您对此有何看法,在数据库层中应该或不应该实现什么?

注意,我不是该问题的 OP,但保留了原始措辞。

gbn*_*gbn 61

各种想法...

您的数据库代码将比您的应用程序客户端技术更长寿。想想 ADO.NET -> Linq -> EF 以及各种 ORM。而您仍然可以针对上述所有客户端技术运行上一千年的SQL Server 2000 代码。

您还有多客户端问题:我有 .net、java 和 Excel。这是 3 组应用程序逻辑。

“业务逻辑”不应与“数据完整性逻辑”混淆。如果您确实有客户端启动事务并进行各种检查,那将是大量的数据库调用和长事务。

应用程序逻辑无法针对高数据量进行扩展。我们使用存储过程每秒有 50k 行。使用 Hibernate 的姐妹团队每秒无法获得一个


Mik*_*ll' 41

我想要所有必须应用于数据库中所有用户和所有应用程序的逻辑。这是唯一明智的地方。

在我工作的最后一个财富 500 强企业中,至少有 25 种语言编写的应用程序访问了他们的 OLTP 数据库。其中一些程序在 1970 年代投入生产。

在数据库中实现这种需求的另一种方法是让每个应用程序程序员 100% 正确地重新实现全部或部分,每次启动编辑器时,从他们第一次走进大门的那一天到公司退出商业。

赔率是多少?

这不是这个星球上最大的“不要重复自己”吗?


Phi*_*llo 29

我正在将我的旧答案从programmers.se 中未经编辑地移出,因为站点之间的答案似乎两极分化。

我知道我在这里受到了伤害,但将业务逻辑放入数据库中,因为:

  • 您可以允许业务高级用户直接访问数据库,而不必担心他们搞砸了(或者比使用基于应用程序的逻辑更不用担心)
  • 高级用户无需等待新软件发布即可创建新报告。
  • 您可以在数据库副本中测试 SP / TRIGGER 代码,就像测试基于应用程序的逻辑一样
  • 您可以保留 SQL 以在文本文件中创建 sp 和触发器(无论如何您应该为表/视图代码执行此操作)
  • 您可以在不移植业务逻辑的情况下混合和匹配语言
  • 您可以更改业务逻辑,而无需升级每一位软件
  • 您审核结构更改的方式与审核数据库活动的方式相同 - 通过日志记录
  • 大大提高了安全性和细粒度访问控制(大多数基于应用程序的逻辑实现使用自己的安全模型,因此数据更容易受到威胁。可逆密码加密并不少见)
  • 数据库端用户安全大大减少了流氓 SQL 可以做的损坏/盗窃

缺点是: - 当用户对自定义报告的依赖程度降低时,开发人员受到威胁 - 开发人员需要学习另一种编程语言

对于熟练的开发人员来说,这些都不重要。

有趣的是,大多数答案都是用“应用程序逻辑”而不是“业务逻辑”来讨论的,好像软件不是用来提供业务功能的。


Jac*_*las 24

最重要的问题是数据库之上的任何“层”是否认为它拥有数据。并发性和数据完整性是解决方案是 RDBMS 的问题 - 有些应用程序的开发好像数据库只是他们个人的比特桶,当然他们最终试图以各种方式重新发明轮子,以及一旦某些其他应用程序访问同一个数据库,就会被不可挽回地破坏

  • 您在使用“自己的”与我不同的意义上:我的观点是,如果您在并发问题访问数据库之前“解决”并发问题,您还必须确保您的应用程序是唯一访问数据库的应用程序,否则必须解决在那个级别重新开始。我同意投票最高的答案:“您的数据库代码 [可能] 比您的应用程序客户端技术更长寿。” (5认同)

Gai*_*ius 19

在我的博客中写下了我对此的回答。我的结论是,一旦您考虑整个应用程序生命周期,在应用程序中执行它就不会扩展。

...
3.向底层数据库添加完整性/检查约束,用数据库的存储过程语言实现更复杂的代码。由此,我们获得了一个中心位置来维护,即使对于我们不知道的应用程序,我们也可以绝对执行规则!我们使用一种语言来表达整个应用程序组合和生命周期中的业务规则,因为日常语言的变化比数据库要频繁得多。它运行在一个与最重要的应用程序一样具有关键任务的系统上。错误由处理这些应用程序中数据库错误的现有代码处理。应用程序当然仍然存在崩溃的风险,但在三种情况中,这是最少的,只有崩溃的应用程序需要进行任何修改,并非所有这些(如果确实非常有必要,大多数 SP/数据库机制将允许对一个应用程序进行例外处理)。认为这在您的新建站点或小公司中无关紧要吗?好吧,如果你的生意成功了,30年后你会希望你听从了我的智慧!

......一些[反对意见]我经常听到:

  • 很难对部署在 DB 中的 SP 代码进行版本控制。我不认为这比说很难对部署在应用服务器中的 Java 代码进行版本控制更真实,也就是说,这根本不难,这是司空见惯的。在 Ruby-land 中,整本书都是关于如何将代码从开发环境投入生产的,这是其他语言社区似乎无法解决的问题。然而,版本控制存储过程显然太困难了。
  • 存储过程很难测试。这是一个奇怪的问题。首先,SP 是强类型的;编译器会告诉您是否有没有意义的输入或输出代码路径,至少在 Oracle 中,它会为您计算所有依赖项。所以这是您可能需要在 Ruby 中立即消除的一组常见单元测试。测试 OO 代码需要模拟来强制对象进入代表测试场景所需的内部状态——设置测试数据有什么不同?除此之外,还有一个用于 PL/SQL 和其他工具的 TAP 生成器。还有调试器和分析器。
  • 存储过程语言不是功能齐全的语言。好吧,我们并不是要尝试仅在存储过程中编写整个应用程序!大多数专用 SP 语言都具有您所期望的所有现代结构,至少在 Oracle 中,您可以使用具有面向对象开发人员熟悉的所有语言特性的 Java 存储过程,或任何语言的外部过程。重要的是逻辑在哪里实现——在一个地方,靠近数据——实际的语言只是一个细节。PL/SQL 编译为本机代码并与数据库一起在进程内运行;没有比这更高性能的架构了。
  • 我不想学习另一种语言。忽略一秒钟,这对任何开发人员来说都是一个巨大的危险信号(尤其是那些建议修改可能使用其他语言的生产应用程序的人!)在任何现代环境中都需要学习很多东西:典型的 Java 商店可能有 Eclipse 、WebLogic、Maven、Hudson、Anthill、Subversion 以及大量其他内容,您需要在编写一行应用程序代码之前学习这些内容。相比之下,非常高级的 SP 语言的工作知识很简单,而且很可能会有专家或 DBA 来帮助您。更不用说开发人员最喜欢的 Hibernate 带有自己的查询语言......


jco*_*and 12

SQL 是否执行诸如设置逻辑和面向应用程序的结果过滤之类的操作?SQL 是一种很棒的集合操作语言。

此外,正如 GBN 上面所指出的,SQL 代码几乎普遍比应用程序代码寿命更长。

虽然 EF 或 NHibernate 或 LinqToSql 或任何可以让您更快地生成代码的东西确实如此,但每个值得他们表现的程序员都知道只有优化 SQL 才能优化数据检索。RDBMS 只理解 SQL,所以你必须在一切都说和做完之前把一切都变成 SQL。(假设我们可以同意 TSQL 和 PLSQL 仍然是 SQL)


Ada*_*sch 12

人们不一定要讨论的一个骗局——这里的专业人士已经用尽了——是成本。

在计算软件许可成本时,数据库服务器上的 CPU 通常是任何组织中最昂贵的 CPU。因此,将业务逻辑移至数据层应该谨慎地进行,而不必统一。


Rol*_*DBA 7

这里是思想的交汇处,也就是说,开发人员 (DV) 和 DBA 的思想必然会发生。使用业务逻辑 (BL) 并将其存储在数据库中可能会产生美化或恐吓其实施的影响。

对于某些 RDBMS 产品,存在用于业务逻辑和对象基础架构的高级库/工具/API,可以在其应用程序中快速学习和使用。对于其他 RDBMS,不存在库/工具/API。

过去,客户端服务器应用程序通过存储过程 (SP) 连接到 BL。对于 Oracle 和 SQL Server 等产品,这很早就完成了。随着 PostgreSQL 和 MySQL 等开源数据库的出现,那些使用它们的人面临着在 BL 中使用存储过程开辟新天地的风险。PostgreSQL 在这方面成熟得非常快,因为不仅实现了存储过程,而且还提供了制作客户语言的能力。MySQL 基本上停止了在存储过程领域的发展,而是以一种具有许多限制的精简语言形式出现。因此,当谈到 BL 时,您完全受制于 MySQL 及其存储过程语言。

实际上只剩下一个问题:不管 RDBMS 是什么,BL 应该全部还是部分驻留在数据库中?

想想开发商。当应用程序出现问题时,调试过程将使开发人员跳入和跳出数据库以跟踪可能间歇性正确也可能不正确的数据更改。这就像编写 C++ 应用程序并在中间调用汇编程序代码。你必须从源代码、类和结构切换到中断、寄存器和偏移量然后返回!!!这将调试提升到同一级别。

开发人员可能能够通过位于内存中而不是数据库中的业务对象,结合语言配置(C++ 的编译器标志、PHP/Python 的不同设置等)来制定执行 BL 的高速方法。有些人试图通过编写库来将这种意识形态桥接起来,以便更快地将代码运行到数据库中,其中调试存储过程和触发器在数据库中很好地集成并且无缝可用。

因此,开发人员面临着以两种语言开发、调试和维护源代码和 BL 的挑战。

现在想想 DBA。DBA 希望在存储过程领域尽可能地保持数据库的精简和有意义。DBA 可能会将 BL 视为数据库外部的东西。然而,当 SQL 调用 BL 所需的数据时,SQL 需要精益求精。

现在,为了心灵的相遇!!!

开发人员编码 SP 并使用迭代方法。DBA 查看 SP。DBA 确定单个 SQL 语句可以替换开发人员编写的迭代方法。开发者看到DBA建议的SQL语句需要调用其他BL相关的代码或SQL,不遵循正常的SQL语句执行计划。

有鉴于此,配置、性能调优和 SP 编码成为数据检索的 BL 深度和数据密集度的函数。BL 的深度和数据密集度越高,开发人员和 DBA 必须在同一页面上处理赋予数据库的数据量和处理能力。

结论

数据检索的方式应该始终涉及开发人员和 DBA 阵营。为了速度和效率,必须始终就哪些编码方法和数据检索范式可以协同工作做出让步。如果在源代码获取数据之前只为源代码准备一次数据,那么 DBA 应该规定使用精益和平均 SQL。如果 BL 是 DBA 不适应的东西,那么控制权就在开发人员手中。这就是为什么 DBA 应该看到他/她自己和项目团队的一部分,而不是他/她自己的孤岛,而开发人员必须让 DBA 对 SQL 进行微调(如果确实需要的话)。