0

I have a "MyUnits" application that let's manage Units (like meters, kilograms, pounds, miles, km/h...). The model is complex, it supports unit compatibilities, operations, conversions, etc.

I have another application (MyApp) that will need to use "units", so I want to make it use my "Units" application.

What I thought is to have a "Units" service (webservice) UnitService that consumes and returns a Unit DTO UnitDTO.

In MyApp, I have this model:

Operand
    value: float
    unit: UnitDTO
OperationAdd
    operand1: Operand
    operand2: Operand
    execute()

The problem: in OperationAdd.execute(), I need to check that units are compatibles (for example).

So either:

  • UnitDTO has a method that will call UnitService::areCompatible, but that is wrong! How a DTO (that should only contain data) knows UnitService which is a webservice! It shouldn't

  • OperationAdd.execute() calls UnitService::areCompatible, but that is wrong! How OperationAdd (an entity) knows UnitService which is a webservice! It shouldn't

  • or I have a OperationService that does the work (and that can call services) but my Operation entities would be like data containers, entities with no methods, and that's not really what DDD is about

I don't want anemic entities, but in the case where I have an entity that uses a service, how can I do?

And: am I wrong thinking that UnitDTO can be used as a VO?

4

1 回答 1

0

一个单元应该“宣传”它的兼容性。我不知道您使用的语言是否支持泛型,但我会这样做。

首先,UnitDto 包含某个 Unit 的状态。使用 UniDto 创建具体的 Unit(顺便说一句,它是一个 VO)。每个 Unit 都应该知道它的兼容性。UnitDTO 应该只是一个 DTO,创建其他可以完成工作的 VO。

C#

public class UnitBase
{
    public virtual bool IsCompatible(UnitBase unit)
    {
        return false;
    }
}

public interface ICompatible<T>
{
     bool IsCompatible(T unit);
}
public class UnitFeet {}
public class UnitMeter:UnitBase,ICompatible<UnitFeet>
{
    bool IsCompatible(UnitFeet unit) { return true;}
 }
 public override bool IsCompatible(UnitBase unit)
 {
    return IsCompatible((UnitFeet)unit);

 } 

编译器应根据比较的单元选择正确的重载。ICompatbile 接口也可以具有从一个单元到另一个单元的转换方法。但是让我们假设你想要更抽象的东西

public class OperandValue:ICompatbile<OperandValue>
{ 
     public decimal Value {get;set;}
     public UnitBase Unit {get;set;}
     public bool IsCompatbile(OperandValue other)
     {
        return Unit.IsCompatbile(other.Unit);
     }

     public static OperandValue FromDto(Operand data)
      {
         return new OperandValue(data.Value,UnitBase.FromDto(data.Unit));
       }
}

 OperandValue first=OperandValue.FromDto(operand1);
 OperandValue second=OperandValue.FromDto(operand2);

if (first.IsCompatbile(second)){
    OperationService.Add(first,second)
  }

所以你不需要 UnitService::AreCompatbile 方法,只需要大量的多态性和仔细的对象设计。

于 2013-04-19T12:59:58.637 回答