用Java重新构想DTO

哈Ha!我提请您注意斯蒂芬·沃特曼(Stephen Waterman)文章“重新思考Java DTO”的业余翻译,作者认为这是在Java中使用DTO的一种有趣且非标准的方法。






我花了12周的时间在Scott Logic研究生培训计划中,与校友一起开展内部项目。有那么一刻让我比其他人停滞不前的多:编写DTO的结构和风格。这在整个项目中引起了很多争议和讨论,但是最后我意识到我喜欢使用DTO。



这种方法不是唯一正确的解决方案,但它对于使用现代IDE进行开发非常有趣并且非常有用。希望最初的冲击消退,您也会喜欢。



什么是DTO(数据传输对象)?



通常,在客户端-服务器应用程序中,客户端(表示层)和服务器(域层)上的数据结构不同。在服务器端,这使我们有机会舒适地将数据存储在数据库中或为了提高性能而优化数据的使用,同时在客户端上进行“用户友好”的数据显示,并且对于服务器端,我们需要找到一种方法来从一个数据库转换数据格式化为另一个。当然,还有其他应用程序体系结构,但是为了简化起见,我们将重点放在当前的体系结构上。可以在任何两个数据表示层之间使用类似DTO的对象。





DTO — value-object , , . DTO , (Request) , (Response). , Spring.



, endpoint DTO :



// Getters & Setters, ,    
public class CreateProductRequest {
    private String name;
    private Double price;
}

public class ProductResponse {
    private Long id;
    private String name;
    private Double price;
}

@PostMapping("/products")
public ResponseEntity<ProductResponse> createProduct(
    @RequestBody CreateProductRequest request
) { /*...*/ }


DTO?



-, , DTO. .



  • , DTO.
  • JSON, !


. DTO , , , (decoupling) , .



, DTO . DTO API .



API, . (endpoint) . , . price “ ”, price . API , - , .



DTO . DTO , , API . DTO “ ”, — , .



DTO, , .



!



, . . , .



, -. , . Double, BigDecimal.



public enum ProductDTO {;
    private interface Id { @Positive Long getId(); }
    private interface Name { @NotBlank String getName(); }
    private interface Price { @Positive Double getPrice(); }
    private interface Cost { @Positive Double getCost(); }

    public enum Request{;
        @Value public static class Create implements Name, Price, Cost {
            String name;
            Double price;
            Double cost;
        }
    }

    public enum Response{;
        @Value public static class Public implements Id, Name, Price {
            Long id;
            String name;
            Double price;
        }

        @Value public static class Private implements Id, Name, Price, Cost {
            Long id;
            String name;
            Double price;
            Double cost;
        }
    }
}


, enum , ProductDTO. , DTO , (Request) , (Response). endpoint Request DTO Response DTO . Response DTO, Public Private .



. - — , . . , @NotBlank DTO .



DTO . @Value Lombok , .



, , . , DTO.



“ !”



. .



enum ! namespace-, .. DTO ProductDTO.Request.Create. “” , ; enum. () ! namespace- DTO, IDE . , , new ProductDTO() new Create(). , .



— ! . , , .



. , . Lombok . , , DTO . , java . , .



()



DTO. ?





. API , . DTO — IDE . :



@Value public static class PatchPrice implements Id, Price {
    String id;    //    Long;
    Double prise; //    price
}


PatchPrice is not abstract and does not override abstract method getId() in Id
PatchPrice is not abstract and does not override abstract method getPrice() in Price


, , , endpoint .





DTO . . :



private interface Cost {
    /**
     * The amount that it costs us to purchase this product
     * For the amount we sell a product for, see the {@link Price Price} parameter.
     * <b>This data is confidential</b>
     */
    @Positive Double getCost();
}


DTO , .





DTO, . , API, , . , , .



&



: . 4 , , DTO . , “” c DTO. , , . , .



, DTO. @Value public static class [name] implements, . , IDE . ! DTO .



, DTO . . . ctrl + q IntelliJ .





, .. . DTO — , .



, , . , , :



markup = (sale_price - cost_price) / cost_price


java, :



public static <T extends Price & Cost> Double getMarkup(T dto){
    return (dto.getPrice() - dto.getCost()) / dto.getCost();
}


T, . dto Price Cost — , Public (.. Cost). , dto (). .





, DTO. :



  1. API .
  2. .
  3. , , !





PS感谢您阅读我关于哈布雷的第一篇文章。我很乐意对翻译提出任何批评,因为 由于缺乏知识和经验,我不得不与原始版本有所不同。




All Articles