为什么在创建团队间的依赖性时使用枚举?

huangapple go评论64阅读模式
英文:

Why use enums when it creates dependency across teams?

问题

我知道枚举在我们期望仅传递一组特定值时使用。我们不希望调用者传递除了明确定义的集合之外的任何内容。
在项目内部,这非常有效。因为你知道你需要传递什么。

但考虑两个项目,我在第二个项目中使用了第一个项目的模型。

第二个项目有一个像这样的方法。

public void updateRefundMode(RefundMode refundMode)

枚举 RefundMode("CASH", "CARD", "GIFT_VOUCHER")

现在,我意识到 RefundMode 也可以是 PHONEPE,所以如果我开始将它传递给第一个项目,它会在他们那边失败(无法反序列化枚举 PHONEPE)。尽管我已经在我的项目中添加了这个枚举。

这是可以理解的,因为如果我的第一个项目不知道 "PHONEPE",那么它就不知道如何处理它,所以他们也必须更新模型。

但我的问题是,想象一下我要传递一个复杂的对象,该对象也采用了这个 RefundMode。当我传递一个新的 RefundMode 时,只是这个字段应该变为 null 或在他们那端被忽略,对吗?而不是拒绝整个对象,并中断整个流程/请求。

我是否可以指定 jackson(jsonproperties)在传递未知值时只是忽略该字段。很好奇...(尽管在这种情况下,我违反了 ENUM 的规则)那么,为什么不使用一个可以解决所有问题的字符串呢?

英文:

I know enums are used when we are expecting only a set of values to be passed. We don't want the caller to pass anything other than the well defined set.
And this works very well inside a project. Because you know what you've to pass.

But consider 2 projects, I am using the models of 1st project in 2nd.

Second project has a method like this.

 public void updateRefundMode(RefundMode refundMode) 

 enum RefundMode("CASH","CARD","GIFT_VOUCHER")

Now, I realise RefundMode can be PHONEPE also, So If I start passing this to 1st project, it would fail at their end (Unable to desirialize enum PHONEPE). Although I've added this enum at my end.

Which is fine, because If my first project doesn't know about the "PHONEPE", then it doesn't know how to handle it, so he has to update the models too.

But my problem is, Let's imagine a complex Object am trying to pass, which also takes this RefundMode, when I pass a new RefundMode just this field should be become null or ignored at their end right ? Rather than not accepting the whole object, and breaking the entire flow/request.

Is there a way I can specify jackson (jsonproperties) to just ignore that field if an unknown value is being passed. Curious to know.. (Although In that case, I am breaking the rule of ENUM) So, why not keep a String which solves all the problem ?

答案1

得分: 4

关键在于合同。

当你处于客户端/服务器的情况下,比如移动应用和网络服务器,或者一个Java库(jar)和另一个Java项目,你必须牢记合同。

正如你所观察到的,合同的变更需要传播到双方:客户端和服务器(供应方)。

处理这个情况的一种方式是使用版本控制。你可以说:“版本1:这些是退款模式。” 然后移动应用可以通过在URL中指定合同版本来调用网络服务器:/api/v1/refund?mode=CASH

当合同需要更改时,你需要考虑如何处理客户端。对于移动应用的情况,用户可能没有将他们的应用程序更新到最新版本,因此他们的应用可能仍然在调用/api/v1(不支持新的退款模式)。在这种情况下,你可能希望在网络服务器中同时支持/api/v1/api/v2(带有新的退款模式)。

正如你的示例所显示的,不总是可能将一个合同版本透明地适应另一个版本(在你的示例中,在原始枚举中没有PHONEPE的良好等价物)。如果你必须处理合同更新,我建议显式地编写代码(你可以使用专用的JSON模式、类和服务)来处理它们,而不是试图弥合差距。想象一下在第三、第四个版本中会发生什么。

编辑:为了回答你的最后一个问题,你可以通过按照这个答案中所解释的方法来忽略JSON中的未知字段(带有上述解释的注意事项):https://stackoverflow.com/a/59307683/2223027

编辑2:一般来说,使用枚举是一种强类型的形式。当然,你可以使用字符串,甚至位,但是那样会更容易出错,比如使用GiftVoucher而不是GIFT_VOUCHER

英文:

It's all about contracts.

When you are in a client/server situation, being a mobile app and a web server, or a Java library (jar) and another Java project, you have to keep the contracts in mind.

As you observed, a change in contracts need to be propagated to both parties: the client and the server (supplier).

One way of working with this is to use versioning. You may say: "Version 1: those are the refund modes.". Then the mobile app may call the web server by specifying the contract version in the URL: /api/v1/refund?mode=CASH

When the contract needs to be changed, you need to consider what to do with the clients. In the case of mobile apps, the users might not have updated their app to the latest version, so their app may still be calling /api/v1 (and not supporting new refund modes). In that case, you may want to support both /api/v1 and /api/v2 (with the new refund mode) in your web server.

As your example shows, it is not always possible to transparently adapt one contract version to another (in your example, there is no good equivalent to PHONEPE in the original enum). If you have to deal with contract updates, I suggest explicitly writing code to them (you can use dedicated JSON schemas, classes and services) instead of trying to bridge the gaps. Think of what would happen with a third, fourth version.

Edit: to answer your last question, you can ignore unknown fields in JSON by following this answer (with the caveats explained above): https://stackoverflow.com/a/59307683/2223027

Edit 2: in general, using Enums is a form of strong typing. Sure, you could use Strings, or even bits, but then it would be easier to make mistakes, like using GiftVoucher instead of GIFT_VOUCHER.

huangapple
  • 本文由 发表于 2020年9月11日 04:09:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63837010.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定