整个“何时抛出异常或返回值”的问题已被提出很多问题(请参阅以下内容仅查看一个示例):
我完全同意主要答案。
现在我的问题来自于在将其应用于更复杂的系统时为上述内容添加更多上下文。我会尽量保持简洁和简单。
我们有一个示例MVC PHP应用程序:
模型A:有一个函数get_car($ id),它返回一个汽车对象。
控制器A具有简单的功能,例如向用户显示汽车
然而,控制器B有一个复杂的功能,即获取汽车,修改它(比如通过模型A的设置功能之一),并通过整个系统中的其他模型和库基于这些新值更新其他表 - 非常复杂的ay lol
我们现在谈谈我的问题的主要部分:
对于数据完整性,我想使用MySQL事务。这是我遇到“什么是最好的/什么是最佳实践”的场景...
如果找不到汽车或存在SQL错误,我们编写模型A以返回FALSE。 这对控制器A来说很好,因为它只是想知道是否有错误并且爆炸,所以我们只需检查返回值是否正常。
我们现在转到控制器B.控制器B说在调用模型A函数之前进行了一些数据库更新,我们需要回滚错误,因此我们需要使用事务。现在这是我遇到问题的地方。我是否将模型A作为返回值并将其检查或者我将其更改为抛出异常,然后还要重新编写控制器A,因为我们现在需要捕获异常...然后(不是完成了; o))我回滚模型的捕获(但我们如何知道交易是否已被使用?)或者我们是否抓住并重新抛出或允许冒泡到控制器捕获和回滚那里?
我想说的是,如果我有很多模型和控制器与数据库交互,我应该让它们抛出异常然后包装我的所有其他代码,例如控制器函数在try catch中包装模型或库函数扔,或者,我是否让模型“自包含”以整理和处理自己的问题但是如果(对于这个“调用”)一个是打开的话,我该如何回滚一个事务(根据我上面的例子而不是每个时间是一个交易开放...)?如果是这种情况我将不得不让我的所有函数返回一些东西,然后在控制器中检查,因为这是唯一知道是否有开放交易的地方......
所以为了澄清我可以使用try catch来捕获并在控制器中回滚,这没关系,但是如何从“更进一步”执行此操作,例如在模型或库函数中......可以同时调用在和事务期间或者只是作为自动提交正常的MySQL调用?
一个解释的答案会很棒(因为我喜欢理解我为什么要做某事)但如果不是对以下解决方案的最爱投票(我能看到的解决方案):
1)使所有模型和库函数始终返回一个值,然后控制器可以只是bom或try try catch在必要时回滚 - 但这意味着我必须检查每个模型和库的返回值功能无处不在。
2)使所有模型和库函数抛出异常(例如SQL错误)并将每个控制器(可以调用模型和库函数)包装在try catch中,其中catch将在必要时生成或回滚。 ..
另请注意“bom”是推送用户某处或显示一个漂亮的错误(在有人说“其不良做法只是让你的应用程序死...”大声笑)
我希望你能从这里来到这里,并为长期的loooooong问题感到抱歉。
提前致谢 本
答案 0 :(得分:0)
[对于数据完整性我想要使用MySQL事务“中隐含一个理论问题......因为MySQL历史上并不是非常ACID - PostgreSQL和Oracle都为ACID提供了更强大的支持。但是,回到真正的问题......]
你的(1)和(2)都关注异常与失败返回值,但我的印象是,这不是纠缠异常,错误返回和打开事务的关键部分(有些数据库支持SQL异常)以及)。相反,我专注于保持事务状态与操作模型的函数的嵌套相关联。以下是这方面的一些想法:
实现一个大事务方法的一种方法是使用启动事务的高级函数,然后本身调用控制器B需要做的任何事情的顶层。这使得冒泡错误或具有特殊的中止事务异常非常简单。如果没有子功能失败且没有捕获异常,则只有top函数会调用commit而不是abort。子功能不会调用commit。
相反,您可以让所有函数都注意在非SQL端(您的代码)中实现的事务深度,尽管在某些语言中设置比其他语言更难(在Python中使用装饰器非常容易,例如)。如果它们完成并且事务深度为零,这将允许它们中的任何一个调用commit。
希望这有助于某人: - )