The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
Некоторое время назад мы говорили о суффиксах “-ER” в именах объектов и классов. Мы согласились, что они являются злом и должны быть избеганы, если мы хотим, чтобы наш код был по-настоящему объектно-ориентированным, а наши объекты были объектами, а не сборниками процедур. Теперь я готов представить новое зло - суффикс Client
.
Давайте сначала рассмотрим пример. Вот как может выглядеть объект с таким суффиксом (это псевдокодовая версия AmazonS3Client
из AWS Java SDK):
Все «клиенты» выглядят одинаково: они инкапсулируют URL-адрес назначения с определенными учетными данными и предоставляют несколько методов для передачи данных на/от «сервера». Несмотря на то, что этот дизайн выглядит как правильный объект, на самом деле он не следует истинному духу объектно-ориентированного программирования. Вот почему он не так поддерживаем, как должен быть, по двум причинам:
- Он фокусируется на данных. В самой идее отношений клиент-сервер речь идет о передаче данных. Возьмем, к примеру, HTTP RESTful API сервиса AWS S3. На стороне AWS есть сущности: бакеты, объекты, версии, политики контроля доступа и т. д., и сервер преобразует их в данные JSON/XML. Затем данные приходят к нам, и клиент на нашей стороне работает с JSON или XML. Но для нас это всегда остается просто данными, и никогда не становится реальными бакетами, объектами или версиями.
Последствия зависят от ситуации, но вот наиболее вероятные:
Дублирующийся код. Если мы действительно решим остаться объектно-ориентированными, нам придется преобразовывать данные, которые возвращает клиент, в объекты. Скорее всего, это приведет к дублированию кода в нескольких проектах. У меня такое уже было, когда я начал работать с S3 SDK. Очень скоро я понял, что чтобы избежать дублирования, мне лучше создать библиотеку, которая выполняет задачу преобразования данных S3 SDK в объекты: jcabi-s3.
Проблемы с тестированием. Поскольку клиент в большинстве случаев представляет собой довольно большой класс/интерфейс, мокирование его в модульных тестах или создание его двойников/фейков является довольно сложной задачей.
Проблемы статики. Классы клиентов, даже если их методы не являются статическими, выглядят очень похожими на утилитарные классы, которые известны своим противоречием объектно-ориентированному программированию. Проблемы, с которыми мы сталкиваемся с утилитарными классами, практически такие же, как и у “клиентских” классов.
Проблемы расширяемости. Как можно понять, почти невозможно украшать объект клиента, когда у него есть более 160 методов и их количество только растет. Единственный возможный способ добавления новой функциональности - создание новых методов. В конечном итоге мы получаем монструозный класс, который невозможно использовать без изменений.
Какая альтернатива?
Правильным решением было бы заменить “клиентов” на объекты-клиенты, которые представляют сущности серверной стороны, а не весь сервер. Например, с помощью SDK S3 это могут быть Bucket
, Object
, Version
, Policy
и т. д. Каждый из них предоставляет функциональность реальных buckets, objects и versions, которые может предоставить AWS S3.
Конечно, нам понадобится объект высокого уровня, который как-то представляет весь API/сервер, но он должен быть небольшим. Например, в примере SDK S3 его можно назвать Region
, что означает весь регион AWS с бакетами. Затем мы можем получить бакет из него и больше не понадобится регион. Затем, чтобы получить список объектов в бакете, мы просим бакет сделать это за нас. Нет необходимости связываться с целым “объектом сервера” каждый раз, хотя, конечно, технически такое взаимодействие происходит.
В заключение, проблема заключается не только в суффиксе имени, но и в самой идее представления на стороне клиента всего сервера, а не его сущностей. Такая абстракция 1) слишком объемная и 2) очень зависит от данных.
Кстати, ознакомьтесь с некоторыми библиотеками JCabi (Java) для примеров объектно-ориентированных клиентов без “клиентских” объектов: jcabi-github, jcabi-dynamo, jcabi-s3 или jcabi-simpledb.
Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-17 at 16:59