使用通知模式进行域验证

2023-11-22

从历史上看,我在对象的构造函数中对对象进行了验证,并在验证失败时抛出异常。例如:

class Name
{
    const MIN_LENGTH = 1;

    const MAX_LENGTH = 120;

    private $value;

    public function __construct(string $name)
    {
        if (!$this->isValidNameLength($name)) {
            throw new InvalidArgumentException(
                sprintf('The name must be between %d and %d characters long', self::MIN_LENGTH, self::MAX_LENGTH)
            );
        }
        $this->value = $name;
    }

    public function changeName(string $name)
    {
        return new self($name);
    }

    private function isValidNameLength(string $name)
    {
        return strlen($name) >= self::MIN_LENGTH && strlen($name) <= self::MAX_LENGTH;
    }
}

虽然我喜欢这种方法,因为我的对象负责强制执行其一致性并确保它始终有效,但我从未对异常的使用过于热衷。虽然有人会争论或反对使用上述异常,但它确实限制了我在对多个对象执行验证时可以返回的验证消息的数量。例如:

class Room
{
    private $name;

    private $description;

    public function __construct(Name $name, Description $description)
    {
        $this->name = $name;
        $this->description = $description;
    }
}

class Name
{
    public function __construct(string $name)
    {
        // do some validation
    }
}

class Description
{
    public function __construct(string $description)
    {
        // do some validation
    }
}

应该两者Name and Description如果验证失败,我希望能够返回两个对象的失败消息,而不仅仅是首先失败的对象的单个异常。

读了一些关于通知模式我觉得这很适合我的场景。我陷入困境的是如何执行验证并防止我的对象在验证失败时进入无效状态。

class Name
{
    const MIN_LENGTH = 1;

    const MAX_LENGTH = 120;

    private $notification;

    private $value;

    public function __construct(string $name, Notification $notification)
    {
        $this->notification = $notification;
        $this->setName($name);
    }

    private function setName(string $name)
    {
        if ($this->isValidNameLength($name)) {
            $this->value = $name;
        }
    }

    private function isValidNameLength(string $name)
    {
        if (strlen($name) < self::MIN_LENGTH || strlen($name) > self::MAX_LENGTH) {
            $this->notification->addError('NAME_LENGTH_INVALID');
            return false;
        }
        return true;
    }

    public function hasError()
    {
        return $this->notification->hasError();
    }

    public function getError()
    {
        return $this->notification->getError();
    }
}

对于以上的情况,我有几个顾虑:

  1. 如果验证失败,则仍会构造该对象,但其$value is null这不是一个有效的状态。
  2. 创建后Name,我一定要记得打电话hasError以确定是否发生验证错误。
  3. 我现在正在用以下方法来处理我的域对象hasError/getError我不确定这是否是一个好的做法。

我是否遗漏了这个拼图的一块?我如何利用通知模式但确保我的对象不会进入无效状态?


我如何利用通知模式但确保我的对象不会进入无效状态?

工厂模式 - 又名“命名构造函数”

您保留构造函数验证 - 您永远不想创建一个无法保留其自身不变量的值。

但是您将构造函数从公共 API 中取出,而是安排客户端代码调用工厂上的方法。该工厂需要决定如何处理构建对象的失败 - 收集你所有的信息通知然后要么

  • 引发包含通知集合的异常
  • 返回包含通知集合的失败类型

取决于您是否喜欢处理带有异常或受歧视联合的控制流。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用通知模式进行域验证 的相关文章

  • 电子商务是否从头开始

    我需要开发一个包含电子商务部分的新网站 我来这里是想从你那里得到一些关于我应该走哪条路的提示 该网站将有一个静态部分 其中包括一些静态页面和用于销售产品的电子商务部分 我是 Django 和 PHP 开发人员 但这是我第一次需要开发电子商务
  • 是检测异常并抛出它们还是让运行时抛出它们更好?

    假设有这样的设置 public class MyClass public void DoSomething string Data if String IsNullOrWhiteSpace Data throw new NullRefere
  • 用于匹配某些数字的正则表达式

    以下正则表达式将匹配 9 11 位数字 d 9 11 编写完全匹配 9 的正则表达式的最佳方法是什么or11位数字 不包括10位 使用输入元素的模式属性 因此正则表达式应该匹配输入字段的整个值 我想接受任何包含 9 或 11 位数字的号码
  • PHP 异常处理与 C#

    这是一个非常基本的问题 我希望如此 我所做的大部分异常处理都是使用 C 进行的 在 C 中 任何在 try catch 块中出错的代码都会由 catch 代码处理 例如 try int divByZero 45 0 catch Except
  • 聚合物在核心输入上使用功能验证

    有人可以解释一下如何使用函数验证吗这种聚合物元素 http www polymer project org docs elements core elements html core input 导航到 验证 部分
  • Symfony2,如何向表单添加隐藏的日期类型字段?

    我正在尝试以下场景 In myclassType public function buildForm FormBuilder builder array options builder gt add day hidden gt add da
  • CakePHP Auth 组件使用 $this->Auth->login() 时未登录;

    我是 cakePHP 的新手 我已经阅读了他们的文档 并且正在遵循他们的简单身份验证示例 我还广泛搜索 包括本网站上的答案 来寻找我的问题的答案 我正在使用 cakePHP 2 0 我的 UsersController 的登录功能如下所示
  • 转义用户数据,无需魔法引号

    我正在研究如何在来自外部世界的数据被用于应用程序控制 存储 逻辑等之前正确地对其进行转义 显然 随着 magic quote 指令在 php 5 3 0 中很快被弃用 并在 php6 中被删除 对于任何想要升级并进入新语言功能 同时维护遗留
  • 如何在没有 session_destroy 的情况下销毁 Zend_Session_Namespace

    我使用以下方法在临时会话中存储一些值 job new Zend Session Namespace application 我如何只销毁会话应用无需清除所有会话 要从会话中删除值 请对对象属性使用 PHP 的 unset 函数 假设 job
  • DataTables 第 2 页的分页未调用放大弹出窗口

    所以我有这个启用分页的数据表 我编码了一种方式 以便用户可以编辑表的行 当用户调用它在放大弹出窗口中打开的编辑页面时 它在第 1 页 从第 2 页起都运行良好 DataTable 及其前面停止调用 Magnific Popup 我只是不明白
  • CryptoJS 使用密码加密 AES,但 PHP 解密需要密钥

    我在用CryptoJS https code google com p crypto js AES加密字符串 function doHash msg msg String msg var passphrase aggourakia var
  • php隐藏所有错误[重复]

    这个问题在这里已经有答案了 隐藏的最佳做法是什么allPHP 错误 因为我不想向用户显示错误 我尝试过使用 htacess通过输入代码php flag display errors off在那里 但它返回给我一个500 error 还有其他
  • 如何使用正则表达式验证 1-99 范围?

    我需要验证一些用户输入 以确保输入的数字在 1 99 范围内 含 这些必须是整数 Integer 值 允许前面加 0 但可选 有效值 1 01 10 99 09 无效值 0 007 100 10 5 010 到目前为止 我已经制定了以下正则
  • 错误 #520009 - 帐户受到限制

    我收到 520009 错误 帐户 电子邮件受保护 cdn cgi l email protection被限制 当尝试进行并行付款时 我的代码使用沙箱运行良好 但我切换到实时端点 它开始失败 有问题的帐户是有效的 PayPal 帐户 我使用的
  • 在 PHP 中将整数转换为十六进制值

    如何将PHP中第一类中的数字转换为第二类中的数字 是否有内置函数来转换数字 也是我的标题 将整数转换为十六进制值 甚至正确 class Permission const READ 1 const UPDATE 2 const DELETE
  • Gearman,php 扩展问题:使用终端在 .. 中找不到类“GearmanWorker”,但可以在浏览器上使用

    我最近在 ubuntu 10 04 上安装了 gearman 并安装了它的 pecl 扩展 现在 当我在浏览器中运行一个 php 文件时 其中包含 client new GearmanWorker die var Dump client I
  • 细胞的 fpdf 对齐

    我正在尝试使用生成 PDFfpdf我有一个小问题 我需要有 2 个单元格 如下所示 Address Line 1 Version Address Line 2 1 0 City 06 05 2011 我尝试过使用MultiCell 但没有运
  • 从检查元素隐藏 ''

    我有这个 HTML 和 PHP 联系表
  • PHP 中根据相似值对数组进行分组

    我有一个具有以下结构的数组
  • Mysql加密/存储敏感数据,

    我的 PHP 网站有以下内容 启用 SSL 饼干 session set cookie params cookieParams lifetime cookieParams path cookieParams domain secure ht

随机推荐

  • 绑定到 DataTable 的滚动事件

    我需要绑定到设置为垂直滚动的 DataTable 的滚动事件 很明显 简单的事件绑定是行不通的 table tbody on scroll function alert 我创建了一个demo here 有谁知道可以执行此操作的 API 方法
  • .NET 中每个文件规则一个类? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 我遵循这条规则 但我的一些同事不同意它 并认为如果一个类较小 它可以与其他类留在同一个文件中 我经常听到的另一个论点是 连微软都不这样做 那我们为什么要这样做呢 对此 普遍的共识是什么 在
  • 模板概念进入了 c++14 吗?

    概念是一个很好的功能 例如 当模板实例化出现问题时 它可以用可读的消息替换丑陋的编译器错误输出 不幸的是他们没有得到to C 11 有人知道它是否进入了 C 14 吗 No but 对 Bjarne Stroustrup 的采访表示它们将被
  • 如何将 FOS\RestBundle 的默认格式指定为 json?

    我对应的配置是 fos rest view view response listener force sensio framework extra view annotations false 将路线指定为确实很烦人 Route jobs
  • Python 过滤器/最大组合 - 检查空迭代器

    使用Python 3 1 我知道这个问题已经被问过很多次 用于测试迭代器是否为空的一般问题 显然 对此没有简洁的解决方案 我猜是有原因的 迭代器在被要求返回下一个值之前并不真正知道它是否为空 不过 我有一个具体的例子 希望我能从中编写出干净
  • 如何将字符串转换为 IP 地址,反之亦然

    如何转换字符串 ipAddress struct in addr 反之亦然 如何提交未签名的长 ip 地址 谢谢 Use inet ntop and inet pton 如果你需要其他方式 不使用inet ntoa inet aton 类似
  • Java 6 启动画面

    我一直无法让 Java 6 启动屏幕正常工作 我已经尝试了我能想到的一切 我的manifest mf包含 Manifest Version 1 0 X COMMENT Main Class will be added automatical
  • 推断 CRTP 中模板化成员函数的返回类型

    是否可以推断 CRTP 基类中模板化成员函数的返回类型 虽然推断参数类型效果很好 但返回类型却失败了 考虑下面的例子 include
  • M1(Apple Silicon)上的 CocoaPods 失败,架构错误

    由于 ffi 问题 在 M1 MacBook 上运行 pod install 失败 如上所述here 我遵循了一些解决方法 我想我以不同的顺序尝试了所有这些方法 但现在我得到了一个略有不同的错误 LoadError dlopen opt h
  • 将 java.util.Calendar ISO 8601 格式转换为 java.sql.Timestamp

    我有一个 ISO 8601 日期格式的日期2015 09 08T01 55 28Z 我使用此代码将 ISO 8601 命运转换为 Calendar 对象 Calendar cal javax xml bind DatatypeConvert
  • 如何在SQL表中插入默认值?

    我有一个这样的表 create table1 field1 int field2 int default 5557 field3 int default 1337 field4 int default 1337 我想插入具有 field2
  • 将浮点数转换为字符串的最快 C++ 方法

    我遇到了将浮点数转换为字符串的问题to string对我来说太慢了 因为我的数据可能涉及几百万个浮点数 我已经有了解决方案如何快速写出这些数据 然而 在解决这个问题之后 我很快意识到浮点到字符串的转换正在留下很大的影响 那么 除了使用其他非
  • SVG 中的 HTML

    我想在一个文件中添加一些 HTML 标记SVG绘画 据我所知 这是不可能的SVG 图像显示在浏览器中 有没有办法画HTML上面的SVG 因为我想使用CSS table特点HTML the SVG
  • 如何以编程方式创建给定网站的屏幕截图?

    我希望能够创建给定网站的屏幕截图 但该网站可能大于屏幕上可以查看的大小 我有办法做到这一点吗 目标是在 WinForms 应用程序中使用 C 中的 NET 来完成此操作 有一些工具 问题是 您需要在某个给定的程序中渲染它 并拍摄它的快照 我
  • Eclipse 选项卡损坏了如何修复?

    我刚刚下载了 eclipse 但它显示的语言是错误的 我该如何解决这个问题 这是由 Windows 中的字体设置引起的 它描述于thisEclipse 错误报告 由于不是 Eclipse 错误而关闭 您应该能够在 Eclipse 中通过更改
  • CakePHP 中的模型可以有多个表吗?

    CakePHP 中的模型可以有多个表吗 从说明书上这句话猜测 模型通常是数据库的访问点 更具体地说 是数据库中某个表的访问点 默认情况下 每个模型都使用其名称的复数形式的表 即 User 模型使用 users 表 我不这么认为 但你可以建立
  • PHP 中参数类型可以特化吗

    假设我们有以下两个类 abstract class Foo public abstract function run TypeA object class Bar extends Foo public function run TypeB
  • 如何自动缩放字体大小以适应 div 的内容?

    我有一个带有一些文本的 div div style width 50px With some text in it div 如何缩放文本的字体大小以使所有文本都可见 反之亦然 您可以将文本包装在内部 DIV 中 并使用 JavaScript
  • 有关 Azure 实例分配带宽的问题

    我从 Azure 了解到一些事实 每个实例的带宽有限 例如 Extra Small 实例有 5Mb s 我们只支付出站带宽 入站免费 同一个数据中心 流量免费 即使对于小实例 我检查了网络接口 连接速度为10G 因此分配的带宽始终低于网络接
  • 使用通知模式进行域验证

    从历史上看 我在对象的构造函数中对对象进行了验证 并在验证失败时抛出异常 例如 class Name const MIN LENGTH 1 const MAX LENGTH 120 private value public function