DevGang
Авторизоваться

Философия ООП и FP с JavaScript

Я не философ, но иногда мне больше нравится понимать "почему", чем "как", особенно когда дело доходит до теоретического программирования.

ООП: парадигма «Какая сущность»

Смотреть на мир через призму сущностей или, если быть точнее, предметов.

Что такое ООП?

Объектно-ориентированное программирование (ООП) построено вокруг объектов — структур данных, которые инкапсулируют свойства и поведение.

Свойства говорят сами за себя (вы лучше поймете на примере), а поведение программы описывается методами.

ООП общается в ясной императивной манере — каждый метод — это директива, действие для выполнения чего-либо.

Первая задача в ООП — идентификация объектов.

Эти объекты имеют свойства, которые действуют как ящики; они хранят сокеты, которые в этом контексте относятся к данным.

В JavaScript эти данные могут быть чем угодно: носки, футболки, шапки, перчатки, телевизионные кабели, телевизоры, столы, стулья, дома, города, планеты, существа и любые материальные или вымышленные объекты.

Все эти элементы могут храниться как переменные или, в терминологии ООП, классы.

Мы добавили в эту статью понимание создания объектов, данных и классов. Будем рады: если она поможет вам в работе.

Например, рассмотрим этот объект Drawer в JavaScript:

class Drawer {

  // Properties of the Drawer are declared within the constructor.
  constructor() {
    this.socks = []; 
    // It is also possible to store multiple properties, or perhaps, a reference to another class.
  }

  addSock(sock) {
    // Class properties are accessed using the keyword `this`
    this.socks.push(sock);
  }

  countSocks() {
    return this.socks.length;
  }
}

Drawer представляет сущность, связывающую связанные свойства (sock) и поведение (методы addSock и countSocks) вместе.

Как это работает?

В ООП вы создаете экземпляр своего класса (создаете экземпляр объекта) и взаимодействуете с ним, используя определенные методы.

Вот как вы будете использовать Drawer:

  const myDrawer = new Drawer();
  myDrawer.addSock('red');
  myDrawer.addSock('blue');
  console.log(myDrawer.countSocks()); // Output: 2

Зачем это использовать?

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

Вы вычисляете сущности реального мира, определяете, что они делают (с помощью методов), а затем записываете это в свою программу.

Благодаря этому отражению в реальном мире ООП помогает вам применять свои повседневные знания в программировании. В реальной жизни вы постоянно имеете дело с объектами.

Использование их в вашем коде кажется естественным!

Функциональное программирование: парадигма «рабочего процесса»

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

Что это такое?

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

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

В FP шаги рассматриваются как преобразования данных.

Давайте посмотрим, как мы можем справиться с нашей проблемой 'socks in drawer' с помощью FP:

let drawer = [];

const addSock = (drawer, sock) => [...drawer, sock];

const countSocks = (drawer) => drawer.length;

drawer = addSock(drawer, 'red');
drawer = addSock(drawer, 'blue');
console.log(countSocks(drawer)); // Output: 2

Эти шаги показывают, как мы можем преобразовать наши данные (drawer и socks), чтобы решить проблему. Мы начинаем с пустого drawer, добавляем в него socks, а затем считаем их. Каждый шаг — это небольшое преобразование, которое приближает нас к решению.

Как это работает?

В FP данные и действия разделены. Это как готовить:

  • Ваши сырые ингредиенты — это ваши данные 🥚🥛🌾
  • Ваш процесс приготовления представляет собой действия 🍳
  • Вы загружаете свои сырые ингредиенты (данные) в процесс приготовления (функции).
  • Эти функции выводят новое блюдо (новые данные), но ваши сырые ингредиенты (данные) все еще остаются сырыми. Они не модифицированы!
let rawIngredients = ['eggs', 'flour', 'milk'];
let cookPancakes = (ingredients) => { /*...process...*/ return 'pancakes'; }
let pancakes = cookPancakes(rawIngredients);
// You now have pancakes, but your rawIngredients are still ['eggs', 'flour', 'milk']

Зачем это использовать?

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

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

Другими преимуществами использования являются:

  • Предсказуемость: FP похож на хорошо написанный рецепт. Вы можете предсказать результат, учитывая один и тот же набор ингредиентов (данных) каждый раз. Это устраняет неожиданности в вашем коде 📖
  • Простота тестирования: в FP вы можете протестировать каждую функцию (или шаг) отдельно, точно так же, как проверить, насколько хорошо работает ваша техника взбивания яиц, прежде чем переходить к следующему этапу приготовления. Эта изоляция упрощает тестирование и отладку вашего кода 🥚➡️🍳
  • Надежность: для проектов, где требуется высокая надежность, лучше всего подходит FP. Это снижает вероятность неожиданных ошибок, что делает его надежным выбором для важных проектов 👍
  • Пригодность для решения современных задач: подобно использованию правильной посуды для правильного блюда, FP предоставляет правильные инструменты для решения проблем, связанных с данными, в программировании. Сосредоточив внимание на рабочем процессе, преобразовании данных (а не на самих данных), вы сделаете свой код более кратким и менее склонным к ошибкам.

Гибкость JS

С JavaScript оба подхода допустимы, хотя я бы рекомендовал FP вместо ООП, так как я думаю, что он больше соответствует характеристикам языка.

Почему я рекомендую FP для JavaScript

Не поймите меня неправильно, я очень ценю модель мышления ООП, принципы SOLID, иерархию и полиморфизм.

Фактически, на протяжении всей своей карьеры я в основном писал ООП-код на C#, .NET, Flutter, Xamarin Native, C и Java.

Однако по мере того, как я глубже погружался в мир JavaScript, меня все больше привлекало функциональное программирование.

Этот переход не был мотивирован шумихой.

Вместо этого оно возникло из искреннего чувства радости при создании кода функционального программирования.

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

Управление состоянием

Обычно в веб-приложении JavaScript вам необходимо обрабатывать локальное или глобальное состояние.

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

FP выступает за неизменность, концепцию данных, которые не изменяются, а всегда заменяются после создания.

Это устраняет ошибки, возникающие из-за неожиданного изменения данных, что делает приложение более надежным и предсказуемым.

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

// Instead of mutating state directly,
// FP creates a new copy with desired changes
const newState = Object.assign({}, oldState, {updatedProp: newValue});

// A pure function in FP - given the same input, the output is always the same
const square = num => num * num;

Преобразования данных

JavaScript часто манипулирует ответами DOM или AJAX. FP преуспевает в этом, рассматривая эти операции как ряд преобразований данных, что может быть очень удобно, когда вы работаете с какой-либо Reactive Framework.

// Mapping data to DOM elements
const elements = data.map(item => `<span key={item.id}>${item.name}</span>`);

Функция map — это чистая детерминированная функция.

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

Реактивные фреймворки

Реактивные фреймворки, такие как React, Vue или Svelte, поддерживают философию реактивного программирования.

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

Всякий раз, когда список выбранных номеров изменяется, вы «execute» «reactive» поведение, то есть:

  1. Проанализируйте свою карту
  2. Если новый выбранный номер присутствует на вашей карте, обведите его
  3. Если нет, ничего не делайте

Это поведение будет реагировать на обновление состояния выбранных номеров бинго.

Подведение итогов

Почему объекты?

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

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

Почему шаги?

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

Если вы изо всех сил пытаетесь решить проблему, разбейте ее на более мелкие задачи.

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

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

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

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

Источник:

#JavaScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу