Одна из худших вещей в айти – это паттерны. Когда я слышу “паттерн”, меня трясет. Хочется, чтобы паттернов было как можно меньше, а может быть, однажды мы доживем до счастливого дня, когда в программировании не будет паттернов.

Откуда такой радикализм? Дело в том, что паттерн – это костыль. Помните картинку с жуком, где слева баг, а справа фича? То же самое с паттерном. Это прокол языка, который решили подпереть костылем.

Builder, Visitor, Singleton – все это ошибки в дизайне языка. Чемпионами по их количеству являются C++ и Java. Вряд ли кто-то в здравом уме назовет их хорошо спроектированными языками.

Builder – прямое следствие того, что нет параметров по умолчанию. Visitor – цена за убогую систему типов и ООП в целом. Singleton вообще рак мозга – кто-то решил, что объект нельзя создать дважды, хотя внятного объяснения этому нет.

Если взять любую книгу по Джаве, половина ее будет о том, как делать не надо и какой паттерн брать взамен. Не лучше ли убрать из языка то, чего делать не надо? Я понимаю, легаси и все такое, но все же.

Книги Банды Четырех и талмуды толщиной с руку, где учат паттернам, наводят гнетущее впечатление. Столько труда потрачено на костыли, чтобы обойти ошибки языка!

Паттерн – это о том, как сделать удобней компилятору или IDE. Ни слова о том, чтобы сделать удобно потребителю кода.

Беда паттернов в том, что они плохо влияют на программиста. Он буквально тупеет, не понимая, что по-прежнему пишет плохой код, просто теперь можно сослаться на книги или громкие имена. Мышление паттернами – это натуральная деградация. Есть надежда, если Джава-программист поддерживает форму, ковыряясь с Лиспом или Хаскелем. Но если он видит только паттерны с десяти до шести, это путь к деградации и больше никуда.

Пример из реальной жизни – Amazon AWS SDK для Джавы. Казалось бы: самое популярное облако, самый популярный язык, самые сильные программисты. Почему же они пишут абсолютное говно, которым нельзя пользоваться? Потому что в голове паттерны, а не задача сделать удобно.

Если вы не знаете, все пакеты SDK V1 следуют паттерну POJO. Это когда каждый класс SDK имеет нулевой конструктор и пачку геттеров и сеттеров. Например, какой-нибудь GetObjectRequest создается так:

GetObjectRequest request = new GetObjectRequest();
request.setBucket("some_bucket")
request.setKey("path/to/file.txt")
request.setIfModifiedSince(...)

И таких классов тысячи – в буквальном смысле. Нигде не сказано, какой из сеттеров является обязательным. Можно запросто убрать вызов setBucket, и запрос будет без бакета. При запуске кода вы получите исключение в рантайме.

Паттерн есть? Есть. Удобно? Нет. Вы же не будете гонять код вручную на S3 каждый раз, когда меняете какой-то сеттер. Поэтому все сводится к тому, чтобы поправить код, прогнать CI и задеплоить на тестовое окружение, чтобы дернуть там и убедиться, что работает. Займет час. Умные ребята поднимают для этого Докер с локальным min.io, но так бывает не везде.

Написав тысячи битых классов, инженеры Амазона почесали голову и сели за AWS SDK V2.0. На этот раз с другим паттерном – Builder. Теперь каждый класс создается цепочкой:

GetObjectRequest request = GetObjectRequest.builder()
  .bucket("some_bucket")
  .key("path/to/file.txt")
  .ifModifiedSince(...)
  .build();

Казалось бы, удобно, современно, все как у Джошуа Блоха. Однако я по-прежнему не вижу, какие параметры обязательны. Легко пропустить метод .bucket и получить объект, который не знает, в какой бакет обращаться.

А вот реальный пример с тегом. Тег – это объект, который хранит пару ключ-значение. Других полей у него нет. Казалось бы, сделай конструктор с двумя полями, чтобы было так:

Tag tag = new Tag("release", "test-123.4");

Но нельзя, у нас же паттерн! Нужен билдер и методы для каждого поля. В результате имеем:

Tag tag = Tag.builder().value("42").build();

#object[....s3.model.Tag ... "Tag(Value=42)"]

Смотрю и не понимаю – как так? Почему позволено иметь тег, в котором нет имени поля?! Оно же Null и в будущем свалится с ошибкой. Как вообще можно создать тег без имени и значения? Кто был тот тупица, который все это дизайнил? Кто нанял клоунов в Амазон за 250 тысяч в год, чтобы они писали подобный код?

Они наколбасили сто новых пакетов и классов с новым паттерном. Но как было невозможно пользоваться, так и осталось. Как так получилось?

Понятно, это вопросы в никуда. Программисты пишут SDK по паттерну – как сказал знакомый джавист, “ходят строем”. Главное, чтобы строй шел ровно, а куда он придет – и надо ли было идти – мало кто задается вопросом.

Пожелаю читателю использовать паттерны как можно меньше. Если вы слышите “паттерн” – это тревожный знак.