В чем разница между объектно-ориентированным и функциональным программированием?


Каковы различия между парадигмами программирования?

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

То же самое происходит и в типах парадигм программирования. Различные виды программирования направлены на решение различных проблем, и для того, чтобы программирование лучше адаптировалось к этим различным целям, способ структурирования и организации кода также будет различным.

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

Объектно-ориентированное программирование (ООП)

Сначала поговорим о самом популярном виде программирования — объектно-ориентированном программировании, или ООП.

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

Еще одной очень яркой особенностью объектно-ориентированных языков является фокус на том, как, а не что. Другими словами, важнее способ достижения действия, чем само действие.

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

Примерами известных языков, включающих объектно-ориентированное программирование, являются Ruby, Scala, Java, Python и др.

Функциональное программирование

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

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

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

Примерами известных языков, включающих функциональное программирование, являются Haskell, Elixir, Erlang, OCaml и др.

Переменная изменяемость

В объектно-ориентированных языках по умолчанию переменные являются изменяемыми, в то время как в функциональных языках переменные по умолчанию неизменяемы. Эта разница возникает из-за чистых функций, потому что одна из философий функционального программирования заключается в том, чтобы представлять возврат функций как «законченную работу», просто присвоив переменной это значение.

Императивное и декларативное программирование

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

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

const senhas =[
"123456",
"senha",
"admin",
"feministech",
"minhasenha",
];
let senhasAprovadas = [];

for (let i = 0; i < senhas.length; i++) {
    const senha = senhas[i];
    if (senha.length >= 9){
    senhasAprovadas.push(senha);
    }
}
Войдите в полноэкранный режим Выход из полноэкранного режима

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

Такой способ программирования, когда инструкции создают одну историю в зависимости от другой, является императивным способом. Слово «императив» означает приказ, например, «сделай это, потом то, потом это».

Мы также можем создать код с тем же результатом, но в декларативном виде, например, так:

const senhasAprovadas = senhas.filter(senha => senha.length >= 9);
Войдите в полноэкранный режим Выход из полноэкранного режима

В приведенном выше коде мы используем функцию filter, чтобы отфильтровать все элементы в этом списке паролей и оставить только те элементы, в которых количество символов больше 9, удалив из списка все остальные.

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

Практический пример: факториал числа

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

Чтобы создать эту функцию в Javascript с помощью ООП, мы можем написать ее следующим образом

function fatorial(numero) {
    if (numero === 0 || numero === 1)
        return 1;
      for (var i = num - 1; i >= 1; i--) {
        numero *= i;
      }
      return numero;

}
Войдите в полноэкранный режим Выход из полноэкранного режима

Анализируя этот код, мы видим, что если это число равно 0 или 1, то возврат будет зафиксирован на 1. Если нет, то будет выполнен for, идущий от числа до 1, уменьшая это значение, и при каждом выполнении этого for число будет умножаться на его значение минус один. После этого будет возвращено факториальное число.

Это решение работает, но мы можем решить эту проблему другим способом, используя концепцию из функционального программирования под названием рекурсия.

function fatorial(numero) {
     if (numero < 0) 
            return -1;
      else if (numero == 0) 
          return 1;
      else {
          return (numero * fatorial(num - 1));
      }

}
Войдите в полноэкранный режим Выход из полноэкранного режима

Глядя на этот код, мы видим, что есть 3 возможности: если число меньше нуля, если число равно нулю, или если число не равно ни нулю (больше нуля).

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

Сначала трудно понять эти концепции рекурсии, но по сути это использование функции внутри одной и той же функции, что позволяет избежать ненужного использования циклов типа for и while.

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

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

defmodule Factorial do
    def of(0), do: 1
    def of(n) when n > 0, do: n * of(n - 1)
end
Войдите в полноэкранный режим Выход из полноэкранного режима

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

Где использовать каждый из них?

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

Для приложений, требующих много классов и много экземпляров объектов, таких как CRUD, с классами для пользователей, постов, транзакций и т.д. И небольшие манипуляции с этими объектами, например, просто выполнение проверок, запись в базу данных и возврат другого объекта, POO может подойти идеально, предоставляя все необходимые функции.

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

Более того, если вы используете смешанный язык, вы можете использовать оба типа программирования в одном приложении.

Смешанные языки

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

Примерами мультипарадигмальных языков являются Kotlin, Python, Javascript и C#.

Отделка

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

Спасибо большое, что читаете ❤️🏳️⚧️ и следите за мной в сетях, это все @lissatransborda 👀

Оцените статью
devanswers.ru
Добавить комментарий