simple design.published

138
Simple Design Applied Spend more time creating valuable code Declan Whelan @dwhelan Alistair McKinnell @mckinnell

Upload: drewz-lin

Post on 14-Jul-2015

134 views

Category:

Documents


0 download

TRANSCRIPT

Simple Design Applied Spend more time creating

valuable code

Declan Whelan @dwhelan

Alistair McKinnell@mckinnell

Exercise

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?

Introductions

?

www.XProgramming.com

Exercise

At your table order the rules of simple design in

priority order.

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 tests2. Minimizes duplication3. Maximizes clarity4. Has fewer elements

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

• Remove duplication• Fix bad names

Simple Design

• Fix bad names

Simple Design(for today)

Choosing good names❤• Remove duplication

Commonality & Variability❤

Exercise

Stroop Effect

Green Red BluePurple Blue Purple

Blue Purple RedGreen Purple Green

Green Red BluePurple Blue Purple

blackyellow

Meaning:

Colour:

blueblack

Meaning:

Colour:

blackyellow

yellowred

redyellow

redyellow

blueblue

yellowblue

redred

bluered

yellowyellow

redyellow

redyellow

blueblack

yellowblack

blackblue

redblack

TheEnd

Exercise

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

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.

Telephone Test

Goal Donor vs Gold Owner

Date genymdhms

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.

Splitting a Lumper

Customer Address

Customer Address

Billing Address Mailing Address Service Address

Splitting a Lumper

Billing Address Mailing Address Service Address

Lumping a Splitter

Customer Address

Billing Address Mailing Address Service Address

Lumping a Splitter

Choosing Good Names

Pronounceable NamesAvoid Encodings

UpdatePerfIndValueDecCountCmd

Pronounceable Names

UpdatePerfIndValueDecCountCmd

DecrementAggregateCommand

Pronounceable Names

Date genymdhms

Pronounceable Names

Date genymdhms

Date generatedTimestamp

Pronounceable Names

LPSTR lpCmdLine

m_name

Avoid Encodings

LPSTR commandLine

name

Choosing Good Names

Intention-Revealing NameRole-Suggesting Name

Intention-Revealing Name

applyMeasureConstraintTo EnableSortingByMeasure()

Intention-Revealing Name

applyMeasureConstraintTo EnableSortingByMeasure()

applyMeasureConstraint()

Role-Suggesting Name

int result

IndexCardPageLayout sut

Choosing Good Names

Ubiquitous Language

CComBstr sVal

Ubiquitous Language

CComBstr sVal

CComBstr calibrationToolName

Ubiquitous Language

Rx rx

Ubiquitous Language

Rx rx

Rx refillable

Ubiquitous Language

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

What’s In A Name?

Moonbeam Zappa

All tests must pass No code is duplicated

Code is self-explanatory No superfluous parts exist

No code is duplicated

Exercise

How do you handle duplicate code

in your codebase?

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

Duplication may be the root of all evil in software.

Avoiding Duplicate Code

Commonality and Variability

Copy & Paste

function something() {

}

function something() {

}

function something() {

}

function somethingElse() {

}

function something() {

}

function somethingElse() {

}

function something() {

}

Duplicate Code

Copy & Paste

☞ Duplicate CodeEdit the Copy

Duplicate Code

Avoid duplication by expressing commonality and variability

explicitly.

function somethingElse() {

}

function something() {

}

Duplicate Code: Select Options

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

Duplicate Code: Compound Result Handler

Can you spot the duplicate code?

How would you make the commonality and variation explicit?

Can you spot the commonality and variation?

if ( ... ) {

} else {

}

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);}

Avoiding Duplicate Code

Commonality and Variability

Duplicate Code

Copy & Paste

☞ Duplicate CodeEdit the Copy

Duplicate Code

Avoid duplication by expressing commonality and variability

explicitly.

All tests must pass No code is duplicated

Code is self-explanatory No superfluous parts exist

0 10 20 30 40 50 60 70 80

0 10 20 30 40 50 60 70 80

0 10 20 30 40 50 60 70 80

0 10 20 30 40 50 60 70 80

“The prime directive that was unanimously agree upon by allpresent was that in the nexttens years Agile leaders must

Demand Technical Excellence.”

Jeff Sutherland

“Failure to do that meansyou are not an Agile leader.”

Jeff Sutherland

Personal Action Plan

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

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