gpt4 book ai didi

java - 添加新字段时如何避免破坏克隆/复制方法?

转载 作者:行者123 更新时间:2023-12-02 02:48:15 25 4
gpt4 key购买 nike

我有一个简单的复制/克隆方法,这对我的应用程序很重要:

  @Override
public Operation getCopy() {
Operation copy = new Operation();
copy.year = this.year;
copy.stage = this.stage;
copy.info = this.info;
copy.user = this.user.getCopy();
// NOT TO BE COPIED! copy.id = this.id;
...
return copy;
}

请注意,有些特定字段不应复制。还有一些复杂的对象(例如 User)有自己的复制方法。

问题是,随着新代码的开发,有时开发人员会创建一个应该复制的新字段,但他忘记将其添加到 copy 方法中:

private String additionalInfo;

即使没有编译错误,也存在一个业务问题,只有我们的 QA 团队甚至用户后来才发现。

我可以采取什么措施来防止这种情况发生?我尝试过在原始对象及其副本之间进行比较的 JUnit 测试,它们对于现有字段效果很好,但不考虑新字段。

最佳答案

我为此使用了所谓的“循环和切换”测试:

for (Field field : Operation.class.getFields()) {
switch (field.getName()) {
case "year":
// Test that year is copied correctly.
// Initialize blah so that year is set.
assertEquals(getCopy(blah).year, blah.year);
break;
case "stage":
// Test that stage is copied correctly.
// Initialize blah so that stage is set.
assertEquals(getCopy(blah).stage, blah.stage);
break;
case "id":
// We don't want to copy id.
// Initialize blah so that id is set.
assertNull(getCopy(blah).id);
break;

// etc.

default:
throw new AssertionError("Unhandled field: " + field.getName());
}
}

这不是一个非常有想象力的名称:您循环遍历类中的所有字段,然后立即切换,以便您可以单独且显式地处理各个字段。

这样做的好处是,default 情况会立即捕获新添加字段的处理缺失。如果您说您需要在测试中处理它,并且推而广之,您也需要在生产代码中处理它,那么您会受到很大的打击。

使用普通旧式 Java 反射的缺点是它无法捕获正在删除的字段。这可能是一个“不太糟糕”的情况,因为它只是留下未使用的代码,而不是生产代码中存在未经测试的代码路径。

<小时/>

我在构建 Protocol Buffer - Protocol Buffer 转换器时开发了(或在某处读过,不幸的是我不记得了)这个习惯用法。 Java Protocol Buffer 有generated field numbers ,因此您实际上可以打开字段编号,而不是名称:

for (FieldDescriptor fieldDesc : proto.getDescriptorForType().getFields()) {
switch (fieldDesc.getNumber()) {
case FIELD1_FIELD_NUMBER:
// ...
case FIELD2_FIELD_NUMBER:
// ...
}
}

这样做的好处是,您也可以找到已删除的案例,因为将不再生成字段编号,这意味着测试开关将不再编译。

关于java - 添加新字段时如何避免破坏克隆/复制方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44231363/

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