簡體   English   中英

根據外部調用構造域對象的最佳實踐是什么?

[英]What is the best practice to construct a Domain Object depending on external calls?

我正在嘗試構建一個從外部 API 獲取其數據的對象。 我將嘗試用一個例子來解釋它:

首先,我在我的 API 中獲得一個 POST 正文來創建一個對象:

class CarRequestBody {
    private String colorId;
    private String engineId;
    //Constructors, etc.
}

然后有了這些信息,我需要構建 Car 的詳細實例。 從外部服務提供數據:

ColorDetails color = colorApiClient.getColor(colorId);
EngineSpecifications engine = engineApiClient.getEngine(engineId);

最后,我用所有這些信息構建了我的域對象。

所以我想知道構建實例的最佳實踐是什么。 我以3種不同的方式思考過:

1 - CarService 中的方法如下:

public Car createCar(CartRequestBody body) {
    ColorDetails color = colorApiClient.getColor(body.getColorId);
    EngineSpecifications engine = engineApiClient.getEngine(body.getEngineId);
    Car car = new Car(color, engine);
} 

2 - 在構造函數中輸入數據:

public Car(CarRequestBody body) {
    this.color = colorApiClient.getColor(body.getColorId);
    this.engine = engineApiClient.getEngine(body.getEngineId);
}

3 - 在域類的吸氣劑中:

class Car {
    private ColorData color;
    private EngineSpecifications engine;
    //Constructor

    public ColorData getColor() {
        if (color == null){
            return colorApiClient.getColor(colorId);
        }
        return this.color;
    }
    ....
}

這種情況有一些設計模式嗎?

我建議使用Builder設計模式。

在這里你可以看到代碼 -

汽車.java

 public class Car{   
   private ColorDetails colorDetails;
   private EngineSpecifications specifications;

  private Car(CarBuilder builder){
      this.colorDetails = builder.colorDetails;
      this.specifications = builder.specifications;
  }

  public static class CarBuilder {

      private ColorDetails colorDetails;
      private EngineSpecifications specifications;

      public CarBuilder withColor(ColorDetails colorDetails) {
        this.colorDetails = colorDetails;
        return this;
    }
     public CarBuilder withSpecifications(EngineSpecifications 
          specifications) {
        this.specifications = specifications;
        return this;
    }
    
   public Car build() {
        Car car = new Car(this);
        return car;
       }
   }
 }

// 客戶端代碼

 public class Client{

  ColorDetails color = colorApiClient.getColor(colorId);
  EngineSpecifications engine = engineApiClient.getEngine(engineId);
 Car car = new Car.CarBuilder()
          .withColor(color)
          .withSpecifications(engine)
          .build();
   }

如果你的目標是保持你的設計干凈,你的域類Car應該只知道它需要正常運行的對象,如ColorDataEngineSpecificationsonly

apiClient注入Car類不是一個好主意,因為它與它的功能無關,並且會增加耦合

此外,如果 API 調用失敗怎么辦,您真的想將處理這種情況的管道代碼添加到構造函數中嗎?

同樣,我看不出定義一個期望CarRequestBody的構造函數有什么好處。

最簡潔的方法是讓域類的構造函數保持簡單,並且不受不需要它們執行的對象的影響。 如果你想概括這些領域類的實例化過程,你可以引入實用方法來處理它。

一個簡單的構造函數會有什么問題? 我不知道 Java,但在 C# 中是這樣的:

class Car {
   ...
    public Car(Color color, Engine engine) {
   ... // set properties with the parameters
   }
}

哦,如果你想做一些解耦,請不要在你的域中使用與 API 中相同的對象。 所以你需要某種 Mapper 對象。

// 編輯

由於您使用的是請求,因此您可以創建一個 requesthandler 類。 如果您使用控制反轉或調解器,您可以通過這種方式將請求連接到處理程序。 所以你可以研究那些設計模式。 您還可以查看 Clean Architecture 以將您的域代碼與外部系統(在這種情況下為 API)分離

public CarRequestHandler : IRequestHandler<CarRequest> {
    public CarRequestHandler(IColorRepository colorRepository, IEngineRepository engineRepository) { 
this.colorRepo = colorRepository; //etc.}
    public Handle(CarRequest request) {
// call repositories with the ids and create the domain object and stuff
       
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM