哪个devise是最可取的:test-create,try-create,create-catch?

我们假设有一个操作可以创build一个用户。 如果指定的电子邮件地址或用户名称存在 如果失败了,就需要知道原因。 我看到这样做有三种方法,我想知道是否有明确的赢家。

所以,这里是一个类的用户:

class User { public string Email { get; set; } public string UserName { get; set; } } 

创build操作有三种方式:

testing创build

 if (UserExists(user)) act on user exists error; if (UsernameExists(user)) act on username exists error; CreateUser(user); 

UserExists和UsernameExists请求数据库服务器进行validation。 这些调用在CreateUser中再次重复,以确保API正确使用。 在validation失败的情况下,我在这两种情况下抛出ArgumentOutOfRangeException。 所以有一个性能问题。

尝试-创build

 enum CreateUserResultCode { Success, UserAlreadyExists, UsernameAlreadyExists } if (!TryCreate(user, out resultCode)) { switch(resultCode) { case UserAlreadyExists: act on user exists error; case UsernameAlreadyExists: act on username exists error; } } 

这种模式只进行一次validation,但我们诉诸使用所谓的错误代码,这不被认为是一种好的做法。

创build,捕捉

 try { CreateUser(user); } catch(UserExistsException) { act on user exists error; } catch(UsernameExistsException) { act on username exists error; } 

我在这里不使用错误代码,但是现在我必须为每个情况创build一个单独的exception类。 这或多或less是应该如何使用exception,但我不知道创build一个单独的exception,而不是枚举input是值得的。

那么,我们有一个明确的赢家还是更多的味道?

那么,我们有一个明确的赢家还是更多的味道?

第一个选项有一个根本的缺陷 – 如果CreateUser依赖于外部资源,那么它永远不会是线程安全的或安全的,其他实现可能会在您的testing之间创build。 总的来说,我倾向于避免这种“模式”。

至于其他两种select – 这是否真的会发生失败。 如果CreateUser预期会在某种程度上正常的基础上失败,那么Try *模式是我的首选,因为使用exception本质上将使用控制stream的exception。

如果失败确实是一个例外情况,那么例外情况就会更容易理解。

testing创build可能会导致竞争条件,所以这不是一个好主意。 它也可能做额外的工作。

如果您希望错误成为正常代码stream的一部分(例如用户input的情况),则Try-Create是很好的。

如果错误是非常特殊的,那么Create-Catch是很好的(所以你不担心性能)。

这是有点主观的,但有一些具体的利弊值得指出。

testing创build方法的一个缺点是竞争条件。 如果两个客户端大致同时尝试创build相同的用户,则可能两个客户都通过testing,然后尝试创build相同的用户。

在Try-Create和Create-Catch之间,我更喜欢Create-Catch,但那是个人的品味。 有人可能会争辩说,Create-Catch使用stream控制的exception,这通常是不被接受的。 另一方面,Try-Create需要一个稍微笨拙的output参数,这个参数可能更容易被忽略。

所以,我更喜欢Create-Catch,但是这里肯定有争议的空间。

您指定UserExistsUsernameExists都进行数据库调用。 我假设CreateUser也会进行数据库调用。

为什么不让数据库处理你的线程问题? 进一步假设在你的表上设置了适当的约束条件,你可以让它在存储的proc调用中出错。

因此,我会投我Create-Catch的投票。