Sehr sich wiederholender Code ist im Allgemeinen eine schlechte Sache, und es gibt Entwurfsmuster, die helfen können, dies zu minimieren. Manchmal ist es jedoch aufgrund der Einschränkungen der Sprache selbst einfach unvermeidlich. Nehmen Sie das folgende Beispiel aus 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;
}
Die obige Schnipsel erscheint im Quellcode 8 mal, mit sehr wenig Änderung in der Dokumentation / Methodensignatur aber genau die gleiche Methode Körper , eine für jede der Wurzel - Array - Typen int[]
, short[]
, char[]
, byte[]
, boolean[]
, double[]
, float[]
, und Object[]
.
Ich glaube, dass diese Wiederholung unvermeidlich ist, wenn man nicht auf Reflexion zurückgreift (was an sich ein völlig anderes Thema ist). Ich verstehe, dass als Dienstprogrammklasse eine derart hohe Konzentration an sich wiederholendem Java-Code höchst untypisch ist, aber selbst mit der besten Vorgehensweise kommt es zu Wiederholungen ! Refactoring funktioniert nicht immer, weil es nicht immer möglich ist (der offensichtliche Fall ist, wenn die Wiederholung in der Dokumentation enthalten ist).
Offensichtlich ist die Pflege dieses Quellcodes ein Albtraum. Ein kleiner Tippfehler in der Dokumentation oder ein kleiner Fehler in der Implementierung wird mit der Anzahl der Wiederholungen multipliziert. Tatsächlich handelt es sich bei dem besten Beispiel um genau diese Klasse:
Der Fehler ist überraschend subtil und tritt in dem auf, was viele für einen einfachen und unkomplizierten Algorithmus hielten.
// int mid =(low + high) / 2; // the bug
int mid = (low + high) >>> 1; // the fix
Die obige Zeile erscheint 11 mal im Quellcode !
Meine Fragen sind also:
- Wie wird mit solchen sich wiederholenden Java-Codes / Dokumentationen in der Praxis umgegangen? Wie werden sie entwickelt, gewartet und getestet?
- Beginnen Sie mit "dem Original" und machen Sie es so ausgereift wie möglich. Kopieren Sie es dann und fügen Sie es nach Bedarf ein und hoffen Sie, dass Sie keinen Fehler gemacht haben?
- Und wenn Sie im Original einen Fehler gemacht haben, beheben Sie ihn einfach überall, es sei denn, Sie möchten die Kopien löschen und den gesamten Replikationsprozess wiederholen?
- Und Sie wenden diesen Prozess auch für den Testcode an?
- Würde Java von einer Art Quellcode-Vorverarbeitung mit eingeschränkter Verwendung für diese Art von Dingen profitieren?
- Vielleicht hat Sun einen eigenen Präprozessor, der beim Schreiben, Verwalten, Dokumentieren und Testen dieser Art von sich wiederholendem Bibliothekscode hilft?
In einem Kommentar wurde ein anderes Beispiel angefordert, daher habe ich dieses aus Google Collections gezogen: com.google.common.base.Predicates Zeilen 276-310 ( AndPredicate
) vs Zeilen 312-346 ( OrPredicate
).
Die Quelle für diese beiden Klassen ist identisch, mit Ausnahme von:
AndPredicate
vsOrPredicate
(jeder erscheint 5 mal in seiner Klasse)"And("
vsOr("
(in den jeweiligentoString()
Methoden)#and
vs#or
(in den@see
Javadoc-Kommentaren)true
vsfalse
(inapply
;!
kann aus dem Ausdruck heraus umgeschrieben werden)-1 /* all bits on */
vs0 /* all bits off */
inhashCode()
&=
vs|=
inhashCode()