我们假设有一个创建用户的操作.如果存在指定的电子邮件或用户名,则此操 如果失败,则需要确切知道原因.在我看来,有三种方法可以做到这一点,我想知道是否有明显的赢家.
所以,这是一个类用户:
class User
{
public string Email { get; set; }
public string UserName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
有三种方法可以完成创建操作:
测试创建
if (UserExists(user)) act on user exists error;
if (UsernameExists(user)) act on username exists error;
CreateUser(user);
Run Code Online (Sandbox Code Playgroud)
UserExists和UsernameExists向db服务器发出请求以进行验证.在CreateUser中再次重复这些调用以确保正确使用API.如果验证失败,我会在两种情况下抛出ArgumentOutOfRangeException.因此性能受到了打击.
尝试 - 创建
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这种模式只进行一次验证,但我们采用所谓的错误代码,这不是一种好的做法.
创建,捕捉
try
{
CreateUser(user);
}
catch(UserExistsException)
{
act on user exists error;
}
catch(UsernameExistsException)
{
act on username exists error;
}
Run Code Online (Sandbox Code Playgroud)
我这里不使用错误代码,但我现在必须为每种情况创建一个单独的异常类.它或多或少应该如何使用异常,但我想知道创建一个单独的异常而不是枚举条目是值得的.
那么,我们是否有一个明确的赢家,或者更多的是品味问题?
Ree*_*sey 80
那么,我们是否有一个明确的赢家,或者更多的是品味问题?
第一个选项有一个根本的缺陷 - 如果CreateUser
依赖外部资源,它永远不会是线程安全的或安全的,并且其他实现可能会在您的测试之间创建.一般来说,我倾向于避免这种"模式".
至于其他两个选项 - 它实际上取决于预计是否会发生失败.如果CreateUser
预计会在某种程度上失败,那么Try*模式是我的首选,因为使用异常本质上变得使用控制流的异常.
如果失败真的是一个例外情况,那么例外将更容易理解.
Meh*_*dad 37
Test-Create会导致竞争条件,所以这不是一个好主意.它也可能做额外的工作.
如果您希望错误成为正常代码流的一部分(例如在用户输入的情况下),则Try-Create是好的.
如果错误确实非常特殊,那么Create-Catch很好(所以你不担心性能).
这有点主观,但有一些具体的优点和缺点值得指出.
测试创建方法的一个缺点是竞争条件.如果两个客户端几乎同时尝试创建同一个用户,则他们可能都会通过测试,然后尝试创建相同的用户.
在Try-Create和Create-Catch之间,我更喜欢Create-Catch,但那是个人品味.有人可能会说,Create-Catch使用流控制的异常,这通常是不受欢迎的.另一方面,Try-Create需要一个有点尴尬的output
参数,这可能更容易被忽视.
所以,我更喜欢Create-Catch,但这里肯定有争论的余地.
归档时间: |
|
查看次数: |
1865 次 |
最近记录: |