simple design.published
TRANSCRIPT
Simple Design Applied Spend more time creating
valuable code
Declan Whelan @dwhelan
Alistair McKinnell@mckinnell
On an index card write up to three facts on an index card.
Be ready to share with your table.
What is Simple Design?
At your table gather the facts and count how many distinct
facts you came up with.
What is Simple Design?
1. All tests must pass2. No code is duplicated3. Code is self-explanatory4. No superfluous parts exist
Simple Design
1. All tests must pass2. No code is duplicated3. Code is self-explanatory4. No superfluous parts exist
Simple Design
1. Passes its tests2. No code is duplicated3. Code is self-explanatory4. No superfluous parts exist
Simple Design
1. Passes its tests2. Minimizes duplication3. Code is self-explanatory4. No superfluous parts exist
Simple Design
1. Passes its tests2. Minimizes duplication3. Maximizes clarity4. No superfluous parts exist
Simple Design
1. Passes its tests (given TDD)2. Minimizes duplication3. Maximizes clarity4. Has fewer elements
Simple Design
1. Passes its tests (given TDD)2. Minimizes duplication3. Maximizes clarity (fix names)4. Has fewer elements
Simple Design
1. Passes its tests (given TDD)2. Minimizes duplication3. Maximizes clarity (fix names)4. Has fewer elements
Simple Design
That leaves me with two key elementsof simple design: remove duplication and fix bad names. When I remove duplication, I tend to seean appropriate structure emerge, and whenI fix bad names, I tend to see responsibilities slide into appropriate parts of the design.
J. B. Rainsberger
• Fix bad names
Simple Design(for today)
Choosing good names❤• Remove duplication
Commonality & Variability❤
Stroop Effect
Green Red BluePurple Blue Purple
Blue Purple RedGreen Purple Green
Green Red BluePurple Blue Purple
CComBstr sVal $.getJSON() int result
Rx rx applyMeasureConstraintToEnableSortingByMeasure() float hp
applyPhq9DateRangeConstraint() public void run() Date genymdhms
m_name Label label IShapeFactory
Customer int i RollOverPerformanceIndicatorsToNextMonthTask
CustomerManager LPSTR lpCmdLine int daysSinceModification
boolean fNewPage UpdatePerfIndValueDecCountCmd DepressionSelfManagementCalculator
PerfIndValueDecCountForMatchingIvpCmd PulseRenderer IndexCardPageLayout sut
Tutorial02
CComBstr sVal $.getJSON() int result
Rx rx applyMeasureConstraintToEnableSortingByMeasure() float hp
applyPhq9DateRangeConstraint() public void run() Date genymdhms
m_name Label label IShapeFactory
Customer int i RollOverPerformanceIndicatorsToNextMonthTask
CustomerManager LPSTR lpCmdLine int daysSinceModification
boolean fNewPage UpdatePerfIndValueDecCountCmd DepressionSelfManagementCalculator
PerfIndValueDecCountForMatchingIvpCmd PulseRenderer IndexCardPageLayout sut
Tutorial02
Find a partner and each of you:
1. select a name you thought was good2. explain why to your partner3. select a name you thought was bad4. explain why to your partner
CComBstr sVal $.getJSON() int result
Rx rx applyMeasureConstraintToEnableSortingByMeasure() float hp
applyPhq9DateRangeConstraint() public void run() Date genymdhms
m_name Label label IShapeFactory
Customer int i RollOverPerformanceIndicatorsToNextMonthTask
CustomerManager LPSTR lpCmdLine int daysSinceModification
boolean fNewPage UpdatePerfIndValueDecCountCmd DepressionSelfManagementCalculator
PerfIndValueDecCountForMatchingIvpCmd PulseRenderer IndexCardPageLayout sut
Choosing Good Names
Use the telephone test for readability. If someone could understand your code when read aloud over the telephone, it's clear enough. If not, then it needs rewriting.
Choosing Good Names
Splitters can be lumped more easily than lumpers can be split.It is easier to combine two concepts that it is to separate them.
applyPhq9DateRangeConstraint()
Ubiquitous Language
The PHQ-9 is the nine item depression scale of the Patient Health Questionnaire.
The PHQ-9 is a powerful tool for assisting primary care clinicians in diagnosing depression as well as selecting and monitoring treatment.
Agile in a FlashSpeed-Learning Agile
Software Development
Jeff Langr andTim Ottinger
edited by Susannah Pfalzer
PragmaticProgrammers
Agile Cards for Agile Teams
Prepared exclusively for Alistair McKinnell Copyright ©2011 Pragmatic Programmers
43 Really Meaningful Names
! Are accurate
! Are purposeful
! Are pronounceable
! Begin well
! Are simple
! Depend on context
! Match name length to scope
Prepared exclusively for Alistair McKinnell Copyright ©2011 Pragmatic Programmers
Alistair McKinnell @amckinnell Declan Whelan @dwhelanNaming Guidelines v1.0 August 2012 ! 1/1
Naming'GuidelinesSystem'of'Names
S1# # Name#pass#the#“telephone”#test.
S2# # There#is#a#clean#name#for#each#concept.#Remember:#later#on#it’s#easier#to#lump#things#together#than#to#split#them#apart.
S3# # Name#is#from#the#problem#or#solu?on#domain#and#support#ubiquitous#language#for#the#team
GeneralG1## Name#is#pronounceable.
G2## Name#avoids#encodings#and#member#prefixes.
G3## Name#suggest#why#it#exists.
G4## Name#suggest#how#it#should#be#used.
G5## Name#suggest#what#it#does.
G6## Name#is#easily#searchable#in#the#code#base.
ClassesC1# If#this#is#an#important#base#class#its#class#name#should#be#a#simple#single#word.
C2# If#this#is#a#subclass#its#class#name#suggests#how#it#differs#from#its#superclass.
C3# The#class#name#is#a#noun#or#a#noun#phrase.
MethodsM1# The#method#name#suggests#why#it#would#be#called.
M2# The#method#is#name#a#verb#or#a#verb#phrase.
Variables/Fields/ArgumentsV1# Its#name#indicate#the#role#it's#playing.
V2# The#length#of#the#name#reflect#its#scope.
Choosing Good Names•Locate one guideline that if applied would have the biggest impact on your code
•Find a partner•Discuss
Choosing Good Namespublic List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList) if (x[0] == 4) list1.add(x);
return list1;}
Source: Clean Code: A Handbook of Agile Software Craftsmanship, Robert C. Martin, pages 18-19
public List<int[]> getFlaggedCells() { List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard) if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.add(cell);
return flaggedCells;}
public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList) if (x[0] == 4) list1.add(x);
return list1;}
Source: Clean Code: A Handbook of Agile Software Craftsmanship, Robert C. Martin, pages 18-19
Choosing Good Names
public List<Cell> getFlaggedCells() { List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard) if (cell.isFlagged()) flaggedCells.add(cell);
return flaggedCells;}
public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList) if (x[0] == 4) list1.add(x);
return list1;}
Source: Clean Code: A Handbook of Agile Software Craftsmanship, Robert C. Martin, pages 18-19
Choosing Good Names
public List<Cell> getFlaggedCells() { List<Cell> result = new ArrayList<Cell>();
for (Cell cell : gameBoard) if (cell.isFlagged()) result.add(cell);
return result;}
public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList) if (x[0] == 4) list1.add(x);
return list1;}
Source: Clean Code: A Handbook of Agile Software Craftsmanship, Robert C. Martin, pages 18-19
Choosing Good Names
Choosing Good Names
int realDaysPerIdealDay = 4;const int WORK_DAYS_PER_WEEK = 5;int sum = 0;
for (int j=0; j < NUMBER_OF_TASKS; j++) { int realTaskDays = taskEstimate[j] * realDaysPerIdealDay; int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK); sum += realTaskWeeks;}
int s = 0;
for (int j=0; j<34; j++) { s += (t[j]*4)/5;}
const int EFFECTIVE_DAYS_PER_WEEK = 4;const int WORKING_DAYS_PER_WEEK = 5;
int effectiveTotalEstimate = 0;
for (int j=0; j < NUMBER_OF_TASKS; j++) { int effectiveTaskEstimate = taskEstimate[j] * EFFECTIVE_DAYS_PER_WEEK / WORKING_DAYS_PER_WEEK; effectiveTotalEstimate += effectiveTaskEstimate;}
Source: Clean Code: A Handbook of Agile Software Craftsmanship, Robert C. Martin, page 23
DRY: Don’t Repeat YourselfEvery piece of knowledge must have a single, unambiguous, authoritative representation within a system.
Avoiding Duplicate Code
Avoiding Duplicate Code
Once and Only OnceData, structure, or logic should exist in only one place in the system.
Avoiding Duplicate Code
Test-Driven Development1. Write new code only if an
automated test has failed.2. Eliminate duplication.
Single Choice PrincipleWhenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list.
Avoiding Duplicate Code
Can you spot the duplicate code?
How would you make the commonality and variation explicit?
Can you spot the commonality and variation?
public static List<SelectOption> createEndMonthList(Date expiryDate) { int selectedMonth = getDateMonth(expiryDate);
SelectOptionsSource months = new SelectOptionsSource(1, 12, selectedMonth); SelectOptions monthOptions = new SelectOptions(months);
return monthOptions.create();}
public static List<SelectOption> createEndDaysList() { int selectedDay = getDateDay(getCurrentDatePlus14Days());
SelectOptionsSource days = new SelectOptionsSource(1, 31, selectedDay); SelectOptions dayOptions = new SelectOptions(days);
return dayOptions.create();}
public static List<SelectOption> createEndYearList() { int selectedYear = getDateYear(getCurrentDatePlus14Days());
SelectOptionsSource years = new SelectOptionsSource(1985, 1985 + 30, selectedYear); SelectOptions yearOptions = new SelectOptions(years);
return yearOptions.create();}
public static List<SelectOption> createEndMonthList(Date expiryDate) { int selectedMonth = getDateMonth(expiryDate);
SelectOptionsSource months = new SelectOptionsSource(1, 12, selectedMonth); SelectOptions monthOptions = new SelectOptions(months);
return monthOptions.create();}
public static List<SelectOption> createEndDaysList() { int selectedDay = getDateDay(getCurrentDatePlus14Days());
SelectOptionsSource days = new SelectOptionsSource(1, 31, selectedDay); SelectOptions dayOptions = new SelectOptions(days);
return dayOptions.create();}
public static List<SelectOption> createEndYearList() { int selectedYear = getDateYear(getCurrentDatePlus14Days());
SelectOptionsSource years = new SelectOptionsSource(1985, 1985 + 30, selectedYear); SelectOptions yearOptions = new SelectOptions(years);
return yearOptions.create();}
public static List<SelectOption> createEndMonthList(Date expiryDate) { int selectedMonth = getDateMonth(expiryDate);
SelectOptionsSource months = new SelectOptionsSource(1, 12, selectedMonth); SelectOptions monthOptions = new SelectOptions(months);
return monthOptions.create();}
public static List<SelectOption> createEndDaysList() { int selectedDay = getDateDay(getCurrentDatePlus14Days());
SelectOptionsSource days = new SelectOptionsSource(1, 31, selectedDay); SelectOptions dayOptions = new SelectOptions(days);
return dayOptions.create();}
public static List<SelectOption> createEndYearList() { int selectedYear = getDateYear(getCurrentDatePlus14Days());
SelectOptionsSource years = new SelectOptionsSource(1985, 1985 + 30, selectedYear); SelectOptions yearOptions = new SelectOptions(years);
return yearOptions.create();}
Select Options
create()
SelectOptions
create()
SelectOptions
getFirst()getLast()isSelected()
SelectOptionsSource
Commonality Variability Resolution
Behaviour Collaborator Encapsulate Collection
Select Options
Commonality Variability Resolution
Data Structure Value of State Simple Java Type
getFirst()getLast()isSelected()
SelectOptionsSource
create()
SelectOptions
Select Options
create()
SelectOptions
Encapsulate Collection
create()
SelectOptions
getFirst()getLast()isSelected()
SelectOptionsSource
Select Options
getFirst()getLast()isSelected()
SelectOptionsSource
create()
SelectOptions
ParameterObject
Can you spot the duplicate code?
How would you make the commonality and variation explicit?
Can you spot the commonality and variation?
Compound Result HandlerisNegative()isPositive()
CompoundResultClassifier
toNumber()
AbstractCompoundResultClassifier
isNegative()isPositive()
QueensCompoundResultClassifier
isNegative()isPositive()
StandardCompoundResultClassifier
CompoundResultHandler
Compound Result HandlerisNegative()isPositive()
CompoundResultClassifier
toNumber()
AbstractCompoundResultClassifier
isNegative()isPositive()
QueensCompoundResultClassifier
isNegative()isPositive()
StandardCompoundResultClassifier
CompoundResultHandler
Compound Result Handler
Commonality Variability Resolution
Behaviour Implementation Inheritance(Object-Oriented)
isNegative()isPositive()
CompoundResultClassifier
toNumber()
AbstractCompoundResultClassifier
isNegative()isPositive()
QueensCompoundResultClassifier
isNegative()isPositive()
StandardCompoundResultClassifier
CompoundResultHandler
isNegative()isPositive()
CompoundResultClassifier
toNumber()
AbstractCompoundResultClassifier
isNegative()isPositive()
QueensCompoundResultClassifier
isNegative()isPositive()
StandardCompoundResultClassifier
CompoundResultHandler
Commonality Variability Resolution
Behaviour Implementation Inheritance(Object-Oriented)
Compound Result Handler
Compound Result HandlerisNegative()isPositive()
CompoundResultClassifier
toNumber()
AbstractCompoundResultClassifier
isNegative()isPositive()
QueensCompoundResultClassifier
isNegative()isPositive()
StandardCompoundResultClassifier
CompoundResultHandler
Commonality Variability Resolution
Implementation None Base Class
Compound Result HandlerisNegative()isPositive()
CompoundResultClassifier
toNumber()
AbstractCompoundResultClassifier
isNegative()isPositive()
QueensCompoundResultClassifier
isNegative()isPositive()
StandardCompoundResultClassifier
CompoundResultHandler
Commonality Variability Resolution
Implementation None Base Class
Factory
Compound Result Handlerpublic static CompoundResultClassifier createCompoundResultClassifier( Patient sourcePatient) { return isRegisteredAtQueens(sourcePatient) ? QUEENS : STANDARD;}
private static boolean isRegisteredAtQueens(Patient sourcePatient) { return sourcePatient.getDataWarehouse().equals(DataWarehouseTag.QHN);}
“The prime directive that was unanimously agree upon by allpresent was that in the nexttens years Agile leaders must
Demand Technical Excellence.”
Jeff Sutherland
ReadingThe Elements of Programming StyleKernighan and Plauger
PrefactoringExtreme Abstraction Extreme Separation Extreme ReadabilityKen Pugh
Agile in a FlashSpeed-Learning Agile
Software Development
Jeff Langr andTim Ottinger
edited by Susannah Pfalzer
PragmaticProgrammers
Agile Cards for Agile Teams
Prepared exclusively for Alistair McKinnell
Agile in a FlashSpeed-Learning Agile DevelopmentJeff Langr and Tim Ottinger
ReadingClean CodeA Handbook of Agile Software CraftsmanshipRobert C. Martin
Domain Driven DesignTackling Complexity in the Heart of SoftwareEric Evans
Implementation PatternsKent Beck
ReadingThe Pragmatic Programmer: From Journeyman to MasterAndrew Hunt and Dave Thomas
Extreme Programming Explained: Embrace ChangeKent Beck and Cynthia Andres
Test Driven Development: By ExampleKent Beck
Object-Oriented Software ConstructionBertrand Meyer
ReadingDesign Patterns: Elements of Reusable Object-Oriented Software Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides
Multi-Paradigm Design for C++James O. Coplien
Lean Architecture: for Agile Software DevelopmentJames O. Coplien and Gertrud Bjørnvig
Photo Creditshttp://www.flickr.com/photos/27558040@N00/4151899795/
http://www.flickr.com/photos/popilop/331357312/
http://www.flickr.com/photos/arlette/3260468/
http://www.flickr.com/photos/36829973@N04/3546657245/
http://www.flickr.com/photos/40838054@N00/7261734660/