0% found this document useful (0 votes)
206 views66 pages

Solid Principal

The document discusses the Single Responsibility Principle (SRP). It defines SRP as requiring that every class have a single responsibility and that responsibility should be entirely encapsulated by the class. It notes that classes should have only one reason to change. The document provides an example of a class with multiple responsibilities that could change for different reasons. It describes refactoring the class to separate the responsibilities into different classes to better follow SRP. It summarizes that following SRP leads to lower coupling and higher cohesion between classes.

Uploaded by

kris2tmg
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
206 views66 pages

Solid Principal

The document discusses the Single Responsibility Principle (SRP). It defines SRP as requiring that every class have a single responsibility and that responsibility should be entirely encapsulated by the class. It notes that classes should have only one reason to change. The document provides an example of a class with multiple responsibilities that could change for different reasons. It describes refactoring the class to separate the responsibilities into different classes to better follow SRP. It summarizes that following SRP leads to lower coupling and higher cohesion between classes.

Uploaded by

kris2tmg
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 66

Fundamentals: The Single Responsibility Principle

Steve Smith http://pluralsight.com/

Outline
SRP Defined The Problem An Example Refactoring to Apply SRP Related Fundamentals

SRP: The Single Responsibility Principle The Single Responsibility Principle states that every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class. Wikipedia There should never be more than one reason for a class to change. Robert C. Uncle Bob Martin

Cohesion and Coupling


Cohesion: how strongly-related and focused are the various responsibilities of a module Coupling: the degree to which each program module relies on each one of the other modules

Strive for low coupling and high cohesion!

Responsibilities are Axes of Change


Requirements changes typically map to responsibilities More responsibilities == More likelihood of change Having multiple responsibilities within a class couples together these responsibilities The more classes a change affects, the more likely the change will introduce errors.

Demo
The Problem With Too Many Responsibilities

The Problem
Cash Transactions Dont Need Credit Card Processing Point of Sale Transactions Dont Need Inventory Reservations

Store inventory is updated separately in our system

Point of Sale Transactions Dont Need Email Notifications


The customer doesnt provide an email The customer knows immediately that the order was a success

Any change to notifications, credit card processing, or inventory management will affect Order as well as the Web and Point of Sale implementations of Order!

Demo
Refactoring to a Better Design

What is a Responsibility?
a reason to change A difference in usage scenarios from the clients perspective Multiple small interfaces (follow ISP) can help to achieve SRP

Summary
Following SRP leads to lower coupling and higher cohesion Many small classes with distinct responsibilities result in a more flexible design Related Fundamentals:

Open/Closed Principle Interface Segregation Principle Separation of Concerns

Recommended Reading:

Clean Code by Robert C. Martin [http://amzn.to/Clean-Code]

Credits
Images Used Under License

http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/soliddevelopment-principles-in-motivational-pictures.aspx

SRP Article

http://www.objectmentor.com/resources/articles/srp.pdf

For more in-depth online developer training visit

on-demand content from authors you trust

Fundamentals: The Open / Closed Principle


Steve Smith http://pluralsight.com/

Outline
OCP Defined The Problem An Example Refactoring to Apply OCP Related Fundamentals

OCP: The Open/Closed Principle

The Open / Closed Principle states that software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. Wikipedia

The Open / Closed Principle Open to Extension New behavior can be added in the future Closed to Modification Changes to source or binary code are not required

Dr. Bertrand Meyer originated the OCP term in his 1988 book, Object Oriented Software Construction

Change behavior without changing code?


Rely on abstractions No limit to variety of implementations of each abstraction In .NET, abstractions include: Interfaces Abstract Base Classes In procedural code, some level of OCP can be achieved via parameters

Demo
A Price Calculator That Is Not Closed To Change

The Problem
Adding new rules require changes to the calculator every time Each change can introduce bugs and requires re-testing, etc. We want to avoid introducing changes that cascade through many modules in our application Writing new classes is less likely to introduce problems

Nothing depends on new classes (yet) New classes have no legacy coupling to make them hard to design or test

Three Approaches to Achieve OCP


Parameters (Procedural Programming)

Allow client to control behavior specifics via a parameter Combined with delegates/lambda, can be very powerful approach

Inheritance / Template Method Pattern

Child types override behavior of a base class (or interface)

Composition / Strategy Pattern


Client code depends on abstraction Provides a plug in model Implementations utilize Inheritance; Client utilizes Composition

Demo
Refactoring to a Better Design

10

When do we apply OCP?


Experience Tells You
If you know from your own experience in the problem domain that a particular class of change is likely to recur, you can apply OCP up front in your design

Otherwise Fool me once, shame on you; fool me twice, shame on me Dont apply OCP at first If the module changes once, accept it. If it changes a second time, refactor to achieve OCP Remember TANSTAAFL There Aint No Such Thing As A Free Lunch OCP adds complexity to design No design can be closed against all changes

Summary
Conformance to OCP yields flexibility, reusability, and maintainability Know which changes to guard against, and resist premature abstraction Related Fundamentals:

Single Responsibility Principle Strategy Pattern Template Method Pattern

Recommended Reading:

Agile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin [http://amzn.to/agilepppcsharp]

Credits
Images Used Under License

http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/soliddevelopment-principles-in-motivational-pictures.aspx

For more in-depth online developer training visit

on-demand content from authors you trust

Fundamentals: The Liskov Substitution Principle


Steve Smith http://pluralsight.com/

Outline
LSP Defined The Problem An Example Refactoring to Apply LSP Related Fundamentals

LSP: The Liskov Substitution Principle

The Liskov Substitution Principle states that Subtypes must be substitutable for their base types. Agile Principles, Patterns, and Practices in C# Named for Barbara Liskov, who first described the principle in 1988.

Substitutability Child classes must not: 1) Remove base class behavior 2) Violate base class invariants And in general must not require calling code to know they are different from their base type.

Inheritance and the IS-A Relationship

Nave OOP teaches use of IS-A to describe child classes relationship to base classes

LSP suggests that IS-A should be replaced with IS-SUBSTITUTABLE-FOR

Invariants
Consist of reasonable assumptions of behavior by clients Can be expressed as preconditions and postconditions for methods Frequently, unit tests are used to specify expected behavior of a method or class Design By Contract is a technique that makes defining these pre- and post-conditions explicit within code itself. To follow LSP, derived classes must not violate any constraints defined (or assumed by clients) on the base classes

Demo
Violating LSP using Shapes

The Problem
Non-substitutable code breaks polymorphism Client code expects child classes to work in place of their base classes Fixing substitutability problems by adding if-then or switch statements quickly becomes a maintenance nightmare (and violates OCP)

LSP Violation Smells


foreach (var emp in Employees) { if(emp is Manager) { _printer.PrintManager(emp as Manager); } else { _printer.PrintEmployee(emp); } }

10

LSP Violation Smells


public abstract class Base { public abstract void Method1(); public abstract void Method2(); } public class Child : Base { public override void Method1() { throw new NotImplementedException(); } public override void Method2() { // do stuff } }

Follow ISP! Use small interfaces so you dont require classes to implement more than they need!

11

Demo
Refactoring to a Better Design

12

When do we fix LSP?


If you notice obvious smells like those shown If you find yourself being bitten by the OCP violations LSP invariably causes

LSP Tips
Tell, Dont Ask

Dont interrogate objects for their internals move behavior to the object Tell the object what you want it to do

Consider Refactoring to a new Base Class


Given two classes that share a lot of behavior but are not substitutable Create a third class that both can derive from Ensure substitutability is retained between each class and the new base

Summary
Conformance to LSP allows for proper use of polymorphism and produces more maintainable code Remember IS-SUBSTITUTABLE-FOR instead of IS-A Related Fundamentals:

Polymorphism Inheritance Interface Segregation Principle Open / Closed Principle

Recommended Reading:

Agile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin [http://amzn.to/agilepppcsharp]

Credits
Images Used Under License

http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/soliddevelopment-principles-in-motivational-pictures.aspx

For more in-depth online developer training visit

on-demand content from authors you trust

Fundamentals: The Interface Segregation Principle


Steve Smith http://pluralsight.com/

Outline
ISP Defined The Problem An Example Refactoring to Apply ISP Related Fundamentals

ISP: The Interface Segregation Principle

The Interface Segregation Principle states that Clients should not be forced to depend on methods they do not use. Agile Principles, Patterns, and Practices in C# Corollary:
Prefer small, cohesive interfaces to fat interfaces

Whats an Interface? Interface keyword/type public interface IDoSomething { } Public interface of a class public class SomeClass { } What does the client see and use?

Demo
Violating ISP

The Problem
Client Class (Login Control) Needs This:

Forced to use this

The Problem
AboutPage simply needs ApplicationName and AuthorName Forced to deal with huge ConfigurationSettings class Forced to deal with actual configuration files

Interface Segregation violations result in classes that depend on things they do not need, increasing coupling and reducing flexibility and maintainability

Demo
Refactoring to a Better Design

ISP Smells
Unimplemented interface methods: public override string ResetPassword( string username, string answer) { throw new NotImplementedException(); }

Remember these violate Liskov Substitution Principle!

ISP Smells
Client references a class but only uses small portion of it

When do we fix ISP?


Once there is pain

If there is no pain, theres no problem to address.

If you find yourself depending on a fat interface you own


Create a smaller interface with just what you need Have the fat interface implement your new interface Reference the new interface with your code

If you find fat interfaces are problematic but you do not own them

Create a smaller interface with just what you need Implement this interface using an Adapter that implements the full interface

ISP Tips
Keep interfaces small, cohesive, and focused Whenever possible, let the client define the interface Whenever possible, package the interface with the client

Alternately, package in a third assembly client and implementation both depend upon

Last resort: Package interfaces with their implementation

Summary
Dont force client code to depend on things it doesnt need Keep interfaces lean and focused Refactor large interfaces so they inherit smaller interfaces Related Fundamentals:

Polymorphism Inheritance Liskov Substitution Principle Faade Pattern

Recommended Reading:

Agile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin [http://amzn.to/agilepppcsharp]

Credits
Images Used Under License

http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/soliddevelopment-principles-in-motivational-pictures.aspx

For more in-depth online developer training visit

on-demand content from authors you trust

Fundamentals: The Dependency Inversion Principle Part 1


Steve Smith http://pluralsight.com/

Outline
DIP Defined The Problem An Example Refactoring to Apply DIP Related Fundamentals

DIP: The Dependency Inversion Principle High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. Agile Principles, Patterns, and Practices in C#

What are dependencies?


Framework Third Party Libraries Database File System Email Web Services System Resources (Clock) Configuration The new Keyword Static methods Thread.Sleep Random

Traditional Programming and Dependencies


High Level Modules Call Low Level Modules User Interface depends on

Business Logic depends on


Infrastructure Utility Data Access

Static methods are used for convenience or as Faade layers Class instantiation / Call stack logic is scattered through all modules

Violation of Single Responsibility Principle

Class Dependencies: Be Honest!


Class constructors should require any dependencies the class needs Classes whose constructors make this clear have explicit dependencies Classes that do not have implicit, hidden dependencies
public class HelloWorldHidden { public string Hello(string name) { if (DateTime.Now.Hour < 12) return "Good morning, " + name; if (DateTime.Now.Hour < 18) return "Good afternoon, " + name; return "Good evening, " + name; } } 7

Classes Should Declare What They Need


public class HelloWorldExplicit { private readonly DateTime _timeOfGreeting; public HelloWorldExplicit(DateTime timeOfGreeting) { _timeOfGreeting = timeOfGreeting; } public string Hello(string name) { if (_timeOfGreeting.Hour < 12) return "Good morning, " + name; if (_timeOfGreeting.Hour < 18) return "Good afternoon, " + name; return "Good evening, " + name; } }

Demo
Violating DIP

The Problem
Order has hidden dependencies:

MailMessage SmtpClient InventorySystem PaymentGateway Logger DateTime.Now

Result

Tight coupling No way to change implementation details (OCP violation) Difficult to test

10

Dependency Injection
Dependency Injection is a technique that is used to allow calling code to inject the dependencies a class needs when it is instantiated. The Hollywood Principle

Dont call us; well call you

Three Primary Techniques


Constructor Injection Property Injection Parameter Injection

Other methods exist as well

11

Constructor Injection
Dependencies are passed in via constructor Pros

Strategy Pattern

Classes self-document what they need to perform their work Works well with or without a container Classes are always in a valid state once constructed

Cons

Constructors can have many parameters/dependencies (design smell) Some features (e.g. Serialization) may require a default constructor Some methods in the class may not require things other methods require (design smell)

12

Property Injection
Dependencies are passed in via a property

Also known as setter injection

Pros

Dependency can be changed at any time during object lifetime Very flexible

Cons

Objects may be in an invalid state between construction and setting of dependencies via setters Less intuitive

13

Parameter Injection
Dependencies are passed in via a method parameter Pros

Most granular Very flexible Requires no change to rest of class

Cons

Breaks method signature Can result in many parameters (design smell)

Consider if only one method has the dependency, otherwise prefer constructor injection

14

Refactoring
Extract Dependencies into Interfaces Inject implementations of interfaces into Order Reduce Orders responsibilities (apply SRP)

15

Demo
Refactoring to a Better Design

16

DIP Smells
Use of new keyword foreach(var item in cart.Items) { try { var inventorySystem = new InventorySystem(); inventorySystem.Reserve(item.Sku, item.Quantity); } }

DIP Smells
Use of static methods/properties message.Subject = "Your order placed on " + DateTime.Now.ToString(); Or DataAccess.SaveCustomer(myCustomer);

Where do we instantiate objects?


Applying Dependency Injection typically results in many interfaces that eventually need to be instantiated somewhere but where? Default Constructor

You can provide a default constructor that news up the instances you expect to typically need in your application Referred to as poor mans dependency injection or poor mans IoC

Main

You can manually instantiate whatever is needed in your applications startup routine or main() method

IoC Container

Use an Inversion of Control Container

IoC Containers
Responsible for object graph instantiation Initiated at application startup via code or configuration Managed interfaces and the implementation to be used are Registered with the container Dependencies on interfaces are Resolved at application startup or runtime Examples of IoC Containers for .NET

Microsoft Unity StructureMap Ninject Windsor Funq / Munq

Summary

Depend on abstractions. Dont force high-level modules to depend on low-level modules through direct instantiation or static method calls Declare class dependencies explicitly in their constructors Inject dependencies via constructor, property, or parameter injection Related Fundamentals:
Single Responsibility Principle Interface Segregation Principle Faade Pattern Inversion of Control Containers

Recommended Reading:

Agile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin [http://amzn.to/agilepppcsharp] http://www.martinfowler.com/articles/injection.html

Credits
Images Used Under License

http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/soliddevelopment-principles-in-motivational-pictures.aspx

For more in-depth online developer training visit

on-demand content from authors you trust

Fundamentals: The Dependency Inversion Principle Part 2


Steve Smith http://pluralsight.com/

Outline
Project Dependencies The Problem An Example Refactoring to Apply DIP Related Fundamentals

Layered / Tiered Application Design


Separate Logical (and sometimes physical) Layers

For instance User Interface (UI) Business Logic Layer (BLL) Data Acces Layer (DAL)

Supports Encapsulation and Abstraction


Work at the abstraction level appropriate Each level only knows about one level deep (ideally)

Provides Units of Reuse

Lowest levels generally are most reusable

Traditional (Nave) Layered Architecture

User Interface BLL


DAL
Database Services Dependency

Common

Inverted Architecture

Data Access
Database

UI

Tests

I/O May be packaged together as one assembly Business Logic (services)

WCF Web Svcs Services

Object Model (Core, Domain Objects)

Demo
Violating DIP with Projects and Assemblies

The Problem
Dependencies Flow Toward Infrastructure Core / Business / Domain Classes Depend on Implementation Details Result

Tight coupling No way to change implementation details without recompile (OCP violation) Difficult to test

Dependency Injection
Dependency is transitive

If UI depends on BLL depends on DAL depends on Database Then *everything* depends on the Database

Depend on abstractions (DIP) Package interfaces (abstractions) with the client (ISP) Structure Solutions and Projects so Core / BLL is at center, with fewest dependencies

Demo
Refactoring to a Better Design

Summary
Dont Depend on Infrastructure Assemblies from Core Apply DIP to reverse dependencies Related Fundamentals:

Open Closed Principle Interface Segregation Principle Strategy Pattern

Recommended Reading:

Agile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin [http://amzn.to/agilepppcsharp] http://www.martinfowler.com/articles/injection.html

For more in-depth online developer training visit

on-demand content from authors you trust

Fundamentals: The Dont Repeat Yourself Principle Part 1


Steve Smith http://pluralsight.com/

Outline
DRY Defined Demo: Repetition in Code Analysis Demos: Refactoring to apply DRY Code Generation Repetition in Process Demo: Automation to apply DRY Summary and Related Fundamentals

Dont Repeat Yourself


Every piece of knowledge must have a single, unambiguous representation in the system. The Pragmatic Programmer Repetition in logic calls for abstraction. Repetition in process calls for automation. 97 Things Every Programmer Should Know
Variations include: Once and Only Once Duplication Is Evil (DIE)

Demo
Violating DRY in a simple Data Warehouse Sample Overview

Analysis
Magic Strings/Values Duplicate logic in multiple locations Repeated if-then logic Conditionals instead of polymorphism Repeated Execution Patterns Lots of duplicate, probably copy-pasted, code Only manual tests Static methods everywhere

Magic Strings / Values

Demo
Applying DRY to Remove Magic Strings

Duplicate Logic in Multiple Locations

Demo
Applying DRY to Duplicate Logic in Multiple Locations

10

Repeated if-then Logic

Demo
Applying DRY to Repeated if-then Logic

12

Conditional Instead of Polymorphism


Example of Flags Over Objects anti-pattern Violates the Tell, Dont Ask principle (aka DIP)

Demo
Applying DRY to use of Conditional Instead of Polymorphism

14

Summary Repetition breeds errors and waste Refactor code to remove repetition Recommended Reading:

The Pragmatic Programmer: From Journeyman to Master http://amzn.to/b2gJdK 97 Things Every Programmer Should Know http://amzn.to/cAse1Y

For more in-depth online developer training visit

on-demand content from authors you trust

Fundamentals: The Dont Repeat Yourself Principle Part 2


Steve Smith http://pluralsight.com/

Outline

Part 1 DRY Defined Demo: Repetition in Code Analysis Demos: Refactoring to apply DRY
Refactoring for greater testability Adding Tests

Part 2

Code Generation Repetition in Process Demo: Automation to apply DRY Summary and Related Fundamentals

Analysis
Part 1 Magic Strings/Values Duplicate logic in several methods Repeated if-then logic Conditionals instead of polymorphism Repeated Execution Patterns (part 3) Lots of duplicate, probably copy-pasted, code (part 3) Only manual tests Static methods everywhere

No Tests
Only manual tests More and more expensive to verify all results are correct as new operations are added More and time wasted as long-running queries are added

Static Methods
Tightly coupled Difficult to test Difficult to change behavior (violates OCP) Cannot use object oriented design techniques

Inheritance Polymorphism

Demo
Refactoring to Eliminate Static Cling and Add Tests

Summary
Repetition breeds errors and waste Abstract repetitive logic in code Related Fundamentals:

Template Method Pattern Command Pattern Dependency Inversion Principle

Recommended Reading:

The Pragmatic Programmer: From Journeyman to Master http://amzn.to/b2gJdK 97 Things Every Programmer Should Know http://amzn.to/cAse1Y

For more in-depth online developer training visit

on-demand content from authors you trust

Fundamentals: The Dont Repeat Yourself Principle Part 3


Steve Smith http://pluralsight.com/

Outline

Part 1 DRY Defined Demo: Repetition in Code Analysis Demos: Refactoring to apply DRY
Refactoring for greater testability Adding Tests

Part 2

Code Generation Repetition in Process Demo: Automation to apply DRY Summary and Related Fundamentals

Analysis
Part 2 Only manual tests Static methods everywhere Part 1 Magic Strings/Values Duplicate logic in several methods Repeated if-then logic Conditionals instead of polymorphism Repeated Execution Patterns Lots of duplicate, probably copy-pasted, code

Repeated Execution Patterns

Demo
Refactoring Repeated Execution Patterns

Duplicate, Copy Pasted Code


Too Numerous to List Commercial Tool (free version available)

Atomiq (http://GetAtomiq.com)
Full disclosure: Im one of the owners of the company that produces Atomiq

Demo
Find Duplicate Code using Tools

Consider Code Generation


T4 Templates

Custom code generation templates Built into Visual Studio 2010

ORM Tools (LINQ to SQL, Entity Framework, nHibernate, LLBLGen)


Reduce repetitive data access code Eliminate common data access errors

Commercial Tools:

CodeSmith CodeBreeze CodeHayStack

Repetition in Process
Testing

Performing testing by hand is tedious and wasteful

Builds

Performing builds by hand is tedious and wasteful

Deployments

Performing deployments by hand is tedious and wasteful

Are you seeing a trend here?


String.Format(Performing {0} by hand is tedious and wasteful, action);

Demo
Automating Processes

10

Summary
Repetition breeds errors and waste Use an ORM tool to eliminate repeated data access code Use Tools to Locate Repeated Code Automate repetitive actions in your processes Recommended Reading:

The Pragmatic Programmer: From Journeyman to Master http://amzn.to/b2gJdK 97 Things Every Programmer Should Know http://amzn.to/cAse1Y

Related Tool

Atomiq http://GetAtomiq.com

Final Code

Check out the final version of the demo in this modules demo zip file

12

For more in-depth online developer training visit

on-demand content from authors you trust

You might also like