PassFront
  1. PassFront
  2. База знаний
  3. Принципы S.O.L.I.D

Как SOLID соотносится с функциональным программированием?

Принципы S.O.L.I.D

SOLID сформулирован в терминах классов, но его суть — управление зависимостями и изменениями — в ФП выражается функциями, композицией и типами, нередко проще.

Соответствия

  • SRP — маленькие чистые функции; чистое ядро отделено от эффектов на границе (functional core, imperative shell).
  • OCP — функции высшего порядка: sortBy(compareFn) расширяется новой функцией сравнения без правки sortBy.
  • LSP — подстановка по сигнатуре и законам: любая реализация моноида обязана соблюдать ассоциативность и нейтральный элемент.
  • ISP — функция принимает ровно нужные аргументы, в TS — узкие структурные типы.
  • DIP — зависимость передаётся параметром: частичное применение, замыкания.
/** @typedef {(url: string) => Promise<unknown>} Fetcher */

const makeLoadUser = fetcher => id => fetcher(`/api/users/${id}`);

const loadUser = makeLoadUser(url => fetch(url).then(r => r.json()));
const loadUserInTest = makeLoadUser(async () => ({ id: '1', name: 'Ann' }));

Expression problem

В ООП легко добавить новый вариант (подкласс), но трудно — новую операцию: её надо дописать во все классы. В ФП с алгебраическими типами наоборот. OCP в каждой парадигме «закрыт» по своей оси.

Где ФП даёт больше

Иммутабельность снимает проблемы LSP из-за мутаций в подтипе и упрощает тесты: нет скрытого состояния.

Коротко для собеседования

В ФП те же идеи выражаются без классов: маленькие чистые функции, функции высшего порядка для расширения и передача зависимостей параметром или замыканием. Стоит помнить про expression problem: ООП легко расширять новыми вариантами, а ФП — новыми операциями.

Другие вопросы раздела