我应该在 Java 中使用语义类型而不是字符串吗?



我维护的库使用各种语义含义的字符串。例如,一个字符串是发票代码,另一个字符串是报价代码。根据这些类型,有这些语义类型和查找方法的讲解员。为了区分这些值的语义,我开始创建CharSequence的实现,称为InvoiceCodeQuotationCode等。

我用Boost.Units作为灵感。在C++中使用物理方程时,绝对没有办法绕过它。使用普通double将很快导致未知单位。我担心在我的图书馆中随处使用String时也会发生同样的情况。

现在我的大学抱怨说,在调用我的图书馆之前从String转换为语义类型太麻烦了,而在想要处理结果时又回到String

在我看来,我的大学应该在他们的代码中使用适当的类型。

所以最后的问题归结为:使用语义类型而不是String Java 中的推荐和/或常见做法吗?

C++有两个关键功能,可以更轻松地使用用户定义的语义类型 - 转换运算符和运算符重载。Java没有两者中的任何一个,这使得你对语义类型的推动成为一场艰苦的战斗。

使用CharSequence接口使库的用户在从库中获取数据时更容易避免转换为字符串。但是,传递所有这些InvoiceCodeQuotationCode对象需要调用方执行更多工作。

如果用户总是这样做

source.yourMethod(new QuotationCode(theirObject.quotationCodeString))

那么你是对的,他们应该用QuotationCode quotationCode替换对象中的String quotationCodeString,并获得它们的易用性。

另一方面,如果他们经常这样做

source.yourMethod(new QuotationCode("xyz-code"))
那么最好为

众所周知的报价代码定义一个来源,让你的用户来写这个:

source.yourMethod(QuotationCode.XyzCode)

其中XyzCode是一个众所周知的报价代码,您的用户将其硬编码为String

没有自己的域类型。

由于这类数据通常存储在数据库中,并且实际上最好在数据库中处理,因此自己的域值类最终可能会产生反作用。声明性业务规则,例如在XML或某些DSL中也受到阻碍。

这取决于这些数据存储库的使用情况:像jOOQL这样的DSL,或者speedment或JPA。后者执行对象/关系映射,ID域通常由java类替换。

对于用户定义的代码,实际上不需要 java 类型:您不希望逐个处理硬编码值。这些应该以声明方式进行。例如,基于发票类别和合同的报告选择不应由嵌套的 ifs/switch 完成。

对于你所描述的,自然的"语义类型"是一个枚举。枚举类型 T 应该覆盖 'T toString((' 并实现 'static T fromString(String('(或者只使用 'valueOf(('(,这使得你的同事很容易使用,因为该类型会执行自己的转换。

您不需要运算符重载,这带来的问题多于解决的问题。您有转换方法,完全消除了对转换运算符的需求,因此与C++的比较是似是而非的。

最新更新