输入验证是一种业务逻辑,因此我们应该将此过程隐藏在域层中。如本文所述
我喜欢这个
登录验证器
class LoginValidator extends Validator {
String email;
String password;
LoginValidator(this.email, this.password);
@override
void validate(Function() success, Function(List<Failure>) errors) {
List<Failure> failures = [];
if (email.trim().isEmpty) {
failures.add(const EmailValidationFailure('Email is required'));
} else if (!validator.isEmail(email)) {
failures.add(const EmailValidationFailure());
}
if (password.trim().isEmpty) {
failures.add(const PasswordValidationFailure('Password is required'));
}
if (failures.isNotEmpty) {
errors(failures);
} else {
success();
}
}
}
我为每个输入字段创建了一个失败类
class EmailValidationFailure extends Failure {
const EmailValidationFailure([String message = 'Email is invalid'])
: super(message);
}
class PasswordValidationFailure extends Failure {
const PasswordValidationFailure([String message = 'Incorrect password'])
: super(message);
}
我在用例中使用验证器
class LoginUseCaseInteractor implements LoginUseCaseInputPort {
final AccountRepository _repository;
final LoginUseCaseOutputPort outputPort;
LoginUseCaseInteractor(this._repository, this.outputPort);
@override
void login(LoginParams params) {
LoginValidator(params.email, params.password).validate(() async {
outputPort.loading();
Result<bool> result = await _repository.login(params);
result.when(
success: (data) {
outputPort.success();
},
error: (error) {
outputPort.requestError(error);
},
);
}, (errors) {
outputPort.formValidationErrors(errors);
});
}
}
最后,我在演示器中处理演示逻辑,它实现了登录用例的输出端口
class LoginPresenter implements LoginUseCaseOutputPort {
Reader read;
LoginPresenter(this.read) : super(LoginState.initial());
@override
void formValidationErrors(List<Failure> errors) =>
state = LoginState.formValidationErrors(errors);
@override
void success() => read(setRootPresenterProvider.notifier).setMainPageAsRoot();
@override
void loading() => state = LoginState.loading();
@override
void requestError(Failure error) => state = LoginState.requestError(error);
}
我所做的我为每个输入字段创建一个故障类,并返回列表中所有字段的故障,在演示逻辑中,我按类型检查输入故障
我的问题:如果我有一个大表单(例如:15个字段(,我应该为每个表单创建一个失败类吗?是否有更好的方法来处理验证?
我的问题:如果我有一个大表单(例如:15个字段(,我应该为每个表单创建一个失败类吗?是否有更好的方法来处理验证?
每个可能发生的错误都必须是可识别的。通过专用类、故障代码或常量。选择哪一个取决于要提供给客户端的错误上下文信息。
我也不会把消息放在失败对象中,因为由演示者为错误类型选择演示。错误呈现给用户的方式在很大程度上取决于用户界面。也许错误不需要字符串,它只是以图标或彩色标记等形式出现。交互程序不应该创建特定语言的字符串。这是用户界面的一部分。
在简单的情况下,您可能只需要一个错误代码或常量,如401
,演示者会将其转换为Login failed
。当然,在这种情况下也可以使用一个常见的错误对象。
类故障{int代码;}
在其他情况下,您可能希望显示更详细的错误消息,如E-mails under the domain '@somedomain.com' are not allowed to login.
。在这种情况下,您应该使用错误对象,而不是仅使用简单的代码来提供详细信息。例如
类登录域失败{字符串localPart;字符串域名}
然后,演示者可以使用这些信息生成失败字符串或以其他方式显示错误,例如在输入字段中突出显示域名或您可以想象的任何内容。