gpt4 book ai didi

c# - 同一实体的多个 Dto

转载 作者:行者123 更新时间:2023-11-30 20:26:05 25 4
gpt4 key购买 nike

对不同 API 端点中的同一实体使用多个 DTO 是否是一种好习惯。例如:
我有一个 api 端点,它接受以下 Dto:

public class AddressDto
{
public string City { get; set; }
public string Country { get; set; }
public string Contact { get; set; }
public string Street1 { get; set; }
public string Street2 { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}

现在有第二个 Api 接受相同的 dto 但在那个 api 调用中我只使用 Streer1, Street2, Contact所有其他都被忽略。

我应该再做一次 DTO第二个 api endpoint喜欢:
public class AddressDtoForSecondAPI
{
public string Contact { get; set; }
public string Street1 { get; set; }
public string Street2 { get; set; }
}

最佳答案

简而言之,是的,这是可以接受的。

但是,正如您在评论和其他答案中所见,并非所有人都同意这里的观点。那么让我解释一下我的答案。

论点 1 - 误导消费者

And now there is second Api which accepts the same dto but in that api call I'm using only Streer1, Street2, Contact all other are ignored.



这里的问题之一是要明确你的意图。如果您允许消费者向您发送完整的 AddressDTO ,但是只使用属性的一个子集,那么你就是在误导你的消费者。你让他们认为其他属性是相关的。

这实际上等同于:
public int AddNumbersTogether(int a, int b, int c, int d)
{
return a + c + d; //we ignore b
}

没有理由 b存在。任何使用这种方法的人都会在 AddNumbersTogether(1,2,3,4) 时挠头。返回值 8 .语法与行为相矛盾。

是的,省略未使用的方法参数比开发第二个 DTO 更容易。但是你需要在这里保持一致并坚持同样的原则:不要误导消费者。

论点 2 - DTO 不是实体

您的消费者与您的 API 的交互需要在消费者不了解您的数据库记录结构的情况下发生。

这就是您使用 DTO 而不是您的实体类的原因!您在执行操作和存储该操作的数据之间提供了逻辑分离。

消费者并不关心数据存储在哪里。无论您是将街道存储在与地址相同的表中,还是完全不同的表(或数据库)中, 没关系在消费者调用 API 方法的范围内。

论点 3 - 反击 S.Akbari

What about inheritance and/or interface segregation principle in SOLID? – S.Akbari



对于这种特殊情况,这些不是有效的论据。

继承是一种有缺陷的方法。是的,从技术上讲,您可以通过执行类似 AddressDto : AddressDtoForSecondAPI 的操作而逃脱惩罚。在发布的示例代码中,但这是一个巨大的代码气味。
当需要第三个 DTO 时会发生什么,例如一个只使用邮政编码和城市名称的地方?你不能有 AddressDto多源继承, AddressDtoForSecondAPI之间没有逻辑重叠和新创建的 AddressDtoForThirdAPI .

接口(interface) 不是这里的解决方案。是的,您可以在技术上创建一个 IAddressDtoForSecondAPIIAddressDtoForThirdAPI与适当的字段接口(interface),然后执行类似 AddressDto : IAddressDtoForSecondAPI, IAddressDtoForThirdAPI 的操作.然而,这又是同样的大量代码味道。

如果第二个和第三个变体有一些共享属性和一些单独的属性,会发生什么?如果应用接口(interface)隔离,那么重叠的属性需要在接口(interface)中自己抽象出来。
如果然后出现第四个变体,它与第二个变体具有一些共同的属性,一些与第三个变体,一些同时具有第二个和第三个变体,以及一些单独的属性,那么您将需要创建更多接口(interface)!

给定相同实体的足够多的变体并重复应用接口(interface)隔离原则;你最终会得到一个实体的每个属性的接口(interface);这需要大量的样板。你最终会得到类似的东西:
public class AddressDto : IAddressCity, IAddressCountry, IAddressContact, IAddressStreet1, IAddressStreet2, IAddressState, IAddressZip
{
public string City { get; set; }
public string Country { get; set; }
public string Contact { get; set; }
public string Street1 { get; set; }
public string Street2 { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}

想象一下必须对所有类都这样做;因为相同的原则适用于 API 使用的每个 DTO。

论点 4 - DRY 不适用于此处

我有点明白你为什么担心创建两个类。最有可能的是,您的脑海中出现了 DRY/WET 错误标志。

避免 WET 是一种很好的 react ;但你不能总是听它。因为如果你要 真的避免重复,那么您实际上也不应该创建单独的实体和 DTO 类,因为它们通常是彼此的复制/粘贴。

DRY 不是绝对的。以实体/DTO 为例,这里有一个平衡的考虑:
  • 你想不惜一切代价避免重复吗? (= 干)
  • 您想将 DAL 与 API 逻辑分开吗? (= 关注点分离)

  • 在这种情况下,后者通常胜出。

    同样的论点适用于您的情况。在这种情况下,反对遵循 DRY(这是我刚刚列出的论点)的论点远远超过遵循 DRY 的好处。

    关于c# - 同一实体的多个 Dto,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50560144/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com