用于检测字符串参数顺序错误的方法调用的注解
Annotations to detect method calls with wrong order of String parameters
我们有一个很大的应用程序,它使用了很多 Strings
:
- 序列号
- 产品名称
- 订单号
- 供客户参考
- ...还有更多...
不幸的是,我们的开发人员只是人。有时 String
值在调用方法时会混淆。
例如:
// this method
public void addProductToOrder(String order, String productname, String serialnumber);
// should be called like:
addProductToOrder(order, productname, serialnumber);
// but is sometimes mistakenly called as:
addProductToOrder(productname, serialnumber, order);
当您的方法需要大约 30 个参数时,很难检测到切换 2 个参数。 (是的,这是那些繁重的业务应用程序之一)
旁注:如果我们创建自己的 class SerialNumber
,它只是作为 String
的包装器,我们就不会遇到这个问题。但这似乎是错误的。
最近,我开始想知道是否有一种使用自定义注释检测混淆的方法。毕竟,已经有像Nullable
、NonNull
这样的注解了……
而这并没有太大的不同。
我们想注释我们的源代码,例如这样:
public void addProductToOrder(@OrderReference String order, @ProductName String productname, @SerialNumber String serialnumber);
接下来,我们想找到一种方法让我们的 IDE 检测到这里切换了 2 个参数。
@OrderReference String order = "ORDER_001";
@SerialNumber String sn = "0001-1213-007";
@ProductName String productname = "beer";
addProductToOrder(productname, serialnumber, order);
// should have been: addProductToOrder(order, productname, serialnumber);
我们正在使用 IntelliJ IDE。 不编写 IDE 插件有什么可能?
虽然您应该将 ControlAltDel 的评论作为最终解决方案,但 Intelij 确实有一项检查 "Suspicious variable/parameter name combination" 可能会有所帮助。你可以输入常用的参数名,如果它认为局部变量不匹配,它会警告你。
你自己的解决方案是一个很好的解决方案:在代码中编写注释,运行 一个在编译时警告你问题的注释处理器。
一个简单的方法是使用 Checker Framework, which enables you to enhance Java's type system with type qualifiers such as @OrderReference
, @SerialNumber
, @ProductName
, etc. The Checker Framework already comes with example checkers that ensure proper usage of strings, such as regular expressions, format strings, property file keys, and internationalization. You can start out with something simpler; in fact, you can create a simple type-checker without writing any code 超出类型限定符注释的定义。
另一种方法是使用常规 Java 类型,正如您也提到的那样。如果可能,这也是一个很好的解决方案。然而,有一些原因可能是不可能的或不可取的,包括:向后兼容性、更广泛的适用性、更丰富的语义、新的超类型、更精确的检查、运行-时间效率和代码混乱。有关这些问题的讨论,请参阅 Checker Framework FAQ 中的项目“Should I use pluggable types or Java subtypes?”。
另一种方法是将单个容器对象传递给您的方法,而不是传递 30 个参数。但是,这种方法在向后兼容性等方面存在一些相同的问题。此外,您仍然需要确保将值放入容器的正确位置,因此可插入类型检查仍然相关。
我们有一个很大的应用程序,它使用了很多 Strings
:
- 序列号
- 产品名称
- 订单号
- 供客户参考
- ...还有更多...
不幸的是,我们的开发人员只是人。有时 String
值在调用方法时会混淆。
例如:
// this method
public void addProductToOrder(String order, String productname, String serialnumber);
// should be called like:
addProductToOrder(order, productname, serialnumber);
// but is sometimes mistakenly called as:
addProductToOrder(productname, serialnumber, order);
当您的方法需要大约 30 个参数时,很难检测到切换 2 个参数。 (是的,这是那些繁重的业务应用程序之一)
旁注:如果我们创建自己的 class SerialNumber
,它只是作为 String
的包装器,我们就不会遇到这个问题。但这似乎是错误的。
最近,我开始想知道是否有一种使用自定义注释检测混淆的方法。毕竟,已经有像Nullable
、NonNull
这样的注解了……
而这并没有太大的不同。
我们想注释我们的源代码,例如这样:
public void addProductToOrder(@OrderReference String order, @ProductName String productname, @SerialNumber String serialnumber);
接下来,我们想找到一种方法让我们的 IDE 检测到这里切换了 2 个参数。
@OrderReference String order = "ORDER_001";
@SerialNumber String sn = "0001-1213-007";
@ProductName String productname = "beer";
addProductToOrder(productname, serialnumber, order);
// should have been: addProductToOrder(order, productname, serialnumber);
我们正在使用 IntelliJ IDE。 不编写 IDE 插件有什么可能?
虽然您应该将 ControlAltDel 的评论作为最终解决方案,但 Intelij 确实有一项检查 "Suspicious variable/parameter name combination" 可能会有所帮助。你可以输入常用的参数名,如果它认为局部变量不匹配,它会警告你。
你自己的解决方案是一个很好的解决方案:在代码中编写注释,运行 一个在编译时警告你问题的注释处理器。
一个简单的方法是使用 Checker Framework, which enables you to enhance Java's type system with type qualifiers such as @OrderReference
, @SerialNumber
, @ProductName
, etc. The Checker Framework already comes with example checkers that ensure proper usage of strings, such as regular expressions, format strings, property file keys, and internationalization. You can start out with something simpler; in fact, you can create a simple type-checker without writing any code 超出类型限定符注释的定义。
另一种方法是使用常规 Java 类型,正如您也提到的那样。如果可能,这也是一个很好的解决方案。然而,有一些原因可能是不可能的或不可取的,包括:向后兼容性、更广泛的适用性、更丰富的语义、新的超类型、更精确的检查、运行-时间效率和代码混乱。有关这些问题的讨论,请参阅 Checker Framework FAQ 中的项目“Should I use pluggable types or Java subtypes?”。
另一种方法是将单个容器对象传递给您的方法,而不是传递 30 个参数。但是,这种方法在向后兼容性等方面存在一些相同的问题。此外,您仍然需要确保将值放入容器的正确位置,因此可插入类型检查仍然相关。