principles of object oriented design s.o.l.i.d. s.o.l.i.d principles what is solid? acrostic of 5...
DESCRIPTION
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 togetherTRANSCRIPT
PRINCIPLES OF
OBJECT ORIENTED
DESIGN
S.O.L.I.D
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 bool IsValid() { 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 int IndexOf(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, int arrayIndex); bool Remove(T item);
// Properties int Count { get; } bool IsReadOnly { 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 readonly IValidator<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