SOLID Principles
Lovingly Plagiarized Prepared
by Ryan Haugh
Why They're Important
- Creates Test Seams
- Improves Readability
- Improves Maintainability
Single Responsibility Principle
A class should only do one thing
Single Responsibility Principle
class Customer
{
public void Add()
{
try
{
// Logic goes here
}
catch (Exception ex)
{
System.IO.File.WriteAllText(@"C:\Error.txt", ex.ToString());
}
}
}
Single Responsibility Principle
What if we want to change our logging implementation?
Single Responsibility Principle
class Customer
{
private readonly ILogger _logger;
public Customer(ILogger logger)
{
_logger = logger;
}
public void Add()
{
try
{
// Logic goes here
}
catch (Exception ex)
{
_logger.error(ex.ToString());
}
}
}
Open-Closed Principle
Software entities (classes, methods, etc.) should be open for extension, but closed for modification
Open-Closed Principle
class Customer
{
public int CustType { get; set; }
public decimal CalculateSalePrice(decimal subtotal)
{
if (CustType == 1)
{
return subtotal * 0.90;
}
else
{
return subtotal * 0.95;
}
}
}
Open-Closed Principle
What if we want to add a new customer type?
Open-Closed Principle
class Customer
{
public virtual decimal CalculateSalePrice(decimal subtotal)
{
return subtotal;
}
}
class SilverCustomer : Customer
{
public override decimal CalculateSalePrice(decimal subtotal)
{
return subtotal * 0.95;
}
}
class GoldCustomer : Customer
{
public override decimal CalculateSalePrice(decimal subtotal)
{
return subtotal * 0.90;
}
}
Liskov Substitution Principle
Subtypes must be substitutable for their base types
Liskov Substitution Principle
class Inquiry : Customer
{
public override decimal CalculateSalePrice(decimal subtotal)
{
return subtotal * 0.95;
}
public override void Add()
{
throw new NotImplementedException();
}
}
Single Responsibility Principle
What if we want to iterate over a list of customers and add them to our system?
List<Customer> customers = new List<Customer>();
customers.Add(new SilverCustomer());
customers.Add(new GoldCustomer());
customers.Add(new Inquiry());
foreach (Customer customer in customers)
{
customer.Add();
}
Liskov Substitution Principle
interface IDiscount {
decimal CalculateSalePrice(decimal subtotal);
}
interface IPersistence {
void Add();
}
class Inquiry : IDiscount {
public decimal CalculateSalePrice(decimal subtotal) {
return subtotal * 0.95;
}
}
class Customer : IDiscount, IPersistence {
public virtual void Add() {
// Logic goes here
}
public virtual decimal CalculateSalePrice(decimal subtotal) {
return subtotal;
}
}
Interface Segregation Principle
Clients should not be forced to depend upon interfaces that they do not use
Interface Segregation Principle
interface IBird
{
void Eat();
void Walk();
void Chirp();
void Fly();
}
Interface Segregation Principle
What about an ostrich?
Interface Segregation Principle
interface IBird
{
void Eat();
void Walk();
void Chirp();
}
interface IFlyingBird : IBird
{
void Fly();
}
Dependency Inversion Principle
High level modules should not depend upon low level modules.
Rather, both should depend upon abstractions.
Dependency Inversion Principle
class Car
{
private BasicEngine _engine;
private BasicSteeringWheel _steeringWheel;
public Car ()
{
_engine = new BasicEngine();
_steeringWheel= new BasicSteeringWheel();
}
}
Single Responsibility Principle
What if we want to swap out the engine and steering wheel?
Single Responsibility Principle
class Car
{
private IEngine _engine;
private ISteeringWheel _steeringWheel;
public Car (IEngine engine, ISteeringWheel steeringWheel)
{
_engine = engine;
_steeringWheel = steeringWheel;
}
}
class BasicEngine : IEngine {}
class SuperFastEngine : IEngine {}
class BasicSteeringWheel: ISteeringWheel {}
class SuperDeluxeSteeringWheel: ISteeringWheel {}
Car basicRide = new Car(new BasicEngine(), new BasicSteeringWheel());
Car fancyRide = new Car(new SuperFastEngine(), new SuperDeluxeSteeringWheel());
The End
SOLID Principles
By Ryan Haugh
SOLID Principles
- 1,122