Levels of Duplication
Starting with the obvious forms of duplication like Cltr+C & Cltr+V pattern to more subtle forms of duplication:
- Literal Duplication. Ex: Same for loop in 2 places
- Semantic Duplication: In essence the code does the same thing, but is syntactically different. Again there are sub-levels:
- 1st Level: Ex: for and foreach loop
for(int i : someList) stack.push(i);
v/s
for(int i=0; i < someList.size(); i++) stack.push(someList.get(i));
- 2nd Level: Ex: Looping over an array of elements instead of each element in a different line
stack.push(1); stack.push(3); stack.push(5); stack.push(10); stack.push(15);
v/s
for(int i : asList(1,3,5,10,15)) stack.push(i);
- 3rd Level: Ex: Loop v/s Recursion
- 1st Level: Ex: for and foreach loop
- Data Duplication. Ex: Some constant declared in 2 classes (test and production)
- Structural Duplication: Ex: Parallel Inheritance Hierarchy
- Conceptual Duplication: Ex: 2 Algos to Sort elements (Bubble sort and Quick sort)
- Representational Knowledge Duplication: Commonly know at WET (violation of DRY – Don’t Repeat Yourself)
- Duplication of logical steps: Same set of steps repeat in different scenarios. Ex: Same set of validations in various points in your applications
- Duplication of statement fragments: Same sections of a statement repeating. Ex:
Assert.IsTrue(response.HasHeader); Assert.IsTrue(response.HasMessageId); Assert.IsTrue(response.Has("X-SenderIP: " + senderIp)); Assert.IsTrue(response.Has("X-SenderDomain: " + senderDomain)); Assert.IsTrue(response.Has("X-recipientDomain: " + recipientDomain)); Assert.IsTrue(response.Has("X-SPF: " + spfValue)); Assert.IsTrue(response.Has("X-1stClassification: " + firstClassificationResult)); Assert.IsTrue(response.Has("X-2ndClassification: " + secondClassificationResult)); Assert.IsTrue(response.Has("X-3rdClassification: " + thirdClassificationResult)); Assert.IsTrue(response.Has("X-MANUALLY-CLASSIFIED: " + manuallyClassified));
Once we clean this up, it might look like:
lets.checkThat(response).HasHeader.HasMessageId.Has + "X-SenderIP" = senderIp + "X-SenderDomain" = senderDomain + "X-recipientDomain" = recipientDomain + "X-SPF" = spfValue + "X-1stClassification" = firstClassificationResult + "X-2ndClassification" = secondClassificationResult + "X-3rdClassification" = thirdClassificationResult + "X-MANUALLY-CLASSIFIED" = manuallyClassified;
Thanks to Corey Haines and the folks who participated in the Biggest Stinkers session @ the Simple Design and Testing Conference 2009. Most of this information was discussed during that session.