SlideShare a Scribd company logo
Removing Structural Duplication
Alex Bolboacă, @alexboly, alex.bolboaca@mozaicworks.com
May 2017
1
What is Structural Duplication?
Why is it a problem?
When to remove?
Example: Exception management
Example: Views
How to remove
In the End . . .
2
What is Structural Duplication?
3
Definition
Structural duplication (better said, similarity) is a similar code
structure that repeats, even though the actions performed inside
the structure are different.
4
Example: conditionals
if(condition1){
...
...
}
if(condition2){
...
...
}
if(condition3){
...
...
}
5
Example: exceptions
try{
...
...
} catch(FirstException firstExc){
...
} catch(SecondException secondExc){
...
}
try{
...
...
} catch(SecondException secondExc){
...
} catch(ThirdException thirdExc){
...
}
6
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
Why is it a problem?
8
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
When to remove?
10
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
Careful
12
Example: Exception management
13
Example code
List<Employee> readEmployeesFromDatabase(){
try{
ResultSet rs = stmt.executeQuery(
"SELECT id, first, last, age FROM Employees");
List<Employee> employees = new List<Employee>();
while(rs.next()){
employees.add(
new Employee(rs.getInt("id"), rs.getString("first"),
rs.getString("last"), rs.getInt("age"));
}
rs.close();
return employees;
} catch(SQLException se){
return new List<Employee>();
} catch(Exception e){
log.error("Exception: " + se.toString());
return null;
}
}
14
Disclaimer
15
Step 0: Clarify responsibilities (find the right name)
List<Employee> readEmployeesFromDatabaseAndReturnEmptyListOnDbErrorAndLogOtherExceptions(){
....
}
16
Step 0: Clarify responsibilities
List<Employee> readEmployeesFromDatabaseAndReturnEmptyListO
try{
ResultSet rs = stmt.executeQuery(
"SELECT id, first, last, age FROM Employees");
List<Employee> employees = new List<Employee>();
while(rs.next()){
employees.add(
new Employee(rs.getInt("id"), rs.getString("fir
rs.getString("last"), rs.getInt("age"));
}
rs.close();
return employees;
} catch(SQLException se){
return new List<Employee>();
17
Step 0: Separate responsibilities (cont’d)
List<Employee> readEmployeesFromDatabaseAndReturnEmptyListOnDbErrorAndLogOtherExceptions(){
try{
List<Employee> employees = readEmployeesFromDatabase();
} catch(SQLException se){
return new List<Employee>();
} catch(Exception e){
log.error("Exception: " + se.toString());
return null;
}
}
18
Step 1: Remove duplication
List<Employee> readEmployeesFromDatabaseAndReturnEmptyListOnDbErrorAndLogOtherExceptions(){
try{
List<Employee> employees = readEmployees();
} catch(Exception e){
if(e is SqlException){
return new List<Employee>();
}
if(e is Exception){
log.error("Exception: " + se.toString());
return null;
}
}
}
19
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
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
Step 4: Push errors and rules up
List<Employee> readEmployeesFromDatabaseAndManageExceptions
try{
List<Employee> employees = readEmployees();
} catch(Exception e){
return exceptionManagementRules
.find{e.first.call(e)}
.second.call(e);
}
}
22
Step 5: Extract final duplication
List<Employee> readEmployeesFromDatabase(){
return callWithExceptionManagement(
rules,
{ -> readEmployees();});
}
Object callWithExceptionManagement(List<> exceptionManagementRules, action){
try{
action.call();
} catch(Exception e){
return exceptionManagementRules
.find{e.first.call(e)}
.second.call(e);
}
}
23
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
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
Example: Views
26
Example Code
<form id="personForm">
<div class="row">
<div class="col-md-4">
<label for="firstName">
</div>
<div class="col-md-4">
<input id="firstName" type="text" value="Alex"></input>
</div>
</div>
<div class="row">
<div class="col-md-4">
<label for="lastName">
</div>
<div class="col-md-4">
<input id="lastName" type="text" value="Bolboacă"></input>
</div>
</div>
</form>
27
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
Step 1: Separate structure from content
<form id="personForm">
<div class="row">
<div class="col-md-4">
<g:render template="firstNameLabel">
</div>
<div class="col-md-4">
<g:render template="firstNameInput" model="Alex">
</div>
</div>
<div class="row">
<div class="col-md-4">
<g:render template src="lastNameLabel">
</div>
<div class="col-md-4">
<g:render template="lastNameInput" model="Bolboacă">
</div>
</div>
</form>
29
Step 2: Separate data model from layout
[
[
label: [template: 'firstNameLabel'],
input: [template: 'firstNameInput', value: 'Alex']
],
[
label: [template: 'lastNameLabel'],
input: [template: 'lastNameInput', value: 'Bolboacă']
]
]
30
Step 3: Replace with loop
<form id="personForm">
<g:each var="formLine" from="${dataModel}">
<div class="row">
<div class="col-md-4">
<g:render template="${formLine.label.template}">
</div>
<div class="col-md-4">
<g:render template="${formLine.input.template}"
model="${formLine.input.value}">
</div>
</div>
</g:each>
</form>
31
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
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
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
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
How to remove
36
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
In the End . . .
38
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
Your choice
40
Q&A
41
Join ProductLeaders
42

More Related Content

What's hot

Ensure code quality with vs2012
Ensure code quality with vs2012Ensure code quality with vs2012
Ensure code quality with vs2012
Sandeep Joshi
 
Net Beans Codes for Student Portal
Net Beans Codes for Student PortalNet Beans Codes for Student Portal
Net Beans Codes for Student PortalPeeyush Ranjan
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql
JOYITAKUNDU1
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Codestasimus
 
The Ring programming language version 1.8 book - Part 32 of 202
The Ring programming language version 1.8 book - Part 32 of 202The Ring programming language version 1.8 book - Part 32 of 202
The Ring programming language version 1.8 book - Part 32 of 202
Mahmoud Samir Fayed
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classes
Pawel Szulc
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 min
Pawel Szulc
 
The Ring programming language version 1.6 book - Part 29 of 189
The Ring programming language version 1.6 book - Part 29 of 189The Ring programming language version 1.6 book - Part 29 of 189
The Ring programming language version 1.6 book - Part 29 of 189
Mahmoud Samir Fayed
 
The Ring programming language version 1.3 book - Part 20 of 88
The Ring programming language version 1.3 book - Part 20 of 88The Ring programming language version 1.3 book - Part 20 of 88
The Ring programming language version 1.3 book - Part 20 of 88
Mahmoud Samir Fayed
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy Code
Daniel Wellman
 
The Ring programming language version 1.10 book - Part 17 of 212
The Ring programming language version 1.10 book - Part 17 of 212The Ring programming language version 1.10 book - Part 17 of 212
The Ring programming language version 1.10 book - Part 17 of 212
Mahmoud Samir Fayed
 
SQL || overview and detailed information about Sql
SQL || overview and detailed information about SqlSQL || overview and detailed information about Sql
SQL || overview and detailed information about Sql
gourav kottawar
 
SQL querys in detail || Sql query slides
SQL querys in detail || Sql query slidesSQL querys in detail || Sql query slides
SQL querys in detail || Sql query slides
gourav kottawar
 
The Ring programming language version 1.3 book - Part 24 of 88
The Ring programming language version 1.3 book - Part 24 of 88The Ring programming language version 1.3 book - Part 24 of 88
The Ring programming language version 1.3 book - Part 24 of 88
Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 34 of 189
The Ring programming language version 1.6 book - Part 34 of 189The Ring programming language version 1.6 book - Part 34 of 189
The Ring programming language version 1.6 book - Part 34 of 189
Mahmoud Samir Fayed
 

What's hot (18)

Ensure code quality with vs2012
Ensure code quality with vs2012Ensure code quality with vs2012
Ensure code quality with vs2012
 
Net Beans Codes for Student Portal
Net Beans Codes for Student PortalNet Beans Codes for Student Portal
Net Beans Codes for Student Portal
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 
The Ring programming language version 1.8 book - Part 32 of 202
The Ring programming language version 1.8 book - Part 32 of 202The Ring programming language version 1.8 book - Part 32 of 202
The Ring programming language version 1.8 book - Part 32 of 202
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classes
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 min
 
The Ring programming language version 1.6 book - Part 29 of 189
The Ring programming language version 1.6 book - Part 29 of 189The Ring programming language version 1.6 book - Part 29 of 189
The Ring programming language version 1.6 book - Part 29 of 189
 
The Ring programming language version 1.3 book - Part 20 of 88
The Ring programming language version 1.3 book - Part 20 of 88The Ring programming language version 1.3 book - Part 20 of 88
The Ring programming language version 1.3 book - Part 20 of 88
 
Java
JavaJava
Java
 
Pre zen ta sion
Pre zen ta sionPre zen ta sion
Pre zen ta sion
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy Code
 
The Ring programming language version 1.10 book - Part 17 of 212
The Ring programming language version 1.10 book - Part 17 of 212The Ring programming language version 1.10 book - Part 17 of 212
The Ring programming language version 1.10 book - Part 17 of 212
 
SQL || overview and detailed information about Sql
SQL || overview and detailed information about SqlSQL || overview and detailed information about Sql
SQL || overview and detailed information about Sql
 
Java day9n
Java day9nJava day9n
Java day9n
 
SQL querys in detail || Sql query slides
SQL querys in detail || Sql query slidesSQL querys in detail || Sql query slides
SQL querys in detail || Sql query slides
 
The Ring programming language version 1.3 book - Part 24 of 88
The Ring programming language version 1.3 book - Part 24 of 88The Ring programming language version 1.3 book - Part 24 of 88
The Ring programming language version 1.3 book - Part 24 of 88
 
The Ring programming language version 1.6 book - Part 34 of 189
The Ring programming language version 1.6 book - Part 34 of 189The Ring programming language version 1.6 book - Part 34 of 189
The Ring programming language version 1.6 book - Part 34 of 189
 

Similar to Removing structural duplication

Knockout.js presentation
Knockout.js presentationKnockout.js presentation
Knockout.js presentationScott Messinger
 
Presentacion clean code
Presentacion clean codePresentacion clean code
Presentacion clean code
IBM
 
The Ring programming language version 1.3 book - Part 83 of 88
The Ring programming language version 1.3 book - Part 83 of 88The Ring programming language version 1.3 book - Part 83 of 88
The Ring programming language version 1.3 book - Part 83 of 88
Mahmoud Samir Fayed
 
Chapter Seven- JDBC.pptx
Chapter Seven- JDBC.pptxChapter Seven- JDBC.pptx
Chapter Seven- JDBC.pptx
BlenKassahun1
 
The Ring programming language version 1.4.1 book - Part 8 of 31
The Ring programming language version 1.4.1 book - Part 8 of 31The Ring programming language version 1.4.1 book - Part 8 of 31
The Ring programming language version 1.4.1 book - Part 8 of 31
Mahmoud Samir Fayed
 
Presentation on template and exception
Presentation  on template and exceptionPresentation  on template and exception
Presentation on template and exception
Sajid Alee Mosavi
 
The Ring programming language version 1.6 book - Part 31 of 189
The Ring programming language version 1.6 book - Part 31 of 189The Ring programming language version 1.6 book - Part 31 of 189
The Ring programming language version 1.6 book - Part 31 of 189
Mahmoud Samir Fayed
 
JavaScript lesson 1.pptx
JavaScript lesson 1.pptxJavaScript lesson 1.pptx
JavaScript lesson 1.pptx
MuqaddarNiazi1
 
New Component Patterns in Ember.js
New Component Patterns in Ember.jsNew Component Patterns in Ember.js
New Component Patterns in Ember.js
Matthew Beale
 
The Ring programming language version 1.7 book - Part 32 of 196
The Ring programming language version 1.7 book - Part 32 of 196The Ring programming language version 1.7 book - Part 32 of 196
The Ring programming language version 1.7 book - Part 32 of 196
Mahmoud Samir Fayed
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
Simon Willison
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
corehard_by
 
Jquery tutorial
Jquery tutorialJquery tutorial
Jquery tutorial
Bui Kiet
 
Vejovis: Suggesting Fixes for JavaScript Faults
Vejovis: Suggesting Fixes for JavaScript FaultsVejovis: Suggesting Fixes for JavaScript Faults
Vejovis: Suggesting Fixes for JavaScript Faults
SALT Lab @ UBC
 
Performance is a feature! - Developer South Coast - part 2
Performance is a feature!  - Developer South Coast - part 2Performance is a feature!  - Developer South Coast - part 2
Performance is a feature! - Developer South Coast - part 2
Matt Warren
 
Converting Db Schema Into Uml Classes
Converting Db Schema Into Uml ClassesConverting Db Schema Into Uml Classes
Converting Db Schema Into Uml ClassesKaniska Mandal
 
VisualStudio2012-WhatsNew-TechEd_v3-9
VisualStudio2012-WhatsNew-TechEd_v3-9VisualStudio2012-WhatsNew-TechEd_v3-9
VisualStudio2012-WhatsNew-TechEd_v3-9SSW
 

Similar to Removing structural duplication (20)

Django quickstart
Django quickstartDjango quickstart
Django quickstart
 
Knockout.js presentation
Knockout.js presentationKnockout.js presentation
Knockout.js presentation
 
Presentacion clean code
Presentacion clean codePresentacion clean code
Presentacion clean code
 
The Ring programming language version 1.3 book - Part 83 of 88
The Ring programming language version 1.3 book - Part 83 of 88The Ring programming language version 1.3 book - Part 83 of 88
The Ring programming language version 1.3 book - Part 83 of 88
 
Chapter Seven- JDBC.pptx
Chapter Seven- JDBC.pptxChapter Seven- JDBC.pptx
Chapter Seven- JDBC.pptx
 
The Ring programming language version 1.4.1 book - Part 8 of 31
The Ring programming language version 1.4.1 book - Part 8 of 31The Ring programming language version 1.4.1 book - Part 8 of 31
The Ring programming language version 1.4.1 book - Part 8 of 31
 
Presentation on template and exception
Presentation  on template and exceptionPresentation  on template and exception
Presentation on template and exception
 
The Ring programming language version 1.6 book - Part 31 of 189
The Ring programming language version 1.6 book - Part 31 of 189The Ring programming language version 1.6 book - Part 31 of 189
The Ring programming language version 1.6 book - Part 31 of 189
 
JavaScript lesson 1.pptx
JavaScript lesson 1.pptxJavaScript lesson 1.pptx
JavaScript lesson 1.pptx
 
New Component Patterns in Ember.js
New Component Patterns in Ember.jsNew Component Patterns in Ember.js
New Component Patterns in Ember.js
 
The Ring programming language version 1.7 book - Part 32 of 196
The Ring programming language version 1.7 book - Part 32 of 196The Ring programming language version 1.7 book - Part 32 of 196
The Ring programming language version 1.7 book - Part 32 of 196
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 
Jquery tutorial
Jquery tutorialJquery tutorial
Jquery tutorial
 
Vejovis: Suggesting Fixes for JavaScript Faults
Vejovis: Suggesting Fixes for JavaScript FaultsVejovis: Suggesting Fixes for JavaScript Faults
Vejovis: Suggesting Fixes for JavaScript Faults
 
Performance is a feature! - Developer South Coast - part 2
Performance is a feature!  - Developer South Coast - part 2Performance is a feature!  - Developer South Coast - part 2
Performance is a feature! - Developer South Coast - part 2
 
Converting Db Schema Into Uml Classes
Converting Db Schema Into Uml ClassesConverting Db Schema Into Uml Classes
Converting Db Schema Into Uml Classes
 
VisualStudio2012-WhatsNew-TechEd_v3-9
VisualStudio2012-WhatsNew-TechEd_v3-9VisualStudio2012-WhatsNew-TechEd_v3-9
VisualStudio2012-WhatsNew-TechEd_v3-9
 
Alfredo-PUMEX
Alfredo-PUMEXAlfredo-PUMEX
Alfredo-PUMEX
 
Alfredo-PUMEX
Alfredo-PUMEXAlfredo-PUMEX
Alfredo-PUMEX
 

More from Alexandru Bolboaca

Refactor legacy code through pure functions
Refactor legacy code through pure functionsRefactor legacy code through pure functions
Refactor legacy code through pure functions
Alexandru Bolboaca
 
Design Without Types
Design Without TypesDesign Without Types
Design Without Types
Alexandru Bolboaca
 
Thinking in Functions
Thinking in FunctionsThinking in Functions
Thinking in Functions
Alexandru Bolboaca
 
Raising the Bar
Raising the BarRaising the Bar
Raising the Bar
Alexandru Bolboaca
 
The Journey to Master Code Design
The Journey to Master Code DesignThe Journey to Master Code Design
The Journey to Master Code Design
Alexandru Bolboaca
 
What is good software design? And why it matters?
What is good software design? And why it matters?What is good software design? And why it matters?
What is good software design? And why it matters?
Alexandru Bolboaca
 
Functional programming in C++
Functional programming in C++Functional programming in C++
Functional programming in C++
Alexandru Bolboaca
 
Agile Technical Leadership
Agile Technical LeadershipAgile Technical Leadership
Agile Technical Leadership
Alexandru Bolboaca
 
TDD As If You Meant It
TDD As If You Meant ItTDD As If You Meant It
TDD As If You Meant It
Alexandru Bolboaca
 
Usable Software Design
Usable Software DesignUsable Software Design
Usable Software Design
Alexandru Bolboaca
 
Hidden loops
Hidden loopsHidden loops
Hidden loops
Alexandru Bolboaca
 
Continuous delivery
Continuous deliveryContinuous delivery
Continuous delivery
Alexandru Bolboaca
 
Why You Should Start Using Docker
Why You Should Start Using DockerWhy You Should Start Using Docker
Why You Should Start Using Docker
Alexandru Bolboaca
 
Pyramid of-developer-skills
Pyramid of-developer-skillsPyramid of-developer-skills
Pyramid of-developer-skills
Alexandru Bolboaca
 
Applied craftsmanship
Applied craftsmanshipApplied craftsmanship
Applied craftsmanship
Alexandru Bolboaca
 
Pyramid of-developer-skills
Pyramid of-developer-skillsPyramid of-developer-skills
Pyramid of-developer-skills
Alexandru Bolboaca
 
Stay focused
Stay focusedStay focused
Stay focused
Alexandru Bolboaca
 
Kanban intro
Kanban introKanban intro
Kanban intro
Alexandru Bolboaca
 
Unit testing-patterns
Unit testing-patternsUnit testing-patterns
Unit testing-patterns
Alexandru Bolboaca
 
Incremental design, simply explained
Incremental design, simply explainedIncremental design, simply explained
Incremental design, simply explained
Alexandru Bolboaca
 

More from Alexandru Bolboaca (20)

Refactor legacy code through pure functions
Refactor legacy code through pure functionsRefactor legacy code through pure functions
Refactor legacy code through pure functions
 
Design Without Types
Design Without TypesDesign Without Types
Design Without Types
 
Thinking in Functions
Thinking in FunctionsThinking in Functions
Thinking in Functions
 
Raising the Bar
Raising the BarRaising the Bar
Raising the Bar
 
The Journey to Master Code Design
The Journey to Master Code DesignThe Journey to Master Code Design
The Journey to Master Code Design
 
What is good software design? And why it matters?
What is good software design? And why it matters?What is good software design? And why it matters?
What is good software design? And why it matters?
 
Functional programming in C++
Functional programming in C++Functional programming in C++
Functional programming in C++
 
Agile Technical Leadership
Agile Technical LeadershipAgile Technical Leadership
Agile Technical Leadership
 
TDD As If You Meant It
TDD As If You Meant ItTDD As If You Meant It
TDD As If You Meant It
 
Usable Software Design
Usable Software DesignUsable Software Design
Usable Software Design
 
Hidden loops
Hidden loopsHidden loops
Hidden loops
 
Continuous delivery
Continuous deliveryContinuous delivery
Continuous delivery
 
Why You Should Start Using Docker
Why You Should Start Using DockerWhy You Should Start Using Docker
Why You Should Start Using Docker
 
Pyramid of-developer-skills
Pyramid of-developer-skillsPyramid of-developer-skills
Pyramid of-developer-skills
 
Applied craftsmanship
Applied craftsmanshipApplied craftsmanship
Applied craftsmanship
 
Pyramid of-developer-skills
Pyramid of-developer-skillsPyramid of-developer-skills
Pyramid of-developer-skills
 
Stay focused
Stay focusedStay focused
Stay focused
 
Kanban intro
Kanban introKanban intro
Kanban intro
 
Unit testing-patterns
Unit testing-patternsUnit testing-patterns
Unit testing-patterns
 
Incremental design, simply explained
Incremental design, simply explainedIncremental design, simply explained
Incremental design, simply explained
 

Recently uploaded

AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Alina Yurenko
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
Google
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 

Recently uploaded (20)

AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 

Removing structural duplication

  • 1. Removing Structural Duplication Alex Bolboacă, @alexboly, alex.bolboaca@mozaicworks.com May 2017 1
  • 2. What is Structural Duplication? Why is it a problem? When to remove? Example: Exception management Example: Views How to remove In the End . . . 2
  • 3. What is Structural Duplication? 3
  • 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
  • 6. Example: exceptions try{ ... ... } catch(FirstException firstExc){ ... } catch(SecondException secondExc){ ... } try{ ... ... } catch(SecondException secondExc){ ... } catch(ThirdException thirdExc){ ... } 6
  • 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
  • 8. Why is it a problem? 8
  • 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
  • 14. Example code List<Employee> readEmployeesFromDatabase(){ try{ ResultSet rs = stmt.executeQuery( "SELECT id, first, last, age FROM Employees"); List<Employee> employees = new List<Employee>(); while(rs.next()){ employees.add( new Employee(rs.getInt("id"), rs.getString("first"), rs.getString("last"), rs.getInt("age")); } rs.close(); return employees; } catch(SQLException se){ return new List<Employee>(); } catch(Exception e){ log.error("Exception: " + se.toString()); return null; } } 14
  • 16. Step 0: Clarify responsibilities (find the right name) List<Employee> readEmployeesFromDatabaseAndReturnEmptyListOnDbErrorAndLogOtherExceptions(){ .... } 16
  • 17. Step 0: Clarify responsibilities List<Employee> readEmployeesFromDatabaseAndReturnEmptyListO try{ ResultSet rs = stmt.executeQuery( "SELECT id, first, last, age FROM Employees"); List<Employee> employees = new List<Employee>(); while(rs.next()){ employees.add( new Employee(rs.getInt("id"), rs.getString("fir rs.getString("last"), rs.getInt("age")); } rs.close(); return employees; } catch(SQLException se){ return new List<Employee>(); 17
  • 18. Step 0: Separate responsibilities (cont’d) List<Employee> readEmployeesFromDatabaseAndReturnEmptyListOnDbErrorAndLogOtherExceptions(){ try{ List<Employee> employees = readEmployeesFromDatabase(); } catch(SQLException se){ return new List<Employee>(); } catch(Exception e){ log.error("Exception: " + se.toString()); return null; } } 18
  • 19. Step 1: Remove duplication List<Employee> readEmployeesFromDatabaseAndReturnEmptyListOnDbErrorAndLogOtherExceptions(){ try{ List<Employee> employees = readEmployees(); } catch(Exception e){ if(e is SqlException){ return new List<Employee>(); } if(e is Exception){ log.error("Exception: " + se.toString()); return null; } } } 19
  • 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
  • 22. Step 4: Push errors and rules up List<Employee> readEmployeesFromDatabaseAndManageExceptions try{ List<Employee> employees = readEmployees(); } catch(Exception e){ return exceptionManagementRules .find{e.first.call(e)} .second.call(e); } } 22
  • 23. Step 5: Extract final duplication List<Employee> readEmployeesFromDatabase(){ return callWithExceptionManagement( rules, { -> readEmployees();}); } Object callWithExceptionManagement(List<> exceptionManagementRules, action){ try{ action.call(); } catch(Exception e){ return exceptionManagementRules .find{e.first.call(e)} .second.call(e); } } 23
  • 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
  • 27. Example Code <form id="personForm"> <div class="row"> <div class="col-md-4"> <label for="firstName"> </div> <div class="col-md-4"> <input id="firstName" type="text" value="Alex"></input> </div> </div> <div class="row"> <div class="col-md-4"> <label for="lastName"> </div> <div class="col-md-4"> <input id="lastName" type="text" value="Bolboacă"></input> </div> </div> </form> 27
  • 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
  • 29. Step 1: Separate structure from content <form id="personForm"> <div class="row"> <div class="col-md-4"> <g:render template="firstNameLabel"> </div> <div class="col-md-4"> <g:render template="firstNameInput" model="Alex"> </div> </div> <div class="row"> <div class="col-md-4"> <g:render template src="lastNameLabel"> </div> <div class="col-md-4"> <g:render template="lastNameInput" model="Bolboacă"> </div> </div> </form> 29
  • 30. Step 2: Separate data model from layout [ [ label: [template: 'firstNameLabel'], input: [template: 'firstNameInput', value: 'Alex'] ], [ label: [template: 'lastNameLabel'], input: [template: 'lastNameInput', value: 'Bolboacă'] ] ] 30
  • 31. Step 3: Replace with loop <form id="personForm"> <g:each var="formLine" from="${dataModel}"> <div class="row"> <div class="col-md-4"> <g:render template="${formLine.label.template}"> </div> <div class="col-md-4"> <g:render template="${formLine.input.template}" model="${formLine.input.value}"> </div> </div> </g:each> </form> 31
  • 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
  • 38. In the End . . . 38
  • 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