I've been doing some reading recently and have encountered the Law of Demeter. Now some of what I've read makes perfect sense e.g. the paperboy should never be able to rifle through a customers pocket, grab the wallet and take the money out. The wallet is something the customer should have control of, not the paperboy.
What throws me about the law, maybe I'm just misunderstanding the whole thing, is that stringing properties together with a heirarchy of functionality/information can be so useful. e.g. .NETs HTTPContext class.
Wouldn't code such as :
If DataTable.Columns.Count >= 0 Then
DataTable.Columns(0).Caption = "Something"
End If
Or
Dim strUserPlatform as string = HttpContext.Current.Request.Browser.Platform.ToString()
Or
If NewTerm.StartDate >= NewTerm.AcademicYear.StartDate And
NewTerm.EndDate <= NewTerm.AcademicYear.EndDate Then
' Valid, subject to further tests.
Else
' Not valid.
End If
be breaking this law? I thought (perhaps mistakenly) the point of OOP was in part to provide access to related classes in a nice heirarchical structure.
I like, for example, the idea of referencing a utility toolkit that can be used by page classes to avoid repetitive tasks, such as sending emails and encapsulating useful string methods:
Dim strUserInput As String = "London, Paris, New York"
For Each strSearchTerm In Tools.StringManipulation.GetListOfString(strUserInput, ",")
Dim ThisItem As New SearchTerm
ThisItem.Text = strSearchTerm
Next
Any clarity would be great...at the moment I can't reconcile how the law seems to banish stringing properties and methods together...it seems strange to me that so much power should be disregarded? I'm pretty new to OOP as some of you might have guessed, so please go easy :)
The Law of Demeter principle states that a module should not have the knowledge on the inner details of the objects it manipulates. In other words, a software component or an object should not have the knowledge of the internal working of other objects or components.
The Law of Demeter asks us to minimize coupling between classes and avoid reaching out to the third object in order in order to make refactoring and developing new features easily.
High Cohesion (HC): Adhering to the Law of Demeter often results in additional methods that mirror methods of aggregated objects. As these objects have other responsibilities, the additional methods have fewer commonalities with the “real” methods of the class, which results in a lower cohesion.
It is so named for its origin in the Demeter Project, an adaptive programming and aspect-oriented programming effort. The project was named in honor of Demeter, “distribution-mother” and the Greek goddess of agriculture, to signify a bottom-up philosophy of programming which is also embodied in the law itself.
What the Law of Demeter (also "Law of Demeter for Functions/Methods") wants to reduce with saying "only use one dot" is that in a method you shouldn't have to assume such a lot of context from the provided arguments. This increases the dependency of the class and makes it less testable.
It doesn't mean that you can't use all of the above examples but it suggests that instead of giving your method the customer which then accesses the wallet and retrieves the money from it:
function getPayment(Customer customer)
{
Money payment = customer.leftpocket.getWallet().getPayment(100);
...
// do stuff with the payment
}
that you instead only pass what the paperboy needs to the method and as such reduce the dependency for the method if it's possible:
function getPayment(Money money)
{
// do stuff with the payment
}
Your benefit from it will be that you dont depend on the customer to have the wallet in the left pocket but instead just process the money the customer gives you. It's a decision you have to base on your individual case though. Less dependencies allow you to test easier.
I think applying the Law of Demeter to individual classes is taking it a bit too far. I think a better application is to apply it to layers in your code. For example, your business logic layer shouldn't need to access anything about the HTTP context, and your data access layer shouldn't need to access anything in the presentation layer.
Yes, it's usually good practice to design the interface of your object so that you don't have to do tons of property chaining, but imagine the hideously complex interface you'd have if you tried to do that to the DataTable
and HttpContext
classes you gave as examples.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With