古老的问题。您应该将业务逻辑放在数据库中作为存储过程(或包),还是应用程序/中间层?更重要的是,为什么?
假设数据库独立性不是目标。
答案 0 :(得分:34)
在确定业务逻辑应该去哪里时,代码的可维护性始终是一个大问题。
集成的调试工具和功能更强大的IDE通常使维护中间层代码比存储过程中的相同代码更容易。除非有其他原因,否则您应该从中间层/应用程序中的业务逻辑开始,而不是在存储过程中。
但是,当您进行报告和数据挖掘/搜索时,存储过程通常可以更好地进行选择。这要归功于数据库聚合/过滤功能的强大功能以及您保持处理非常接近数据源的事实。但这可能不是大多数人认为的经典商业逻辑。
答案 1 :(得分:29)
在数据库中放入足够的业务逻辑,以确保数据的一致性和正确性。
但不要害怕必须在另一个级别复制一些逻辑以增强用户体验。
答案 2 :(得分:28)
对于非常简单的情况,您可以将业务逻辑放在存储过程中。通常即使是简单的情况也会随着时间的推移变得复杂。以下是我没有将业务逻辑放在数据库中的原因:
将业务逻辑紧密地放在数据库中,将其与数据库的技术实现紧密结合在一起。更改表将导致您再次更改大量存储过程,从而导致大量额外错误和额外测试。
通常,UI依赖于业务逻辑来进行验证。将这些内容放在数据库中会导致数据库与UI之间的紧密耦合,或者在不同情况下会重复这两者之间的验证逻辑。
很难让多个应用程序在同一个数据库上运行。一个应用程序的更改将导致其他应用程序中断。这很快就会变成维护噩梦。所以它并没有真正扩展。
更实际上,SQL不是一种以可理解的方式实现业务逻辑的好语言。 SQL非常适合基于集合的操作,但它错过了“大规模编程”的构造,很难维护大量的存储过程。现代OO语言更适合并且更灵活。
这并不意味着您无法使用存储过程和视图。我认为在表和应用程序之间放置一层额外的存储过程和视图来解耦这两者是一个好主意。这样,您可以在不更改外部接口的情况下更改数据库的布局,从而允许您独立地重构数据库。
答案 3 :(得分:9)
这取决于你,只要你是一致的。
将其放入数据库层的一个很好的理由:如果您确信您的客户端永远不会更改其数据库后端。
将其放入应用程序层的一个很好的理由:如果您的应用程序针对多种持久性技术。
您还应该考虑核心竞争力。您的开发人员主要是应用程序层开发人员,还是主要是DBA类型?
答案 4 :(得分:7)
虽然在应用程序层上拥有业务逻辑肯定有好处,但我想指出语言/框架似乎比数据库更频繁地更改。
我支持的一些系统在过去的10到15年中经历了以下用户界面:Oracle Forms / Visual Basic / Perl CGI / ASP / Java Servlet。没有改变的一件事 - 关系数据库和存储过程。
答案 5 :(得分:6)
在这种情况下,提问者排除作为考虑因素的数据库独立性是将逻辑排除在数据库之外的最强有力的论据。数据库独立性的最有力论据是能够将软件销售给拥有自己的数据库后端优先权的公司。
因此,我认为将数据库中的存储过程仅作为商业过程而不是技术过程的主要论点。可能存在技术原因,但也有技术原因可以将其保留在那里 - 性能,完整性以及允许多个应用程序使用相同API的能力。
是否使用SP也会受到您要使用的数据库的强烈影响。如果您不考虑数据库独立性,那么您将使用T-SQL或使用PL / SQL获得非常不同的体验。
如果您使用Oracle开发应用程序,那么PL / SQL作为一种语言显然是一种选择。它与数据紧密耦合,在每次重复中都不断改进,任何体面的开发工具都会将PL / SQL开发与CVS或Subversion或其他一些整合。
Oracle的基于Web的Application Express开发环境甚至可以使用PL / SQL 100%构建。
答案 6 :(得分:6)
任何影响数据完整性的内容都必须放在数据库级别。除了用户界面之外的其他事情通常是将数据放入,更新或删除数据库中的数据,包括导入,批量更新以更改定价方案,热修复等。如果您需要确保始终遵循规则,请将逻辑置于默认值中和触发器。
这并不是说在用户界面中也不是一个好主意(为什么要发送数据库不会接受的信息),但忽略数据库中的这些东西就是为了惹恼灾难
答案 7 :(得分:6)
虽然没有一个正确的答案 - 这取决于有问题的项目,但我会推荐Eric Evans在“Domain Driven Desig n”中倡导的方法。在这种方法中,业务逻辑在其自己的层中被隔离 - 域层 - 位于基础架构层之上 - 可能包括您的数据库代码,并位于应用层之下,后者将请求发送到域层实现并听取确认完成,有效推动申请。
通过这种方式,业务逻辑被捕获在一个模型中,可以与那些除了技术问题之外了解业务的人讨论,并且应该更容易隔离业务规则本身的变化,技术实现问题,以及与业务(域)模型交互的应用程序流。
如果你有机会我推荐阅读上面的书,因为它非常擅长解释这个纯粹的理想如何在真实代码和项目的现实世界中实际近似。
答案 8 :(得分:5)
现在可以提交subversion存储的proc代码并使用良好的工具支持调试此代码。
如果使用组合sql语句的存储过程,则可以减少应用程序与数据库之间的数据流量,并减少数据库调用次数并获得较大的性能提升。
一旦我们开始使用C#构建,我们决定不使用存储过程,但现在我们正在将越来越多的代码移动到存储过程。特别是批量处理。
但是,不要使用触发器,使用存储过程或更好的包。触发确实会降低可维护性。
答案 9 :(得分:5)
如果您需要数据库独立性,您可能希望将所有业务逻辑放在应用程序层中,因为应用程序层中的可用标准比数据库层可用的标准更为普遍。
但是,如果数据库独立性不是第一因素,并且团队的技能组合包含强大的数据库技能,那么将业务逻辑放在数据库中可能是最佳解决方案。您可以让您的应用程序人员执行特定于应用程序的事情,并让您的数据库人员确保所有查询都飞行。
当然,能够将SQL语句放在一起并具有“强大的数据库技能”之间存在很大差异 - 如果您的团队比后者更接近前者,那么使用其中一个Hibernates将逻辑放入应用程序中这个世界(或改变你的团队!)。
根据我的经验,在企业环境中,您将拥有该领域的单一目标数据库和技能 - 在这种情况下,您可以将所有内容都放在数据库中。如果您从事软件销售业务,那么数据库许可证成本将使数据库独立性成为最重要的因素,您将在应用程序层中实现所有功能。
希望有所帮助。
答案 10 :(得分:4)
将代码放在应用程序层中将导致数据库独立的应用程序。
出于性能原因,有时最好使用存储过程。
它(照例)取决于应用要求。
答案 11 :(得分:4)
数据库中唯一存在的就是数据。
存储过程是维护的噩梦。它们不是数据,不属于数据库。开发人员和DBA之间的无休止协调只不过是组织摩擦。
很难对存储过程保持良好的版本控制。数据库外部的代码非常容易安装 - 当您认为版本错误时,您只需执行SVN UP(可能是安装)并将应用程序恢复到已知状态。您有应用程序的环境变量,目录链接和许多环境控制。
您可以通过简单的PATH
操作,针对不同情况(培训,测试,质量保证,生产,客户特定的增强等等)提供变体软件。
然而,数据库中的代码更难管理。没有合适的环境 - 没有“PATH”,目录链接或其他环境变量 - 提供对正在使用的软件的任何可用控制;你有一套永久的,全球范围内的应用软件,它固定在数据库中,与数据相结合。
触发器更糟糕。它们既是维护也是调试的噩梦。我看不出他们解决了什么问题;它们似乎是一种解决设计糟糕的应用程序的方法,在这种应用程序中,有人无法正确使用可用的类(或函数库)。
虽然有些人发现性能参数引人注目,但我仍然没有看到足够的基准数据来说服我存储过程都那么快。每个人都有一个轶事,但没有人有并排的代码,算法或多或少相同。
[在我看过的例子中,旧的应用程序是一个设计糟糕的混乱;在编写存储过程时,应用程序被重新构建。我认为设计变更对平台变化的影响更大。]
答案 12 :(得分:3)
业务逻辑应作为第一选择放在应用程序/中间层中。这样,它可以以域模型的形式表示,放在源代码控制中,拆分或与相关代码(重构)等结合使用。它还为您提供了一些数据库供应商独立性。
面向对象语言也比存储过程更具表现力,使您能够更好,更轻松地在代码中描述应该发生的事情。
在存储过程中放置代码的唯一好理由是:如果这样做会产生重要且必要的性能优势,或者需要由多个平台(Java,C#,PHP)执行相同的业务代码。即使在使用多个平台时,也存在可能更适合共享功能的Web服务等替代方案。
答案 13 :(得分:3)
根据我的经验,答案取决于一系列价值观,通常取决于贵组织的技能所在。
DBMS是一种非常强大的野兽,这意味着适当或不恰当的治疗会带来巨大的好处或巨大的危险。可悲的是,在太多的组织中,主要关注编程人员; dbms技能,尤其是查询开发技能(与管理相对)被忽略了。由于评估dbms技能的能力也可能缺失,这进一步加剧了这一点。并且很少有程序员能够充分理解他们对数据库不了解的内容。
因此,次优概念的流行,如Active Records和LINQ(引入一些明显的偏见)。但它们可能是这些组织的最佳答案。
但是,请注意,高度规模的组织倾向于更加关注数据存储的有效使用。
答案 14 :(得分:2)
IMHO。在决定关系数据库驱动的应用程序中业务逻辑的位置时,存在两个相互矛盾的问题:
重新。可维护性:为了实现有效的未来开发,业务逻辑属于应用程序中最容易调试和版本控制的部分。
重新。可靠性:当存在重大的不一致风险时,业务逻辑属于数据库层。可以设计关系数据库以检查对数据的约束,例如,不允许在特定列中使用NULL值等。当您的应用程序设计中出现某些数据需要处于特定状态的情况时,这些状态太复杂而无法用这些简单的约束表达,使用触发器或类似的东西是有意义的在数据库层。
触发器是一件很难跟上的事情,尤其是当您的应用程序应该在您甚至无法访问的客户端系统上运行时。但这并不意味着无法跟踪它们或更新它们。 S.Lott在他的回答中认为这是一种痛苦和麻烦是完全有效的,我会在那之后并且也在那里。但是,如果您在第一次设计数据层时考虑到这些限制,并且除了绝对必需品之外不使用触发器和函数,那么它是可管理的。
在我们的应用程序中,大多数业务逻辑包含在应用程序的模型层中,例如发票知道如何从给定的销售订单初始化自己。当一堆不同的东西按顺序修改为一组复杂的变化时,我们会在事务中将它们卷起来以保持一致性,而不是选择存储过程。总计等的计算都是使用模型层中的方法完成的。但是当我们需要对某些内容进行非规范化处理或将数据插入到所有客户端使用的“更改”表中以确定它们需要在其会话缓存中过期的对象时,我们使用数据库层中的触发器/函数来插入新行并从此触发器发出通知(Postgres listen / notify stuff)。
我们的应用程序在现场使用了大约一年,每天都有数百名客户使用,如果我们从头开始,我唯一要改变的就是设计我们的系统来创建数据库功能(或存储过程) ,但是你想要打电话给他们)从版本开始,并从一开始就考虑到它们的更新。
值得庆幸的是,我们确实有一些系统来跟踪架构版本,因此我们在此基础上构建了一些内容来处理替换数据库函数。如果我们考虑到从一开始就需要更换它们,那么它现在可以节省一些时间。
当然,当你走出RDBMS领域之外的一切都会变成像Amazon SimpleDB和Google的BigTable这样的元组存储系统。但那是一个不同的故事:)
答案 15 :(得分:2)
业务应用程序'层'是:
这实现了业务用户对h(is / er)作业的看法。它使用用户熟悉的术语。
这是计算和数据操作发生的地方。涉及更改数据的任何业务逻辑都在此处实现。
这可以是:规范化的顺序数据库(标准的基于SQL的DBMS);一个OO数据库,存储包装业务数据的对象;等
在进入上述层时,您需要进行必要的分析和设计。这将指示最佳实现业务逻辑的位置:数据完整性规则和有关数据更新的并发/实时问题通常会尽可能接近数据实现,与计算字段相同,这是一个很好的指针存储过程/触发器,绝对需要数据完整性和事务控制。
涉及数据含义和使用的业务规则大部分将在处理层中实现,但也会作为用户的工作流出现在用户界面中 - 以某种顺序链接各种流程这反映了用户的工作。
答案 16 :(得分:2)
业务逻辑将放在应用程序层而不是数据库中。 原因是数据库存储过程始终依赖于您使用的数据库产品。这打破了三层模型的优势之一。除非为此数据库产品提供额外的存储过程,否则无法轻松更改为其他数据库。 另一方面,有时,将逻辑放入存储过程以进行性能优化是有意义的。
我想说的是将业务逻辑放入应用层,但也有例外(主要是性能原因)
答案 17 :(得分:2)
这个问题没有独立的正确答案。这取决于您的应用程序的要求,开发人员的偏好和技能,以及月亮的阶段。
答案 18 :(得分:1)
这是一个连续统一体。恕我直言,最大的因素是速度。如何尽可能快地启动和运行这个吸盘,同时仍然坚持良好的编程租户,如可维护性,性能,可伸缩性,安全性,可靠性等。通常,SQL是最简洁的表达方式,也恰好是性能最高,除了字符串操作等,但这是你的CLR Procs可以提供帮助的地方。我的信念是,无论您认为哪种方式最适合手头的事业,都可以自由地散布业务逻辑。如果你有一大堆应用程序开发人员在查看SQL时会把他们的裤子弄脏,那就让他们使用他们的app逻辑。如果您真的想要创建具有大型数据集的高性能应用程序,请尽可能多地在数据库中添加逻辑。解雇您的DBA并为开发人员提供他们的Dev数据库的最终自由。这项工作没有一个答案或最好的工具。你有多个工具,所以在应用程序的各个层面都成为专家,你很快就会发现你花费了更多的时间来编写好的表达性SQL,并在其他时候使用应用程序层。对我来说,最终,减少代码行数是导致简单性的原因。我们刚刚将一个仅有2500行应用程序代码和1000行SQL的sql rich应用程序转换为域模型,该模型现在拥有15500行应用程序代码和2500行SQL,以实现以前的sql rich app所做的工作。如果您可以将代码增加6倍作为“简化”,那么请继续前进。
答案 19 :(得分:1)
这是一个很好的问题!我在问过simliar question之后发现了这个,但这更具体。它是由于我没有参与制作的设计变更决定而产生的。
基本上,我被告知的是,如果数据库表中有数百万行数据,那么请考虑将业务逻辑放入存储过程和触发器中。这就是我们现在正在做的事情,将java应用程序转换为存储过程以实现可维护性,因为java代码已经变得复杂。
我发现这篇文章:The Business Logic Wars作者还在一个表格参数中创建了百万行,我觉得这很有趣。他还在javascript中添加了业务逻辑,javascript是客户端和业务逻辑层之外的。我之前没想过这个,即使我多年来一直使用javascript进行验证,还有服务器端验证。
我的观点是,您希望应用程序/中间层中的业务逻辑作为经验法则,但不要打算将其放入数据库的情况。
最后一点,还有另一个我正在工作的小组正在为研究做大量的数据库工作,他们正在处理的数据量是巨大的。但是,对于他们来说,他们在数据库本身中没有任何业务逻辑,而是将其保留在应用程序/中间层中。对于他们的设计,应用程序/中间层是正确的位置,因此我不会将表的大小用作唯一的设计考虑因素。
答案 20 :(得分:1)
我记得在某个地方读过一篇文章时指出,在某种程度上,一切都可以是业务逻辑的一部分,所以这个问题毫无意义。
我认为给出的例子是在屏幕上显示发票。用红色标记过期的决定是商业决策......
答案 21 :(得分:1)
可扩展性也是将业务逻辑放在中间层或应用层而不是数据库层的非常重要的因素。应该理解,DatabaseLayer仅用于与数据库进行交互而不是操纵返回到数据库或从数据库返回的数据。
答案 22 :(得分:1)
我们在存储过程中添加了许多业务逻辑 - 它并不理想,但通常在性能和可靠性之间取得了良好的平衡。
我们知道它的位置,而无需搜索大量的解决方案和代码库!
答案 23 :(得分:0)
业务逻辑通常由对象以及封装,继承和多态的各种语言结构体现。例如,如果银行应用程序正在转移资金,则可能存在Money类型,其定义了“钱”的业务元素。这与使用原始小数来表示金钱相反。出于这个原因,精心设计的OOP是“业务逻辑”所在的地方,而不是严格意义上的任何层。