The document discusses removing structural duplication from code. It defines structural duplication as similar code structures that repeat even if the internal actions differ. Examples given include conditional statements, exception handling, and views. The risks of duplication include increased size and unintended changes. The document provides steps to remove duplication such as separating structure from actions, extracting data models, and using loops to consolidate duplicated code. Both advantages like improved separation of concerns and disadvantages like increased rigidity are discussed.
4. Definition
Structural duplication (better said, similarity) is a similar code
structure that repeats, even though the actions performed inside
the structure are different.
4
7. Example: views
<form id="personForm">
<div class="row">
<div class="col-md-4">
Show something here
</div>
<div class="col-md-4">
Show something different here
</div>
</div>
<div class="row">
<div class="col-md-4">
Show yet something else here
</div>
<div class="col-md-4">
And again something else here
</div>
</div>
</form>
7
9. Issues
• Risk: when the same structure is spread throughout the code,
it’s likely that:
• it will grow
• it will keep increasing in duplication (eg. we’ll treat
ThirdException in the same way in another place)
• similar structures might change in similar ways, resulting in
duplicated work
• Intent hidden inside the structure
• Long methods
• Duplication in tests
9
11. Criteria for removal
• When it appears at least 3 times
• When it’s expected to grow
• When the intent is unclear
• When we expect the structure of the code to change in similar
ways in multiple places
• Judgement call
11
20. Step 2: Extract action for each if statement
List<Employee> readEmployeesFromDatabase(){
try{
List<Employee> employees = readEmployees();
} catch(Exception e){
if(e is SqlException) return emptyList();
if(e is Exception) return logError();
}
}
20
21. Step 3: Refactor to set of rules
List<Employee> readEmployeesFromDatabaseAndReturnEmptyListO
List rules = new List(){
new Pair(
{e -> e is SqlException},
{e -> emptyList()}),
new Pair(
{e -> e is Exception},
{e -> logError(e)})
}
try{
List<Employee> employees = readEmployees();
} catch(Exception e){
return rules.find{e.first(e)}.second(e)
}
}
21
24. Advantages
• Clear and consistent set of rules for exception management
• Separate the behaviour from exception management (SRP)
• Change the exception management rules from one place (OCP)
• Easier to write new code of the same kind
24
25. Disadvantages
• Can prove difficult to extend for certain exception management
treatments. Eg. retries, transactional behaviour etc.
• Requires understanding of lambdas
• Can be difficult to understand for programmers unused with
the idea
25
28. Step 0: which structure do we want to separate?
Could be:
• A two column form, if we have many two column forms and
expect to change their layout at the same time
• A stack of rows, if we have multiple stacks of rows and
expect to change them in similar ways (e.g. switch from one
grid system to another)
• Others, depending on the rest of the code
28
32. Careful with accidental duplication
<div class="col-md-4">
...
</div>
<div class="col-md-4">
...
</div>
Looks like structural duplication, but label width doesn’t
necessarily change at the same time with input width
32
33. Step 4: More separation of layout
<form id="personForm">
<g:each var="formLine" from="${dataModel}">
<g:render template="formLine" model="${formLine}">
</g:each>
</form>
33
34. Advantages
• All two-column forms have the same structure, and we can
change it from one place
• Smaller, more focused code (SRP)
• Follow OCP (yes, it applies to views too!)
• Clear where to change details (label and input templates) and
where to change structure (form, formLine templates)
34
35. Disadvantages
• If only one of the forms changes structure (eg. to three
columns), it can be painful (aka rigidity to certain types of
change)
• Can be harder to navigate to the places where you need to
change things. The structure and conventions need to be
documented and learned
35
37. Steps
1. Define precisely which structural duplication you want to
remove
2. Double-check if it’s accidental
3. Separate structure from actions
4. Extract data structure
5. Replace with loops or functional constructs
37
39. Recap
• Structural duplication is a code construct that has similar
structure but does different actions
• If we expect the structure to change in multiple places, it’s
worth separating from the actions
• It leads to code that follows SRP & OCP
• But be very careful at accidental duplication
39