establishing a solid foundation - an intro to software design

74

Upload: cameron-presley

Post on 22-Jan-2017

118 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Establishing a SOLID Foundation - An Intro to Software Design
Page 2: Establishing a SOLID Foundation - An Intro to Software Design

Establishing a SOLID FoundationAn Intro To Software Design

Cameron Presley@pcameronpresley

http://blog.thesoftwarementor.com

Page 3: Establishing a SOLID Foundation - An Intro to Software Design

Outline What is SOLID?

Why should our code be SOLID?

Exploring the SOLID principles

Additional Resources

Page 4: Establishing a SOLID Foundation - An Intro to Software Design

What is SOLID?

Page 5: Establishing a SOLID Foundation - An Intro to Software Design

What is SOLID? Clever mnemonic for a set of principles that would allow us to write easier to

maintain code

Concepts aren’t new Barbara Liskov – 1987 (Liskov Substitution) Bertrand Meyer – 1988 (Open/Closed)

Robert C. Martin (Uncle Bob) would introduce these concepts in Agile Principles, Patterns, and Practices

Michael Feathers (Working Effectively with Legacy Code) would come up with SOLID

Page 6: Establishing a SOLID Foundation - An Intro to Software Design

What is SOLID?Single ResponsibilityOpen/ClosedLiskov SubstitutionInterface SegregationDependency Inversion

Page 7: Establishing a SOLID Foundation - An Intro to Software Design

Why Should We Write SOLID Code? Easier to maintain

Easier to debug Easier to extend

The most expensive part of software development is maintenance Steve McConnell (Code Complete)

It’s fiscally responsible for us to write maintainable code

Page 8: Establishing a SOLID Foundation - An Intro to Software Design

Why Should We Write SOLID Code? By following SOLID

Small, focused classes Interchangeable abstractions

This allows our code to easily evolve and adapt to changing specifications Which in turn decreases the time it takes to develop features and the likelihood of shipping a bug Which lowers our maintenance cost

This in turn will lead to us to write more testable code Which in turn allows us a way to make sure we don’t ship broken code Which lowers our maintenance cost

Page 9: Establishing a SOLID Foundation - An Intro to Software Design

Single ResponsibilityOpen/ClosedLiskov SubstitutionInterface SegregationDependency Inversion

Page 10: Establishing a SOLID Foundation - An Intro to Software Design

Single Responsibility Principle

Page 11: Establishing a SOLID Foundation - An Intro to Software Design

Single Responsibility Principle Classes should have only one reason to change

NOTE: Doesn’t mean that classes can only do one thing Repository

Coined by Robert C. Martin

Referred to as SRP

Page 12: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Problem It Solves Large classes are hard to maintain

If multiple developers need to work on the class at the same time… What do you call a group of developers … a merge conflict

SRP forces us to write smaller classes

Easier to combine many small classes than using a large one

Page 13: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Signs of Violation Opening the class in an editor and the scroll bar disappears

Page 14: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Signs of Violation 27 public methods

Page 15: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Signs of Violation 52 private methods, 1 public method

Page 16: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Resolving Violations Every public method will become a class

Private methods used by a public method will be moved to the new class Private method used everywhere? That becomes a new class

Update places that used the large class to use the smaller classes Can’t change the signature of the large class? Instantiate the newly created class as part of the method

Page 17: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Violation

Page 18: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Resolving ViolationsIdentify public methods

Page 19: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Resolving ViolationsExtract the public methods to new classes

Page 20: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Resolving ViolationsNow that the methods have been extracted to new classes, identify the helper methods

Page 21: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Resolving Violations

And add them to the appropriate classes

Page 22: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Resolving Violations

See the same helper method in multiple places?

Time to move that to a new class

Page 23: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Resolving Violations

Page 24: Establishing a SOLID Foundation - An Intro to Software Design

SRP – Resolving ViolationsUpdate the large class to delegate the work to the newly created classes

Page 25: Establishing a SOLID Foundation - An Intro to Software Design

Single Responsibility PrincipleSummary

Classes should only have one reason to change

By breaking classes down into smaller pieces, it allows us to work on the separate pieces of functionality without stepping on each other

Allows us to combine just-what-we need functionality into new classes

Page 26: Establishing a SOLID Foundation - An Intro to Software Design

Single ResponsibilityOpen/ClosedLiskov SubstitutionInterface SegregationDependency Inversion

Page 27: Establishing a SOLID Foundation - An Intro to Software Design

Open/Closed Principle

Page 28: Establishing a SOLID Foundation - An Intro to Software Design

Open/Closed Principle Classes should be open for extension, closed for modification

Means that we should add new functionality by adding new classes, not modifying existing ones

NOTE: Doesn’t mean that we can’t modify a class to fix bugs

Coined by Bertrand Meyer

Referred to as OCP

Page 29: Establishing a SOLID Foundation - An Intro to Software Design

OCP – Problem It Solves If we modify a class to add additional functionality, it’s hard to make sure

that we didn’t break something downstream

OCP forces us to add functionality by creating new classes and then using an abstraction

Easier to create a new class and use it then to modify an existing one and make sure we didn’t break anything

Page 30: Establishing a SOLID Foundation - An Intro to Software Design

OCP – Signs of Violation

Page 31: Establishing a SOLID Foundation - An Intro to Software Design

OCP – Resolving Violations Instead of adding additional logic, need to move logic to an abstraction

Each if or switch statement needs to be moved to a new class with a public method

Define a new interface that has the method

New classes will implement the interface

Modify the original class to use the new abstraction

Page 32: Establishing a SOLID Foundation - An Intro to Software Design

OCP – Resolving ViolationsMove logic to new classes

Page 33: Establishing a SOLID Foundation - An Intro to Software Design

OCP – Resolving ViolationsDefine the new abstraction (Shape) and have the new classes implement it

Page 34: Establishing a SOLID Foundation - An Intro to Software Design

OCP – Resolving Violations

Page 35: Establishing a SOLID Foundation - An Intro to Software Design

OCP – Resolving Violations Need to add an additional shape (Triangle)?

Define a Triangle class Have it inherit from Shape abstract class Implement CalculateArea method

Notice how we don’t have to modify the AreaCalculator class to add additional shapes

Page 36: Establishing a SOLID Foundation - An Intro to Software Design

Open/Closed PrincipleSummary

Classes should be open for extension, closed for modification

By introducing abstractions, we can easily extend our application without worrying about breaking something downstream

Allows us to add additional functionality by creating new classes, not modifying pre-existing ones

Page 37: Establishing a SOLID Foundation - An Intro to Software Design

Single ResponsibilityOpen/ClosedLiskov SubstitutionInterface SegregationDependency Inversion

Page 38: Establishing a SOLID Foundation - An Intro to Software Design

Liskov Substitution Principle

Page 39: Establishing a SOLID Foundation - An Intro to Software Design

Liskov Substitution Principle If two classes are derived from the same abstraction, then they are

interchangeable

NOTE: Without Special Handling

Coined by Barbara Liskov

Referred to as LSP

Page 40: Establishing a SOLID Foundation - An Intro to Software Design

LSP – Problem It Solves Abstractions hide implementation details

If we have to special handle the abstraction based on what it is, the code becomes much more complex and harder to maintain

Jeff Atwood (Coding Horror) refers to this as “leaky abstractions” because they leak implementation knowledge throughout the code base

Page 41: Establishing a SOLID Foundation - An Intro to Software Design

LSP – Signs of Violation

Page 42: Establishing a SOLID Foundation - An Intro to Software Design

LSP – Signs of Violation

What should happen if Quadrilateral is a Square?

Page 43: Establishing a SOLID Foundation - An Intro to Software Design

LSP – Signs of ViolationSpecial handling based on the class

Page 44: Establishing a SOLID Foundation - An Intro to Software Design

LSP – Resolving Violations Some cases, the abstraction doesn’t make sense

Square vs Rectangle Square doesn’t have length and width, it has a side Therefore, Quadrilateral is the wrong abstraction

Makes sense to find a better abstraction (not always possible)

In some cases, it’s possible to move the special handling logic to the offending class

Page 45: Establishing a SOLID Foundation - An Intro to Software Design

LSP – Resolving Violations

Page 46: Establishing a SOLID Foundation - An Intro to Software Design

Liskov Substitution PrincipleSummary

If two classes are derived from the same abstraction, then they should be interchangeable

We don’t have to add special handling code in the client

If found, try to find a better abstraction or move the special handling to the offending class

Page 47: Establishing a SOLID Foundation - An Intro to Software Design

Single ResponsibilityOpen/ClosedLiskov SubstitutionInterface SegregationDependency Inversion

Page 48: Establishing a SOLID Foundation - An Intro to Software Design

Interface Segregation Principle

Page 49: Establishing a SOLID Foundation - An Intro to Software Design

Interface Segregation Principle Clients should only depend on what they need

Should not have to implement methods that aren’t used

Coined by Robert C. Martin

Referred to as ISP

Page 50: Establishing a SOLID Foundation - An Intro to Software Design

ISP – Problem It Solves When we define “fat” interfaces, it’s hard to know what functionality we

actually need Ever tried to autocomplete and there were a lot of choices?

By having tighter interfaces, we can control what we expose to our clients

This in turn allows us to tailor our interfaces to what exactly our client needs Role interfaces vs Header interfaces (Martin Fowler)

Page 51: Establishing a SOLID Foundation - An Intro to Software Design

ISP – Signs of ViolationAccess to Methods and Properties that aren’t being used

Page 52: Establishing a SOLID Foundation - An Intro to Software Design

ISP – Resolving Violations Identify which methods are being used

Move those methods/properties to their own interface

Update the client to use the new interface

Update the original class to implement the new interface

Similar to Single Responsibility Principle, need to break the interface down into smaller pieces

Page 53: Establishing a SOLID Foundation - An Intro to Software Design

ISP – Resolving Violation

Page 54: Establishing a SOLID Foundation - An Intro to Software Design

ISP – Resolving ViolationIdentify methods that are being used in the client

Page 55: Establishing a SOLID Foundation - An Intro to Software Design

ISP – Resolving ViolationMove the method to new interface, update Atm to implement both interfaces

Page 56: Establishing a SOLID Foundation - An Intro to Software Design

ISP – Resolving ViolationUpdate AtmBalanceChecker to use IAtmBalanceChecker

Page 57: Establishing a SOLID Foundation - An Intro to Software Design

Interface Segregation PrincipleSummary

Clients should only have access to methods and properties that they need

This allows us to create role interfaces, not header interfaces

We can spot violations by checking if our client has access to more than we need

Similar to Single Responsibility, break down large interfaces into smaller ones and update the client accordingly

Page 58: Establishing a SOLID Foundation - An Intro to Software Design

Single ResponsibilityOpen/ClosedLiskov SubstitutionInterface SegregationDependency Inversion

Page 59: Establishing a SOLID Foundation - An Intro to Software Design

Dependency Inversion Principle

Page 60: Establishing a SOLID Foundation - An Intro to Software Design

Dependency Inversion Principle Concrete classes should depend upon abstractions, not other concrete

classes

Two rules Classes shouldn’t depend upon concrete classes Classes shouldn’t be responsible for creating their own dependencies

Coined by Robert C. Martin

Referred to as DIP

Page 61: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Problem It Solves If we have our concrete classes instantiate their own dependencies, the only

way to change these dependencies is to change the class which violates the Open/Closed Principle

Impossible to write unit tests that cross system boundaries (network communication, database access, file system)

Provides another way to determine if a class is doing too much (32 dependencies)

Page 62: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Signs of ViolationUsing the “new” keyword

Page 63: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Signs of ViolationUsing static classes

Page 64: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Signs of ViolationPassing concrete classes instead of abstractions

Page 65: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Resolving Violations Two goals

Make sure the dependency can be passed in Make sure the dependency has an abstraction

If the class is static, make it not static If the class doesn’t have an interface, define one (remember ISP)

Inject the dependency using constructor injection or method injection

Page 66: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Static Classes Static classes suck

Can’t pass them as parameters Can’t implement an interface or base class

Removing the static attribute is ideal, but not always possible

Using the Wrapper pattern, we can define another class that is not static to wrap around the static and then pass that around

Page 67: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Working With Static Classes

Page 68: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Working With Static Classes Define an interface that has all the public methods from the static class Create a new class that implements the interface and have the new class

call the static class

Page 69: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Passing Dependencies Method Injection

Passes the dependency as part of the method call Use when the dependency can change per method call

Constructor Injection Passes the dependency as part of instantiation Use when the dependency should be the same for the lifetime of the object

When deciding, we should ask ourselves “Will this change during the course of the program?”

Page 70: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Passing Dependencies

Page 71: Establishing a SOLID Foundation - An Intro to Software Design

DIP – Passing Dependencies

Page 72: Establishing a SOLID Foundation - An Intro to Software Design

Dependency Inversion PrincipleSummary

Concrete classes should depend upon abstractions, not other concrete classes

Allows us to switch dependencies at runtime Useful for testing

Use the Wrapper pattern to handle static classes

Use method injection or constructor injection for passing dependencies

Page 73: Establishing a SOLID Foundation - An Intro to Software Design

Summary What is SOLID?

Why should our code be SOLID?

What the principles stand for How to spot violations How to fix them