• 520 likes • 1.38k Views
S.O.L.I.D. Principles of object oriented Design. S.O.L.I.D Principles. What is SOLID? Acrostic of 5 Principles: The S ingle Responsibility Principle The O pen Closed Principle The L iskov Substitution Principle The I nterface Segregation Principle The D ependency Inversion Principle.
E N D
S.O.L.I.D Principles of object oriented Design
S.O.L.I.D Principles • What is SOLID? • Acrostic of 5 Principles: • The Single Responsibility Principle • The Open Closed Principle • The Liskov Substitution Principle • The Interface Segregation Principle • The Dependency Inversion Principle
S.O.L.I.D Principles • The Open Closed Principle • The Liskov Substitution Principle • The Single Responsibility Principle • The Dependency Inversion Principle • The Interface Segregation Principle • Bringing it all together
S.O.L.I.D Principles • How can SOLID help? • Drives good design • Maintenance • Refactorability • Clarity • Coupling and Cohesion • We want LOW coupling • And HIGH cohesion
S.O.L.I.D Principles The Open/Closed Principle and The Liskov Substitution Principle
OCP and LSP • OCP • “Classes should be open for extension but closed for modification” • Polymorphism / abstraction • LSP • “Derived classes must be substitutable for their base class” • Basic polymorphism/inheritance • Has implications with covariance/contravariance
S.O.L.I.D Principles The Single Responsibility Principle
The Single Responsibility Principle • “Every object should have a single responsibility, and that all its services should be narrowly aligned with that responsibility” • Achieved with • Dependency Inversion • Interface Segregation
The Single Responsibility Principle public class User { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string GenerateUpdate() { return String.Format( "UPDATE Users SET FirstName='{0}', LastName='{1}' WHERE Id={2}", FirstName, LastName, Id); } public string GenerateDelete() { return String.Format( "DELETE FROM Users WHERE Id={0}", Id); } public string GenrateInsert() { if (Id != 0) throw new InvalidOperationException( String.Format( "This user already exists with an ID of {0}", Id)); return String.Format( "INSERT INTO Users VALUES ({0},{1})", FirstName, LastName); } public boolIsValid() { return !String.IsNullOrEmpty(FirstName) && !String.IsNullOrEmpty(LastName); } }
S.O.L.I.D Principles The Dependency Inversion Principle
The Dependency Inversion Principle “Depend on abstractions and not concretions” “High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.”
The Dependency Inversion Principle • Heavily uses • Interface based programming • Achieved with • Dependency Injection
The Dependency Inversion Principle • Interface based programming • public string Concatenate(List<string> parts, string delimeter) • { • string result = ""; • foreach (var part in parts) • result += part + delimeter; • return result; • }
The Dependency Inversion Principle • Interface based programming • public string Concatenate(List<string> parts, string delimeter) • { • string result = ""; • foreach (var part in parts) • result += part + delimeter; • return result; • } • public string Concatenate(string[] parts, string delimeter) • { • string result = ""; • foreach (var part in parts) • result += part + delimeter; • return result; • }
The Dependency Inversion Principle • Interface based programming • public string Concatenate(IList<string> parts, string delimeter) • { • string result = ""; • foreach (var part in parts) • result += part + delimeter; • return result; • } • public string Concatenate(string[] parts, string delimeter) • { • string result = ""; • foreach (var part in parts) • result += part + delimeter; • return result; • }
The Dependency Inversion Principle • Interface based programming • public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable • { • // Methods • intIndexOf(T item); • void Insert(int index, T item); • void RemoveAt(int index); • // Properties • T this[int index] { get; set; } • }
The Dependency Inversion Principle • Interface based programming • public interface ICollection<T> : IEnumerable<T>, IEnumerable • { • // Methods • void Add(T item); • void Clear(); • bool Contains(T item); • void CopyTo(T[] array, intarrayIndex); • bool Remove(T item); • // Properties • int Count { get; } • boolIsReadOnly { get; } • }
The Dependency Inversion Principle • Interface based programming • public string Concatenate(IEnumerable<string> parts, string delimeter) • { • string result = ""; • foreach (var part in parts) • result += part + delimeter; • return result; • }
The Dependency Inversion Principle DRY Don’t Repeat Yourself!
The Dependency Inversion Principle • Dependency Injection • “Depend on abstractions and not concretions” • Never call “new” to obtain a dependency • Inject dependencies instead
The Dependency Inversion Principle Dependency Injection public interface IRepository<TEntity> { IQueryable<TEntity> Query(); void Insert(TEntity entity); void Update(TEntity entity); void Delete(TEntity entity); } public interface IValidator<TEntity> { IEnumerable<IViolation> Validate(TEntity entity); }
The Dependency Inversion Principle • Dependency Injection • public class Repository<TEntity> : IRepository<TEntity> • { • private readonlyIValidator<TEntity> validator; • public Repository(IValidator<TEntity> validator) • { • this.validator = validator; • } • public void Insert(TEntity entity) • { • var violations = this.validator.Validate(entity); • if (violations.Count() != 0) • throw new ValidationException(violations); • // Insert if validation passed • Session.Save(entity); • } • // other methods • }
S.O.L.I.D Principles The Interface Segregation Principle
The Interface Segregation Principle • “Clients should not be forced to depend on interfaces that they do not use” • Fat vs Thin Interfaces • Drives low coupling • Helps create self-documenting code
The Interface Segregation Principle Example: public interface ICRUDService<TEntity> { TEntity Find(int id); void Insert(TEntity entity); void Update(TEntity entity) void Delete(TEntity entity); }
The Interface Segregation Principle Example: public interface ICRUDService<TEntity> { TEntity Find(int id); void Insert(TEntity entity); void Update(TEntity entity) void Delete(TEntity entity); }
The Interface Segregation Principle Example public class CountryService : ICRUDService<Country> { Country Find(int id) { // bla } void Insert(Country entity) { throw new NotImplementedException(); } void Update(Country entity) { // bla } void Delete(Country entity) { throw new NotImplementedException(); } }
The Interface Segregation Principle Example: public interface IQueryService<TEntity> { TEntity Find(int id); } public interface IInsertService<TEntity> { void Insert(TEntity entity); }
The Interface Segregation Principle Example: public class CountryService : IQueryService<Country>, IUpdateService<Country> { Customer Get(int id) { // bla } void Update(Customer customer) { // bla } }
Implementing S.R.P. • To achieve SRP • Inject Dependencies by Inverting Control • Deal with abstractions not concretions by using interface based programming • Segregate interfaces into groups of concerns
Moving Forwards Using IoC Containers to help with Dependency Injection Using N-Tier architecture to create layers of concerns to aid with SRP