在软件领域的商业模型中,领域模型是否通常更非规范化?我对这个特别的例子有疑问,
这是数据库中的客户服务案例。
在领域模型中,
是将所有字段放到一个类中,将CustomerService、CustomerServiceStatus、Type等组合成一个域类(一个平坦的宽表),还是保持原始数据模型结构的规范化?我相信CustomerService大小写是指向查找表、类型和状态等的聚合根吗?
数据库中的支架模型:
CustomerService Case
public class CustomerServiceCase
{
public int CustomerServiceCaseId { get; set; }
public int? CustomerServiceCaseStatusId { get; set; }
public int? CustomerServiceCaseTypeId { get; set; }
public int? LastModifiedByUserId { get; set; }
public string CustomerServiceCaseNumber { get; set; }
public DateTime? CustomerServiceCaseReceiveDate { get; set; }
public DateTime? CustomerServiceCaseCreateDate { get; set; }
public virtual CustomerServiceCaseStatus CustomerServiceCaseStatus { get; set; }
public virtual CustomerServiceCaseType CustomerServiceCaseType { get; set; }
}客户案例服务状态:
public class CustomerServiceCaseStatus
{
public int CustomerServiceCaseStatusId { get; set; }
public int? LastModifiedByUserId { get; set; }
public string CustomerServiceCaseStatusCode { get; set; }
public string CustomerServiceCaseStatusDescription { get; set; }
public bool? Status { get; set; }
public DateTime? CreateDate { get; set; }
public DateTime? EffectiveStartDate { get; set; }
public DateTime? EffectiveEndDate { get; set; }
public virtual ICollection<CustomerServiceCase> CustomerServiceCase { get; set; }
}客户服务案例类型:
public class CustomerServiceCaseType
{
public int CustomerServiceCaseTypeId { get; set; }
public string CustomerServiceCaseTypeCode { get; set; }
public string CustomerServiceCaseTypeDescription { get; set; }
public int? LastModifiedByUserId { get; set; }
public bool? Status { get; set; }
public DateTime? CreateDate { get; set; }
public DateTime? EffectiveStartDate { get; set; }
public DateTime? EffectiveEndDate { get; set; }
public virtual ICollection<CustomerServiceCase> CustomerServiceCase { get; set; }
}发布于 2019-08-13 00:14:12
我不确定我是否完全理解您的用例(比如需要单独存储CustomerServiceCaseType --我认为用例类型是有限的、定义得很好)。您可能在谈论用于存储CustomerServiceCaseType的主表,这是您在CustomerServiceCase类中所引用的。
尽管如此,让我从领域驱动的设计角度来概括地回答这个问题.
DDD本身并不关心数据如何存储在底层的持久化存储中,您的域模型应该与数据库无关,而不关心使用哪种基础结构。
所有与持久性相关的方面都应该由存储库处理。他们负责加载和持久化聚合,他们可以自由地以任何他们认为合适的方式来处理这个问题。应用程序服务通常使用这些存储库加载和持久化数据。
如果您使用像MongoDB这样的文档存储,您的聚合可能会存储为一个大文档,包括它自己的字段以及它所包含的实体和value对象的字段。因此,存储库只需对数据库进行一次查询。
如果使用RDBMS,可能最终会有一个非规范化结构。然后,您的存储库将执行多个调用或使用联接来加载数据。但无论何时加载聚合,它都会这样做。在加载聚合时,不应该懒洋洋地评估链接,因为聚合应该满足其封闭域对象的所有不变量。
下面是一个粗略的伪代码示例,它显示了域对象和数据存储之间的断开。
##############
Domain Classes
##############
class Order
{
String order_number;
List<OrderLine> order_lines;
Timestamp ordered_on;
String status;
public Order build(params)
{
...
}
}
class OrderLine
{
Integer product_id;
Float price;
Float quantity;
Float tax;
Float total;
Integer sequence;
String shipped_status;
public OrderLine build(params)
{
...
}
}
###################
Application Service
###################
class OrderService
{
Boolean place_order(params)
{
IRepository OrderRepository; // Repository object is injected here
new_order = Order.build(params);
OrderRepository.create_new_order(new_order);
}
}
##############
Infrastructure
##############
class OrderRepository extends IRepository
{
public create_new_order(order)
{
// This is for illustration purposes only. You would probably use ORM tool to accomplish this.
order_sql = "INSERT INTO order VALUES".format(order.order_number, order.ordered_on, ...)
List<String> order_line_sqls;
for each order_line in order.order_lines
{
order_line_sqls.append("INSERT into order_line VALUES(?, ?, ...)".format(order_line.product_id, order_line.price, ...))
}
// You would use a Unit of Work here
result = db.exec(order_sql)
if result = true:
for each order_line_sql in order_line_sqls
{
result = db.exec(order_line_sql)
if result != true:
raise Error("Transaction Failed") // and rollback
}
}
}下面是相反情况的一个例子,其中有一个域元素,但是存储在两个单独的表中(可能是出于性能、报告、数据导出等原因,尽管我在过去的项目中从未亲自做过):
class User
{
String email;
String username;
String password;
String address1;
String address2;
String address3;
String city;
String province;
String zipcode;
public User build(params)
{
...
}
}
class UserRepository extends IRepository
{
public static persist_user(user)
{
// This is for illustration purposes only. You would probably use ORM tool to accomplish this.
user_sql = "INSERT INTO user VALUES(?, ?, ?, ...)".format(user.email, user.username, user.password)
address_sql = "INSERT INTO user_address VALUES(?, ?, ?, ...)".format(user.address1, user.city, ...)
// You would use a Unit of Work here
result = db.exec(user_sql)
if result = true
{
result = db.exec(address_sql)
if result != true
{
raise Error("Transaction Failed") // and rollback
}
}
}
}https://stackoverflow.com/questions/57469316
复制相似问题