Upload
techwellpresentations
View
411
Download
1
Tags:
Embed Size (px)
DESCRIPTION
The question of how much design to do up-front on a project is an engaging one. Too much design often results in overkill, complexity, and wasted effort. Too little design results in insufficient system structures that require later rework, additional complexity, and wasted effort. How can we know what the right balance is? Ken Pugh shows how to use advice taken from Design Patterns, coupled with the attitude of not building what you don’t need from agile. The trick is in observing potential variation, how it may affect you in the future, and then how to isolate these risks in a simple manner. Ken describes the essence of emergent design – that is, start with a simple design and let it evolve as the requirements evolve. He also demonstrates how to refactor to achieve better designs and how this is different from refactoring bad code.
Citation preview
!
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"