如何更新具有大量字段的领域模型?

问题描述 投票:0回答:1

假设我有一个领域模型


@Table(name = "room")
@Getter
@FieldNameConstants
@AllArgsConstructor(onConstructor = @__({@PersistenceCreator}))
public class HotelRoom extends AbstractEntity implements HotelAware, Sellable {

    @Id
    private final String id;

    @Column(value = "hotel_id")
    private final String hotelId;

    @Column(value = "name")
    private String name;

    @Column(value = "size")
    private RoomSize size;

    @Column(value = "sale_state")
    private SaleState saleState;

    @Embedded.Empty
    private Stock stock;

    @Embedded.Empty
    private RoomDesc desc;

    private HotelRoom(String roomId, String hotelId) {
        this.id = roomId;
        this.hotelId = hotelId;
    }

    public static HotelRoom create(String id, Hotel hotel, String name, RoomDesc desc, RoomSize size, Stock stock) {
        DomainUtils.must(stock.greaterTan(Stock.ZERO), () -> new IllegalArgumentException("stock must gather than zero"));

        var hotelId = hotel.getId();
        var room = new HotelRoom(id, hotelId);
        room.name = name;
        room.size = size;
        room.stock = stock;
        room.desc = desc;
        room.saleState=SaleState.STOPPED;
        return room;
    }

    @Override
    public void startSale() {
        this.saleState = SaleState.STARTED;
    }

    @Override
    public void stopSale() {
        this.saleState = SaleState.STOPPED;
    }

    @Override
    public SaleState getSaleState() {
        return this.saleState;
    }

    @Override
    public boolean isOnSale() {
        return saleState.isOnSale();
    }

    public void updateDesc(RoomDesc desc) {
        this.desc = desc;
    }

    public void updateName(String name) {
        this.name = name;
    }

    public void updateSize(RoomSize size) {
        this.size = size;
    }

    public void updateStock(Stock stock) {
        this.stock = stock;
    }
}

它有 updateDesc/updateName/updateSize/updateStock 这些我将在服务层调用的方法。

 @Override
    public void updateRoom(RoomUpdateCommand command) {
        var room = hotelRoomRepository.requireById(command.getRoomId());
        room.updateDesc(RoomDesc.builder()
            .desc(command.getDesc())
            .build());
        room.updateName(command.getName());
        room.updateSize(command.getSize());
        room.updateStock(command.getStock());
        hotelRoomRepository.save(room);
    }

但我认为那些从 update 开始的方法与 setter 方法没有区别。

这很简单,我真正的意思是我们最终拥有一个包含很多字段的大型模型,即海关申报或类似的东西:

class ExampleModel{
 field1:string 
 field2:string 
 field3:string 
 ...
 field50:string 
 ...
 state...
 money...

}

fields1...50 是用户可以自由更改的属性,就像备忘录一样。

我该如何处理这个问题?

  1. 创建一个像HotelRoomPatch这样的补丁类作为领域层下的值bean,HotelRoom可以处理它。
  2. 开放包含这些字段的setter方法,服务层可以调用它。
  3. 为主题定义 updateXxx 方法,服务层可以调用。

我认为#1与#2相同,我们无法保护我们的领域模型。

不知道你的想法如何?

domain-driven-design
1个回答
0
投票

一种可能的解决方案可能是用一个方法替换许多“更新”方法。

class HotelRoom {

    // fields and constructors

    void apply(HotelRoomPatch patch) {
        // logic of update
    }
}
interface HotelRoomPatch {
    Optional<String> name();
    Optional<SaleState> saleState();
    // etc.
}
© www.soinside.com 2019 - 2024. All rights reserved.