标签: value-objects

DDD:值对象中是否有列表?

我不熟悉域驱动设计,最近我开始为项目创建域模型.我还没有决定使用ORM(虽然我可能会选择NHibernate)而且我目前正在努力确保我的Value Objects应该就是这样.

我有一些VO除了封装"喜欢"术语之外几乎没有任何行为,例如:

public class Referral {
    public Case Case { get; set; } // this is the a reference to the aggregate root
    public ReferralType ReferralType { get; set; } // this is an enum
    public string ReferralTypeOther { get; set; }
} // etc, etc.
Run Code Online (Sandbox Code Playgroud)

这个特殊的类有一个参考"案例",这是两个级别,所以如果说我要访问推荐我可以去:case.social.referral(案例,社交和推荐都是所有类,有一个单一的社交在一个案例中,社交中有一个推荐).现在,当我输入它时我正在查看它,我认为我不需要推荐中的案例,因为它可以通过社交实体访问,对吗?

现在,毫无疑问,我认为这应该是一个VO,而我计划用来将其保存到数据库的方法是让NHibernate为它分配一个代理标识符(我仍然不太清楚) ,如果有人可以请详细说明它也会帮助我,因为我不知道代理标识符是否要求我已经在我的VO中有一个Id,或者它是否可以在没有一个的情况下运行)和/或受保护的Id属性不会在Referral类之外暴露(仅用于持久保存到DB).

现在转到我的标题问题:VO应该有一个集合,(在我的情况下是一个List)里面吗?我只能将其视为数据库中的一对多关系,但由于没有身份,因此使类成为实体似乎不够.以下是代码:

public class LivingSituation {
    private IList<AdultAtHome> AdultsAtHome { get; set; }
    public ResidingWith CurrentlyResidingWith { get; set } // this is an enum
} // etc, etc.
Run Code Online (Sandbox Code Playgroud)

这个类目前没有Id,而AdultsAtHome类只有内在类型(string,int).所以我不确定这是否应该是一个实体,或者它是否可以作为VO保留,我只需要使用自己的表和私有/受保护的Id字段将我的ORM配置为使用1:m关系,以便ORM可以持久保存到DB.

另外,我应该为每个课程使用规范化表格吗?我想我只需要为每个类使用一个表,当有可能将类的多个实例分配给实体或值对象时和/或有可能与这些对象中的某些对象具有集合1:m的关系.对于具有内部类型但具有嵌套类型的某些值对象使用单个表我没有问题我认为使用规范化表是有利的.对此有何建议? …

c# domain-driven-design nhibernate-mapping value-objects

7
推荐指数
1
解决办法
1817
查看次数

域对象和值对象 - 它们是否相等?

通过查看Zend Quickstart教程中的域对象示例以及考虑DAO/VO模式的其他示例,它们似乎都非常相似.

我们可以推断说"价值对象"与"域对象"是一样的吗?

如果没有,你能澄清一下它们之间的区别吗?

一个人的功能是什么,如果另一个人的功能怎么办?

我问这个是因为,两者都是由吸气剂和制定者组成的,仅此而已.看起来,他们做同样的功能......

更新:

所以,Zend Framework Quick Tutorial文档称之为域对象:

 // application/models/Guestbook.php

    class Application_Model_Guestbook
    {
        protected $_comment;
        protected $_created;
        protected $_email;
        protected $_id;

        public function __construct(array $options = null)
        {
            if (is_array($options)) {
                $this->setOptions($options);
            }
        }

        public function __set($name, $value)
        {
            $method = 'set' . $name;
            if (('mapper' == $name) || !method_exists($this, $method)) {
                throw new Exception('Invalid guestbook property');
            }
            $this->$method($value);
        }

        public function __get($name)
        {
            $method = 'get' . $name;
            if (('mapper' == $name) || !method_exists($this, $method)) { …
Run Code Online (Sandbox Code Playgroud)

oop design-patterns zend-framework domain-object value-objects

7
推荐指数
1
解决办法
4930
查看次数

REST API中的聚合值

我正在申请一项需要一些复式记账的申请.目前有两个端点

/account
/transaction
Run Code Online (Sandbox Code Playgroud)

/account处理账户的一般数据时,/transaction处理存款/取款的交易.账户余额根据相关交易计算.我将它们分开以便在将值从一个账户转移到另一个账户时保持一致性.

我的问题是如何在/account端点上表示帐户的余额,因为它总是在请求时计算.响应是否应将余额作为只读字段包含?这有点像糟糕的API设计,因为所有字段,但这一个是可写/可更新的.

我想到的另一种方法是将端点扩展到

/account/{id}/balance
Run Code Online (Sandbox Code Playgroud)

仅返回相关帐户的余额.但是,除了帐户的剩余数据之外,这总是需要第二次调用以获得余额.也许答案可以概括如何表示聚合值.

api rest transactions aggregate value-objects

7
推荐指数
1
解决办法
885
查看次数

如何使用 Entity Framework Core 3.0 创建所需的拥有类型

我正在努力使用 Entity Framework Core 创建一个不可为空/必需的拥有类型。我正在对 PostgreSQL 数据库使用 EF Core 3.0。

我的价值对象:

    public class PersonName
    {
        public PersonName(string name)
        {
            this.Name = name;
        }

        public string Name { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

我的实体:

    public class Person
    {
        public int Id { get; set; }

        public virtual PersonName FullName { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

我的实体配置:

    public void Configure(EntityTypeBuilder<Person> builder)
    {
        builder.ToTable(nameof(Person));
        builder.HasKey(person => person.Id);

        builder.OwnsOne(person => person.FullName, personName =>
        {
           personName.Property(pn => pn.Name).IsRequired().HasColumnName("FullName");
        });
    }
Run Code Online (Sandbox Code Playgroud)

值类型属性已成功保存到数据库中的“Person”表中,但尽管我使用的是“IsRequired()”方法,但该列仍然可以为空。

非常感谢!

c# postgresql value-objects entity-framework-core owned-types

7
推荐指数
1
解决办法
1328
查看次数

DDD:实体和价值对象之间的差异有什么用?

实体和值对象都是域对象.了解DDD中两者之间的区别有什么用?例如,将域对象视为实体或值对象是否会促成更清晰的域模型?

entities domain-driven-design value-objects

6
推荐指数
1
解决办法
1602
查看次数

如何使用Fluent NHibernate自动化一组组件?

我的所有实体和值对象都实现了标记接口IEntityIValueObject.我把它们设置为像这样的组件:

public override bool IsComponent(Type type)
{
    return typeof(IValueObject).IsAssignableFrom(type);
}

public override bool ShouldMap(Type type)
{
    return typeof(IEntity).IsAssignableFrom(type) || typeof(IValueObject).IsAssignableFrom(type);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这似乎不允许将具有值对象集合的实体自动化为组件集合.例如:

public class MyEntity : IEntity
{
    public IList<MyValueObject> Objects { get; set; }
}

public class MyValueObject : IValueObject
{
    public string Name { get; set; }
    public string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法定义一个约定,这样,只要IEntityIList一个类型实现IValueObject,它就像我指定的那样被映射:

HasMany(x => x.Objects)
    .Component(x => { 
        x.Map(m => m.Name); 
        x.Map(m => m.Value); …
Run Code Online (Sandbox Code Playgroud)

nhibernate components fluent-nhibernate automapping value-objects

6
推荐指数
1
解决办法
760
查看次数

DDD:如何保持复杂值对象不可变?

我想将一个模型Address作为一个值对象.因为将它变为不可变是一个好习惯,所以我选择不提供任何可能允许稍后修改它的setter.

一种常见的方法是将数据传递给构造函数; 但是,当值对象非常大时,可能会变得非常臃肿:

class Address {
    public function __construct(
        Point $location,
        $houseNumber,
        $streetName,
        $postcode,
        $poBox,
        $city,
        $region,
        $country) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是将参数作为数组提供,从而产生一个干净的构造函数,但这可能会破坏构造函数的实现:

class Address {
    public function __construct(array $parts) {
        if (! isset($parts['location']) || ! $location instanceof Point) {
            throw new Exception('The location is required');
        }
        $this->location = $location;
        // ...
        if (isset($parts['poBox'])) {
            $this->poBox = $parts['poBox'];
        }
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这对我来说也有点不自然.

关于如何正确实现一个非常大的价值对象的任何建议?

domain-driven-design immutability value-objects php-5.3

6
推荐指数
1
解决办法
2228
查看次数

在D中实现值对象模式

我想在D中实现值对象模式.也就是说,我希望将可变引用变量赋予不可变对象.T变量应该是可赋值的,但是T对象永远不应该改变它们的状态.

我对D constimmutableD 之间的区别感到困惑.让我用骷髅Rational课来说明我的疑惑:

class Rational
{
    int num;
    int den;
Run Code Online (Sandbox Code Playgroud)

我应该声明numden作为constimmutable?整数有区别吗?

    invariant()
    {
        assert(den > 0);
        assert(gcd(abs(num), den) == 1);
    }
Run Code Online (Sandbox Code Playgroud)

我应该声明invariantconstimmutable?将其标记为immutable导致编译时错误,但这可能是由于其他成员未被标记immutable.

    this(int numerator, int denominator) { ... }
Run Code Online (Sandbox Code Playgroud)

我应该将构造函数声明为constimmutable?那是什么意思?

    string toString()
    {
        return std.string.format("(%s / %s)", num, den);
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该声明toStringconstimmutable? …

design-patterns d const immutability value-objects

6
推荐指数
1
解决办法
337
查看次数

如何在域驱动设计中共享表单和值对象之间的验证?

#1.验证表单上的EmailAddress

我有一个后端表单类,其emailAddress属性具有验证逻辑,以便我可以将错误消息返回给用户.我使用类似的方式验证所有表单输入:

$form->fillWith($request->input());

if($form->validate()){
    $form->dispatch($command); // if synchronous, form takes command's messageBag
}

return response($form->getMessageBag()->toJson());
Run Code Online (Sandbox Code Playgroud)

#2.在命令处理程序中验证EmailAddress值对象

我有一个命令处理程序,它将获取原始字符串电子邮件并创建一个值对象.如果电子邮件无效,则value对象将在创建时抛出异常:

public function handle($command){

   try {
      $emailAddress = new ValueObjects\EmailAddress($command->emailAddress);

      // create more value objects...

      // do something else with the domain...

   } catch (DomainException $e) {
        $this->messageBag->add("errors", $e->getMessage());
   } catch (\Exception $e) {
        $this->messageBag->add("errors", "unexpected error");
   }

   return $this->messageBag;
}
Run Code Online (Sandbox Code Playgroud)

在#1中,我希望在发送命令之前尽早捕获验证.但是在#2中,当我构建VO时,重复验证逻辑.

我遇到的问题:

  • 如果我需要更改电子邮件地址的验证要求,那么我必须更新这两个地方.
  • 如果我在表单上使用VO,那么在传递给命令时我将不得不再次解构它们.另外,如果我的表单处于不同的Bounded Context中,那么我将让VO从其他Bounded Context中泄漏域(可能这是必要的吗?).

所以我的问题是,我应该创建一些验证器对象,我的表单验证和VO可以共享/利用吗?或者如何捕获表单和值对象之间的重复验证问题?

forms validation domain-driven-design value-objects

6
推荐指数
1
解决办法
784
查看次数

EF Core - 使用值对象和父类型创建复合唯一索引

我有一个带有ExternalSystemName 值对象和另一个实体的部署父类型的实体。该模型的重要部分如下所示:

public sealed class ExternalSystem : Entity
{
    public ExternalSystemName Name { get; private set; }

    public Deployment Deployment { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

该实体的唯一性由部署 ID(存储在部署实体类中)和名称(ExternalSystemName 值对象的值)的组合确定。换句话说,一个部署不能有 2 个同名的外部系统。

我在尝试使用 IEntityTypeConfiguration 实现设置此组合唯一索引时遇到问题:

internal sealed class ExternalSystemsConfiguration : 
IEntityTypeConfiguration<ExternalSystem>
{
    public void Configure(EntityTypeBuilder<ExternalSystem> builder)
    {
        builder.ToTable("TblExternalSystems");

        builder.OwnsOne(e => e.Name, navigationBuilder =>
        {
            navigationBuilder.Property(e => e.Value)
            .HasColumnName("Name");
        });

        builder.HasIndex(e => new { e.Name, e.Deployment }).IsUnique();
    }
}
Run Code Online (Sandbox Code Playgroud)

我在运行 API 时遇到此异常:

System.InvalidOperationException: ''Name' cannot be used as a property on entity …
Run Code Online (Sandbox Code Playgroud)

c# unique-constraint value-objects entity-framework-core

6
推荐指数
1
解决办法
1598
查看次数