Чистый код: должны ли объекты иметь публичные свойства? - PullRequest
27 голосов
/ 07 июля 2010

Я читаю книгу «Чистый код» и борюсь с концепцией.Обсуждая объекты и структуры данных, он заявляет следующее:

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

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

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

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

Ответы [ 13 ]

30 голосов
/ 07 июля 2010

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

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

18 голосов
/ 07 июля 2010

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

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

public int Height { get; set; }

на

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

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

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

10 голосов
/ 07 июля 2010

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

Пример:
Открытое свойство 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 # совершенно хороши, просто не устанавливайте их по умолчанию вслепую, чтобы установить и , и не делайте каждое поле данных в вашем классе публичным свойством, подумайтео том, что пользователи вашего класса действительно должны знать / изменять.

9 голосов
/ 07 июля 2010

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

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

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

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

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

...

}

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

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


За исключением:

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

5 голосов
/ 07 июля 2010

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

Кодирование с разумом Йехиэля Кимчи (из книги 97 Вещи, которые должен знать каждый программист )

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

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

4 голосов
/ 07 июля 2010

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

3 голосов
/ 04 октября 2011

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

Внутренние данные НИЧЕГО НЕ ЗАКРЫТЫ, НЕ ПРОИЗВЕДЕНЫ, просто перенаправив доступ к ним через свойство!

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

3 голосов
/ 07 июля 2010

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

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

3 голосов
/ 07 июля 2010

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

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

2 голосов
/ 07 июля 2010

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

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

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

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

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

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

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

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

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

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