Что случилось с возвратом?
В компании я работаю над документом, описывающим хорошие практики, которые мы должны придерживаться на Java. Один из них - избегать методов, возвращающих this
, например, например:
class Properties {
public Properties add(String k, String v) {
//store (k,v) somewhere
return this;
}
}
У меня был бы такой класс, чтобы я мог писать:
properties.add("name", "john").add("role","swd"). ...
Я видел такую идиому много раз, как в StringBuilder
, и не нашел в ней ничего плохого.
Их аргументация такова:
... может быть источником проблем синхронизации или неудачными ожиданиями относительно состояний целевых объектов.
Я не могу представить себе ситуацию, когда это может быть правдой, может ли кто-нибудь из вас дать мне пример?
РЕДАКТИРОВАТЬ В документе ничего не говорится о изменчивости, поэтому я не вижу разницы между цепочкой вызовов и выполнением:
properties.add("name", "john");
properties.add("role", "swd");
Я попытаюсь связаться с создателями, но я хотел сделать это с загруженным оружием, вот почему я разместил вопрос.
SOLVED. Мне нужно поговорить с одним из авторов, его первоначальное намерение состояло в том, чтобы, по-видимому, не выпускать объекты, которые еще не готовы, как в шаблоне Builder, и объяснили, что если переключатель контекста происходит между вызовами, объект может находиться в недопустимом состоянии. Я утверждал, что это не имеет никакого отношения к возврату this
, поскольку вы могли бы совершить ту же ошибку, купив вызов методов один за другим и больше связавшись с синхронизацией процесса сборки должным образом. Он признал, что документ может быть более явным и вскоре пересмотрит его. Победа моя/наша!
Ответы
Ответ 1
Единственная серьезная основа для практики - избегать изменчивых объектов; критика, что она "запутывает" и ведет к "неудачным ожиданиям", довольно слаба. Нужно никогда использовать объект, не ознакомившись с его семантикой, а принудительные ограничения на API просто для того, чтобы обслуживать тех, кто отказывается от чтения Javadoc, не является хорошей практикой вообще -— особенно потому, что, как вы отмечаете, возвращение this
для создания свободного API-интерфейса является одним из стандартных подходов в Java и действительно очень приятным.
Ответ 2
Я предполагаю, что они против изменчивого состояния (и часто это справедливо). Если вы не создаете плавные интерфейсы, возвращающие this
, а вернете новый неизменяемый экземпляр объекта с измененным состоянием, вы можете избежать проблем с синхронизацией или не иметь "failed expectations about the states of target objects"
. Это может объяснить их требование.
Ответ 3
Я думаю, что иногда этот подход может быть действительно полезен, например, в шаблоне "builder".
Я могу сказать, что в моей организации такие вещи контролируются правилами сонара, и у нас нет такого правила.
Другая догадка заключается в том, что, возможно, проект был построен поверх существующей кодовой базы, и это своего рода ограничение устаревания.
Поэтому единственное, что я могу предложить здесь, - поговорить с людьми, которые написали этот документ:)
Надеюсь, что это поможет
Ответ 4
Я думаю, что вполне приемлемо использовать этот шаблон в некоторых ситуациях.
Например, как разработчик Swing, я часто использую GridBagLayout для своих сильных сторон и гибкости, но любой, кто когда-либо использовал его (вместе с ним причастный к преступности GridBagConstraints), знает, что он может быть довольно многословным и не очень читаемым.
Общим обходным решением, которое я видел в Интернете (и тем, которое я использую), является подкласс GridBagConstraints (GBConstraints), который имеет средство настройки для каждого другого свойства, и каждый установщик возвращает это. Это позволяет разработчику связывать различные свойства по мере необходимости.
Результирующий код составляет около 1/4 размера и гораздо читабельнее/поддерживается даже для случайного разработчика, который может быть не знаком с использованием GridBagConstaints.