Date post: | 21-Feb-2018 |
Category: |
Documents |
Upload: | securedome |
View: | 214 times |
Download: | 0 times |
of 63
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
1/63
Are You a SOLID Coder?
Principles of Software Design
Steve Green @stephenpgreen
[email protected] /stevepgreen
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
2/63
Who is this Guy?
My professional experienceI consider code an art form, and have
last 15 years at some of the finest techcompanies in Kansas City, trying to ma
"
If itswork, wetry to do
less.
If its art,
we try todo more.
- Seth Godin
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
3/63
What is Software Design?
To understand what software design is, it isimportant to contrast it with software analysis.
The process and effort usedto determine what should bebuilt is software analysis. Thisis generally a single activityconducted before the buildcycles start.
The constant decisionssurrounding how to build anapplication are its design.These are made both beforethe build starts and continuethrough delivery.
DesigIs Not
One-TActiv
Design is an evolutionary prthe construction of an appli
Software Analysis Software Design
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
4/63
Why Is Good Design Important?
Any fool can write code acomputer can understand. Gooprogrammers write code thathumans can understand. Fo
Good Design Is
Easily Consumed
1 Delivery: maintaining
good design allows us todeliver solutions fastergiven it is easier to workwith the code.
2 Change: a solution thatpreserves good designis more flexible whichmakes it easier for it tomanage change.
3 Compledesignefor simpdevelopcomple
Bad design often leads to frustrated, depressed, and de-motivated teams.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
5/63
How Does Bad Design Happen?
Bad design builds quietly over time until itbecomes unmanageable.
No one sets out to design software poorly; rather it happens slowly over time. Consider this messyThe designer didnt set out to create this disaster. Instead, it happened naturally over time as the rsmall bad decisions that incrementally destroyed this space.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
6/63
Identifying Good Design
Metrics are Key to Early DetectionMany teams have difficulty developing an earlymetric for good design, instead relying mostlyon the eye test during code reviews.
A Better Design CriteriaIdentifying good design is easier if we urubric based on common code smells.
Rigidity How easy is the des
Fragility Is the design easy to
Immobility Can the design b
Viscosity Is it hard to do the
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
7/63
Characteristics of Good Design
Low
Dependencies
Low
omplexity
High
Specificity
High
Testability
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
8/63
Good Design Is Everyones Responsibility
Always leave the code youreediting a little better than you fit. Bob Martin
The Boy Scout Ru
When teams accept the responsibility for the design, the system as a whole improves over time. Asoftware evolves, developers take an active approach to enhancing the system. Much like pickingtrash on the side of the road, if everyone does just a little bit, the highway remains clean for everyo
Being a SOLID coder means you have the skills necessary to carry
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
9/63
Meet Uncle Bob Martin
Bob Martin provided usaccepted guidelines tosolutions based on besThese principles are re
the SOLID principles oforiented design.
Uncle Bobs SPrinciples of
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
10/63
The SOLID Principles of Software Design
SOLID is an acronym that can help us remember the concepts of good design. In a single word, we canof the most important patterns and practices to use when building applications.
SingleResponsibility
PrincipleS
DependencyInversionPrinciple
D
LiskovSubstitution
PrincipleL
Open/ClosedPrinciple
O
InterfaceSegregation
PrincipleI
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
11/63
What is the Single Responsibility Principle?
Avoid Trying to Do Too MuchCode that tries to do too much becomes hardto understand, maintain, and use.
You should focus on doing one thin
A unit of code (whether it is a cmethod or function) should tryONLY one thing.
If the code adheres to this ideait is only susceptible to a singlechange in the softwaresspecification, but no more.
Single ResponsibPrinciple
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
12/63
What is a Responsibility?
Softwarerequirem
responsib
The moreresponsibmore likefor chang
1
2
3
Grouping
responsibcouples t
The morechange ehigher chproduce
4
A responsibility is an axis ofchange. When viewed from the
perspective of the client, itgenerally reflects a difference inthe possible use of the software.
A Responsibility Is aReason for Change
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
13/63
A Quick Example: The Modem
Lets Consider a ModemA modem has two main responsibestablish connections and transmit
The Modem InterfaceBelow we design a simple interface that will represent amodem in our project.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
14/63
A Quick Example: The Modem
Lets Refactor Towards the SRPOnce we refactor our example to adhere to the single responsibility principle, wmodem represented as multiple discrete interfaces.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
15/63
Maximizing Class Cohesion
Magnet Classes Attract The LazyA class that has low cohesion acts like amagnet attracting lazy developers. Theseclasses quickly become dumping grounds.
Methods Must Be Strongly-ReMaximizing cohesion ensures that all the cclass works together to accomplish a sing
High cohesion enhances the readcode.
Classes that expose singular funceasier to reuse.
Code that is well organized avoidpollution.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
16/63
Why is Cohesion Important?
This theater used to bejewel for the city of Dehas been converted intdowntown parking lot.
This is extremely odd. T
clearly dont go togethusing a theater this wayconfusion and more qu
Detroits MiTheate
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
17/63
Identifying Low Cohesion
The Name MattersRemember that cohesion is abougroupings. If youre having troublclass, chances are you have low c
Features of Low CohesionBelow are some traits of low cohesion within your classes:
Watch out for methods that dont interact withthe rest of the class.
Check your fields and make sure they are usedby more than one method.
Monitor your source control to find classes thathave a higher frequency of change.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
18/63
Minimizing Code Coupling
Classes that maintain the singleresponsibility principle naturallybecome loosely coupled.
When code is tightly coupled, anymodification becomes a risky
proposition, as the change has ahigh chance of interfering with theother responsibilities of the class.
Loosely CoupledCode
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
19/63
Summarizing Single Responsibility Principle
Remembering the Single Responsibility Principle is easy:
only do one thing at a time in your code.
If you follow this principle, you will notice that you have very few if, switch or other branching stbecause you have isolated and segregated those other functions into different classes. Those clastheir own context and understand their unique behaviors.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
20/63
What is the Open/Closed Principle?
Avoid Getting Under the HoodClasses that require a change to internallycontained code for new behavior is inflexible.
New behaviors should be added by extending
Software entities should be opextension, but closed tomodification.
We shouldnt need to dig into internals of the software in ordadd or change its behavior. Inswe should add behavior byextension.
Open/ClosedPrinciple
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
21/63
Why Is the Open/Closed Principle Important?
Calling coisolated f
Sometimdependecannot b
1
2
3
New claslikely to p
errors witsoftware
Reducesof necessany chan
4
The open/closed principle helpsto ensure that the risks that code
edits endure are properlymitigated. This helps us buildhighly flexible systems.
ChangeManagement
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
22/63
The Open/Closed Principle Using Parameters
Parameters Are Explicit Extending code using parameterspowerful tool in procedural langu
Such parameters generally contain some type of state
information that allows a method to behavedifferently.
Allow clients to controlbehavior by passingcontextual parametersto a method.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
23/63
Extending the Modem Using Parameters
The Modem ChannelHere we have refactored the modemto demonstrate the open/closed prin
parameters.
Note that new behaviors for any chanwould not require modifications to thimplementation.
Delegates Are Very PowerfulUsing delegates or lambda expressions can bea potent tool for building flexible code.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
24/63
The Template Method Pattern
Overriding Inherited CoThe most common form of exteninheritance using object oriented
Deferred Code ExecutionThe template method behavioral pattern allows somepieces of an algorithm to be deferred to a subclass.
A skeleton of the algorithm is defined in a baseor root class.
Some implementations can contain defaultbehavior in template methods.
Subclasses then override the template withdifferent behavior without modifying the root.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
25/63
The Strategy Pattern
The strategy pattern forces clito depend upon abstractions tcan be swapped in or out witheffecting the caller.
Extension WithPluggable Modul
When implementing a strategy pattern, it is common to see behaviors exposed to clients thrabstraction such as an interface or base class. The calling code can then use various mechaplug the concrete module in at run time, including: dependency injection, composition, etc.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
26/63
The Strategy Pattern: Extending the Modem
Favoring CompositionComposing objects offers much more flexibilitythan other extension mechanisms.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
27/63
When Should You Apply the Open/Closed Principle?
Dont Fool Me TwiceApply the Fool me once shame me twice, shame on me rule.
New problem domainsWhen dealing with a new problem domain startwith simplicity and work towards complexity.
Begin your initial implementation without usingthe open/closed principle.
If a change happens, just accept it and modifythe code.
If a change happens again, then refactor utilizingthe open/closed principle.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
28/63
Avoid Complexity When Possible
Remember that there is no such thingas a free lunch.
The open/closed principle adds the cost of complexity to the design. So make sure that the compleand is providing a benefit to the system.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
29/63
Be Careful Not To OveruseAbstractions
Lets consider a boxing matchA boxing match is always between twoindividual fighters in a ring.
The boxing match modelObviously, the below model is silly. Howthis are quite common as developers fee
provide an interface for every object.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
30/63
Summarizing the Open/Closed Principle
Remembering the Open/Closed Principle is easy:
guard against change by forcing modifications as extensions.
Conformance to the open/closed principle adds flexibility, reusability, and maintainability to your sThe key is to decide what changes to guard against while resisting premature abstraction.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
31/63
What is the Liskov Substitution Principle?
If it looks like a duck, and quacksObviously, a rubber duck is not a substitutionfor a real duck. This is a clear violation of Liskov.
Proper abstractions should be substitu
Subtypes must be substitutabtheir base types in all cases.
Calling code should not need aware that it is consuming a surather than the base type. Suctransactions must remaincompletely transparent.
Liskov SubstitutiPrinciple
Wh t D S b tit t bl M ?
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
32/63
What Does Substitutable Mean?
Child subnever remclass beh
Derived cnot violatclass inva
1
2
The Liskov Substitution Principlehelps ensure the integrity of thesystem by ensuring abstractionsbehave as expected.
If there is a drastic change inbehavior for a subclass, then thesystem is said to be volatile.
Integrity as theMetric
3Child clasnot throw
of excep
Subtypesadd new extend th
4
S ti M tt
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
33/63
Semantics Matter
Classic object oriented techniqmight describe a subclass as aA relationship. Instead, thing oan IS-SUBSTITUTABLE-FOR
Be Careful withNave Language
Event though we all learned object oriented programming by thinking in concrete terms such is a vehicle or a square is a rectangle, this is dangerous. Instead, it is safer to consider if a nbe substituted for another noun. Can a square be substituted for a rectangle in all cases?
What is an Invariant?
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
34/63
What is an Invariant?
Assumptions about aclass are expressed aspre/post-conditions.
Conditions are rarelyexpressed in code,but instead unit tests.
1
2Preserving the invarianof the base class is reaensuring the integrity omodels our classes rep
This consists of the reaassumptions that clienwhen calling the base
Its All AbouMode
3Derived classes mustnot violate any baseconstraints.
A Quick Example: The Square
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
35/63
A Quick Example: The Square
Is a Square a Rectangle?Obviously it is; however, is a square a suitablereplacement for a rectangle? Maybe not in allcases.
Lets start with a rectangleA rectangle has two simple properties: hBy its definition, a rectangle can have a h
from its width. This is depicted in the cod
A Quick Example: The Square
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
36/63
A Quick Example: The Square
Is a Square a Rectangle?Obviously it is; however, is a square a suitablereplacement for a rectangle? Maybe not in allcases.
Now consider a squareA square changes the basic constraints erectangle: height and width must always
Some Helpful Tips
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
37/63
Some Helpful Tips
Discovering Liskov issues can be difficult. However,once an issue is detected, here is some practical
advice to resolve the issue.
Tell, Dont AsDo not interrogatetheir internal state
them the behavio
Use New BasWhen two objectbut are not substiadding a new roo
Tests Are YoRemember, testinfor post-conditioneasiest way to fin
Identifying and ResolvingLiskov ViolationsCan Be Tricky
A Quick Example: The Square
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
38/63
A Quick Example: The Square
Thinking About BehavioSometimes it helps to think abouinstead of state, and abstract froarea calculation is a primary use
A Better ModelA better model is to introduce a new base class that bothrectangle and square extend. In this way, both are alwayssubstitutable for a shape.
Summarizing the Liskov Substitution Principle
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
39/63
Summarizing the Liskov Substitution Principle
Remembering the Liskov Substitution Principle is easy:
ask if an object can be substituted for another object before inheriting
Conformance to the Liskov Substitution Principle ensures proper use of polymorphism that maintaintegrity to your software model. This helps produce more maintainable code and reliable tests.
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
40/63
What is the Interface Segregation Principle?
Grouping a Bunch of InterfacesUsing a bunch of discrete interfaces makes ourcode more explicit and easier to understand.
Avoid fat interfaces that have unus
Clients should not be forced todepend on methods they do nuse. Instead, they should consclean cohesive interfaces.
This prevents client objects frodepending on members they use.
InterfaceSegregation Princ
Why Does It Matter?
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
41/63
Why Does It Matter?
Interfacemany meless reus
Useless mleads to icoupling
1
2
The Interface SegregationPrinciple ensures that our code islean and nimble. When adependency has too many
unused members, it just createsextra baggage we have to dealwith.
Giant Interfaces AreExtra Baggage
3Additionaleads to i
complex
Multiple sinterfacesingle res
4
How to Identify?
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
42/63
y
Look for Unused CodeTo find interface segregation violations just lookfor unused code. Once found, isolate theunused blocks in separate logical interfaces.
Some Simple TechniquesIdentifying good design is easier if we urubric based on common code smells.
Reference UtilizationIf a client references a class, bvery small subset of its functio
Not Implemented Exceptions
If a client only implements a feand throws errors when a clienimplemented members.
A Quick Example: A Bird
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
43/63
p
How would you model Chances are, you would add capflight. However, what happens wimplement an Ostrich?
Consider a Simple Bird ModelWe create an interface that expresses what webelieve are the behaviors of a bird.
A Quick Example: A Bird
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
44/63
p
How would you model Chances are, you would add capflight. However, what happens wimplement an Ostrich?
A Better SolutionBelow, weve refactored our solution toaccommodate the different types of birds usingthe Interface Segregation Principle.
When Should You FixViolations?
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
45/63
As in most refactoring sthe only time you shouexisting interface segreviolations is when theyOtherwise, there are likvaluable things to spenbuilding.
Is the viol
painfu
Summarizing the Interface Segregation Principle
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
46/63
Remembering the Interface Segregation Principle is easy:
look for wasteful members that are not being used and separate them.
Conformance to the Interface Segregation Principle ensures flexible solutions that are highly mobialso promotes reusability as it lowers the barriers for other developers to consume your code.
Wh t i th D d I i P i i l ? D d b t ti t
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
47/63
What is the Dependency Inversion Principle?
Consider an Electrical OutletOutlets provide an easy abstraction forelectronic devices. Imagine the alternative,soldering a wire directly to the power line?
Depend upon abstractions, not co
High level modules should nodepend upon low level modulInstead, both should depend uabstractions.
Likewise, abstractions should depend upon details. Rather, dshould also depend uponabstractions.
DependencyInversion Princip
Why Does It Matter?
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
48/63
Two clas
tightly codirectly deach othe
Tightly coclasses cindependother.
1
2The Dependency InversionPrinciple ensures that our code isflexible. When our solution istightly coupled, any change forcesa recompilation of the entireproject.
Avoid TightCoupling
3Any chanclass cancascade classes.
A Quick Example: The Carpenter
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
49/63
Lets consider a carpenterCarpenters use various tools to perform theirwork. We create a corresponding model tomeet the requirement.
The carpenter modelInitially, all carpenters only use hammersour diagram below.
High-Level Class
This class must conform tothe public interface of theHammer.
Low-Level Class
This class decides on itsinterface independent of anyhigher level callers.
A Quick Example: The Carpenter
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
50/63
The carpenter modelCarpenters have been upgraded; now, sohammers and others can use mallets.
Lets consider a carpenterCarpenters use various tools to perform theirwork. We create a corresponding model tomeet the requirement.
Traditional Application Layering
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
51/63
Presentation Layer
Business Layer
Data LayerResponsible for managingpersisted storage, or any otexternal data integrations.
Responsible for externalconnectivity with either a uanother computer system.
Responsible for logic uniqubusiness domain in which tsystem functions.
In a traditional n-tier application, a dependency chain is created by stacking higher level components omodules. This chain becomes fragile as the overall system experiences change.
Dependency Inversion Layering
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
52/63
Responsible for allshared interfacedefinitionsthroughout the
application.
In an application designed for inversion, the dependency chain is severed so that high-level modules ndirectly on low-level components. Change is easily accommodated since no explicit references exist.
Abstraction
Layer
Presentation Layer
Business Layer
Data LayerResponsible for managingpersisted storage, or any otexternal data integrations.
Responsible for externalconnectivity with either a uanother computer system.
Responsible for logic uniqubusiness domain in which tsystem functions.
The Button Example
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
53/63
Lets consider a simple A button is a very general concebe easily reused for many applic
The button modelInitially, our button is used to turn a lamp on and off. TheButton class has an explicit dependency on the Lampobject.
The Button Example
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
54/63
Lets consider a simple A button is a very general concebe easily reused for many applic
The button modelNow, our button can be used to control any device, not justa lamp since it no longer has a direct dependency.
Summarizing the Dependency Inversion Principle
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
55/63
Remembering the Dependency Inversion Principle is easy:use abstractions to when wiring your objects together.
Conformance to the Dependency Inversion Principle ensures both flexibility and reusability. This alcreate large systems that are inherently protected from change.
Summary of the SOLID Principles
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
56/63
Remember that design decisions areof the coding cycle, not just at the beimportant to remain SOLID.
In each coding tasalways try to remeto be SOLID.
Single Responsibility PrincipleA class should not contain multipleresponsibilities.
Open/Closed PrincipleA class should be open to extension, but closedfor modification.
Liskov Substitution PrincipleAn object should be replaceable with its sub-types without altering any system behavior.
Interface Segregation PrincipleMany specific interfaces are preferable to asingle generic interface.
Dependency Inversion PrincipleA class should only depend upon abstractions,not implementations.
Keep It Simple
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
57/63
Simplicity is BeautifulOften, developers think for software to bevaluable it must be complex. I find it help toremind myself that simple is beautiful.
Strive for elegant, clean desigComplexity often creates noise in the desinefficient and unmanageable.
Avoid creating unnecessary combest coders command the simple
More files doesnt mean its moreOften, it means its simpler.
Always start with the simplest, eaand work towards complexity.
Dont RepeatYourself
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
58/63
Stay DRY: Try to ensure your design maximizesreusability throughout your solution.
Following the DRY principle of trying not to repeat yourself leads to code that naturally conforSOLID principles.
You Arent Gonna Need It
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
59/63
Avoid Coding for the FuThis can be really hard for develreality is, no value exists in buildinow.
If we try to build something now for a futurerequirement, chances are we dont know enough to
do it adequately.
When designing, try toground yourself in theY.A.G.N.I. Principle
The Principle of Least Surprise
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
60/63
Try to follow well established patterns and practices. The best code is
like the best systems: stable and predictable.
Realize this doesnt mean be boring. Great developers are normally very creative. However, ithere is already an accepted way of doing something then you should have an incredibly goodeviate.
Remember Principles Arent Rules
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
61/63
Remember these are principleguides, not rules. There are alwexceptions, so its ok to groundyourself by asking why.
Never Be ScaredAsk Why
A software principle violation is not always bad, but it is a code smell. If I see one in a code regenerally ask a developer why they choose to deviate. If the coder has a good justification, suggest a refactor.
Being a SOLID coder comes down to making common
Next Steps
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
62/63
Remember that a little knowledge
can be dangerous. To be a greatdeveloper, I highly recommend
these resources to guide you
towards deeper understanding.
If its work, we try
to do less. If its art
we try to do more. Seth Godin
7/24/2019 KCDC2015-SteveGreen-AreYouaSOLIDCoder
63/63
Are You a SOLID Coder?
Principles of Software Design
Steve Green @stephenpgreen
[email protected] /stevepgreen