Итак. Сегодня, так получается, очень много разговоров, что, композиции должны всё "упростить". Особенно в 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); // фильтр на несуществующее
Такой код сработает быстро. Васю это устраивает и он переходит к следующей задаче. Это не плохо. Но можно лучше!
Пайплайны из stage 1
Вряд ли они увидят свет. Но сейчас немного их хайпуют, поэтому покажу. Смотрите, какой наглядной станет наша композиция:
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);
Конечно, преимущество такого подода не слишком очевидно, когда композиция составлена из трёх функций. Но, когда этих функций пять или больше - читабельность кода увеличивается в разы!
Зачем вообще эти композиции функций
Сама суть композиции какая? Несколько чего-то используется вместе. Так и с функциями - несколько функций используются вместе. Вы можете просто заранее сделать композицию и использовать её в разных частях кода в разных файлах. Это крайне удобно.