更新操作是否违反单一职责原则?

5
我喜欢使用Upsert存储过程,如果记录存在则更新记录,否则插入记录。如果没有Upsert存储过程,我需要先查找记录是否存在,然后根据结果调用两个单独的存储过程。
今天我创建了一个名为UpdateOrDeleteRow的存储过程,才意识到Upsert实际上是相同的操作,之前从未考虑过这个问题。
这是否违反了SRP原则?如果是,是否可以接受?如果不是,我该怎么做?
我知道SRP是面向对象编程的原则,而T-SQL不是面向对象语言,但是这个原则的基础似乎也应该适用于这里。

2
什么是单一职责原则? - Gordon Linoff
基本上每个类应该只做一件事情。 - Jon Crowell
我同意@餐饮主管的观点,即每个类应该只做一件事情,但是什么是“一件事情”呢?每个类应该有一个单一的职责,其中职责被定义为“发生改变的原因”。因此,为了符合单一职责原则,一个类只应该有一个发生改变的原因。 - Jacob Adams
我同意你的看法,Jake。我绝对不主张盲目遵循原则。然而,我喜欢审查自己的行为,以确保当我打破“规则”时,我是出于正确的理由这样做的。 - Jon Crowell
5个回答

5

有一个原则比 SRP 更受我喜欢 - DRY。如果你在一个地方调用这个序列,你可以考虑单一责任。但是当你多次重复相同的操作序列时,DRY 让我消除重复。

顺便提一下,你可以避免在过程/方法名称中使用 ORUpdateOrInsert 操作有一个非常好的名字 Save。我认为它不会违反 SRP。


我认为你刚刚创造了石头剪刀布原则:当单一责任原则(SRP)和不重复原则(DRY)相冲突时,DRY 胜出。 - Jon Crowell
@HeadofCatering :) 我们应该找到一些比DRY更好但比SRP更差的东西。 - Sergey Berezovskiy

3

个人认为这个原则并不完全适用于SQL Server。存储过程并不总是执行单一操作(我认为把存储过程等同于类的观念是有缺陷的)。我认为把存储过程中的每个语句都分成一个单独的存储过程是没有意义的,这样做会变得非常荒谬。

当然,需要注意平衡,不要走向另一个极端。您不希望一个存储过程有18种不同的方式来指定参数,并且根据组合可以执行540种不同的操作。

对于UPSERT,我仍建议使用单个存储过程即可。如果您想让它只服务于一个目的,将您的更新/插入更改为单个MERGE可能会让您感到更舒适。:-) 话虽如此,请认真对待MERGE


你能否提供一些定义,以便在拆分存储过程时使用(你提出了一些边界情况,说明为什么极端情况不好,但我仍然缺乏对于所有灰色区域的定义)? - BornToCode
@BornToCode,你想让我为你定义灰色地带吗? - Aaron Bertrand
我特别想找一些关于联合等方面的指南,如何知道何时编写一个带有联合的存储过程比编写两个单独的存储过程更好? - BornToCode

2
我认为在此情况下使用principal并不合适,因为这会导致代码重复。首先让我们来看看UPSERT的作用,根据数据是否存在执行INSERT或UPDATE操作。如果在codebehind中实现,你需要对数据库进行两次调用,这取决于应用程序的结构,可能还需要打开和关闭两个连接。所以你需要在codebehind中编写3个方法(一个执行每个存储过程),然后再编写一个方法来调用每一个方法,并做出判断是需要插入还是更新。此外,你需要在数据库中编写3个独立的存储过程以执行每个操作。在我看来,这似乎是一个编写不良结构的代码,因为你会将相同的参数传递给插入/更新过程和upsert,因此最好在一个地方处理所有操作。通过使用UPSERT,你只需要一个存储过程和一个连接,从codebehind中调用一个方法即可。我认为这样可以得到更好、更干净的代码。

1
如果您已经有独立执行更新或删除操作的过程(希望能够记录日志以进行审计),您可以让您的upsert过程单独调用这些过程。这样只有这些过程在执行工作,这应该有助于使事情更易管理,即使它们被多个位置调用。

1
单一职责原则指出一个对象应该只有一个改变的理由。如果表结构发生变化,Upsert存储过程应该改变的唯一原因就是这个。因此,我认为创建Upsert存储过程是可以的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接