Предположим, что существует операция, которая создает пользователя. Эта операция может завершиться неудачно, если указанная электронная почта или имя пользователя существуют. Если это не удалось, необходимо точно знать, почему. Есть три подхода к этому, поскольку я вижу это, и мне интересно, есть ли явный победитель.
Итак, здесь пользователь класса:
class User
{
public string Email { get; set; }
public string UserName { get; set; }
}
И есть три способа выполнения операции create:
Test-Создать
if (UserExists(user)) act on user exists error;
if (UsernameExists(user)) act on username exists error;
CreateUser(user);
UserExists и UsernameExists делают запрос на сервер db для проверки. Эти вызовы снова повторяются в CreateUser, чтобы гарантировать правильность использования API. В случае неудачи проверки я бросаю ArgumentOutOfRangeException в обоих случаях. Таким образом, есть производительность.
Try-Создать
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;
}
}
Этот шаблон выполняет проверку только один раз, но мы прибегаем к использованию так называемых кодов ошибок, которые не считаются хорошей практикой.
Create-Поймайте
try
{
CreateUser(user);
}
catch(UserExistsException)
{
act on user exists error;
}
catch(UsernameExistsException)
{
act on username exists error;
}
Здесь я не использую коды ошибок, но теперь мне нужно создать отдельный класс исключения для каждого случая. Это более или менее то, как предполагается использование исключений, но мне интересно, стоит ли создавать отдельное исключение вместо записи enum.
Итак, у нас есть явный победитель, или это скорее вопрос вкуса?