Итак. Сегодня, так получается, очень много разговоров, что, композиции должны всё "упростить". Особенно в JavaScript. Потому что нельзя просто так взять и сделать правильный подход к коду - нужно накинуть туда кучу функционала, чтобы его потом отменить. Но, не про то.
Как это выглядит в нашей "легаси" жизни? Был некоторый разработчик Вася, у которого была задача. Он получал со стороннего API список потенциальных клиентов. После ему нужно выбрать только платежеспособных. После, только мужчин в возрасте до 30. Дальше из имени и фамилии нужно составить целое. А, после, посчитать и сравнить шанс на успех в заключении контракта по чудесной чудо-формуле придуманной бизнес-аналитиками и добавить результат в объект клиента. Например. И он начинает и получает что-то такое:
const clients = await externalApiCall();
const result = clients
.filter(client => выбирает платежеспособных)
.filter(client => выбирает мужчин младше 30)
.map(client => прибавляет имя к фамилии)
.map(client => высчитывает всё по чудо формуле)
.filter(client => отбрасывает всех, кто не прошёл по чудо-формуле);
Всё хорошо ровно до реальных данных. Как только Вася запускает свой код на реальных данных - ему приходится ждать минуту. И он задумывается что не так. Очень быстро до него доходит, что вся проблема в том, что он 5 раз перебирает массивы. И что он делает? Композицию!
function filterClients(val) {
// только платежеспособные мужчины до 30
}
function fullName(val) {
// прибавляем имя к фамилии
}
function chudoFormula(val) {
// считаем по чудо формуле и отбрасываем что не нужно
}
const clients = await externalApiCall();
const getAllValidClientsComposition =
(client) => chudoFormula(
fullName(
filterClients(client);
);
);
const result = clients
.map(getAllValidClientsComposition)
.filter(client => !!client); // фильтр на несуществующее
Такой код сработает быстро. Васю это устраивает и он переходит к следующей задаче. Это не плохо. Но можно лучше!
Я говорю об этих изменениях
Вряд ли они увидят свет. Но сейчас немного их хайпуют, поэтому покажу. Смотрите, какой наглядной станет наша композиция:
const getAllValidClientsComposition =
filterClients(client)
|> fullName
|> chudoFormula;
Теперь всё читается сверху-вниз, как и должно. Только когда это будет - наверное - никогда.
Но вообще, проблема композиций решилась, когда к нам пришли промисы. И нам не нужно иметь промис для начала. Смотрите, как та же композиция сделается промисами:
const getAllValidClientsComposition = Promise.resolve(clients)
.then(filterClients)
.then(fullName)
.then(chudoFormula);
const compositionArray = clients.map(client => getAllValidClientsComposition(client));
const result = await Promise.all(compositionArray);
Конечно, преимущество такого подода не слишком очевидно, когда композиция составлена из трёх функций. Но, когда этих функций пять или больше - читабельность кода увеличивается в разы!
В чём же суть композиции? Несколько чего-то используется вместе.
Так и с функциями - несколько функций используются вместе. Вы можете просто заранее сделать композицию и использовать её в разных частях кода в разных файлах. Это крайне удобно.