Avoiding Overdesign and Underdesign
-
Upload
techwellpresentations -
Category
Technology
-
view
411 -
download
1
description
Transcript of Avoiding Overdesign and Underdesign
!
BT6 Concurrent!Session!11/14/2013!2:15!PM!
!!!!
"Avoiding Overdesign and
Underdesign" !!!
Presented by:
Ken Pugh
Net Objectives !!!!!!!!!
Brought(to(you(by:(!
!!
340!Corporate!Way,!Suite!300,!Orange!Park,[email protected]!E!www.sqe.com
!!!!Ken!Pugh!!!Net!Objectives!!
A fellow consultant with Net Objectives, Ken Pugh helps companies transform into lean-agile organizations through training and coaching. His special interests are in communication (particularly effectively communicating requirements), delivering business value, and using lean principles to deliver high quality quickly. Ken trains, mentors, and testifies on technology topics from object-oriented design to Linux/Unix. He has written several programming books, including the 2006 Jolt Award winner Prefactoring and his latest Lean-Agile Acceptance Test Driven Development: Better Software Through Collaboration. Ken has helped clients from London to Boston to Sydney to Beijing to Hyderabad. He enjoys snowboarding, windsurfing, biking, and hiking the Appalachian Trail. Reach Ken at [email protected]!
info@netobjec+ves.com000www.netobjec+ves.com0
1" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Avoiding(Over(and(
Under(Design(In"Agile"Projects"
"Ken"Pugh"
Fellow"Consultant"Net"Objec6ves"
2" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Agenda"
! Emergent"Design"– Code"Quali6es"– Refactoring"
! Case"Study"! Advice"from"the"Gang"of"Four"! Emergent"Design"In"Ac6on""
"
3" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Ken"Pugh"
ken.pugh"@netobjec6ves.com"
Photo Size: Height: 2.25 Position: from top left corner Horizontal 0.75 Vertical 1. Picture Style: Simple Black Frame
No code goes in till the test goes on. A journey of two thousand miles begins with a single step.
! Fellow"Consultant"! OOA&D,"Design"PaSerns,"Lean,"Scrum,"TestVDriven"
Development"
! Over"2/5"century"of"soYware"development"experience"
! Author"of"seven"books,"including:"– 0Prefactoring:0Extreme0Abstrac+on,0Extreme0
Separa+on,0Extreme0Readability00(2006"Jolt"Award)"
– 0Interface0Oriented0Design0
– Lean0Agile0Acceptance0TestFDriven0Development:0BeHer0SoIware0Through0Collabora+on0
4" "Copyright"©"2007"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Lean"Enterprise"
Business"
Management"Team"
ASSESSMENTS"CONSULTING"TRAINING"COACHING"
Lean Management Project Management
Kanban / Scrum ATDD / TDD / Design Patterns Emergent Design
Lean for Executives Product Portfolio Management Business Product Owner Scaled Agile Framework
technical" process"
5" """ "6"November"2013"
Emergent(Design(
3(Code(Quali8es(
6" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Predictability"
! Can’t"predict"how"requirements"going"to"change"! Can"predict"how"code"will"adapt"to"unpredictable"requirements"changes"
! How"to"increase"predic6on"abili6es"of"code"quality?"
7" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Ques6on"to"Ask"
! When"working"on"a"mature"system"consider"when"adding"a"new"func6on…"""""""which"task"area"takes"more"6me"" " "–"wri6ng"the"new"func6on"or""
" " "–"integra6ng"it"into"the"system?"
8" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
9" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Creeping"Changes"
function() { Do_this; Do_that; Do_something_else; }
10" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Creeping"Changes"(2)""
function() { if (a) {
Do_another_thing: //… }
else { Do_this; Do_that; Do_something_else; }
}
11" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Creeping"Changes"(3)""
function() { if (a) {
if (b) { Do_another_thing:; //… }
else { Do_one_more_thing; //.. }
} else {
Do_this; Do_that; Do_something_else; }
}
12" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Cohesion"
! Cohesion""– How"“closely"the"opera6ons"in"a"rou6ne"[or"class]"are"related.”""– Cohesion"as"“clarity”""
! Because"the"more"opera6ons"are"related"in"a"rou6ne"[or"class]"the"easier"it"is"to"understand"the"code"and"what"it's"intended"to"do."*"
! Strong"cohesion"related"to"clarity"and"understanding."! “No"schizophrenic"classes”"
*"Steve(McConnell,"Code0Complete,"1993,"p."81."Note:"This"concept"was"first"described"by"Larry"Constan6ne"in"1975,"but"we"like"McConnell’s"defini6on"best."
13" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Coupling"
! Coupling""– Strength"of"a"connec6on"between"two"rou6nes"[or"classes].""– Coupling"is"a"complement"to"cohesion."""
! Cohesion"describes"how"strongly"the"internal"contents"of"a"rou6ne"[or"class]"are"related"to"each"other.""
! Coupling"describes"how"strongly"a"rou6ne"is"related"to"other"rou6nes.""
– Goal"is"to"create"rou6nes"[and"classes]"with"internal"integrity"(strong"cohesion)"and"small,"direct,"visible,"and"flexible"rela6ons"to"other"rou6nes"[and"classes]"(loose"coupling).”*"
! Tight"coupling"is"related"to"highly"interconnected"code."
*"Steve(McConnell,"Code0Complete,"1993,"p."81."Note:"This"concept"was"first"described"by"Larry"Constan6ne"in"1975,"but"we"like"McConnell’s"defini6on"best."
14" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Coupling"To"Data"
Global Data
Function One
Function Two
Function Three
Attributes
Method One
Method Two
Method Three
Class
15" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
No"Redundancy"
! "One"Rule"in"One"Place""! Redundancy"is"not"just:"
– Redundant"state"– Redundant"func6ons"
! It"can"also"be"redundant"rela+onships0
16" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Encapsula6on"
Usual"encapsula6on""! Data"
– Hide"from"other"en66es."! Implementa6on"
– How"par6cular"func6on"is"implemented"or"whether"it"delegates"to"other"objects"
Also:"(
! Object"Type"– Abstract"classes"and"interfaces"hide"implemen6ng"classes."
! Design"– Assembling"collabora6ng"classes"with"factory"keeps"clients"decoupled"from"design"
! Construc6on"– Encapsula6on"of"construc6on""V"wrap""new"""in"getInstance()"method""
"
17" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Abstrac6on"
! Abstrac6on"encompasses"encapsula6on"– Think"about"what"you"want"done,"not"how"you"want"it"done""
! “When"You’re"Abstract,"Be"Abstract"All"the"Way”"– Never"use"a"primi6ve"
! Example:"– double"GetCost();""– AddToOrder(double"price);"
! Versus"– Dollar"GetCost();"– AddToOrder(Dollar"price);""
""
18" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Observa6on"
! Reversible"changes"are"oYen"not"equal"in"difficulty"! Usually"easier"to"deobjec6vey"for"performance"than"it"is"to"objec6vey"for"code"quality""
! Example:"– double"GetCost()""""Dollar"GetCost()"
– Dollar"GetCost()"""double"GetCost()""
19" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Testability"and"Design"
! Crea6ng"tests"first"is"a"kind"of"design"! Forces"look"at:"
– Public"method"defini6ons"
– What"responsibili6es"of"object"are"
! Easy"testability"6ghtly"correlated"to:"– Loose"coupling""– Strong"cohesion"
20" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Testability"
! Difficult"to"unit"test""code"is"oYen:"– Tightly(Coupled:""
"I"cannot"test"this"without"instan6a6ng"half"the"system“"
– Weakly(Cohesive:"""This"class"does"so"much,"the"test"will"be"enormous"and"complex!“"
– Redundant:"""I'll"have"to"test"this"in"mul6ple"places"to"ensure"it"works"everywhere""
21" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Unit"Tes6ng"
! Tests"at"low"or"granular"level"! Test"confirms"that"code"reflects"one"inten6on"of"system"! Good"test"of"our"thought"process:"
– If"class"does"one"thing"(strong"cohesion)"! Then"func6onality"is"testable"
– If"class"does"not"create"side"effects"in"other"classes,"(loose"coupling),""! Then"testable"individually"
22" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Testability"and"Contracts"
! Contracts"– Seman6c"–"desired"behavior""
– Syntac6c"–"enforced"by"language""! Seman6c"contract"enforced"by"syntac6c"contract"requires"less"tes6ng"
! Example:"– void"setPriority(int"priority);""versus"
– void"setPriority(Priority"aPriority);"
23" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Quali6es"and"Pathologies"
! Strong"cohesion"– Goal:"classes"do"one"thing"–"easier"to"understand"– Pathology:"the"“God"object”"is"as"bad"as"it"gets"
! Proper"coupling"– Goal:"well"defined"rela6onship"between"objects"– Pathology:"side"affects"when"have"improper"coupling"
! No"redundancy"– Goal:"once"and"only"once"– Pathology:"a"change"in"one"place"must"be"duplicated"in"another"
! Readability"– Goal:"coding"standards"– Pathology:"nonVreadable"code"
! Encapsula6on"– Goal:"hide"data,"type,"implementa6on"– Pathology:"assump6ons"about"how"something"is"implemented"makes"it"
difficult"to"change"
24" """ "6"November"2013"
Emergent(Design(
Refactoring(
25" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Refactoring"
! Refactoring:""Improving"the"Design"of"Exis6ng"Code"*"! “Refactoring"is"the"process"of"changing"a"soYware"system"in"such"a"way"that"it"does"not"alter"the"external"behavior"of"the"code"yet"improves"its"internal"structure.”*"
*0Mar8n(Fowler,"Refactoring:0Improving0the0Design0of0Exis+ng0Code."AddisonVWesley."1999."
26" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Types"of"Refactoring"
Refactoring(Bad(Code(
! Code""smells""! Improve"code"quality"
! Clean"up"code"without"breaking"system"
Refactoring(Good(Code(
! Code"is""6ght""! New"Requirement"means"change"in"code"/"design"
! Way"to"make"change"without"breaking"system"
27" """ "6"November"2013"
Case(Study(Monitoring"Microwave""
Communica6ons"Hardware""
28" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Complete"Requirements"
! Need"to"monitor"both"chips"and"cards"– Program"requests"status"of"either"and"sends"it"""
! Over"either"a"TCP/IP"connec6on"or"via"eVmail"(SMTP)""
! Messages"may"be"encrypted""– PGP64"bit"or"PGP128"bit"
! Chip"status"queued"for"sending"up"to"10"minutes"unless"an"error"– Card"status"sent"immediately"
! Configura6on"file"gives"transmission"method"to"use"
29" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Accommoda6ng"Change"with"Specializa6on"
! One"way"problem"could"evolve:"– Start"with"Chip"and"TCP/IP"– Add"one"func6on"at"a"6me"– Accommodate"through"specializa6on"
! Result"not"preSy"(except"as"in"preSy"common)"
30" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Start"with"ChipTCPIP"Requirement"
ChipTCPIP+ getAndSendStatus()# sendWithTCPIP()
Client
31" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Now"Get"Card"with"SMTP"
ChipTCPIP+ getAndSendStatus()# getStatus()# send()
Client
CardSMTP# getStatus()# send()
32" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
BeSer"Way"
Client
ChipTCPIP# getStatus()# send()
CardSMTP# getStatus()# send()
Hardware+ getAndSendStatus()
33" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Then"Get"Chip"with"SMTP"Requirement"
Client Hardware + getAndSendStatus()
Chip # getStatus()
ChipTCP # send()
ChipSMTP # send()
CardSMTP # getStatus() # send()
34" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Finally"Get"Card"with"TCPIP"Requirement"
Client Hardware+ getAndSendStatus()
Chip# getStatus()
Card# getStatus()
ChipTCPIP# send()
ChipSMTP# send()
CardTCPIP# send()
CardSMTP# send()
35" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
It"Is,"Of"Course,"Worse0
! Have"not"discussed"varia6ons"of"encryp6on"– Will"make"things"worse"
! Using"switches"instead"of"inheritance""– Will"have"coupled"switches"instead"of"class"hierarchy"
36" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Problems"with"This"
! BriSle.""– Not"easily"allow"for"new"deriva6ons"of"Card"and"Chip"
! Or"new"transmission"types"
! Redundant.""– Changes"in"send()"in"ChipTCPIP"causes"changes"in"CardTCPIP"
! Weak"cohesion."""– Concrete"classes"are"about"mul6ple"things."
! Mul6ple"varia6ons"cause"combinatorial"(class)"explosion"– Increases"maintenance"problems"
! In"Short:""– Using"inheritance"for"specializa6on"does0not0scale0
37" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Combinatorial"Explosion"
Client Hardware+ getAndSendStatus()
Chip# getStatus()
Card# getStatus()
ChipTCPIP# send()
ChipSMTP# send()
CardTCPIP# send()
CardSMTP# send()
ChipFTP# send()
CardFTP# send()
38" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Tes6ng"
! 10"Varia6ons"of"sending""! 10"Varia6ons"of"encryp6ng""! 10"Varia6ons"of"compressing""
! How"many"classes"if"use"inheritance?""! How"many"if"use"delega6on?"""
39" """ "6"November"2013"
Advice(from(the(
Gang(of(Four(
40" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Gang"of"Four"Gives"Us"Guidelines*"
! Design"to"interfaces"! Favor"object"delega6on"over"class"inheritance."
Gamma,(E.,(Helm,(R.,(Johnson,(R.,(Vlissides,(J."Design0PaHerns:0Elements0of0Reusable0ObjectFOriented0SoIware,"1995,"pp."18,"20,"29."
41" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Design"to"Interfaces"
! Determine"interface"for"class""– Design"to"that,"ignoring"implementa6on"details"
! Therefore"cannot"couple"to"them"
– What"you"hide"you"can"change"
! Stay"at"conceptual"level,"while"designing"– Promotes"Cohesion"
42" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Find"What"Varies"and"Encapsulate"It"
! Iden6fy"varying"behavior"! Define"interface"for"behavior""
– Tailor"as"you"go"– Extract"varia6ons"resul6ng"from"new"requirements"
– Put"those"into"their"own"interfaces"
43" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Favor"Delega6on"Over"Inheritance"
! Define"interface"encapsula6ng"varia6on""! Use"delega6on"to"instance"of"an"implementa6on""
Socket0
1. Decouples"concepts"2. Can"defer"decisions"un6l"run6me"3. Small"performance"hit"
Socket_cmp1" Socket_cmp2"
Compression0
Cmp1" Cmp2"
Socket"
Class0Inheritance0to0Specialize0 Object0delega+on0
44" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Interface"Oriented"Design"
! To"save"code,"you"can"use""– Inheritance""– Delega6on"to"another"class""
! Cannot"inherit"from"two"classes"(other"than"C++)"
! Therefore"either""– Need"to"determine"the"“most"important”"rela6onship""
45" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Interface"Oriented"Design"(2)"
! Lean"principle""– Make"commitment"at"the"last"possible"moment""
– (Or"not"at"all"if"possible)""! Prefactoring"guideline"
– Avoid"premature"hierarchiliza6on""– Don’t"make"hierarchy"unless"it"is"necessary"""
46" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Separate"Use"From"Construc6on"
! An"object"should"construct"another"object"or"use"another"object"– But"not"both"
! Implement"construc6on"with"a"factory""
47" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Concept"/"Varia6ons"
Encryption
E128
E64
E0
Send
TCP
FTP
UDP
48" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
"Factory"Example""
// Client Selection enum EncryptionType {Strong, Weak, None}; Encrypt getEncryptInstance(EncryptionType et)
{ switch(et) { case Strong: return new E128(); case Weak: return new E64(); case None: return new E0(); default: throw new Exception( “Look at the EncryptionType”); } }
49" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Factory"For"Two"Strategies"
enum ChipType {ForCommercial, ForUS, ForImportantCustomer}; Chip getChip(ChipType ct) {
switch (ct) { case ForCommercial:
return new Chip(GetEncryptInstance(Weak), GetSendInstance(TCP));
case ForUS: return new Chip(GetEncryptInstance(Strong), GetSendInstance(FTP));
case ForImportantCustomer: return new Chip(GetEncryptInstance(Weak), GetSendInstance(FTP); }}
// Or use table
50" """ "6"November"2013"
Emergent(Design(In"Ac6on"
51" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Emergent"Design"
! TestVDriven"Development,"integrated"with:"– High"quality"code"– Knowledge"of"design"paSerns"– A~tude"of"building"only"what"you"need"(Agile,"YAGNI)"
! Allows"for"designs"to"emerge"! Can"take"advantage"of"what"we"know"
– Without"overbuilding"or"overVdesigning."
52" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Requirements"as"“Stories”"
! Story(1:"Request"the"status"of"a"chip,"encrypt"it"with"PGP64"bit"encryp6on"and"send"that"status"out"via"TCP/IP"
! Story(2:"Allow"for"not"encryp6ng"the"status"or"using"either"PGP64"bit"or"PGP128"bit"encryp6on.""A"configura6on"file"will"determine"what"(if"any)"encryp6on"is"needed"
! Story(3:"Support"transmission"via"an"eVmail"connec6on.""A"configura6on"file"will"determine"which"type"of"transmission"to"use"
! Story(4:"Support"ge~ng"and"sending"the"status"for"a"card"as"well"
53" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Emergent"Design:"Star6ng"with"Story"1"
! Request"status"of"a"chip,"encrypt"it"with"PGP64"bit"encryp6on"and"send"that"status"out"via"TCP/IP"
! Implement"simplest"solu6on"possible:"– No"extra"func6on"– Design"for"full"system"will"emerge"via"refactoring"
54" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Thinking"from"a"Testability"Perspec6ve"
! What"do"we"need"to"test?"– Ge~ng"status"
– Encryp6ng"a"string"– Sending"an"encrypted"string"
! Straigh�orward"to"write"tests"for"individual"methods"! Where"should"the"methods"lie?"! What’s"the"easiest"way?"
55" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
TestVFirst"Development"Steps"
1. Write"a"test"that"expresses"an"intent"of"a"class"in"system"
– Stub"out"class"(enough"to"allow"the"test"to"compile)"2. Fail"the"test"(don't"skip"this)"
– Change"class"just"enough"to"pass"test"3. Pass"the"test"4. Examine"class"for"coupling,"cohesion,"redundancy,"and"
clarity"problems."""– Refactor."
5. Pass"the"test"6. Return"to"#1"un6l"all"inten6ons"are"expressed"
56" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Solu6on"Diagrammed"
Chip+ getAndSendStatus()# getStatus()# encrypt()# send()
Encrypt+ encrypt()
TCPIP+ transmit()
Client
57" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Why"Is"this"BeSer?"
! Clear"what"pieces"do"and"how"they"relate"– Increases"extensibility"– Eases"maintainability"
! Some6mes"requirements"misVlead"us"
58" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Transi6on"
! Remember:"Two"Kinds"of"Refactoring"1. Refactoring0Bad0Code:""
! To"improve"code"quality"
2. Refactoring0Good0Code:"! To"implement"new/changed"requirement,"
– Now"going"to"do"the"second"
59" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Story"2:"Mul6ple"Encryp6ons"
! Allow"for"using"no"encryp6on,"PGP64"bit"encryp6on"or"PGP128"bit"encryp6on"
60" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Refactoring"Says"to"Restructure"Before"Adding"
! Refactoring:""– Change"code"before"adding"new"func6on."– Keep"func6on"same,"but"restructure"code"to"improve"it"
! Advantages:"– If"upVfront"tes6ng,"tests"don’t"need"to"change"
! Doing"same"things"
– Always"have"something"that"works"– If"one"step"at"a"6me"and"something"breaks"
! More"likely"to"know"what"caused"it""
61" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
How"Can"We"Most"Easily"Test"Things?"
! Need"to"test"every"encryp6on"! Want"to"deal"with"encryp6ons"same"way."! Easy"if"have"a"common"interface"for"encryp6ons"! If"interfaces"aren’t"the"same,"then"either:"
– Chip"has"to"deal"with"differences""– Use"design"paSerns"to"hide"varia6ons"
! Requires"wrapping"differences"
62" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
OpenVClosed"Principle"
! Ivar"Jacobson"said:""– “All"systems"change"during"their"life"cycles.""This"must"be"borne"in"mind"
when"developing"systems"expected"to"last"longer"than"the"first"version”"
! Bertrand"Meyer"summarized"this"as:""– SoYware"en66es"(classes,"modules,"func6ons,"etc.)"should"be"open"for"
extension,"but"closed"for"modifica6on"
! In"short:"– Design"modules"so"that"they"never"change."""– When"requirements"change,"add"new"modules"to"handle"things"
For"a"good"ar6cle"on"the"OpenVClosed"Principle,"see"www.objectmentor.com/publica6ons/ocp.pdf""
63" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Refactoring"to"OpenVClosed"
! First"refactor"code"so"can"add"new"func6on"following"OCP"
! Then"add"new"code"
64" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
First,"Add"Needed"Interface"and"Factory"
Chip+ getAndSendStatus()# getStatus()# encrypt()# send()
Encrypt+ encrypt()
TCPIP+ transmit()
Encrypt64
Client
Config+ getEncrypt()
Used by Client or Chip
65" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Now,"Can"Put"in"the"New"Func6on"
! Someone"must"determine"which"encryp6on"to"use"! Maybe"configura6on"object"can"do"that""
! Client"object"asks"configura6on"object"what"to"use"! Chip"object"given"needed"behavior""! Now"add"encrypt128"and"no"encrypt"op6ons"! Note:""
– Chip"object"could"talk"to"configura6on"object"– Then"Client"must"give"Chip"informa6on"configura6on"object"needs"
"
66" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Then,"Add"New"Implementa6ons"
Chip+ getAndSendStatus()# getStatus()# encrypt()# send()
Encrypt+ encrypt()
TCPIP+ transmit()
Encrypt64
Client
EncryptNull
Encrypt128
Config+ getEncrypt()
Used by Client or Chip
makes one of these
67" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Story"3"
! Support"transmission"via"an"eVmail"connec6on.""A"configura6on"file"will"determine"which"type"of"transmission"to"use"
! Testability"suggests"concept"of"Transmission"– Don’t"have"to"test"all"combina6ons"
! Design"PaSerns"tell"us"same"thing"
68" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Want"to"Follow"Gang"of"Four"Advice"
! Because"transmission"will"vary,"– Encapsulate"it"and"delegate"to"it"from"Chip"
! To"implement"– First"pull"out"exis6ng"transmission"func6onality"into"own"class"""
! No"extra"cost"by"doing"this"now"instead"of"when"possibility"first"no6ced"
69" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Refactor"First"
Chip+ getAndSendStatus()# getStatus()# encrypt()# send()
Encrypt+ encrypt()
TCPIP
Encrypt64
Client
EncryptNull
Encrypt128
Config+ getEncrypt()+ getTransmit()
Used by Client or Chip
Transmit+ transmit()
makes one of these
makes this
70" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Add"Other"TransmiSers"
TCPIP
Chip+ getAndSendStatus()# getStatus()# encrypt()# send()
Encrypt+ encrypt()
Encrypt64
Client
EncryptNull
Encrypt128
Config+ getEncrypt()+ getTransmit()
Used by Client or Chip
Transmit+ transmit()
SMTP
makes one of these
makes one of these
71" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Story"4:"Support"Cards"
! For"tes6ng"reasons"– Don’t"want"to"have"to"handle"different"func6onal"test"cases"when"we"have"Cards"or"Chips"
– Want"to"handle"them"together"
! Want"Cards"and"Chips"to"appear"to"be"the"same"to"the"Client"
! Implement"with"twoVstep"RefactorVOCP"shuffle"
72" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
First,"Refactor"So"OCP"Can"Apply"
TCPIP"
Chip"
Encrypt"+ encrypt()"
Encrypt64"
Client"
EncryptNull"
Encrypt128"Config"
+ getEncrypt()"+ getTransmit()"
Used by Client "or Hardware"
Transmit"+ transmit()"
SMTP"
Hardware"+ getAndSendStatus()"# getStatus()"# encrypt()"# send()"
makes one of these"
makes one of these"
+getHardware()"
73" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Then,"Add"New"Func6on"
TCPIP"
Chip"
Encrypt"+ encrypt()"
Encrypt64"
Client"
EncryptNull"
Encrypt128"
Transmit"+ transmit()"
SMTP"
Card"
Hardware"+ getAndSendStatus()"# getStatus()"# encrypt()"# send()"
makes one of these"makes one of these"
Config"+ getEncrypt()"+ getTransmit()"
Used by Client "or Hardware"
+getHardware()"
This(is(a(brid
ge(paRern!
(
74" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
"A"Few"Comments"
! Not"coincidence"or"good"luck"change"is"easy"! Happened"because"
– No"redundancy""– Unrelated"things"in"different"classes"
! Low"level"dis6nc6ons"easy"to"see"– Even"if"immediate"benefit"is"not"
! Use"them"because"they"represent"very"low"cost"– Will"result"in"significant"gains"if"things"change"(which"they"almost"certainly"will)"
75" """ "6"November"2013"
Code(Quali8es((
As(A(Guide(
76" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Using"Coding"Quali6es"
! Could"arrive"by"following"coding"quali6es.""! TDD,"DPs"and"CVA"(Commonality/Variability"Analysis)"are"related"to"code"quali6es""– Easy"to"use,"so"use"them""
! However,"to"illustrate,"say"started"with:"
! and"then"got"another"transmiSer."
ChipTCPIP+ getAndSendStatus()# sendWithTCPIP()
Client
77" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Handling"This"in"Chip"Weakens"Cohesion"
! Handle"varia6on"as:"private void sendStatus(String anInfo) { if (transType== TCPIP) sendStatusTCPIP(anInfo); else sendStatusSMTP(anInfo); }
! Requires"Chip"class"to"remember"more"detail"about"transmission."– More"than"how"TCP/IP"works"– Now""SMTP"stuff""– This"erodes"cohesion""
! So"split"out"TransmiSer."
78" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Using"Encapsula6on"
! Consider"how"to"break"up"func6onality"into"classes"– Where"as"much"as"possible"is"encapsulated""
! Implementa6on"encapsula6on"implies""– Pull"out"encryp6on"
! Design"encapsula6on"means""– Chip"should"not"know"about"mul6ple"encryp6ons"– Hence"polymorphism"and"factory"
79" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Different"Approaches"for"Different"Situa6ons"
! Emergent"Design"allows"forward"mo6on:"– When"certainty"
! PaSern"Oriented"Design"– When"a"lack"of"certainty"
! TestVDriven"Development,"supported"by"– Refactoring"
! PaSerns"help"us"see""leading"edge""of"new"designs""
80" """ "6"November"2013"
Not(An(Ending,(
But(a(Beginning(
""
81" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Conclusions(1)"
! Design"emerges"from:"– Concepts"and"varia6ons"(Commonality/Variability"Analysis)""– Abstrac6ons"(and"encapsula6on)"– Refactoring,"with"adherence"to"good"principles"– Thinking"about"paSerns,"which"reflect"past"adherence"to"good"principles"
82" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Conclusions"(2)"
! Agility"requires"flexibility"! Flexibility"comes"from:"
– Adherence"to"Good"Principles,"– Maintaining"awareness"of"emergent"design,"
– Understanding"the"forces"of"change"– Recognizing"applicable"paSerns"in"a"design"
"! We"can"create"maintainable"code!"
83" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
! Thank"you"
! Please"fill"out"evalua6ons""
info@netobjec+ves.com000www.netobjec+ves.com0
84" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Supplemental(
85" """ "6"November"2013"
Designing(with(
PaRerns(
86" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
The"Bridge"PaSern"
! GoF(Intent:"“DeVcouple"an"abstrac6on"from"its"implementa6on"so"that"the"two"can"vary"independently”*"
! In"example:"– Abstrac6on"is"Hardware"V"Chips"and"Cards)"– Implementa6on"is"oneaspect"of"its"responsibility"(TCP/IP"communica6on"
and"eVmail"communica6on)"
! All"implementa6ons"must"look"same"to"abstrac6on"
Gamma, E., Helm, R., Johnson, R., Vlissides, J. Design Patterns: Elements of Reusable Object-Oriented Software, 1995.
87" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
An"Abstrac6on"(Hardware)"Tightly"Coupled"to"Its"Implementa6on"(Transmission)"
Client Hardware + getAndSendStatus()
Chip + getAndSendStatus()
Card + getAndSendStatus()
ChipTCPIP + getAndSendStatus() # sendWithTCPIP()
ChipSMTP + getAndSendStatus() # sendWithSMTP()
CardTCPIP + getAndSendStatus() # sendWithTCPIP()
CardSMTP + getAndSendStatus() # sendWithSMTP()
88" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Bridge"Would"Tell"Us"to"Build"It"This"Way"
Client Hardware + getAndSendStatus()
Chip + getAndSendStatus()
Card + getAndSendStatus() TCPIP
+ sendInfo(string) + start() + done()
SMTP + sendInfo(string)
Transmit + sendInfo(string) + start() + done()
89" """ "6"November"2013"
Refactoring(a(
Poor(Design(
90" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Poor"Design"as"a"Result"of"Using"En66es""and"Behaviors"/"Specializa6on"
Client Hardware + getAndSendStatus()
Chip + getAndSendStatus()
Card + getAndSendStatus()
ChipTCPIP + getAndSendStatus() # sendWithTCPIP()
ChipSMTP + getAndSendStatus() # sendWithSMTP()
CardTCPIP + getAndSendStatus() # sendWithTCPIP()
CardSMTP + getAndSendStatus() # sendWithSMTP()
91" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Pull"Out"Duplica6on"of"Transmission"
Client Hardware + getAndSendStatus()
Chip + getAndSendStatus()
Card + getAndSendStatus()
ChipTCPIP + getAndSendStatus()
ChipSMTP + getAndSendStatus()
CardTCPIP + getAndSendStatus()
CardSMTP + getAndSendStatus()
TCPIP + sendTCPIP(string) + start() + done()
SMTP + sendSMTP(string)
92" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Create"Trans0Class"to"Simplify"Things"
SMTP + sendInfo(string)
Client Hardware + getAndSendStatus()
Chip + getAndSendStatus()
Card + getAndSendStatus()
ChipTCPIP + getAndSendStatus()
ChipSMTP + getAndSendStatus()
CardTCPIP + getAndSendStatus()
CardSMTP + getAndSendStatus()
TCPIP + sendInfo(string) + start() + done()
Transmit + sendInfo(string) + start() + done()
93" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Derived"Classes"Now"Not"Needed"
SMTP + sendInfo(string)
Client Hardware + getAndSendStatus()
Chip + getAndSendStatus()
Card + getAndSendStatus()
TCPIP + sendInfo(string) + start() + done()
Transmit + sendInfo(string) + start() + done()
94" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Can"Keep"Reference"in"Hardware"
HWComp + getAndSendStatus()
Transmit + sendInfo(string, int) + start() + done()
Chip + getAndSendStatus()
Card + getAndSendStatus()
TCPIP + sendInfo(string, int) + start() + done()
SMTP + sendInfo(string, int)
Client
95" """ "6"November"2013"
Technical(
Solu8ons(to(Aid(
Scaling(
96" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Keep"Technical"Dependencies"Low"
! Ways"minimize"dependencies"of"different"projects"on"each"other"– Design"PaSerns"– APIs"to"return"Value"Objects"– Mocks"to"provide"layering""
! And"to"avoid"scheduling"dependencies"! Difficul6es"when"one"project"uses"another"
– Use"component"tes6ng"as"a"method"of"decoupling"components"– Implement"with"up"front"testVspecifica6on"and"mocks"
! Minimize"impacts"that"do"occur"with"Test"Driven"Development"
97" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Using"Design"PaSerns"
! Design"paSerns"– How"to"deal"with"implementa6ons"at"the"conceptual"level,"i.e.,"through"an"API"
– If"added"or"changed"implementa6on""! Using"code"does"not"change"
– Handles"varia6on"! DP"can"be"used"in"agile"projects"effec6vely.""
98" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Decoupling"Projects"
! 4"Groups"(A,"B,"C,"D)"– All"use"a"network"maintained"by"E"– These"groups"all"need"informa6on"from"each"other"– They"stated"what"info"was"needed"at"start"of"project"
Group"A"
Group"E"
Group"C" Group"D"
Group"B"
99" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Good"Start,"Bad"Finish"
! New"informa6on"becomes"needed."– Group"A"needs"something"from"Group"B"
– Group"B"is"busy"and"not"par6cularly"helpful"– Group"B"will"not"allow"group"A"to"touch"their"code"
! How"could"we"have"set"it"up"to"resolve"these"issues?"– While"not"requiring"us"to"be"preVcogni6ve?"
! Use"the"ValueVObject"PaSern"
100" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Value"Object"PaSern"
! Have"each"group"have"an"API"that"has:"– setUp("flag,"GetInfo"useThis)"–"used"to"say"which"value"object"to"use."– ValueObject"getInfo(flag)"
! Calling"program"knows"– Type"of"value"object"to"use""
! and"the"rou6ne"to"fill"it"out"– Knows"what"it"gets"back"
! Can"use"that"par6cular"informa6on"
101" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Shown"in"the"UML"
Group"A"Group"B"
"""+getInfo(flag)"
Group"C"
Group"D"
GetInfo"+ValueObject"getInfo()"
GetInfoForC"+ValueObject"getInfo()"
GetInfoForA"+ValueObject"getInfo()"
GetInfoForD"+ValueObject"getInfo()"
ValueObject"
ValueObjectC"ValueObjectA"
ValueObjectD"
+setUp(flag,"GetInfo"useThis)"""""
102" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
How"This"Works"
Group"A"Group"B"
"""+getInfo(flag)"
Group"C"
Group"D"
GetInfo"+ValueObject"getInfo()"
GetInfoForC"+ValueObject"getInfo()"
GetInfoForA"+ValueObject"getInfo()"
GetInfoForD"+ValueObject"getInfo()"
ValueObject"
ValueObjectC"ValueObjectA"
ValueObjectD"
+setUp(flag,"useThis)"""""
info@netobjec+ves.com000www.netobjec+ves.com0
103" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Mocks(on(a(Large(
Scale(
104" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Managing"Dependencies"
! Let’s"say"group"A"needs"to"use"the"system"built"by"group"B""
! Group"A"specifies"to"Group"B"what"group"B"needs"to"provide"
! Group"A’s"and"Group"B’s"understanding"is"changing"as"6me"goes"by"
! How"can"we"manage"this?"
105" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Managing"Dependencies"
Team"A:"“We"need"this”"
Team"B:"“How"will"we"know"we’ve"done"
that?”"
“When"your"system"does"this”"
How"should"team"B"respond?"
106" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Managing"Dependencies"
Mock"
Team"B"should"build"a"mock"of"their"system"
The"mock"sa6sfies"the"tests"that"team"A"specifies"
A’s""System" Uses"
107" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
A"Mock"as"Requirements/Test"
! Note"mock"fulfills"the"following"uses:"– Defines"the"requirements"for"A"
– Can"be"used"by"A"to"run"while"team"B"builds"it"– Is"an"executable"specifica6on"for"team"B"
! So"they"can"see"if"they"are"building"the"right"thing"! Tests"that"define"the"mock"can"be"used"as"tests"for"team"B’s"system"
! What"happens"if"team"A’s"or"team"B’s"understanding"changes?"– The"mock"must"be"updated"
108" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Resources"
! Resources:"www.netobjec6ves.com/resources""– Webinars/Training"Videos"(PowerPoint"with"audio)"– Ar6cles"and"whitepapers"– Pre/post"course"support"Suppor6ng"materials"– Quizzes"– Recommended"reading"paths"
! Blogs"and"podcasts:"blogs.netobjec6ves.com"! Annotated"Bibliography"! AYerVCourse"Support"(students"only)"! Addi6onal"Training"! Two"User"Groups"
– hSp://tech.groups.yahoo.com/group/leanagile""– hSp://tech.groups.yahoo.com/group/leanprogramming""
Join"our"eVmail"list"to"receive"regular"updates"and"informa6on"about"our"resources"and"training"of"interest"to"you"
109" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Context"
! How"do"you"avoid"over"and"under"design"in"agile"projects?"
110" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Exercise"
1. Imagine"a"6me"you"built"something"in"2"steps"(or"more)"and"had"significant"rework"in"later"steps"because"of"not"looking"ahead."That"is,"this"is"the"situa6on"you"are"concerned"about."
2. Now,"imagine"you"can"go"back"and"do"the"first"step"again"with"the"following"condi6ons:"1. You"know"everything"you"know"now"2. You"can"design"it"differently,"but"you"can’t"add"anything"that"
isn’t"needed"for"the"first"step"
3. How"would"you"design"it?"
111" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Good"Ques6ons"to"Ask"
! How"would"you"do"your"design"if"you"knew"later"that"whatever"you"did"now"was"wrong?""
112" """ "6"November"2013"
Emergent(Design(Design"PaSerns"and"Refactoring"for"Agile"
Development"
113" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Test:"What"Does"It"Mean?"
! 1(a"chiefly0Bri+sh":(CUPEL"b((1)":"a"cri6cal"examina6on,"observa6on,"or"evalua6on":(TRIAL;"specifically":"the'procedure'of'submi1ng'a'statement'to'such'condi4ons'or'opera4ons'as'will'lead'to'its'proof'or'disproof'or'to'its'acceptance'or'rejec4on(<a"test"of"a"sta6s6cal"hypothesis>"(2)":"a"basis"for"evalua6on":(CRITERION"c":"an"ordeal"or"oath"required"as"proof"of"conformity"with"a"set"of"beliefs""
! Test"can"be"thought"of:"– Specifica6on"that"says"you"are"doing"what"you"should"be"doing"
114" """ "6"November"2013"
Inheritance(
Versus(Interface(
115" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Inheritance"Issues""
! Combines"two"perspec6ves"– Common"interface"(specifica6on)"
! Derived"classes"play"the"same"role"as"base"class""
– Common"implementa6on""! inherited"methods,"aSributes"
! OYen"mix"up"these"perspec6ves"""
116" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Changing"Base"vs"Interface"
Base Class
Methodone()
Addedmethod() //New
Interface
Methodone()
Addedmethod() // New
Derived Class
Does Addedmethod() need overriding ?
Implementing Class
Addedmethod() needs implementation
117" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Inheritance"Versus"Interface"
BaseClass Method(); NewMethod():
DerivedClass AnotherDerivedClass Method() { anotherway;}
Interface Method(); NewMethod():
ImplementingClass AnotherImplementingClass
What happens if new method added to base class? Is it applicable to all derived classes? Do you know everything that is derived? What if four derived classes and two use same override? Need a helper class
InterfaceHelper Method(); NewMethod(): AnotherWay();
OneMore DerivedClass
Fourth DerivedClass Method() { anotherway;}
OneMoreImplementingClass FourthImplementingClass
118" "Copyright"©"2008"Net"Objec6ves."All"Rights"Reserved."" "6"November"2013"
Prefactoring"Guideline"
! Avoid"premature"hierarchiliza6on""– Don’t"create"hierarchies"un6l"you"really"need"them""
! It"is"easier"to"create"the"right"hierarchy"than"to"dehierarchalize"the"wrong"one"