Immutable Objects Are Not Dumb

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

После нескольких недавних постов об изменении, включая “Объекты должны быть неизменяемыми” и “Как неизменяемый объект может иметь состояние и поведение?”, я был удивлен количеством комментариев, где говорилось, что я плохо понимаю идею. Большинство из этих комментариев утверждали, что неизменяемый объект должен всегда вести себя одинаково — об этом идет речь при изменении. Какая это неизменность, если метод возвращает разные результаты при каждом вызове? Так не ведут себя известные неизменяемые классы. Возьмите, например, String, BigInteger, Locale, URI, URL, Inet4Address, UUID, или оберточные классы для примитивов, такие как Double и Integer. Другие комментарии возражали против самого определения неизменяемого объекта как представителя изменяемой реальной сущности. Как неизменяемый объект может представлять изменяемую сущность? Что это за фигня?

Я очень удивлен. В этом посте я собираюсь прояснить определение неизменяемого объекта. Сначала, вот быстрый ответ. Как неизменяемый объект может представлять изменяемую сущность? Взгляните на неизменяемый класс, File, и его методы, например length() и delete(). Согласно документации Oracle, класс является неизменяемым, и его методы могут возвращать разные значения при каждом вызове. Объект класса File, будучи полностью неизменяемым, представляет изменяемую реальную сущность, файл на диске.

В этом посте я сказал, что “объект является неизменяемым, если его состояние не может быть изменено после создания”. Это определение не мое, оно взято из Java Concurrency in Practice by Goetz et al., раздел 3.4 (кстати, я очень рекомендую его прочитать). Теперь взгляните на этот класс (я использую jcabi-http для чтения и записи через HTTP):

Что представляет собой “состояние” в этом классе? Верно, this.uri - это состояние. Оно уникально идентифицирует каждый объект этого класса и неизменяемо. Таким образом, класс создает только неизменяемые объекты. И каждый объект представляет изменяемую сущность реального мира, веб-страницу с URI.

В этой ситуации нет противоречия. Класс абсолютно неизменяемый, в то время как представляемая им веб-страница изменяема.

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

Вот откуда исходит ложный вывод - объект не является структурой данных. Он является живым организмом, представляющим сущность реального мира внутри среды жизни объекта (компьютерной программы). Он инкапсулирует некоторые данные, которые помогают определить местоположение сущности в реальном мире. Инкапсулированные данные - это координаты представляемой сущности. В случае с String или URL координаты совпадают с самой сущностью, но это только изолированный случай, а не общее правило.

Неизменяемый объект - это не структура данных, которая не изменяется, даже если String, BigInteger или URL выглядят такими. Объект является неизменяемым только в том случае, если он не меняет координаты представляемой сущности реального мира. В классе Page это означает, что объект класса, после создания, никогда не изменит this.uri. Он всегда будет указывать на одну и ту же веб-страницу, вне зависимости от всего остального.

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

Концептуально говоря, неизменяемость означает преданность, вот и все.

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-05 at 21:19

sixnines availability badge   GitHub stars