Является ли антишаблон всегда использовать методы get и set для доступа к собственным полям-членам класса?[дубликат]

StackOverflow https://stackoverflow.com/questions/1095034

  •  11-09-2019
  •  | 
  •  

Вопрос

На этот вопрос уже есть ответ здесь:

В классах Java считается хорошей или плохой практикой доступ к полям-членам с помощью их методов получения и установки?

например, что лучше:

public Order {
    private Agreement agreement;

    public Agreement getAgreement() {
    return agreement;
    } 

    public void process() {
       //should I use:
       getAgreement().doSomething();
       //Or:
       agreement.doSomething();
    }
}

В целом я считаю, что прямой доступ к полю лучше всего из-за принципа KISS, а также кто-то может позже переопределить метод get с непредсказуемыми результатами.

Однако мои коллеги утверждают, что лучше сохранять уровень абстракции.Есть ли консенсус по этому поводу?

Это было полезно?

Решение

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

Другие советы

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

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

Поэтому, если вы не абсолютно уверены, что существует только один способ доступа к этому полю и что он на 100% прямой, вероятно, лучше разделить поиск и изменение значений, чтобы в какой-то момент в будущем вы могли избавить себя от трудностей с перезаписью.

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

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

Мне кажется, что некоторые люди интерпретируют этот вопрос как вопрос о геттерах и сеттерах, которые используются извне;моя интерпретация вопроса Пабложима заключалась в том, что речь идет об использовании их внутри класса, а не о прямом доступе класса к своим полям.(которые являются частными.)

В этом смысле я на стороне Джерико и Патроса;используйте прямой доступ изнутри класса, если нет причин не делать этого.

Сохранение уровня абстракции — это хорошо в Java.

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

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

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

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

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

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

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

Однако все зависит от того, как вы используете свои геттеры и сеттеры.

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

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

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

class EXAMPLE
feature
  variable: INTEGER
  variable_function: INTEGER
    do
      result := 4
    end
  variable_two: INTEGER assign variable_assign
  variable_assign (in: INTEGER)
    do
      variable_two := in
    end  
end

feature
test
local
  test: EXAMPLE
  value: INTEGER
do
  create test
  value := test.variable  -- Valid
  value := test.variable_function  -- Valid and same even though it's a function
  test.variable := value -- Invalid
  test.variable_two := value -- Valid, an explicit setter is defined
end

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

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

Если вы пишете свой код для доступа к переменным без метода получения, подумайте о том, чтобы сделать функцию получения «окончательной».Таким образом, никто не попытается переопределить ваш код и рвать на себе волосы, задаваясь вопросом, почему он не работает.(Обратите внимание, что прокси-серверы Spring и Hibernate могут сделать это плохой идеей.)

Чтобы это был анти-паттерн, он должен быть явно вредным.Я не понимаю, какой вред может быть от определения геттеров и сеттеров.В лучшем случае это пустая трата времени (и набора текста), что делает его бессмысленным, но не антипаттерном.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top