Подтвердить что ты не робот

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

Я читаю книгу "Чистый код" и борюсь с концепцией. При обсуждении объектов и структур данных он утверждает следующее:

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

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

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

Спасибо заранее!

4b9b3361

Ответ 1

Публичные свойства прекрасны. Не нужно писать явные методы GetHeight() и SetHeight(). Свойство в С# не является данным; его лучше всего рассматривать как пару методов getter/setter. (Свойства фактически скомпилированы в методы в сгенерированном ИЛ.)

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

public int Height { get; set; }

в

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

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

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

Ответ 2

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

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

Ответ 3

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

Пример:
Открытое свойство С++:

class foo
{
  public:
    int x;
};

Соответствующий член в С# будет публичным полем:

class foo
{
  public int x;
}

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

С#:

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

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

class foo
{
  private:
    int x;

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

Вкратце:
Свойства С# полностью прекрасны, просто не слепо по умолчанию они не получают и не устанавливают и не делают каждое поле данных в вашем классе общедоступным, подумайте о том, что пользователи вашего класса действительно должны знать/изменять.

Ответ 4

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

Шаблоны Agile Principles и Практика в С#

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

Например, в "Agile patterns..." используется следующий код:

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

...

}

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

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


Помимо

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

Ответ 5

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

Кодирование с разумом Yechiel Kimchi (из книги 97 вещей, которые должен знать каждый программист)

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

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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

Внутренние данные НЕ СКРЫТЫЕ, НЕ РЕАЛИРУЮТСЯ только путем маршрутизации доступа к нему через свойство!

Чтобы ответить на ваш вопрос: - Избегайте публичных свойств, если вы пишете объект - Используйте публичные атрибуты, если вы пишете структуры данных (публичное поле также будет выполнять задание)

Ответ 10

Генерация открытых аксессуаров с частными полями устанавливает контракт между кодом пользователя и вашим классом. В идеале, этот контракт не должен изменяться над версиями кода.

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

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

Ответ 11

Здесь сделка.

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

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

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

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

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

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

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

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

Ответ 12

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

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

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

Ответ 13

Собственно, используя свойство, например

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.