简体   繁体   English

SOLID存储过程和函数

[英]SOLID stored procedures and functions

I want to start using stored procedures more in an application I am working with. 我想在我正在使用的应用程序中开始更多地使用存储过程。 The application searches a dozen or so databases. 该应用程序搜索十几个数据库。 The application stores information in its own database. 应用程序将信息存储在自己的数据库中。

I was thinking about offsetting business logic to stored procedures in specific databases. 我正在考虑将业务逻辑偏移到特定数据库中的存储过程。 Therefore if the logic is generic to all external databases then hold it in the application (.NET). 因此,如果逻辑对所有外部数据库都是通用的,则将其保存在应用程序(.NET)中。 If the logic is specific to a database then create a stored procedure. 如果逻辑特定于数据库,则创建存储过程。

I am unsure how SOLID works with stored procedures and functions as there are no interfaces or abstractions. 我不确定SOLID如何与存储过程和函数一起工作,因为没有接口或抽象。 The following post seems to suggest that you should try to consolidate queries: http://ledgersmbdev.blogspot.co.uk/2013/02/building-solid-databases-interface.html . 以下帖子似乎建议您应该尝试合并查询: http//ledgersmbdev.blogspot.co.uk/2013/02/building-solid-databases-interface.html For example, if a stored procedure has four SQL statements, then why not try to combine them into one SQL statement? 例如,如果存储过程有四个SQL语句,那么为什么不尝试将它们组合成一个SQL语句呢? Is this what the post is saying? 这是帖子的意思吗? Is this a SOLID approach? 这是一种SOLID方法吗?

I was thinking about offsetting business logic to stored procedures in specific databases. 我正在考虑将业务逻辑偏移到特定数据库中的存储过程。 Therefore if the logic is generic to all external databases then hold it in the application (.NET). 因此,如果逻辑对所有外部数据库都是通用的,则将其保存在应用程序(.NET)中。 If the logic is specific to a database then create a stored procedure. 如果逻辑特定于数据库,则创建存储过程。

This statement causes great concern in my mind. 这句话引起了我的极大关注。 When you say if the logic is specific to a database, to which I presume you mean one of the twelve aforementioned, this is a design flaw. 当你说逻辑是特定于数据库时,我认为你指的是上述十二个中的一个,这是一个设计缺陷。 Databases are just that, information stores, they should not require any "special" logic to access them outside of whatever view structure is exposed. 数据库只是信息存储,它们不应该要求任何“特殊”逻辑来访问它们在任何视图结构之外。 Further, if the data needs to be manipulated in a non-set manner than you need to put it inside your application. 此外,如果需要以非设置方式操作数据,而不是将其放入应用程序中。 That is don't make your perform calculations when they can be offset to your application. 当它们可以偏移到您的应用程序时,这不会使您的执行计算。

When you design your application you must ensure that you are not morphing your database to ignore the relational model. 在设计应用程序时,必须确保不要变形数据库以忽略关系模型。 In my experience this is one of the best ways to make your application unmanageable and slow. 根据我的经验,这是使您的应用程序无法管理和缓慢的最佳方法之一。 To clarify, business logic should not live in the database, this makes it hard for others to use your data. 为了澄清,业务逻辑不应该住在数据库中,这使得它很难为他人使用您的数据。 The typical argument against this is, "I am the only one using the data", to which I say that is an awful design reason. 反对这一点的典型论点是,“我是唯一一个使用数据的人”,我说这是一个可怕的设计理由。

Moving on, you should try to determine what actually works in the relational (set) model and build an application that can query that data. 继续,您应该尝试确定关系(集)模型中实际工作的内容,并构建可以查询该数据的应用程序。 Instead of building a database to fit your application. 而不是构建适合您的应用程序的数据库。 That being said, SOLID DOES NOT WORK WITH RELATIONAL MODELS AS THEY ARE NOT OBJECT ORIENTED 话虽这么说, SOLID 不与关系模型一起工作 ,因为它们不是面向对象的
WIKI WIKI

In computer programming, SOLID (Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion) is a mnemonic acronym introduced by Michael Feathers for the "first five principles" identified by Robert C. Martin 1 [2] in the early 2000s[3] that stands for five basic principles of object-oriented programming and design. 在计算机编程中,SOLID(单一责任,开放式闭合,Liskov替换,接口隔离和依赖性反转)是Michael Feathers在早期由Robert C. Martin 1 [2]确定的“前五条原则”中引入的助记符缩写。 2000s [3]代表了面向对象编程和设计的五个基本原则。

UPDATE FROM COMMENTS 评论的更新

The application links information from different systems and decides when a group of records can be deleted (these are generic rules that apply to all systems). 应用程序链接来自不同系统的信息,并决定何时可以删除一组记录(这些是适用于所有系统的通用规则)。 There are then database specific rules that must be applied before deleting. 然后,在删除之前必须应用特定于数据库的规则。 I was thinking about offsetting the local business rules to stored procedures. 我在考虑将本地业务规则与存储过程相抵消。 -

Looking at this comment, I don't fully understand what database specific rules would be in place outside of auditing / soft deletes. 看一下这个评论,我不完全理解在审计/软删除之外的数据库特定规则。 I would agree that database specific rules can be set to administrative stored procedures in the database, where you have to draw the line is when you get to issues such as the following: 我同意数据库特定的规则可以设置为数据库中的管理存储过程,当你遇到如下问题时,必须绘制该行:

My application queries against historic data unless it is older than 6 months then it must be retrieved from offline storage. 我的应用程序会查询历史数据,除非它超过6 months然后必须从脱机存储中检索。

The option you have for removing this data after 6 months , is to allow the application to purge it via some business logic OR to create a scheduled task to do this cleanup as it is a normal database operation to remove tuples. 6 months后删除此数据的选项是允许应用程序通过某些业务逻辑清除它或创建计划任务来执行此清理,因为它是删除元组的正常数据库操作。

My argument here would be to place this in the database and to disallow your application from invoking these procedures. 我在这里的论点是将它放在数据库中,并禁止你的应用程序调用这些过程。 In fact your application shouldn't even know a database exists, in a correctly abstracted application. 实际上,您的应用程序甚至不应该知道数据库存在于正确抽象的应用程序中。 So if this is the example you are proposing then my solution would be as follows: 因此,如果这是您提出的示例,那么我的解决方案如下:

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.  

I agree with the notion of not putting business logic into SQL as well the concept of SQL being a set based language. 我同意不将业务逻辑放入SQL的概念以及SQL作为基于集合的语言的概念。

Think of SOLID as an OO specific implementation of some really good programming practices and apply them to any code you write, including SQL. 将SOLID视为一些非常好的编程实践的OO特定实现,并将它们应用于您编写的任何代码,包括SQL。 Good table schema design will incorporate SOLID ideas. 良好的表格模式设计将包含SOLID创意。

I have spent too much of my life debugging large complex stored procedures so if you can avoid it, please do. 我花了太多时间调试大型复杂的存储过程,所以如果你能避免它,请做。 If you must write stored procedure code then SOLID can help you. 如果您必须编写存储过程代码,那么SOLID可以帮助您。

For example I have a large Stored Procedure which queries against a few dozen tables and it returns a data set for use by the printer to send 'welcome letters' . 例如,我有一个大型存储过程,它会查询几十个表,并返回一个数据集,供打印机用来发送“欢迎信” That is a classic example of a business process disguised as a 'report' and written in SQL. 这是一个伪装成“报告”并用SQL编写的业务流程的典型示例。

Looking at this operation from a SOLID lens: 从SOLID镜头看这个操作:

It should have a Single responsibility and a Single reason to change. 它应该有一个单一的责任和一个改变的理由。

The code both determines who gets a letter as well as what data goes into that letter. 代码既可以确定谁收到一封信,也可以确定该信中的数据。 If either aspect of the process changes you have to update and retest the entire system. 如果流程的任何一个方面发生变化,您必须更新并重新测试整个系统。 A solid principle would be to have a function that determines who gets a letter and what is in it. 一个坚实的原则是拥有一个确定谁得到一封信及其中的内容的功能。

This could be as simple as having a single query which will return a list of customers. 这可能就像拥有一个返回客户列表的查询一样简单。 Feed that as an array of IDs or TVP into another stored procedure to collect data. 将其作为ID或TVP数组馈送到另一个存储过程以收集数据。

Open / Closed 打开关闭

In most SP (Stored Procedure) code the entire procedure is either hard coded or 'data driven'. 在大多数SP(存储过程)代码中,整个过程是硬编码或“数据驱动”。 Data driven is a usually a SQL effort against this principle. 数据驱动通常是针对此原则的SQL工作。 The SQL flow is modified by a CASE pivoting off a field value or SQL in text fields that gets EVAL'd. SQL流程通过一个CASE来修改,这个CASE在字段值或SQL中获得EVAL的文本字段。

A SOLID approach to my problem can be seen in the 'master' SP that we just created Now I have a SP that calls GET_CUSTOMERS and another that calls GET_DATA . 我们刚刚创建的' master'SP中可以看到我的问题的SOLID方法现在我有一个调用GET_CUSTOMERS的SP和另一个调用GET_DATA的SP This master basically controls the workflow and that workflow should not change. 主人基本上控制工作流程,工作流程不应更改。 The master is closed for modification. 主人关闭进行修改。

If we then need to enhance the system to send emails, and emails have different data fields then I can swap out the call to GET_DATA with a call to GET_DATA_FOR_EMAIL . 如果我们需要增强系统以发送电子邮件,并且电子邮件具有不同的数据字段,那么我可以通过调用GET_DATA_FOR_EMAIL将调用交换到GET_DATA Open for modification . 打开修改

The master has a single responsibility. 主人有一个责任。 If the workflow changes, then this master changes, as per rule #1. 如果工作流程发生更改,则此主服务器会根据规则#1进行更改。

Liskov substitution principle 利斯科夫替代原则

This is very OO, but to make a point let's say that the GET_CUSTOMERS SP can been seen as a replaceable object here. 这是非常OO,但为了说明一点,我们可以说GET_CUSTOMERS SP在这里被视为可替换的对象。 I should be able a different lookup, say GET_CUSTOMERS_WHO_NEED_DIFFERENT_LETTER and be able to reuse my code. 我应该能够进行不同的查找,例如GET_CUSTOMERS_WHO_NEED_DIFFERENT_LETTER,并且能够重用我的代码。 Or maybe GET_CUSTOMERS_FOR_INTERNAL_TEST ? 或者也许是GET_CUSTOMERS_FOR_INTERNAL_TEST If all the components of your system as one –off and not reusable then the system will be harder to maintain and understand. 如果系统的所有组件都是一次性且不可重复使用,那么系统将难以维护和理解。 This one may be a stretch. 这可能是一个延伸。 Think less about OO object inheritance and more about functions with similar arguments that can be reused. 少考虑OO对象继承,更多地考虑具有可重用的类似参数的函数。

Dependency inversion principle 依赖倒置原则

This is the biggest FAIL I've seen. 这是我见过的最大失败。 Don't write the code around selects and where clauses. 不要在selection和where子句周围编写代码。 Where my system started with a *SELECT * FROM table, table, table where customers.letter-sent=false* (actually over 1k lines) I will hopefully end with Find all customers and send them a letter . 我的系统开始时使用* SELECT * FROM表,table,table,其中customers.letter-sent = false *(实际超过1k行)我希望以查找所有客户并向他们发送信件结束 Start with the abstractions and code to where the highest level controls the workflow in the SP. 从抽象和代码开始,最高级别控制SP中的工作流程。

The idea is that the abstraction is 'find customers' and that returns a list of customers. 我们的想法是抽象是“找到客户”并返回客户列表。 I should be able to swap that logic for something else in the code. 我应该能够将该逻辑交换为代码中的其他内容。 A violation of this which I often see is to have a 'find customers' that writes to a table joined on the customers table, and then another SP that reads that table. 我经常看到的违反这种情况的方法是让一个“查找客户”写入连接在customers表上的表,然后是另一个读取该表的SP。 In that case your abstraction leaked into the implementation and you went from reusable code to a system that sends letters for a specific table. 在这种情况下,您的抽象泄露到实现中,您从可重用代码转到为特定表发送字母的系统。

SQL is very powerful and it is way too easy to combine steps that should be separate in the abstraction to be comingled in the implementation. SQL非常强大,并且很容易将在抽象中应该分开的步骤组合在一起来实现。

Stored Procedures are a good tool that helps team exchange readability for performance and brings convenience at the expense of scalability. 存储过程是一个很好的工具,可以帮助团队交换性能的可读性,并以可扩展性为代价带来便利。 It is still code and stealing patterns from other languages will only help if your overall design. 它仍然是代码,并且从其他语言中窃取模式只会对您的整体设计有所帮助。

Very often you don't need a design pattern if your needs a simple. 如果您的需求很简单,通常您不需要设计模式。 If your code is more then 50 lines or so try to move it out to an app layer and / or think about a solid re-factoring. 如果您的代码超过50行左右,请尝试将其移至应用层和/或考虑可靠的重新分解。

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

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