TGViewer
Cross Join - канал о разработке Cross Join - канал о разработке @crossjoin · 3.82K subscribers
Post #424 3.84K
В одном подкасте слышал такое мнение, что мол любой http-эндпоинт - это лишь функция, которая условно принимает на вход заголовки и json, а выдаёт другие заголовки и json. Поэтому функциональное программирование (речь была про Clojure) максимально подходит для таких задач.

А я вот не понимаю, почему все так молятся на функциональное программирование и чистые функции.

Блин, http-запрос обычно еще порождает запись в базу. А иногда несколько чтений и записей в базу/редис/кафку, там чистыми функциями и не пахло. Например, перевод денег с одного счета на другой с проверкой на наличие средств. Полно побочных эффектов. Да, я знаю про монады и прочие обёртки для эффектов, но по факту это то же самое, что и обычный императивный код, только сложнее читать.

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

А еще много раз видел, даже без Кложи, как вместо одного тупого цикла с двумя понятными ифами строят целый пайплайн из map и прочих функций



// Допустим, у нас есть массив заказов и надо посчитать сумму всех
// валидных заказов со скидкой больше 20%

// Императивный подход - простой и понятный:
function calculateTotalSimple(orders: Order[]): number {
let total = 0;

for (const order of orders) {
if (order.status === 'valid' && order.discount > 20) {
total += order.amount;
}
}

return total;
}

// "Функциональный" подход - попытка сделать "красиво":
const calculateTotal = (orders: Order[]): number =>
orders
.filter(order => order.status === 'valid')
.filter(({discount}) => discount > 20)
.map(({amount}) => amount)
.reduce((acc, amount) => acc + amount, 0);

// Или еще "круче":
const isValid = (order: Order): boolean => order.status === 'valid';
const hasHighDiscount = (order: Order): boolean => order.discount > 20;
const getAmount = (order: Order): number => order.amount;
const sum = (a: number, b: number): number => a + b;

const calculateTotalFP = (orders: Order[]): number =>
pipe(
orders,
filter(isValid),
filter(hasHighDiscount),
map(getAmount),
reduce(sum, 0)
);
  • 👍 36
  • 👎 6
  • 💊 5
  • ❤ 2
  • 🔥 1
More from @crossjoin
  1. Sep 29, 2026😱 Отправили свое резюме на 129 вакансий на хх, а в ответ тишина .. Думаете, что дело в ры…
  2. Sep 28, 2026Слышал недавно в каком-то подкасте мысль, что Haskell плохо подходит для вайбкодинга прост…
  3. Sep 26, 2026Антон Жиянов написал мини-книгу по Go-concurrency. Это что-то вроде плотного конспекта с и…
  4. Sep 22, 2026photo post
  5. Sep 14, 2026Поможем Руслану собрать фидбек. Проект некоммерческий 👆
  6. Sep 14, 2026AGBX (Agent Box) — небольшой open-source CLI для запуска Claude Code и Codex в изолированн…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →