Парадигма функционального и императивного методов программирования

Несколько определений о функциональном программировании.

Это не про функции!

В программировании есть два больших подхода — императивное и функциональное. Они существенно отличаются логикой работы, ещё и создают путаницу в названиях. Сейчас объясним.
Нет. Функциональное — это не про функции. Функции есть почти в любых языках программирования: и в функциональных, и в императивных. Отличие функционального программирования от императивного — в общем подходе.

Метафора: инструкция или книга правил.

Представьте, что вы открываете кафе-столовую. Сейчас у вас там два типа сотрудников: повара и администраторы.

Для поваров вы пишете чёткие пошаговые инструкции для каждого блюда. Например:

1.    Налить воды в кастрюлю

2.    Поставить кастрюлю с водой на огонь

3.    Добавить в кастрюлю с водой столько-то соли

4.    Если нужно приготовить 10 порций, взять одну свёклу. Если нужно приготовить 20 порций, взять две свёклы.

5.    Почистить всю свёклу, которую вы взяли

6.    … Повар должен следовать этим инструкциям ровно в той последовательности, в которой вы их написали. Нельзя сначала почистить свёклу, а потом взять её. Нельзя посолить кастрюлю, в которой нет воды. Порядок действий важен и определяется вами. Это пример императивного программирования. Вы повелеваете исполнителем. Можно сказать, что исполнители выполняют ваши задания.

Для администратора вы пишете не инструкцию, а как бы книгу правил:

• У нас нельзя со своим. Если гости пришли со своим, то сделать им замечание такое-то.
• В зале должно быть чисто. Если в зале грязно, вызвать уборщика.
• Если образовалась очередь, открыть дополнительную кассу.
Это тоже команды, но исполнять их администратор будет не в этой последовательности, а в любой на своё усмотрение. Можно сказать, что задача этого человека — исполнять функции администратора, и мы описали правила, по которым эти функции исполнять. Это пример функционального программирования.

Получается, что смысл функционального программирования в том, чтобы описать не сами чёткие шаги к цели, а правила, по которым компилятор сам должен дойти до нужного результата.
Программисты, не бомбите.
Конечно же, это упрощено для понимания. Вы сами попробуйте это нормально объяснить (можно прямо в комментах).

Как же без них?

Абстракция.

Представьте, что вы попросили нескольких человек описать в общих чертах, что такое телефон и как им пользоваться: пусть это будут бабушка, мама и подруга. Бабушка вспомнит про дисковые телефоны и трубки с витым проводом. Мама расскажет про радиотелефоны, у которых есть база и есть трубка, с которой можно ходить по всей квартире, а подруга начнёт описывать мобильник.

Несмотря на то что рассказы будут сильно отличаться между собой, у них будет несколько общих моментов про телефон:
• у телефона есть трубка;
• в трубку мы говорим, из трубки — слушаем;
• можно набрать номер нужного человека и позвонить ему;
• если вам позвонят по телефону, вы это услышите и примете звонок.

Получается, что если представить абстрактный телефон, то получится такое устройство с динамиком, микрофоном и средством набора номера.
Это и есть абстракция: когда мы описываем только самые существенные детали, которые важны для задачи.

В нашем случае задача такая — понять, что такое телефон и как им пользоваться. Поэтому микрофон и динамик для этой задачи важен, а способ связи телефона с сетью — нет. Устройство набора номера важно, а то, какая мелодия играет при вызове — нет.

Абстракция — это когда мы сосредотачиваемся только на существенных для задачи деталях и игнорируем всё остальное. В ООП абстракция означает, что для каждого объекта мы задаём минимальное количество методов, полей и описаний, которые позволят нам решить задачу. Чем меньше характеристик, тем лучше абстракция, но ключевые характеристики убирать нельзя.
Чтобы работать с абстракциями, используют интерфейсы.

Интерфейс.

Итак, у нас есть некое устройство с трубкой, микрофоном, динамиком и средством набора номера. Но если вы вспомните рассказы мамы, бабушки и подруги, то обнаружите вот что:
• в микрофон говорят, чтобы собеседник мог вас услышать;
• чтобы слышать самому, ухо прикладывают к динамику;
• чтобы набрать номер, нужно с помощью номеронабирателя вызвать нужную последовательность цифр;
• когда идёт вызов, слышны гудки в динамике.

Всё это - интерфейсы.

Они позволяют работать с объектом, не вникая в то, как он устроен внутри. Если вы умеете работать с интерфейсом номеронабирателя, то вам всё равно, нужно ли крутить диск, нажимать физические кнопки на радио трубке или давить пальцем на сенсорный экран.

Такой интерфейс как бы говорит нам - я передам в телефон любые цифры, какие захочешь. Как я это сделаю внутри и как они будут обработаны — неважно, просто набери номер, а дальше телефон сам разберётся.
Интерфейсы — это действия над объектом, доступные другим объектам (поэтому они называются публичными).

Есть ещё инкапсулированные, то есть внутренние методы. Например, у микрофона есть публичный метод «Слушать голос», и есть внутренний метод «Преобразовать голос в электрические сигналы». С его помощью он взаимодействует с другими частями нашего абстрактного телефона при поддержке средств инкапсуляции.

Сложная терминология.

Строго говоря, интерфейсы — это не действия, а методы.

Сейчас объясним.
В программировании есть операции — это простейшие действия, например, скопировать значение из одной переменной в другую.
Из простых действий составляются функции — это когда несколько операций «склеиваются» в нечто единое. Мы даём этой склейке название и получаем функцию. Например, может быть функция «проверить правильность электронного адреса», которая состоит из нескольких десятков простых операций.

На языке ООП функции, привязанные к объектам, называются методами. Просто такой термин. По сути, это функции, то есть склеенные вместе операции.
Итого: метод — это набор простых действий, которые склеили в единое целое и засунули в объект.

Для чего это всё.

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

Если логическое ядро с такой абстракцией интерфейса обеспечивает разработчику более комфортное достижение конечной цели, значит такая среда по праву заслуживает массового признания и курса на ее дальнейшее масштабирование среди более широкого сообщества специалистов.

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

Где применяется и кому подходит.

Самое подходящее место для применения, это стартапы и небольшие проекты.
Для стартапов будет плюсом высокая скорость разработки и мгновенная обратная связь от пользователей, поэтому большинство новых проектов делается именно так.
Что немаловажно, в небольших проектах чаще всего важнее уложиться в бюджет.

Вместо эпилога.

Руководствуясь вышеизложенным, было разработано логическое ядро инструмента с интерфейсной абстракцией для проведения функционального программирования процессов управления аппаратными компонентами на бинарной логике в том числе и медийной инкапсуляцией команд:


 

Комментарии

Популярные сообщения из этого блога

Робототехника на изнанку.