Языки
|
Императивные
|
Функциональные
|
Динамические
|
JavaScript, Ruby,
Python, PHP
|
Clojure,
Erlang, Scheme
|
Статические
|
Java, C#, C++,
Go
|
Scala, Haskell,
OCaml
|
суббота, 27 сентября 2014 г.
Простая таблица языков программирования
Мне нравятся языки программирования, которые позволяют как можно больше ошибок отсеять на этапе компиляции. Статические языки в этом плане лучше динамических, а функциональные ‒ лучше императивных (функциональный стиль более строгий). Таким образом, самые лучшие языки ‒ это языки статические и функциональные:
понедельник, 22 сентября 2014 г.
Декомпозиция в ФП vs декомпозиция в императивном программировании
Любой программист разбивает программу на модули, модули на файлы, файлы на классы, классы на функции (если язык не объектно-ориентированный, то файлы сразу на функции). В среде императивных программистов есть устоявшийся набор правил, по которому эту декомпозицию надо делать. В основном, люди отталкиваются от принципов SOLID, KISS, DRY, Tell Don't Ask, закона Деметры, шаблонов проектирования, правил вроде "функция должна умещаться в экран" и т.п.
Забавно, но нигде из вышеупомянутых правил вообще нет никакого упоминания о side-эффектах. Схематично, программа, написанная в императивном стиле, выглядит примерно вот так:
Голубые прямоугольники ‒ это функции/классы, красные ‒ это строки с side-эффектами, желтые ‒ строки без side-эффектов.
Всё вроде бы хорошо, однако до тех пор, пока вам не приходится эти функции компоновать, т.е. объединять вызовы функций в более высокоуровневые функции, чтобы получилась программа. Часто бывает, что одна и та же функция может быть вызвана более 1 раза в проекте.
Почему трудно компоновать функции с side-эффектами? Потому что объединяя несколько функций в одну, вам нужно держать в голове все side-эффекты, которые каждая из функций содержит, и всё время анализировать: "устраивает ли меня, что серия вызовов вот этих функций кроме того что делает основную работу, ещё имеет следующий набор side-эффектов?"
Очень часто вот этот итоговый набор side-эффектов нежелателен. К примеру, функция f осуществляет запуск ракеты в космос и возвращает массу ракеты. Если вам нужно в проекте в 10 местах узнать массу ракеты, но запуск ракеты вам не нужен, то функция f для вас бесполезна! Вы её не сможете переиспользовать! Вы ведь не хотите, чтобы ракета запустилась тогда, когда пользователь запустил вашу программу, просто чтобы посмотреть характеристики этой ракеты?!
Что нужно сделать с функцией f(), чтобы её можно было использовать не только в случае реальной необходимости запуска ракеты, но и в других местах? Нужно выделить часть, отвечающую за запуск (side-эффект), в отдельную функцию, а часть, отвечающую за расчет массы ракеты, ‒ в другую функцию. Таким образом, вы отделяете чистые функции от функций с side-эффектами:
Вот эта желтая часть должна содержать большую часть вашей бизнес-логики и составляет где-то 70-80 процентов от всего проекта.
Что самое интересное, никто не мешает вам совмещать вот такое разделение с использованием вышеперечисленных привычных вам правил и законов. Хотите применять ООП, наследование и паттерны GoF (если вам так нравится) ‒ применяйте! Только отделяйте side-эффекты от чистых функций! Несколько паттернов, конечно, придется немного подкорректировать. Вот здесь описан, например, чистофункциональный визитор.
Что самое интересное, никто не мешает вам совмещать вот такое разделение с использованием вышеперечисленных привычных вам правил и законов. Хотите применять ООП, наследование и паттерны GoF (если вам так нравится) ‒ применяйте! Только отделяйте side-эффекты от чистых функций! Несколько паттернов, конечно, придется немного подкорректировать. Вот здесь описан, например, чистофункциональный визитор.
Выделение чистых функций, конечно, даётся не бесплатно. Но время, потраченное, на такую правильную декомпозицию, с лихвой окупается, когда дело доходит до компоновки и переиспользования функций! Чистые функции можно переиспользовать как угодно и сколько угодно, не задумываясь! Вы смотрите только на входные аргументы и на результат функции. Кроме того, чистые функции очень легко тестировать (любители TDD оценят).
Подписаться на:
Сообщения (Atom)