Это хорошая форма для представления производных значений в качестве свойств?

2

Мне нужно получить важное значение, учитывая 7 потенциальных входов. Дядя Боб призывает меня избегать функций с таким количеством параметров, поэтому я извлечен класс. Все параметры, теперь являющиеся свойствами, у меня остается метод вычисления без аргументов.

"Это, я думаю," может быть собственностью, но я не уверен, что этот идиоматический С# ".

Должен ли я отображать конечный результат как свойство или как метод без аргументов? Может ли средний программист на С# находить свойства запутанными или оскорбительными? Как насчет толпы Alt.Net?

decimal consumption = calculator.GetConsumption(); // obviously derived
decimal consumption = calculator.Consumption; // not so obvious

Если последнее: должен ли я объявлять промежуточные результаты как [частные] свойства, также? Благодаря тяжелой извлечению метода, у меня есть несколько промежуточных результатов. Многие из них не должны быть частью публичного API. Некоторые из них могут быть интересными, и мои выражения выглядели бы более чистыми, если бы я мог получить к ним доступ как свойства:

decimal interim2 = this.ImportantInterimValue * otherval;

Счастливый экспериментальный отдел:

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

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

// Clean method declaration; compulsive verby name; callers need
// parenthesis despite lack of any arguments.
decimal DetermineImportantInterimValue() {
    return this.DetermineOtherInterimValue() * this.SomeProperty;
}

// Messier property declaration; clean name; clean access syntax
decimal ImportantInterimValue {
    get {
        return this.OtherInterimValue * this.SomeProperty;
    }
}

Я должен объяснить, что я кодировал в Python в течение десятилетия. У меня осталась тенденция тратить дополнительное время на то, чтобы мой код стал проще звонить, чем писать. Я не уверен, что сообщество Python будет рассматривать этот стиль, ориентированный на свойства, как приемлемо "Pythonic", однако:

def determineImportantInterimValue(self):
    "The usual way of doing it."
    return self.determineOtherInterimValue() * self.someAttribute

importantInterimValue = property(
    lambda self => self.otherInterimValue * self.someAttribute, 
    doc = "I'm not sure if this is Pythonic...")
Теги:
idioms

5 ответов

5
Лучший ответ

Важный вопрос здесь выглядит следующим образом:

Какой из них дает более четкий, поддерживаемый код для вас в долгосрочной перспективе?

По моему личному мнению, выделение отдельных вычислений как свойств имеет несколько отличительных преимуществ над одним вызовом монолотного метода:

  • Вы можете видеть вычисления, как они выполняются в отладчике, независимо от метода класса, в котором вы находитесь. Это преимущество производительности при отладке класса.

  • Если вычисления дискретны, свойства будут выполняться очень быстро, что означает (на мой взгляд), они соблюдают правила проектирования свойств. Абсурдно думать, что руководство для дизайна должно рассматриваться как смирительная рубашка. Помните: нет серебряной пули.

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

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

  • Наконец, если окончательный метод, который возвращает ваш окончательный расчет, намного проще поддерживать и понимать, потому что вы можете его прочитать, это совершенно убедительный аргумент сам по себе.

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

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

  • 0
    Я в восторге от поведения отладчика со свойствами, особенно с вашей главной версией: все производные значения могут быть проверены в любое время. Я был шокирован тем, насколько быстрее я решил эту проблему. Это окупилось за 10 и более раз.
3

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

  • 0
    К счастью, все расчеты быстрые. Это все тривиальная логика и арифметика. Просто этого много. Как одно выражение, это был бы кошмар.
3

Лично я предпочел бы, если вы создадите свой общедоступный API как метод вместо свойства. В С# свойства должны быть как можно более быстрыми. Подробнее об этом обсуждении: Свойства vs Методы

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

  • 0
    Я думаю, я понял: частные свойства, чтобы упростить мою отладку и обслуживание, но публичный способ сделать потребление проще и понятнее. Милый.
0

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

  • Что произойдет, если вызывающий абонент не сможет установить один или несколько из семи свойств ввода? Имеет ли смысл все еще смысл? Будет ли выбрано исключение (например, деление на ноль)?

  • В некоторых случаях API может быть менее уязвимым. Если я должен вызвать метод, который принимает семь параметров, я знаю, что я должен предоставить все семь параметров, чтобы получить результат. И если некоторые из параметров являются необязательными, разные перегрузки метода дают понять, какие из них.

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

  • Если у вас есть метод с несколькими параметрами, вы можете более легко получить более надежную проверку. Например, вы можете вызвать ArgumentException, если "параметр A и параметр B равны нулю".

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

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

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

  • 0
    CalculateConsump () не меняет состояние. Вы бы использовали недвижимость в этом случае?
  • 0
    Нет, потому что это все еще действие на объекте. в то время как свойства используются для установки / получения членов объекта и выполнения проверки на них.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню