How do you tell whether one design is better than another? This talk provides the answer. By walking through a simple example business problem and its software solution, we examine a few key principles that can be applied to make designs simpler, easier to maintain and change, and overall better.
5. !
public class Part
{
private decimal price;
public Part(string name, decimal price)
{
this.price = price;
}
public decimal Price
{
get { return price; }
set { price = value; }
}
}
6. !
public class ServiceOrder {
private List<Part> parts;
public ServiceOrder() {
parts = new List<Part>();
}
public void AddPart(Part part) {
parts.Add(part);
}
public decimal Total() {
decimal total = 0;
foreach (Part aPart in parts) {
total += aPart.Price;
}
return total;
}
}
7. Now we want to specify additional
quantities of each part.
(because we are lazy)
11. !
public class LineItem
{
private Part part;
private int quantity;
public LineItem(Part part, int quantity) {
this.part = part;
this.quantity = quantity;
}
public Part Part {
get { return part; }
}
public int Quantity {
get { return quantity; }
private set { quantity = value; }
}
}
12. public class ServiceOrder
{
private List<LineItem> lineItems;
public ServiceOrder() {
lineItems = new List<LineItem>();
}
public void AddPart(Part part) {
this.AddPart(part, 1);
}
public void AddPart(Part part, int quantity) {
LineItem lineItem = new LineItem(part, quantity);
lineItems.Add(lineItem);
}
public decimal Total() {
decimal total = 0;
foreach (LineItem aLineItem in lineItems) {
total += aLineItem.Part.Price * aLineItem.Quantity;
}
return total;
}
}
16. !
public class Part
{
private string name;
private decimal wholesalePrice;
private int markupPercentage;
public Part(string name, decimal price) :this(name, price, 0)
{}
public Part(string name, decimal price, int markupPercentage) {
this.name = name;
this.wholesalePrice = price;
this.markupPercentage = markupPercentage;
}
public string Name {
get { return name; }
}
public decimal WholesalePrice {
get { return wholesalePrice; }
}
public int MarkupPercentage {
get { return markupPercentage; }
}
}
17. !
public class ServiceOrder
{
private List<LineItem> lineItems;
public ServiceOrder() {
lineItems = new List<LineItem>();
}
public void AddPart(Part part) {
this.AddPart(part, 1);
}
public void AddPart(Part part, int additionalQuantity) {
LineItem lineItem = new LineItem(part, additionalQuantity);
lineItems.Add(lineItem);
}
public decimal Total() {
decimal total = 0;
foreach (LineItem aLineItem in lineItems) {
total += aLineItem.Part.WholesalePrice
* (aLineItem.Part.MarkupPercentage/100m + 1)
* aLineItem.Quantity;
}
return total;
}
}
19. !
// New methods in the Part class
public decimal Price {
get { return wholesalePrice * MarkupMultiplier(); }
}
!
private decimal MarkupMultiplier() {
return (markupPercentage / 100m + 1);
}
!
!
// And one in the LineItem class
public decimal LineTotal() {
return part.Price * quantity;
}
20. !
// In the ServiceOrder class...
public decimal Total() {
decimal total = 0;
foreach (LineItem aLineItem in lineItems) {
total += aLineItem.LineTotal();
}
return total;
}
43. S ingle Responsibility Principle
O pen/Closed Principle
L iskov Substitution Principle
I nterface Segregation Principle
D ependency Inversion Principle