如何保持DRY与域对象和服务中的验证相对于UI层中的验证

如何解决如何保持DRY与域对象和服务中的验证相对于UI层中的验证

|| 我已经搜索了答案,甚至问了几个与此主题有关的问题,但还没有真正找到正确的答案。如何在POCO Domain对象和服务中向UI层公开验证方法?目前,我正在使用Web表单。 例如,我有以下域对象:
class Person
{
    public string Name { get; set; }
    public string Email { get; set; }

    public bool IsValidEmail(string email) {}
    public bool IsValidName(string name) {}

    public bool IsValidPerson()
    {
        if (IsValidEmail(Email) && IsValidName(Name)) { return true; }
        return false;
    }
}
和域服务:
class PersonService
{

    private Person person;
    private PersonRepository pRepo;

    public PersonService()
    {
        person = new Person();
        pRepo = new PersonRepository();
    }

    public AddPerson(Person p)
    {
        if (p.IsValidEmail(p.Email) && p.IsValidName(p.Name) && !DoesEmailExistInDatabase(p.Email))
        { pRepo.Save(p); }
        else
        { throw new ArgumentException(); }
    }

    public GetPersonByEmail(string email)
    {
        if (person.IsValidEmail(Email))
        { pRepo.GetByEmail(email)); }
        else
        { throw new ArgumentException(); }
    }

    public bool DoesEmailExistInDatabase(string email) { //code if exists.. }
}
和UI / Codebehind层: 通过电子邮件找人
string emailInput = EmailTextBox.Text;

PersonService pService = new PersonService();
Person p = new Person();

if(p.IsValidEmail(emailInput))
{
    Person myPerson = pService.GetPersonByEmail(emailInput);
}
else
{
    //give user error here...
}
为可能需要验证的域对象中的每个属性创建单独的验证方法是否正确? 域对象和服务中的那些方法是否应该是静态的,所以我不必仅仅为了进行验证而创建person的实例? 我是否应该在Service中公开来自Person域对象的验证,以便用户不需要知道从哪里查找(因为我将某些服务投入使用,而将一些POCO投入的原因实际上是实现问题)? 4.有更好的方法吗?     

解决方法

关于#1-是的(这是一种有效方法),前提是假定域对象最适合“知道”什么是正确的输入。 关于#2-是的。 关于#3-这样做没有什么害处,但是,如果您不信任类外部的某些事物能够/负责进行实际的验证,那么为什么您会信任它调用验证呢? 设置值后,我将强制执行验证,一旦您在对象中具有“好数据”,以后就无需验证它了。这导致第4点... 关于#4-以某种方式提供/公开验证的好处是系统的其他部分可以使用它;经典示例在用户界面上,您可以通过验证输入或提交的输入来提供更好的用户体验。 验证的另一种方法是确定(从总体角度看)什么样的好数据-并为(独立的)公共域级别“服务”定义一堆规则。验证每个域对象内的输入是不错的选择,因为随着各个域对象随着时间的推移逐渐成熟(可以限制孤立更改的影响),您可以更改特定的规则-缺点是您将重复很多规则。 普通服务可以解决此问题,服务会说“这是有效的电子邮件地址的样子”,您所有的域对象都将服从该服务以告诉他们什么是好的电子邮件地址。 使用这种方法的“技巧”是要小心命名验证方法的方式-不要太含糊或模棱两可。例如,您可能会发现大多数具有电子邮件属性的域对象都使用一种\“ main \”电子邮件验证方法
ValidateGenericEmail()
,但是您经常会遇到其他对象是具有特殊规则
ValidateCorporateEmail()
的特殊情况。可以,将它们添加到验证服务中,因为这是域层中用于管理这些规则的中心位置。 然后,您的域对象仍然可以执行您需要他们做的所有事情-除了将规则拉到单独的公共位置。     ,我只会在表示层上进行验证,并从中清除域模型。因此,域模型假设数据已经过验证(是经过验证的,不是吗?)。还是您有其他数据来源?  这将使您的域模型更加纯净,您将看到其核心。但是在对象的创建时通过使用保护子句检查构造函数参数来强制执行一些约束是很不错的。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-