在 Java 中管理高度重复的代码和文档
高度重复的代码通常是一件坏事,并且有一些设计模式可以帮助最大限度地减少这种情况。但是,有时由于语言本身的限制,这是不可避免的。以下示例取自 :java.util.Arrays
/**
* Assigns the specified long value to each element of the specified
* range of the specified array of longs. The range to be filled
* extends from index <tt>fromIndex</tt>, inclusive, to index
* <tt>toIndex</tt>, exclusive. (If <tt>fromIndex==toIndex</tt>, the
* range to be filled is empty.)
*
* @param a the array to be filled
* @param fromIndex the index of the first element (inclusive) to be
* filled with the specified value
* @param toIndex the index of the last element (exclusive) to be
* filled with the specified value
* @param val the value to be stored in all elements of the array
* @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
* @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
* <tt>toIndex > a.length</tt>
*/
public static void fill(long[] a, int fromIndex, int toIndex, long val) {
rangeCheck(a.length, fromIndex, toIndex);
for (int i=fromIndex; i<toIndex; i++)
a[i] = val;
}
上面的代码片段在源代码中出现了 8 次,文档/方法签名的变化很小,但方法主体完全相同,每个根数组类型 、 、 和 .int[]
short[]
char[]
byte[]
boolean[]
double[]
float[]
Object[]
我认为,除非人们诉诸反思(这本身就是一个完全不同的主题),否则这种重复是不可避免的。我知道,作为一个实用程序类,如此高度集中的重复Java代码是非常不典型的,但即使使用最佳实践,重复也会发生!重构并不总是有效,因为它并不总是可能的(明显的情况是当重复在文档中时)。
显然,维护这个源代码是一场噩梦。文档中的轻微拼写错误或实现中的小错误会乘以重复次数。事实上,最好的例子恰好涉及这个确切的类:
这个错误是一个令人惊讶的微妙错误,发生在许多人认为只是一个简单明了的算法中。
// int mid =(low + high) / 2; // the bug
int mid = (low + high) >>> 1; // the fix
上面的行在源代码中出现了11次!
所以我的问题是:
- 在实践中如何处理这些重复的Java代码/文档?它们是如何开发、维护和测试的?
- 你是否从“原件”开始,让它尽可能成熟,然后根据需要复制和粘贴,希望你没有犯错?
- 而且,如果您在原始副本中确实犯了错误,那么只需在任何地方修复它,除非您愿意删除副本并重复整个复制过程?
- 您是否也将相同的过程应用于测试代码?
- Java会从这种事情的某种有限使用的源代码预处理中受益吗?
- 也许 Sun 有自己的预处理器来帮助编写、维护、记录和测试这些重复的库代码?
一条评论要求另一个例子,所以我从Google Collections中提取了这个:com.google.common.base.谓词行276-310()与行312-346()。AndPredicate
OrPredicate
这两个类的源代码是相同的,除了:
-
AndPredicate
vs(每个在同类产品中出现 5 次)OrPredicate
-
"And("
vs(在各自的方法中)Or("
toString()
-
#and
vs (在 Javadoc 注释中)#or
@see
-
true
vs (在 ; 可以重写出来的表达式)false
apply
!
-
-1 /* all bits on */
与在0 /* all bits off */
hashCode()
-
&=
与在|=
hashCode()