У меня есть метод:
public ??? AuthManager.Login(Credentials credentials)
Вот набор допустимых выходных значений этого метода:
- Успех (+ accountId)
- Отказ: AccountLockedOut
- Отказ: UsernameNotFound
- Отказ: InvalidPassword (+ счет неудачных попыток)
В зависимости от типа возврата пользователю отображаются разные представления (да, представление для AccountLockedOut отличается от InvalidPassword).
Я мог бы пойти с:
public class LoginAttemptResult {
public bool Succeeded { get; set; }
public AccountId AccountId { get; set; } // for when success
public LoginAttemptResultEnumType Result { get;set; } // Success, Lockedout, UsernameNotFound, InvalidPassword
public int FailedAttemptCount { get; set; } // only used for InvalidPassword
}
Мне это не нравится и вы ищете лучшее решение. Во-первых, это приводит к частично инициализированному объекту, два - к нарушению принципа сегрегации интерфейса, три - к SRP.
ОБНОВЛЕНИЕ: исключения исключений также не являются изящным решением, потому что InvalidPassword
, как я вижу, это не исключение. Исключением является неудачное соединение с БД. Исключение составляет аргумент null. InvalidPassword
- допустимый ожидаемый ответ.
Я думаю, что лучшим решением является создание иерархии классов:
abstract class LoginAttemptResult
sealed class LoginSuccess : LoginAttemptResult { AccountId }
abstract class LoginFailure : LoginAttemptResult
sealed class InvalidPasswordLoginFailure : LoginFailure { FailedAttemptCount }
sealed class AccountLockedoutLoginFailure : LoginFailure
вызывающий метод Login
тогда должен был бы сделать что-то вроде:
if (result is LoginSuccess) {
..."welcome back mr. account id #" + (result as LoginSuccess).AccountId
}
else if (result is InvalidPasswordLoginFailure ) {
..."you failed " + (result as InvalidPasswordLoginFailure).FailedAttemptCount + " times"
}
Я не вижу ничего неправильного (концептуально) с этим подходом (кроме ряда классов, с которыми он идет).
Что еще не так с этим подходом?
Обратите внимание, что этот подход по существу представляет собой F # дискриминационный союз (DU).
Есть ли лучший способ моделировать это? У меня уже есть несколько решений, которые работают - теперь я хочу использовать элегантное решение.