The principle states: Each unit should only talk to its friends; Don’t talk to strangers. A method of an object should invoke only the methods of the following kinds of objects:
Interface : IOrderManager
Interface: IItem
Class: Item : IItem
In the above example the OrderManager has the responsibility of adding and removing Items to and from the List collection in the Order class, and even worse it has the responsibility of changing the name of a particular Item inside that collection. This tightly couples the OrderManager to the Order and Item class, if we would change how the Order class is maintaining her Items than we automatically have to change the OrderManager class. The Order should be responsible for its Items, not the OrderManager. Below is the Law Of Demeter implementation of this example:
Interface: IOrder
Class: Order : IOrder
Class: OrderManager : IOrderManager
Now we can change how the Order class is keeping its Items without having to change the OrderManager. One nice rule of thumb is: One dot should be enough.
- 1. itself 2. its parameters 3. any objects it creates/instantiates 4. its direct component objects
Violation of above principle
Below is an example of some code breaking this principle:Interface : IOrderManager
public interface IOrderManager { void AddItemToOrder(IItem item); void RemoveItemFromOrder(IItem item); void ChangeItemName(IItem item, string name); }
Interface: IItem
public interface IItem { int Id { get; set; } string Name { get; set; } }
Class: Item : IItem
public class Item : IItem { private int _Id; private string _Name; public int Id { get { return _Id; } set { _Id = value; } } public string Name { get { return _Name; } set { _Name = value; } } }Class :OrderManager : IOrderManager
public class OrderManager implements IOrderManager { private IOrder _Order; public OrderManager() { _Order = new Order(); _Order.Items = new List<IItem>(); } public void AddItemToOrder(IItem item) { if (_Order.Items != null) { if ( ! _Order.Items.Contains(item)) { _Order.Items.Add(item); } } } public void RemoveItemFromOrder(IItem item) { if (_Order.Items != null) { if (_Order.Items.Contains(item)) { _Order.Items.Remove(item); } } } public void ChangeItemName(IItem item, string name) { if (_Order.Items != null) { if (_Order.Items.Contains(item)) { _Order.Items[_Order.Items.IndexOf(item)].Name = name; } } }
In the above example the OrderManager has the responsibility of adding and removing Items to and from the List collection in the Order class, and even worse it has the responsibility of changing the name of a particular Item inside that collection. This tightly couples the OrderManager to the Order and Item class, if we would change how the Order class is maintaining her Items than we automatically have to change the OrderManager class. The Order should be responsible for its Items, not the OrderManager. Below is the Law Of Demeter implementation of this example:
Interface: IOrder
public interface IOrder { void AddItem(IItem item); void RemoveItem(IItem item); void ChangeItemName(IItem item, string name); }
Class: Order : IOrder
public class Order implements IOrder { private List<IItem> _Items; public Order() { _Items = new List<IItem>(); } public void AddItem(IItem item) { if (_Items != null) { if (!_Items.Contains(item)) { _Items.Add(item); } } } public void RemoveItem(IItem item) { if (_Items != null) { if (_Items.Contains(item)) { _Items.Remove(item); } } } public void ChangeItemName(IItem item, string name) { if (_Items != null) { if (_Items.Contains(item)) { _Items[_Items.IndexOf(item)].Name = name; } } } }
Class: OrderManager : IOrderManager
public class OrderManager implements IOrderManager { private IOrder _Order; public OrderManager() { _Order = new Order(); } public void AddItemToOrder(IItem item) { _Order.AddItem(item); } public void RemoveItemFromOrder(IItem item) { _Order.RemoveItem(item); } public void ChangeItemName(IItem item, string name) { _Order.ChangeItemName(item, name); } }
Now we can change how the Order class is keeping its Items without having to change the OrderManager. One nice rule of thumb is: One dot should be enough.
No comments:
Post a Comment