A class should have only one reason to change. This means that every class, or similar structure, in your code should have only one job to do.
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public bool SaveIntoEmployeeTable(Employee em)
{
// Save to Employee table.
return true;
}
public void CreateExcelReport(Employee em)
{
// Write into Excel
}
}
The problem:
CreateExcelReport violates the rule so need a seperate class
public class CreateReport
{
public void ExcelReport(Employee em)
{
// Write into Excel
}
public void CsvReport(Employee em)
{
// Write into Excel
}
}
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
public class CreateReports
{
public void CreateReport(Employee em)
{
if (ReportType== "CRS")
{
// Crystal Report
}
if (ReportType == "PDF")
{
// PDF format
}
}
}
The problem:
CreateReport
too many "if"
The solution:
Put into seperate class
abstract class Report
{
public int ReportId { get; set; }
public string ReportName { get; set; }
public abstract void CreateReport(Employee em);
}
class CrystalReportCreate : Report
{
public override void CreateReport(Employee em)
{
// Crystal Report
}
}
class PDFReportCreate : Report
{
public override void CreateReport(Employee em)
{
// PDF report
}
}
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it
public abstract class Bird
{
public abstract string Fly();
public abstract string Walk();
}
public class Chicken : Bird
{
public override string Fly()
{
throw new NotImplementedException();
}
public override string Walk()
{
return "Walking...";
}
}
public class Pigeon : Bird
{
public override string Fly()
{
return "Fly...";
}
public override string Walk()
{
return "Walking...";
}
}
static void Main(string[] args)
{
Bird myBird = new Pigeon();
myBird.Fly();
myBird.Walk();
myBird = new Chicken();
myBird.Fly(); //Error throw new NotImplementedException
myBird.Walk();
}
The problem:
myBird.Fly();
//Error throw new NotImplementedException
The solution:
Seperating interfaces so not reachable
public interface IFlyAnimals
{
string Fly();
}
public interface IWalkingAnimals
{
string Walk();
}
public class Chicken : IWalkingAnimals
{
public string Walk()
{
return "Walking...";
}
}
public class Pigeon : IWalkingAnimals, IFlyAnimals
{
public string Fly()
{
return "Fly...";
}
public string Walk()
{
return "Walking...";
}
}
No client should be forced to implement methods which it does not use, and the contracts should be broken down to thin ones.
public interface IOrder
{
void AddToCart();
void CreditCardProcess();
}
public class OnlineOrder : IOrder
{
public void AddToCart()
{
// Do Add to Cart
}
public void CreditCardProcess()
{
// Process through to Cart
}
}
public class OfflineOrder : IOrder
{
public void AddToCart()
{
// Do Add to Cart
}
public void CreditCardProcess()
{
// Not required, Cash only
throw new NotImplementedException();
}
}
The problem:
CreditCardProcess not suitable for Offline order
The solution:
By dividing IOrder interface
public interface IOrder
{
void AddToCart();
}
public interface IOnlineOrder
{
void CreditCardProcess();
}
public class OnlineOrder : IOrder, IOnlineOrder
{
public void AddToCart()
{
// Do Add to Cart
}
public void CreditCardProcess()
{
// Process through to Cart
}
}
public class OfflineOrder : IOrder
{
public void AddToCart()
{
// Do Add to Cart
}
}
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.
public class Production
{
public void ProductionWork()
{
Car car = new Car();
car.AssembleParts();
}
}
public class Car
{
public bool AssembleParts()
{
//Assemble process..
return true;
}
}
The problem:
AssembleParts is depend on Production class
interface IProduction
{
bool AssembleParts();
}
public class ProductionController
{
private IProduction _IProduction;
public ProductionController(IProduction iProduction)
{
_IProduction = iProduction;
}
public void Produce()
{
_IProduction.AssembleParts();
}
}
public class Motorcyle : IProduction
{
public bool AssembleParts()
{
//Motorcyle pieces assembly..
return true;
}
}
public class Car : IProduction
{
public bool AssembleParts()
{
//Car pieces assembly..
return true;
}
}
class Program
{
static void Main(string[] args)
{
Motorcyle mlet = new Motorcyle();
mlet.Id = 1;
var pMan = new ProductionController(mlet);
pMan.Produce();
Car car = new Car();
car.Id = 2;
var cMan = new ProductionController(car);
cMan.Produce();
}
}