Защитная копия: должна ли она быть указана в Javadoc? - PullRequest
3 голосов
/ 12 сентября 2009

Насколько я понимаю, геттеры / сеттеры всегда должны делать копии, чтобы защитить данные.

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

b = a.getB();
b.setC(someValue);

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

b = a.getB();
b.setC(someValue);
a.setB(b);

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

Ответы [ 4 ]

4 голосов
/ 12 сентября 2009

В приведенном выше примере есть хороший аргумент, что, поскольку A поддерживает ссылку на B, A должен присматривать за B, а не раздавать его, а манипулировать им от вашего имени. В противном случае вы можете утверждать, что нарушаете инкапсуляцию (поскольку A показывает, что она имеет ссылку на B), и в идеале объекты должны делать что-то для вас , а не экспортировать их содержимое, чтобы вы могли ими манипулировать. 1003 *

Сказав все это, вышесказанное, безусловно, не является необычной практикой и часто прагматичным выбором.

Когда вы выставляете объект с помощью get (), у вас есть три варианта:

  1. выставить фактический объект
  2. сделать защитную копию
  3. выставить объект, который оборачивает оригинал, но запрещает модификацию. например Вы можете обернуть оригинальный объект в ограниченном интерфейсе. См. (Например) Collections.unmodifiableCollection () , которая оборачивает исходную коллекцию (и не копирует ее), но предоставляет интерфейс, который не допускает изменения.

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

4 голосов
/ 12 сентября 2009

Что ж, setC нарушает закон Деметры , поэтому я не думаю, что я бы назвал это лучшей практикой. («Закон» немного силен - например, он обычно не применяется к свободным интерфейсам.)

Тем не менее, получатели должны не всегда делать копии ИМХО. Делать глубокий клон может быть дорого. Есть и другие варианты, такие как неизменяемые объекты.

И, действительно, есть прагматические соображения.

Но я бы ошибался на стороне TMI (слишком много информации) в JavaDoc.

3 голосов
/ 12 сентября 2009

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

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

// Immutable interface definition.
public interface Record {
  String getContent();
}

// Mutable implementation of Record interface.
public class MutableRecord implements Record {
  private final String content;

  public MutableRecord(String content) {
    this.content = content;
  }

  public String getContent() {
    return content;
  }

  public void setContent(String content) {
    this.content = content;
  }
}

// API that only exposes the object via its Record interface.
public class MyApi {
  private final MutableRecord mutableRecord;

  public Record getRecord() {
    return mutableRecord;
  }
}
0 голосов
/ 12 сентября 2009

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

Поэтому, если вы доверяете клиентскому коду, не беспокойтесь об этом .

Это очень академично, и лично у меня никогда не было проблем с этим. Я также немедленно отключаю проверку в FindBugs (Java), например ...

А разве есть проблема, кто вообще читает JavaDoc и тому подобное? Кто-нибудь там?

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