繁体   English   中英

SOLID存储过程和函数

[英]SOLID stored procedures and functions

我想在我正在使用的应用程序中开始更多地使用存储过程。 该应用程序搜索十几个数据库。 应用程序将信息存储在自己的数据库中。

我正在考虑将业务逻辑偏移到特定数据库中的存储过程。 因此,如果逻辑对所有外部数据库都是通用的,则将其保存在应用程序(.NET)中。 如果逻辑特定于数据库,则创建存储过程。

我不确定SOLID如何与存储过程和函数一起工作,因为没有接口或抽象。 以下帖子似乎建议您应该尝试合并查询: http//ledgersmbdev.blogspot.co.uk/2013/02/building-solid-databases-interface.html 例如,如果存储过程有四个SQL语句,那么为什么不尝试将它们组合成一个SQL语句呢? 这是帖子的意思吗? 这是一种SOLID方法吗?

我正在考虑将业务逻辑偏移到特定数据库中的存储过程。 因此,如果逻辑对所有外部数据库都是通用的,则将其保存在应用程序(.NET)中。 如果逻辑特定于数据库,则创建存储过程。

这句话引起了我的极大关注。 当你说逻辑是特定于数据库时,我认为你指的是上述十二个中的一个,这是一个设计缺陷。 数据库只是信息存储,它们不应该要求任何“特殊”逻辑来访问它们在任何视图结构之外。 此外,如果需要以非设置方式操作数据,而不是将其放入应用程序中。 当它们可以偏移到您的应用程序时,这不会使您的执行计算。

在设计应用程序时,必须确保不要变形数据库以忽略关系模型。 根据我的经验,这是使您的应用程序无法管理和缓慢的最佳方法之一。 为了澄清,业务逻辑不应该住在数据库中,这使得它很难为他人使用您的数据。 反对这一点的典型论点是,“我是唯一一个使用数据的人”,我说这是一个可怕的设计理由。

继续,您应该尝试确定关系(集)模型中实际工作的内容,并构建可以查询该数据的应用程序。 而不是构建适合您的应用程序的数据库。 话虽这么说, SOLID 不与关系模型一起工作 ,因为它们不是面向对象的
WIKI

在计算机编程中,SOLID(单一责任,开放式闭合,Liskov替换,接口隔离和依赖性反转)是Michael Feathers在早期由Robert C. Martin 1 [2]确定的“前五条原则”中引入的助记符缩写。 2000s [3]代表了面向对象编程和设计的五个基本原则。

评论的更新

应用程序链接来自不同系统的信息,并决定何时可以删除一组记录(这些是适用于所有系统的通用规则)。 然后,在删除之前必须应用特定于数据库的规则。 我在考虑将本地业务规则与存储过程相抵消。 -

看一下这个评论,我不完全理解在审计/软删除之外的数据库特定规则。 我同意数据库特定的规则可以设置为数据库中的管理存储过程,当你遇到如下问题时,必须绘制该行:

我的应用程序会查询历史数据,除非它超过6 months然后必须从脱机存储中检索。

6 months后删除此数据的选项是允许应用程序通过某些业务逻辑清除它或创建计划任务来执行此清理,因为它是删除元组的正常数据库操作。

我在这里的论点是将它放在数据库中,并禁止你的应用程序调用这些过程。 实际上,您的应用程序甚至不应该知道数据库存在于正确抽象的应用程序中。 因此,如果这是您提出的示例,那么我的解决方案如下:

1) Create stored procedures in the database that only a maintenance based user can invoke,   NOT THE APPLICATION  
2) Create a database scheduled task to run these based on your data needs.  

我同意不将业务逻辑放入SQL的概念以及SQL作为基于集合的语言的概念。

将SOLID视为一些非常好的编程实践的OO特定实现,并将它们应用于您编写的任何代码,包括SQL。 良好的表格模式设计将包含SOLID创意。

我花了太多时间调试大型复杂的存储过程,所以如果你能避免它,请做。 如果您必须编写存储过程代码,那么SOLID可以帮助您。

例如,我有一个大型存储过程,它会查询几十个表,并返回一个数据集,供打印机用来发送“欢迎信” 这是一个伪装成“报告”并用SQL编写的业务流程的典型示例。

从SOLID镜头看这个操作:

它应该有一个单一的责任和一个改变的理由。

代码既可以确定谁收到一封信,也可以确定该信中的数据。 如果流程的任何一个方面发生变化,您必须更新并重新测试整个系统。 一个坚实的原则是拥有一个确定谁得到一封信及其中的内容的功能。

这可能就像拥有一个返回客户列表的查询一样简单。 将其作为ID或TVP数组馈送到另一个存储过程以收集数据。

打开关闭

在大多数SP(存储过程)代码中,整个过程是硬编码或“数据驱动”。 数据驱动通常是针对此原则的SQL工作。 SQL流程通过一个CASE来修改,这个CASE在字段值或SQL中获得EVAL的文本字段。

我们刚刚创建的' master'SP中可以看到我的问题的SOLID方法现在我有一个调用GET_CUSTOMERS的SP和另一个调用GET_DATA的SP 主人基本上控制工作流程,工作流程不应更改。 主人关闭进行修改。

如果我们需要增强系统以发送电子邮件,并且电子邮件具有不同的数据字段,那么我可以通过调用GET_DATA_FOR_EMAIL将调用交换到GET_DATA 打开修改

主人有一个责任。 如果工作流程发生更改,则此主服务器会根据规则#1进行更改。

利斯科夫替代原则

这是非常OO,但为了说明一点,我们可以说GET_CUSTOMERS SP在这里被视为可替换的对象。 我应该能够进行不同的查找,例如GET_CUSTOMERS_WHO_NEED_DIFFERENT_LETTER,并且能够重用我的代码。 或者也许是GET_CUSTOMERS_FOR_INTERNAL_TEST 如果系统的所有组件都是一次性且不可重复使用,那么系统将难以维护和理解。 这可能是一个延伸。 少考虑OO对象继承,更多地考虑具有可重用的类似参数的函数。

依赖倒置原则

这是我见过的最大失败。 不要在selection和where子句周围编写代码。 我的系统开始时使用* SELECT * FROM表,table,table,其中customers.letter-sent = false *(实际超过1k行)我希望以查找所有客户并向他们发送信件结束 从抽象和代码开始,最高级别控制SP中的工作流程。

我们的想法是抽象是“找到客户”并返回客户列表。 我应该能够将该逻辑交换为代码中的其他内容。 我经常看到的违反这种情况的方法是让一个“查找客户”写入连接在customers表上的表,然后是另一个读取该表的SP。 在这种情况下,您的抽象泄露到实现中,您从可重用代码转到为特定表发送字母的系统。

SQL非常强大,并且很容易将在抽象中应该分开的步骤组合在一起来实现。

存储过程是一个很好的工具,可以帮助团队交换性能的可读性,并以可扩展性为代价带来便利。 它仍然是代码,并且从其他语言中窃取模式只会对您的整体设计有所帮助。

如果您的需求很简单,通常您不需要设计模式。 如果您的代码超过50行左右,请尝试将其移至应用层和/或考虑可靠的重新分解。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM