Чистый Код: Объекты должны иметь общественные собственности?

Я читаю книгу "Чистый Код" и борюсь с понятием. При обсуждении Объектов и Структур данных, это указывает следующее:

  • Объекты скрывают свои данные позади абстракций и выставляют функции, которые воздействуют на те данные.
  • Структуры данных выставляют свои данные и не имеют никаких значимых функций.

Так, что я получаю от этого, то, что у меня не должно быть общественных собственностей на моем объекте, у меня должны только быть методы, которые выполняют операции на свойствах. Если я действительно должен получить доступ к свойствам, они должны быть на Структуре данных, которая могла быть возвращена из метода на моем объекте? С этим подходом кажется, что мне был бы нужен GetHeight () и SetHeight (), метод для моего свойства Height на моем объекте, вместо просто использования добираются и набор свойства.

Возможно, я не понимаю точно, что предлагается, но это - мое понимание "Объектов, скрывают их данные". Если бы Вы могли бы помочь мне понять это, я был бы очень признателен за его!

Заранее спасибо!

27
задан JSprang 7 July 2010 в 13:23
поделиться

12 ответов

Публичные свойства - это хорошо. Отсутствие необходимости писать явные методы GetHeight() и SetHeight() - вот что такое свойства. Свойство в C# - это не данные; его лучше всего рассматривать как пару методов getter/setter. (Свойства фактически компилируются в методы в генерируемом IL.)

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

public int Height { get; set; }

на

public int Height { get { return m_width; } set { m_width = value; } }

если вы решили, что ваш объект всегда должен быть квадратным. Код, использующий ваш класс, не потребует никаких изменений.

Таким образом, если ваш объект раскрывает публичные свойства, он по-прежнему "скрывает свои данные за абстракциями и раскрывает функции, которые работают с этими данными", как рекомендует книга.

19
ответ дан 28 November 2019 в 04:12
поделиться

Фактически, используя свойство, например

public class Temp
{
   public int SomeValue{get;set;}
   public void SomeMethod()
   {
     ... some work
   }
}

Вы скрываете его данные, поскольку существует неявная переменная для хранения значения, установленного и возвращаемого свойством SomeValue.

Если у вас есть

public class Temp
{
   private int someValue;
   public int SomeValue
   {
     get{ return this.someValue;}
     set{ this.someValue = value;}
   }
   public void SomeMethod()
   {
     this.someValue++;
   }
}

, тогда вы поймете, что я имею в виду. Вы скрываете данные объекта someValue и ограничиваете доступ к ним с помощью свойства SomeValue.

0
ответ дан 28 November 2019 в 04:12
поделиться

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

Тем не менее, если у вас есть простые объекты, то это жесткое правило не выдерживает никакой критики. В случае прямоугольника высота и ширина являются основными свойствами, которые пользователь захочет знать. И поскольку реализация этого проста, отказ от использования get и set только усложнит ваш код, чем он должен быть.

3
ответ дан 28 November 2019 в 04:12
поделиться

Создание общедоступных средств доступа с частными полями устанавливает договор между кодом пользователя и вашим классом. В идеале этот контракт не должен изменять изменения кода.

В C # для обеспечения соблюдения условий контракта используется интерфейс . Интерфейсы позволяют указать требуемые реализации методов и свойств, но не позволяют использовать поля.

Более того, в различных аспектах .NET свойства часто предпочтительнее полей. например Элемент управления PropertyGrid перечисляет только свойства, классам моделей ASP.NET MVC требуются свойства и т. Д.

2
ответ дан 28 November 2019 в 04:12
поделиться

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

Coding with Reason by Yechiel Kimchi (из книги 97 Things Every Programmer Should Know)

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

Это не всегда входит в игру (например, объекты передачи данных). Чего я остерегаюсь, так это Неуместной близости.

5
ответ дан 28 November 2019 в 04:12
поделиться

Свойства на самом деле являются методами.
Компилятор компилирует свойства для получения / установки методов MIL.

4
ответ дан 28 November 2019 в 04:12
поделиться

Когда вы закончите Чистый код, я рекомендую вам прочитать другую книгу Боба Мартина:

Шаблоны принципов гибкой разработки и Практики в C#

В этой книге обсуждается тематическое исследование, и в нем Боб применяет принципы, обсуждаемые в Clean Code. Сначала я прочитал Clean Code, но в ретроспективе я думаю, что «Agile Patterns..» следует прочитать в первую очередь, поскольку Clean Code - это скорее повседневное руководство или руководство по хорошим принципам SW.

Например, в «Agile-шаблонах...» Используется следующий код:

public class OrderData
{
public string customerId;
public int orderId;
public OrderData() {}

...

}

Следующая проверка использования общедоступных данных относится к вашему вопросу:

Не обижайтесь на использование общедоступных данных члены данных. Это не объект в истинный смысл. Это просто контейнер для данных. У него нет интересное поведение, которое должно быть Инкапсулированный. Создание данных переменные частные, и предоставление геттеры и сеттеры были бы пустой тратой времени времени. Я мог бы использовать структуру вместо класса,но я хочу OrderДанные для передачи по ссылке а не по стоимости.


В сторону:

Лично я должен сказать, что Роберт Мартин внес огромный вклад в сообщество разработчиков SW (наряду с Мартином Фаулером, Майклом Физерсом..) этими книгами. Я думаю, что их надо читать.

9
ответ дан 28 November 2019 в 04:12
поделиться

Это в основном другое определение термина "свойство". Свойство в C# - это не то, что большинство других языков считают свойствами.

Example:
Публичное свойство в C++:

class foo
{
  public:
    int x;
};

Соответствующий термин в C# - публичное поле:

class foo
{
  public int x;
}

То, что мы называем в C# свойствами, в других языках было бы сеттерами и геттерами:

C#:

class foo
{
  public int X { get; set; }
}

соответствующий C++:

class foo
{
  private:
    int x;

  public:
    void setX(int newX) { this->x = newX; }
    int  getX() { return this->x; }
}

Короче говоря:
Свойства в C# - это совершенно нормально, только не надо слепо назначать их по умолчанию get и set и не надо делать каждое поле данных в вашем классе публичным свойством, подумайте о том, что пользователям вашего класса действительно нужно знать/изменять.

10
ответ дан 28 November 2019 в 04:12
поделиться

Действительно, свойство C # - это не данные, это средство доступа, поэтому это функция, работающая с данными.

Вам следует избегать общедоступных полей, а не общедоступных свойств.

31
ответ дан 28 November 2019 в 04:12
поделиться

Свойства по сути являются сокращением методов Getter и Setter. Смысл методов Getter и Setter в том, чтобы объект обрабатывал любые операции над переменными, чтобы вы могли выполнять любые дополнительные операции (например, проверку данных) без нежелательных последствий.

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

3
ответ дан 28 November 2019 в 04:12
поделиться

Как и другие сообщения в этой теме, я отмечу, что свойства в C # - это просто особые случаи функций доступа, о которых вы упомянули. Фактически, вы можете настроить методы get_Property и set_Property в IL вашего объекта, у которых есть флаг, указывающий, что они являются свойствами, то же самое верно для событий, которые реализуют методы с префиксом add_ и remove_.

Одно важное различие при работе с абстракциями заключается в том, будет ли установка свойства воздействовать на объект иначе, чем просто обновлять внутреннее состояние или вызывать исключение PropertyChanged.

Если вы посмотрите на множество внутренних объектов BCL, свойства реализованы таким образом, что вы можете установить все свойства в любом порядке для настройки объекта. Если выполняется какая-либо сложная обработка, то обычно лучший выбор - метод, описывающий, что должно произойти.

1
ответ дан 28 November 2019 в 04:12
поделиться

Вот в чем дело.

Хотя общедоступные переменные могут быть полезны в некоторых случаях, часто лучше оставить их закрытыми.

Упорядочить код легко, если только объект может управлять своей переменной.

Представьте, что вы хотите поддерживать высоту от 0 до 200. Если у вас есть способ установить свой рост, вы можете легко это контролировать.

Например (я буду использовать Java для скорости):

public void setHeight(int newHeight)
{
    if (newHeight < 0)
        height = 0;
    else if (newHeight > 200)
        height = 200;
    else
        height = newHeight
}

Как видите, этот подход очень структурирован и управляем.

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

Очень простой пример, но я думаю, что он передает суть.

2
ответ дан 28 November 2019 в 04:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: