Как применять принципы SOLID в приложениях React

В этой статье мы рассмотрим принципы SOLID и способы их применения в React.

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

Принцип единой ответственности

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

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

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

Я вижу эти причины.

  1. Каждый раз я хочу изменить заголовок приложения.
  2. Каждый раз, когда я хочу добавить в приложение новый компонент (например, нижний колонтитул).
  3. Каждый раз я хочу изменить механизм выборки пользователей, например, адрес конечной точки или протокол.
  4. Каждый раз, когда я хочу изменить таблицу списка пользователей (например, стиль столбца и т. Д.)

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

Попробуем исправить эту проблему. Приступим к рефакторингу компонента Приложение.

Теперь, когда мы хотим изменить заголовок, мы меняем компонент Заголовок, а когда мы хотим добавить новый компонент, мы меняем компонент Приложение. Мы решили проблему 1 (изменить заголовок приложения) и 2 (добавить новый компонент в приложение), переместив эту логику из компонента приложения в новые компоненты. Решим задачу 3 и 4.

Это наш новый компонент контейнера UserList. Мы решили проблему 3 ( изменить механизм выборки пользователей), создав функции свойств fetchUser и saveUser. Итак, когда мы хотим изменить конечную точку HTTP, мы переходим к функции (save / fetch) User и меняем ее там.

Последняя проблема 4 (изменение таблицы списка пользователей) была решена путем создания простого компонента представления UserTable, который инкапсулировал HTML и стили пользовательской таблицы.

Принцип открытости закрыт

Этот принцип гласит: «программные объекты (классы, модули, функции и т. Д.) Должны быть открыты для расширения, но закрыты для модификации».

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

Этому принципу можно следовать, используя Компонентную композицию.

Посмотрите на отредактированный компонент UserList ниже.

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

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

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

Принцип замены Лискова

«Объекты в программе должны заменяться экземплярами их подтипов без изменения правильности этой программы».

Или, если не возражаете, более точное описание.

Посмотрите на пример ниже.

У нас есть класс User, который принимает роли в конструкторе. Затем мы создали класс AdminUser, который является производным от User.

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

Но после того, как мы вызвали функцию showUserRoles с экземплярами normalUser и adminUser, произошел сбой.

И почему? AdminUser выглядит как Пользователь. Он определенно «крякает», как Пользователь, потому что у него такие же методы. Проблема была в «батарейках». Потому что при создании пользователя-администратора мы создали объект ролей вместо массива.

Мы нарушили принцип замены Лискова, потому что функция showUserRoles должна правильно работать с пользователем и ее производными!

Исправить просто, мы просто создадим массив ролей вместо объекта.

Принцип разделения интерфейса

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

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

Приведем пример.

Компонент UserTable отображает компонент UserRow, передавая весь пользовательский объект своим свойствам. Когда вы смотрите на компонент UserRow, он зависит от всего пользователя, но заботится только о его id и имени .

Когда вы пишете тест для этого компонента в Typescript или Flow, вы должны издеваться над всем пользователем, потому что в противном случае ваш компилятор выйдет из строя.

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

Но все же так он более наглядный.

Имейте в виду, что этот принцип применим не только к типам опор.

Принцип инверсии зависимостей

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

Посмотрим на пример.

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

Модуль высокого уровня не должен зависеть от деталей низкого уровня, оба должны зависеть от абстракции.

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

И реализация.

Мы можем сказать, что приложение слабо связано, потому что оно не знает, используем ли мы протокол HTTP, SOAP или даже протокол PowerPoint. Это не волнует.

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

И тестирование действительно простое, мы можем легко смоделировать эти функции выборки.

Резюме

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

Мы создаем впечатляющие приложения, проверьте auriosoftware.com

Оставайся со мной на связи в Твиттере.

📝 Прочтите этот рассказ позже в Журнале.

🗞 Просыпайтесь каждое воскресное утро и слышите самые интересные истории, мнения и новости недели, ожидающие в вашем почтовом ящике: Получите примечательный информационный бюллетень›