Я не думаю, що на це є відповідь мови-агностика, оскільки те, що є "властивістю", - це питання, пов'язане з мовою, і що очікує, хто викликає "властивість", - це також питання, пов'язане з мовою. Я думаю, що найбільш плідно задуматися над цим - подумати про те, як це виглядає з точки зору абонента.
У C # властивості відрізняються тим, що вони (умовно) з великої літери (як методи), але відсутні у дужках (як змінні загальнодоступних екземплярів). Якщо ви бачите наступний код, відсутні документи, що ви очікуєте?
var reciprocalHeading = myHeading.Reciprocal;
Як родич-початківець C #, але той, хто читав Правила користування майном Microsoft , я б сподівався Reciprocal
, серед іншого:
- бути логічним членом даних
Heading
класу
- недорого зателефонувати, таким чином, щоб мені не потрібно кешувати значення
- відсутність помітних побічних ефектів
- дають той же результат, якщо дзвонити два рази поспіль
- (можливо) запропонувати
ReciprocalChanged
подію
З цих припущень (3) і (4), ймовірно, є правильними (якщо припустити Heading
, що це непорушний тип значення, як у відповіді Евана ), (1) є дискусійним, (2) невідомим, але також дискусійним, і (5) навряд чи мають смисловий сенс (хоча все, що має заголовок, може мати HeadingChanged
подію). Це підказує мені, що в API C # "отримати або обчислити зворотній зв'язок" не слід реалізовувати як властивість, але особливо, якщо обчислення дешеве і Heading
незмінне, це прикордонний випадок.
(Однак зауважте, що жодна з цих проблем не має нічого спільного з тим, чи викликає властивість навіть новий екземпляр (2). Створення об'єктів у CLR, саме по собі, є досить дешевим.)
У Java властивості - це метод, який називає умову. Якщо я бачу
Heading reciprocalHeading = myHeading.getReciprocal();
мої очікування схожі з вищезазначеними (якщо менш чітко викладено): я очікую, що дзвінок буде дешевим, безсильним і не має побічних ефектів. Однак поза рамками JavaBeans поняття "властивість" не настільки важливе для Яви, і, особливо, якщо розглядати незмінне властивість без відповідних setReciprocal()
, getXXX()
конвенція зараз дещо старомодна. Від другого видання « Ефективна Java» (якому вже більше восьми років):
Методи, що повертають нефункцію boolean
чи атрибут об’єкта, на який вони викликаються, зазвичай називають іменником, фразою іменника або словосполученням, що починається з дієслова get
…. Існує вокальний контингент, який стверджує, що лише третя форма (починаючи з get
) є прийнятною, але для цього твердження є мало підстав. Перші дві форми зазвичай призводять до більш читаного коду ... (стор. 239)
Тоді я б сподівався, що в сучасній більш плавній API
Heading reciprocalHeading = myHeading.reciprocal();
- що ще раз припускає, що виклик дешевий, безсильний і не має побічних ефектів, але нічого не скаже про те, чи виконується новий обчислення чи створюється новий об’єкт. Це добре; в хорошому API, мені не байдуже.
У Рубі немає такого поняття як власність. Є "атрибути", але якщо я бачу
reciprocalHeading = my_heading.reciprocal
У мене немає безпосереднього способу дізнатися, чи я отримую доступ до змінної примірника @reciprocal
за допомогою attr_reader
простого або методу accessor або я викликаю метод, який виконує дорогий обчислення. Той факт, що назва методу є простим іменником, хоча, замість того, щоб сказати calcReciprocal
, знову ж таки говорить про те, що виклик є принаймні дешевим і, ймовірно, не має побічних ефектів.
У Scala умовою називання є те, що методи з побічними ефектами мають круглі дужки, а методи без них не мають, але
val reciprocal = heading.reciprocal
може бути будь-який із:
// immutable public value initialized at creation time
val reciprocal: Heading = …
// immutable public value initialized on first use
lazy val reciprocal: Heading = …
// public method, probably recalculating on each invocation
def reciprocal: Heading = …
// as above, with parentheses that, by convention, the caller
// should only omit if they know the method has no side effects
def reciprocal(): Heading = …
(Зверніть увагу, що Scala допускає різні речі, які, тим не менше, не відволікає керівництво по стилю . Це одне з моїх головних роздратовань щодо Scala.)
Відсутність дужок говорить про те, що виклик не має побічних ефектів; назва, знову ж таки, говорить про те, що дзвінок повинен бути відносно дешевим. Крім того, мені байдуже, як це отримує для мене цінність.
Якщо коротко: знайте мову, якою ви користуєтесь, і знайте, які очікування принесуть іншим програмістам до вашого API. Все інше - деталь реалізації.
Heading
непорушний тип іreciprocal
повертати новеHeading
- це «хороша практика». (із застереженням у двох закликахreciprocal
повернути "те саме", тобто вони повинні пройти тест на рівність.)