GithubHelp home page GithubHelp logo

talhakaanozkan / solid Goto Github PK

View Code? Open in Web Editor NEW
0.0 2.0 0.0 8 KB

SOLID is an acronym created by Michael Feathers from the principles of object-oriented programming identified by Robert C. Martin (Uncle Bob).

License: MIT License

csharp solid-principles

solid's Introduction

SOLID

SOLID is an acronym created by Michael Feathers from the principles of object-oriented programming identified by Robert C. Martin (Uncle Bob).

These principles aim to make the code more readable, easy to maintain, extensible, reusable and without repetition.

Single Responsibility Principle

The Single Responsibility Principle says that a class must have only one reason to change and only one responsibility.

Bad

public sealed class Customer
{
    public int Id { get; set; }

    public string Name { get; set; }

    public bool Active { get; set; }

    public void Activate()
    {
        Active = true;
    }

    public void Inactivate()
    {
        Active = false;
    }

    public void Insert()
    {
        /// Implementation for ADDING to DATABASE
    }

    public void Delete()
    {
        /// Implementation for DELETING to DATABASE
    }
}

The code is incorrect because it has two responsibilities, business rules and database persistence.

Good

public sealed class Customer
{
    public int Id { get; set; }

    public string Name { get; set; }

    public bool Active { get; set; }

    public void Activate()
    {
        Active = true;
    }

    public void Inactivate()
    {
        Active = false;
    }
}
public sealed class CustomerRepository
{
    public void Insert(Customer customer)
    {
        /// Implementation for ADDING to DATABASE
    }

    public void Delete(Customer customer)
    {
        /// Implementation for DELETING to DATABASE
    }
}

The code is correct because the responsibilities have been split, each class has only one reason to change.

Open Closed Principle

The Open Closed Principle says the code must be open for extension and closed for modification.

Bad

public enum PaymentMethod
{
    Cash = 1,
    CreditCard = 2,
    DebitCard = 3
}
public class PaymentService
{
    public void Pay(PaymentMethod paymentMethod)
    {
        /// Implementation

        if (paymentMethod == PaymentMethod.Cash)
        {
            /// Implementation
        }
        else if (paymentMethod == PaymentMethod.CreditCard)
        {
            /// Implementation
        }
        else if (paymentMethod == PaymentMethod.DebitCard)
        {
            /// Implementation
        }

        /// Implementation
    }
}

The code is incorrect because it is open for modification. If a new payment method is added, the class has to be changed.

Good

public interface IPaymentMethod
{
    void Pay();
}
public sealed class Cash : IPaymentMethod
{
    public void Pay()
    {
        /// Implementation
    }
}
public sealed class CreditCard : IPaymentMethod
{
    public void Pay()
    {
        /// Implementation
    }
}
public sealed class DebitCard : IPaymentMethod
{
    public void Pay()
    {
        /// Implementation
    }
}
public class PaymentService
{
    private readonly IPaymentMethod _paymentMethod;

    public PaymentService(IPaymentMethod paymentMethod)
    {
        _paymentMethod = paymentMethod;
    }

    public void Pay()
    {
        /// Implementation

        _paymentMethod.Pay();

        /// Implementation
    }
}

The code is correct because if a new payment method is added the class is not modified.

Liskov Substitution Principle

The Liskov Substitution Principle says that derived classes must be substitutable for their base classes.

Bad

public class Cat
{
    public virtual string GetName()
    {
        return nameof(Cat);
    }

    public void Move()
    {
        /// Implementation
    }

    public void Eat()
    {
        /// Implementation
    }
}
public class Dog : Cat
{
    public override string GetName()
    {
        return nameof(Dog);
    }
}
public static class Program
{
    public static void Main()
    {
        Cat cat = new Dog();
        cat.GetName();
    }
}

The code is incorrect because the Dog class is inheriting from the Cat class only because it has similar behaviors. Executing "cat.GetName()" will display "Dog".

Good

public abstract class Animal
{
    public abstract string GetName();

    public virtual void Move()
    {
        /// Implementation
    }

    public void Eat()
    {
        /// Implementation
    }
}
public sealed class Cat : Animal
{
    public override string GetName()
    {
        return nameof(Cat);
    }
}
public sealed class Dog : Animal
{
    public override string GetName()
    {
        return nameof(Dog);
    }

    public override void Move()
    {
        /// Implementation
    }
}
public static class Program
{
    public static void Main()
    {
        var animals = new List<Animal>
        {
            new Cat(),
            new Dog()
        };

        foreach (var animal in animals)
        {
            animal.GetName();
            animal.Move();
            animal.Eat();
        }
    }
}

The code is correct because the Cat and Dog classes can be replaced by the Animal class without having unexpected behaviors.

Interface Segregation Principle

The Interface Segregation Principle says that many specific interfaces are better than a single interface.

Bad

public interface IBase
{
    void ChangeId(int id);

    void ChangeAddress(string address);

    void ChangePrice(decimal price);
}
public sealed class Customer : IBase
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Address { get; set; }

    public void ChangeId(int id)
    {
        Id = id;
    }

    public void ChangeAddress(string address)
    {
        Address = address;
    }

    public void ChangePrice(decimal price)
    {
        throw new NotImplementedException();
    }
}
public sealed class Product : IBase
{
    public int Id { get; set; }

    public string Description { get; set; }

    public decimal Price { get; set; }

    public void ChangeId(int id)
    {
        Id = id;
    }

    public void ChangePrice(decimal price)
    {
        Price = price;
    }

    public void ChangeAddress(string address)
    {
        throw new NotImplementedException();
    }
}

The code is incorrect because the Customer class is required to have the ChangePrice method, and the Product class is required to have the ChangeAddress method, only because they implement the same interface.

Good

public interface IBase
{
    void ChangeId(int id);
}
public interface ICustomer : IBase
{
    void ChangeAddress(string address);
}
public interface IProduct : IBase
{
    void ChangePrice(decimal price);
}
public sealed class Customer : ICustomer
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Address { get; set; }

    public void ChangeId(int id)
    {
        Id = id;
    }

    public void ChangeAddress(string address)
    {
        Address = address;
    }
}
public sealed class Product : IProduct
{
    public int Id { get; set; }

    public string Description { get; set; }

    public decimal Price { get; set; }

    public void ChangeId(int id)
    {
        Id = id;
    }

    public void ChangePrice(decimal price)
    {
        Price = price;
    }
}

The code is correct because the generic interface has been split into specific interfaces. The classes do not implement methods that are not part of your business logic.

Dependency Inversion Principle

The Dependency Inversion Principle says to depend on abstraction, not implementation.

Bad

public sealed class Customer
{
    public int Id { get; set; }

    public string Name { get; set; }
}
public sealed class CustomerRepository
{
    public CustomerRepository(string connectionString)
    {
        /// Implementation
    }

    public void Add(Customer customer)
    {
        /// Implementation
    }
}
public sealed class CustomerService
{
    private readonly CustomerRepository _customerRepository = new CustomerRepository("ConnectionString");

    public void Add(Customer customer)
    {
        _customerRepository.Add(customer);
    }
}

The code is incorrect because the CustomerService class depends on the CustomerRepository class and also knows how to instantiate it.

Good

public sealed class Customer
{
    public int Id { get; set; }

    public string Name { get; set; }
}
public interface ICustomerRepository
{
    void Add(Customer customer);
}
public sealed class CustomerRepository : ICustomerRepository
{
    public CustomerRepository(string connectionString)
    {
        /// Implementation
    }

    public void Add(Customer customer)
    {
        /// Implementation
    }
}
public sealed class CustomerService
{
    private readonly ICustomerRepository _customerRepository;

    public CustomerService(ICustomerRepository customerRepository)
    {
        _customerRepository = customerRepository;
    }

    public void Add(Customer customer)
    {
        _customerRepository.Add(customer);
    }
}

The code is correct because the CustomerService class depends only on the ICustomerRepository interface. It does not know the implementation or how to instantiate it.

solid's People

Contributors

talhakaanozkan avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.