Как 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: ООП легко расширять новыми вариантами, а ФП — новыми операциями.