You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何验证传递给Domain Service的基本类型参数?以cost参数为例

如何验证Domain Service中的cost参数?值对象是最优解吗?

嘿,这个问题问到点子上了!在领域驱动设计(DDD)的场景里,把cost封装成值对象绝对是处理这类带业务规则参数的最优方案,远胜过在Domain Service里零散添加验证逻辑。我来给你拆解下原因,再举个实际例子:

为什么要用值对象封装?

  • 业务规则内聚:把英镑金额的所有验证规则(大于0、必须保留两位小数)都放在值对象的构造/创建方法里,所有用到这个金额的地方都会自动遵循规则,不会出现重复验证、遗漏规则的情况,完全符合DRY原则。
  • 代码表达力拉满:用SterlingAmount代替冷冰冰的decimal,其他开发者一看就知道这是专属英镑的金额类型,不是随便的数字,可读性直接提升一个档次。
  • 不可变性保障:值对象天生应该是不可变的——一旦创建就不能修改,从根源上避免业务逻辑中意外篡改金额的风险,让状态更可控。

举个具体的实现例子(以C#为例)

先定义英镑金额的值对象:

public sealed record SterlingAmount
{
    // 对外暴露只读的金额值
    public decimal Value { get; }

    // 私有构造函数,强制通过Create方法创建实例
    private SterlingAmount(decimal value)
    {
        Value = value;
    }

    // 静态工厂方法,集中处理验证逻辑
    public static SterlingAmount Create(decimal cost)
    {
        // 验证规则1:金额必须大于0
        if (cost <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(cost), "英镑支付金额必须大于0");
        }

        // 验证规则2:必须保留两位小数(确保是合法的货币格式)
        if (Math.Round(cost, 2) != cost)
        {
            throw new ArgumentException("英镑支付金额必须保留两位小数", nameof(cost));
        }

        return new SterlingAmount(cost);
    }

    // 还可以添加业务相关的方法,比如金额加减
    public SterlingAmount Add(SterlingAmount other)
    {
        return Create(Value + other.Value);
    }
}

然后在你的Domain Service里直接使用这个值对象:

public class PaymentDomainService
{
    public void ProcessSterlingPayment(SterlingAmount cost, PaymentDetails paymentDetails)
    {
        // 这里完全不用再验证cost了!
        // 因为能传到这里的SterlingAmount一定是符合所有业务规则的合法实例
        // 直接专注于支付处理的核心业务逻辑即可
        Console.WriteLine($"开始处理金额为{cost.Value}英镑的支付请求");
        // ... 其他业务代码
    }
}

如果不封装值对象会有什么问题?

要是你直接在Service里写验证逻辑,会出现这些麻烦:

  • 每次用到cost参数都要重复写一遍验证代码,容易漏写或者写错;
  • 业务规则分散在多个地方,后续如果要调整规则(比如改成保留三位小数),得找到所有验证的地方逐一修改,维护成本极高;
  • 代码表达力弱,别人看到decimal cost根本不知道这是英镑还是其他货币,容易误用。

所以总结下来,把带业务规则的参数封装成值对象,是完全符合DDD思想的最佳实践,既保证了业务规则的一致性,又让代码更清晰、更易维护。

内容的提问来源于stack exchange,提问作者w0051977

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:38:08