Object-Oriented Declarative Input/Output in Cactoos

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

Cactoos - это библиотека объектно-ориентированных примитивов Java, над которой мы начали работать всего несколько недель назад мы. Нашей целью было предложить чистую и более декларативную альтернативу JDK, Guava, Apache Commons и другим. Вместо вызова статических процедур мы хотим использовать объекты так, как они должны использоваться. Давайте посмотрим, как работает ввод/вывод в чисто объектно-ориентированном стиле.

Отказ от ответственности: Версия, которую я использую на момент написания, - 0.9. Поздние версии могут иметь другие названия классов и совершенно другой дизайн.

Допустим, вы хотите прочитать файл. Вот как вы сделали бы это с помощью статического метода readAllBytes() из утилитарного класса Files в JDK7:

Этот код очень императивный - он считывает содержимое файла прямо здесь и сейчас, помещая его в массив.

Вот как это делается с помощью Cactoos:

Обратите внимание - пока нет вызовов методов. Просто три конструктора трех классов, которые составляют больший объект. Объект source имеет тип Bytes и представляет содержимое файла. Чтобы получить это содержимое, мы вызываем его метод asBytes().

Это момент, когда касается файловая система. Этот подход, как вы видите, абсолютно декларативный и благодаря этому имеет все преимущества объектно-ориентированного программирования.

Вот еще один пример. Предположим, вы хотите записать некоторый текст в файл. Вот как это делается в Cactoos. Сначала вам нужно Input:

Затем вам понадобится Output:

Теперь мы хотим скопировать ввод в вывод. В чистом ООП нет операции “копирования”. Более того, здесь вообще не должно быть операций. Просто объекты. У нас есть класс с именем TeeInput, который является Input и копирует все, что вы читаете из него в Output, подобно тому, что делает TeeInputStream из Apache Commons, но инкапсулированно. Так что мы не копируем, а создаем Input, который будет копировать, если вы его касаетесь.

Теперь нам нужно “касаться” его. И мы должны коснуться каждого отдельного байта, чтобы убедиться, что они все скопированы. Если мы просто read() первый байт, то будет скопирован только один байт в файл. Лучший способ коснуться всех байтов - это вычислить размер объекта tee, перебирая каждый байт. У нас есть объект для этого, называемый LengthOfInput. Он инкапсулирует Input и ведет себя как его длина в байтах.

Затем мы извлекаем значение из него, и происходит операция записи файла.

Таким образом, весь процесс записи строки в файл будет выглядеть следующим образом:

Вот его процедурная альтернатива из JDK7:

“Почему объектно-ориентированный подход лучше, несмотря на то, что он длиннее?” - я слышу, как ты спрашиваешь. Потому что он идеально разъединяет концепции, в то время как процедурный подход их объединяет.

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

Работает хорошо, но что произойдет, когда вы решите расширить его, чтобы также записывать в OutputStream? Как вы измените этот класс? Каким он станет некрасивым после этого? Это происходит потому, что дизайн не является объектно-ориентированным.

Вот как можно сделать ту же самую конструкцию, в объектно-ориентированном стиле, с использованием Cactoos:

Что мы делаем с этим дизайном, если мы хотим, чтобы OutputStream был принят? Мы просто добавляем один дополнительный конструктор:

Готово. Это настолько просто и элегантно.

Все потому, что концепции полностью разделены, а функциональность инкапсулирована. В процедурном примере поведение объекта находится вне него, в методе encode(). Сам файл не знает, как писать, это знает внешняя процедура Files.write().

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

Теперь вы видите прекрасное в объектно-ориентированном программировании?

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-17 at 14:30

sixnines availability badge   GitHub stars