The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
Вот новая идея, которую я открыл всего несколько дней назад, работая с Codexia, веб-приложением на Ruby. Мне нужно было получить строки данных из PostgreSQL и вернуть объекты клиенту. Это всегда была проблема для меня, как сделать это без превращения объектов в DTO. Вот решение, которое я нашел и назвал: Veil Objects.
Допустим, я получаю список проектов из PostgreSQL:
Метод exec()
на @pgsql
(я использую pgtk gem) возвращает массив Hashes, которые выглядят так, если мы преобразуем их в JSON:
Было бы замечательно, если бы метод fetch()
возвращал массив объектов, а не массив хешей. Таким образом, мой класс Project
выглядит следующим образом:
Он идеально подходит для манипуляций с одним проектом:
Два SQL-запроса здесь - это не проблема. Однако, если я преобразую список Хэшей в Проекты таким образом, у меня возникнут серьезные проблемы с производительностью.
Вот что убьет меня в плане производительности:
Этот код будет генерировать слишком много избыточных SQL-запросов. Мы будем делать поездки в PostgreSQL, чтобы получить данные, которые у нас были несколько миллисекунд назад, когда мы выполняли SELECT * FROM project
.
Самое простое и очевидное решение, которое многие из вас, возможно, предложат, - это инкапсулировать полученный хэш в объект Project
. Другими словами, превратить Project
в DTO, хранителя данных. Что ж, в этом случае нам даже не понадобится объект, а можно просто вернуть хэш с данными. Но так мы не хотим проектировать наше объектно-ориентированное программное обеспечение. Мы хотим иметь дело с объектами, а не с структурами данных. И в то же время мы не хотим, чтобы объекты были настолько глупыми, чтобы возвращаться к базе данных за теми же данными, которые у нас были секунду назад. Вот решение, которое я предлагаю:
Этот новый объект Veil
из гема veils является декоратором Project
. Он ведет себя как Project
, но некоторые его методы переопределены: name()
и author()
. Когда они вызываются, вызовы не достигают инкапсулированного Project
. Вместо этого возвращаются данные, хранящиеся в Veil
.
Он называется “вуаль”, потому что он действует так же: предустановленные данные возвращаются только до тех пор, пока не будет вызван какой-то другой метод, который не был предустановлен. Если это происходит, вуаль пронзается и объект Veil
становится полностью прозрачным, пропуская все вызовы методов.
Таким образом, эффективность DTO сочетается с элегантностью ООП.
Я использую эти новые объекты-вуали в yegor256/codexia, чтобы вы могли видеть, как они работают.
P.S. Я также создаю класс Unpiercable
, который ведет себя точно так же, как Veil
, но его нельзя пронзить. Это очень полезно, когда вы не ожидаете, что будут происходить взаимодействия, изменяющие данные с объектом, и просто хотите, чтобы некоторые из его методов были предварительно вычислены.
P.P.S. Это реализация для Kotlin.
Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-22 at 10:07