Закон Деметры и ООП путаница - PullRequest
5 голосов
/ 03 августа 2011

Я недавно немного читал и столкнулся с Законом Деметры. Теперь то, что я прочитал, имеет смысл, например, разносчик газет никогда не должен быть в состоянии сунуть деньги в карман клиента, схватить кошелек и вытащить деньги. Кошелек - это то, что клиент должен контролировать, а не разносчик газет .

Что подводит меня к закону, может быть, я просто неправильно понимаю, что струнные свойства вместе с иерархией функций / информации могут быть очень полезны. например .NET HTTPContext класс.

Не код, такой как:

If DataTable.Columns.Count >= 0 Then
   DataTable.Columns(0).Caption = "Something"
End If

Или

Dim strUserPlatform as string = HttpContext.Current.Request.Browser.Platform.ToString()

Или

If NewTerm.StartDate >= NewTerm.AcademicYear.StartDate And 
   NewTerm.EndDate <= NewTerm.AcademicYear.EndDate Then
   ' Valid, subject to further tests.
Else
   ' Not valid.
End If
1015 * нарушать этот закон? Я подумал (возможно, ошибочно), что цель ООП частично заключалась в том, чтобы обеспечить доступ к связанным классам в хорошей иерархической структуре.

Мне нравится, например, идея ссылки на служебный инструментарий, который может использоваться классами страниц, чтобы избежать повторяющихся задач, таких как отправка электронных писем и инкапсуляция полезных строковых методов:

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

Любая ясность была бы велика ... в настоящий момент я не могу смириться с тем, что закон, по-видимому, запрещает связывать свойства и методы вместе ... мне кажется странным, что так много власти следует игнорировать? Я довольно новичок в ООП, как могли догадаться некоторые из вас, поэтому, пожалуйста, будьте спокойны:)

Ответы [ 3 ]

6 голосов
/ 03 августа 2011

То, что закон Деметры (также «Закон Деметры для функций / методов») хочет уменьшить, говоря «используйте только одну точку», - это то, что в методе вам не нужно принимать такой большой контекст изпредоставленные аргументы.Это увеличивает зависимость класса и делает его менее тестируемым.

Это не означает, что вы не можете использовать все приведенные выше примеры, но предлагает вместо того, чтобы дать вашему методу клиент, который затем обращается ккошелек и извлекает из него деньги:

function getPayment(Customer customer)
{
    Money payment = customer.leftpocket.getWallet().getPayment(100);
    ...
    // do stuff with the payment
}

, что вы вместо этого передаете методу только то, что нужно разносчику газет, и таким образом уменьшаете зависимость для метода, если это возможно:

function getPayment(Money money)
{
    // do stuff with the payment
}

Ваша выгода от этого будет заключаться в том, что вы не зависите от клиента, у которого кошелек в левом кармане, а вместо этого просто обрабатываете деньги, которые клиент дает вам.Это решение, которое вы должны основывать на своем индивидуальном случае.Меньше зависимостей позволяют вам легче тестировать.

3 голосов
/ 03 августа 2011

Я думаю, что применение Закона Деметры к отдельным классам заходит слишком далеко. Я думаю, что лучшее приложение - это применить его к layer в вашем коде. Например, ваш уровень бизнес-логики не должен иметь доступа к чему-либо, касающемуся контекста HTTP, а ваш уровень доступа к данным не должен иметь доступа к чему-либо на уровне представления.

Да, обычно хорошая практика для разработки интерфейса вашего объекта, так что вам не нужно выполнять тонны цепочки свойств, но представьте себе ужасно сложный интерфейс, который вы бы получили, если бы попытались сделайте это с классами DataTable и HttpContext, которые вы дали в качестве примеров.

1 голос
/ 03 августа 2011

Закон не гласит, что у вас вообще не должно быть доступа к какой-либо информации в классе, но что у вас должен быть доступ к информации только таким способом, которым вы не можете легко злоупотреблять ею.

Например, вы не можете добавлять столбцы в таблицу данных, присваивая что-либо свойству Count:

DataTable.Columns.Count = 42;

Вместо этого вы используете метод Add объекта Columns, который позволяет добавлять столбец таким образом, чтобы в нем находилась вся необходимая информация о столбце, а также чтобы таблица данных была настроена с данными для этот столбец.

...