Красная или синяя?

 Красная или синяя?

Aleksey

Пост для канала "Эргономичный код"

Меня тут осенило.
Возьмём вот такой кусочек кода на кложуре (чисто функциональном языке):

Функциональный стиль

Здесь переменная users-service биндится на какое-то значение возвращаемое функцией new-users-service, которая на вход получает некий conn, а потом вызываюется функция reset-password из неймспейса my-app.users с параметрами users-service и user.

А потом сделаем несколько трансформаций.
Вжух, переносим скобку, меняем def на val и добавляем =:

Элегантные штаны превращаются...

Вжух, меняем кебаб на камел кейс:

преваращаются...

Вжух, меняем неймспейс на объект:

превращаются...

И вишенка, на торте, чтобы по СОЛИДнее было:

в кровавый энтерпрайз

Знакомый код?
Если у вас бэк на спринге, то готов поставить тыщу, что у вас где-то есть com.my_company.my_app.services.UserService:)

Пока этот пост отлёживался случайно наткнулся на очередное подтверждение повсеместности такого подхода:
Случай из жизни
Хотя тут конечно не самый запущенный случай - как минимум пакет сервисов бьётся по компонентам (service.client), а то и ваще вся система (user.service).
С другой стороны помесь клиентов и юзеров слегка мозг выносит.


При том

OO makes code understandable by encapsulating moving parts.
FP makes code understandable by minimizing moving parts.
Объектно-ориентированный подход делает код понимаемым (прим. пер.: поддерживаемым) по средствам инкапсуляции движущихся частей (прим. пер.: изменяемого состояния).
Функциональное программирование делает код поддерживаемым по средствам минимизации изменяемого состояния.
https://twitter.com/mfeathers/status/29581296216?lang=en,

Это цитата Майкла Фэзерса, автора Working Effectively with Legacy Code и чувака придумавшего акроним SOLID:)


А приведённый выше стиль не является ОО, т.к. не инкапсулирует "двигающиеся части" (состояние, структуру User в данном случае).
ООПный код был бы примерно такой:

ОО-стиль
И на самом деле это не наша вина - Тръу ООП нарушает SRP (в любой интерпретации), loose coupling/high cohesion и вообще заточено под масштабирование кол-ва типов данных в системе, а не фич реализуемых на основе этих типов.
А софт, как привило, всё таки обрастает новыми фичами поверх старых данных, а не новыми данными для старых фич.
Поэтому у девеолперов был только один разумный выбор, чтобы хоть как-то выжить - дефакто отказаться от ООП.
Справедливости ради можно масштабироваться ещё наследованием.
Но, во-первых, оно вроде уже повсеместно признано не удачной затеей.
А, во-вторых, не понятно кто от кого должен наследоваться в случае RelationalUser (работа с БД) и JsonUser ((де)сериализация Json).
Что будет если пойти этим путём можно посмотреть у Егора Бугаенко.
Но вместе с водой выкинули и младенца - ООД.


Поэтому единственный способ сделать такой код поддерживамым - это ФП (а дизайн - ООД).
И положа руку на сердце, ваши сервисы - это неймспейсы чистых функций, или пакеты процедур с побочками?
Мои всё ещё как правило - пакеты процедур. Где-то гайдлайн такой, где-то инфраструктуры нет, а где-то это тупо быстрее и привычнее.

Но в последнее время проекты с удачно сложившимися звёздами, мне удаётся сделать в ФП-стиле. И оно того стоит.


А какую таблетку выбираете вы?:)