интерфейс на javascript что это
Внутренний и внешний интерфейс
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Один из важнейших принципов ООП – отделение внутреннего интерфейса от внешнего.
Это – обязательная практика в разработке чего угодно сложнее hello world.
Чтобы это понять, отвлечёмся от разработки и переведём взгляд на объекты реального мира.
Как правило, устройства, с которыми мы имеем дело, весьма сложны. Но разделение интерфейса на внешний и внутренний позволяет использовать их без малейших проблем.
Пример из жизни
Например, кофеварка. Простая снаружи: кнопка, индикатор, отверстия,… И, конечно, результат – кофе 🙂
Но внутри… (картинка из пособия по ремонту)
Масса деталей. Но мы можем пользоваться ей, совершенно не зная об этом.
Кофеварки – довольно-таки надёжны, не правда ли? Можно пользоваться годами, и только когда что-то пойдёт не так – придётся нести к мастеру.
Секрет надёжности и простоты кофеварки – в том, что все детали отлажены и спрятаны внутри.
Если снять с кофеварки защитный кожух, то использование её будет более сложным (куда нажимать?) и опасным (током ударить может).
Как мы увидим, объекты очень схожи с кофеварками.
Только для того, чтобы прятать внутренние детали, используется не кожух, а специальные средства языка и соглашения.
Внутренний и внешний интерфейс
В программировании мы будем разделять методы и свойства объекта на две группы:
Если продолжить аналогию с кофеваркой – то, что спрятано внутри кофеварки: трубка кипятильника, нагревательный элемент, тепловой предохранитель и так далее – это её внутренний интерфейс.
Внутренний интерфейс используется для обеспечения работоспособности объекта, его детали используют друг друга. Например, трубка кипятильника подключена к нагревательному элементу.
Но снаружи кофеварка закрыта специальным кожухом, чтобы никто к ним не подобрался. Детали скрыты и недоступны. Виден лишь внешний интерфейс.
Получив объект, всё, что нужно для пользования им – это знать внешний интерфейс. О внутреннем же знать вообще не обязательно.
Это были общие слова по теории программирования.
Далее мы реализуем кофеварку на JavaScript с приватными и публичными свойствами. В кофеварке много деталей, мы конечно, не будем моделировать каждый винтик, а сосредоточимся на основных приёмах разработки.
Шаг 1: публичное и приватное свойство
Локальные переменные, включая параметры конструктора, можно считать приватными свойствами.
В примере выше это power – мощность кофеварки, которая указывается при создании и далее будет использована для расчёта времени кипячения.
К локальным переменным конструктора нельзя обратиться снаружи, но они доступны внутри самого конструктора.
Здесь свойство waterAmount записано в объект, а значит – доступно для модификации снаружи. Можно доливать и выливать воду в любом количестве.
Далее мы будем называть power как «локальной переменной», так и «приватным свойством» объекта.
Это, смотря, с какой стороны посмотреть.
Термины «приватное свойство/метод», «публичное свойство/метод» относятся к общей теории ООП. А их конкретная реализация в языке программирования может быть различной.
Здесь ООП-принцип «приватного свойства» реализован через локальные переменные, поэтому и «локальная переменная» и «приватное свойство» – правильные термины, в зависимости от того, с какой точки зрения взглянуть – кода или архитектуры ООП.
Шаг 2: публичный и приватный методы
В результате естественным образом получается, что доступ к ним (через замыкание) имеют только другие функции, объявленные в том же конструкторе.
Шаг 3: константа
Удельная теплоёмкость WATER_HEAT_CAPACITY выделена большими буквами, так как это константа.
Внимание, при запуске кода выше в методе getBoilTime будет ошибка. Как вы думаете, почему?
Шаг 4: доступ к объекту из внутреннего метода
Её можно решить, если вызвать getBoilTime с явным указанием контекста: getBoilTime.call(this) :
К счастью существуют более элегантные решения.
Привязка через bind
Сохранение this в замыкании
Пожалуй, самый удобный и часто применяемый путь решения состоит в том, чтобы предварительно скопировать this во вспомогательную переменную и обращаться из внутренних функций уже к ней.
Теперь getBoilTime получает self из замыкания.
Итого
Итак, мы сделали кофеварку с публичными и приватными методами и заставили их корректно работать.
В терминологии ООП отделение и защита внутреннего интерфейса называется инкапсуляция.
Кратко перечислим бонусы, которые она даёт:
Защита пользователей от выстрела себе в ногу
Представьте, команда разработчиков пользуется кофеваркой. Кофеварка создана фирмой «Лучшие Кофеварки» и, в общем, работает хорошо, но с неё сняли защитный кожух и, таким образом, внутренний интерфейс стал доступен.
Все разработчики цивилизованны – и пользуются кофеваркой как обычно. Но хитрый Вася решил, что он самый умный, и подкрутил кое-что внутри кофеварки, чтобы кофе заваривался покрепче. Вася не знал, что те изменения, которые он произвёл, приведут к тому, что кофеварка испортится через два дня.
Виноват, разумеется, не только Вася, но и тот, кто снял защитный кожух с кофеварки, и тем самым позволил Васе проводить манипуляции.
В программировании – то же самое. Если пользователь объекта будет менять то, что не рассчитано на изменение снаружи – последствия могут быть непредсказуемыми.
Удобство в поддержке
Ситуация в программировании сложнее, чем с кофеваркой, т.к. кофеварку один раз купили и всё, а программа может улучшаться и дорабатываться.
При наличии чётко выделенного внешнего интерфейса, разработчик может свободно менять внутренние свойства и методы, без оглядки на коллег.
Гораздо легче разрабатывать, если знаешь, что ряд методов (все внутренние) можно переименовывать, менять их параметры, и вообще, переписать как угодно, так как внешний код к ним абсолютно точно не обращается.
Ближайшая аналогия в реальной жизни – это когда выходит «новая версия» кофеварки, которая работает гораздо лучше. Разработчик мог переделать всё внутри, но пользоваться ей по-прежнему просто, так как внешний интерфейс сохранён.
Люди обожают пользоваться вещами, которые просты с виду. А что внутри – дело десятое.
Программисты здесь не исключение.
Всегда удобно, когда детали реализации скрыты, и доступен простой, понятно документированный внешний интерфейс.
Задачи
Добавить метод и свойство кофеварке
[js] Программируйте на уровне интерфейсов
Когда я гуглил эту тему, я планировал выпустить только видео для плейлиста о Паттернах. Но как то мне не очень понравились уже существующие статьи, возможно потому что я пишу на JS, а там примеры были, то на python, то еще на каком языке. Поэтому я решил опубликовать свое видение темы Программируйте на уровне интерфейсов. Возможно это будет кому-то полезным (Данная статья является расшифровкой видео).
Что подразумевается под словом интерфейс?
Начнем с базовых понятий. Что в данном принципе подразумевается под словом интерфейс? Ведь в JS нет интерфейсов, нам что нужен TypeScript, чтобы пользоваться этим принципом? Ответ, однозначно нет
Интерфейс в данном случае, это скорее идея. Мне нравится как эта идея описана в википедии:
Интерфе́йс — граница между двумя функциональными объектами, требования к которой определяются стандартом совокупность средств, методов и правил взаимодействия (управления, контроля и т. д.) между элементами системы.
Интерфейсы в реальном мире
Допустим вы хотите посмотреть кино на телевизоре. В данном случае функциональные объекты это вы и телевизор и вам нужно как то взаимодействовать. У вас есть требования к телевизору: включить его, сделать громче или тише, поставить на паузу или продолжить просмотр. И в данном случае границей между двумя функциональными объектами, удовлетворяющей нашим требованиям является пульт от телевизора. Да, именно он является интерфейсом взаимодействия с телевизором.
Интерфейсы в js
Интерфейсы существуют не только у npm пакетов, но и даже в любом вашем внутреннем модуле, компоненте или просто функции. Ровно в тот момент когда вы придумали, какие параметры функция принимает, как функция называется и что именно она возвращает, вы придумали интерфейс данной функции. А такие инструменты как TypeScript позволяют вам лишь описать интерфейс более явно.
Определение принципа
Я думаю вы поняли, что подразумевается под словом интерфейс в данном принципе. Остается лишь ответить на вопрос: “а что значит программировать на уровне интерфейсов?”
Давайте применим эту трактовку к предыдущим примерам. Пульт от телевизора спроектирован так, чтобы его работоспособность не зависела от конкретной модели, или вообще от марки телевизора. Зачастую мы можем увеличить или уменьшить звук одним пультом в разных телевизорах в разных комнатах.
И если вы решите создать свой телевизор, вы будете думать: «Ага! Мой телевизор должен хорошо взаимодействовать с любым пультом». Т.е. интерфейс был разработан ранее и вы сейчас делаете реализацию вашего телевизора, которая будет удовлетворять условиям уже существующего интерфейса, а не наоборот. Это и есть программировать на уровне интерфейсов, а не на уровне реализаций.
Реальный пример
Но если вы так поступите, у вас в будущем могут возникнуть например следующие сложности:
Вы зададите вопрос, так а как программирование на уровне интерфейсов решает эту проблему?
Программируем на уровне интерфейсов
При таком подходе, чату стало абсолютно все равно какую из технологий вы используете. Все нюансы технологии скрыты за слоем абстракции. Мы лишь знаем как выглядит интерфейс этой абстракции. И даже более того, если сервер еще не решил какую из технологий он будет использовать для отправки сообщений, внутри этого модуля можно поставить заглушку, которая будет имитировать поведение сервера.
А когда серверная команда закончит выбирать технологию, вы не спеша можете запланировать на один из будущих спринтов миграцию с вашего генератора, на SSE реализацию или какую-либо другую технологию, это уже совсем не важно. И более того, если окажется, что сервер плохо работает и вы ловите ошибки, вы сможете временно вернуть реализацию с рандомным генератором сообщений. Согласитесь, удобно ведь.
Дополнительная мотивация
К сожалению, для многих разработчиков все это не имеет никакой ценности, и данная статья их никак не переубедит. Все потому, что нет очевидной выгоды здесь и сейчас, а есть лишь эфемерная выгода, что когда-то будет замена технологий, или появится React Native или произойдет еще какое-то событие.
А многие могут ответить, ой да у нас нативные разработчики делают мобилки, и сервер точно не будет мигрировать с сокетов ближайшие 5 лет, а там уже никто не знает что будет, может уже на новый Фреймворк переезжать будем и смысла особого нет, писать на уровне интерфейсов.
Но это совсем не так. Если вы начнете писать такие независимые модули и планировать свой проект на уровне интерфейсов. Вы обнаружите, что ваши многие модули совсем не зависят от текущего фреймворка. Вы увидите, как новым разработчикам гораздо проще и быстрее вникнуть в проект и начать вносить изменения в тот или иной модуль, т.к. весь лишний код инкапсулирован и не отвлекает от сути задачи. А весь ваш проект напоминаниет конструктор из модулей, который можно в любой момент заменить на новый и не нужно будет переписывать пол приложения на любой чих.
Только представьте насколько facebook нуждается в такого рода модулях. У них десятки тысяч компонентов в проекте и если не придерживаться такого рода программирования, вы никогда не сможете зарефакторить такой сложный проект. И как думаете наймут они вас, если вы скажете, что кодить на уровне интерфейсов, все это фигня или вы никогда этим не занимались, потому что видите ли у вас проект по проще?
Поэтому я рекомендую, вернувшись к своему рабочему проекту, взглянуть на ваш код новыми глазами. И подумать, где уже прям очевидно стоило бы добавить такого рода модуль с интерфейсом отвязанным от реализации. И тем самым уменьшить связанность вашей основной кодовой базы с конкретной реализацией модуля
Введение
Что такое Объектная Модель Документа (DOM)?
Объектная Модель Документа (DOM) – это программный интерфейс (API) для HTML и XML документов. DOM предоставляет структурированное представление документа и определяет то, как эта структура может быть доступна из программ, которые могут изменять содержимое, стиль и структуру документа. Представление DOM состоит из структурированной группы узлов и объектов, которые имеют свойства и методы. По существу, DOM соединяет веб-страницу с языками описания сценариев либо языками программирования.
Веб-страница – это документ. Документ может быть представлен как в окне браузера, так и в самом HTML-коде. В любом случае, это один и тот же документ. DOM предоставляет другой способ представления, хранения и управления этого документа. DOM полностью поддерживает объектно-ориентированное представление веб-страницы, делая возможным её изменение при помощи языка описания сценариев наподобие JavaScript.
Стандарты W3C DOM и WHATWG DOM формируют основы DOM, реализованные в большинстве современных браузеров. Многие браузеры предлагают расширения за пределами данного стандарта, поэтому необходимо проверять работоспособность тех или иных возможностей DOM для каждого конкретного браузера.
Например: стандарт DOM описывает, что метод getElementsByTagName в коде, указанном ниже, должен возвращать список всех элементов
DOM и JavaScript
Вначале JavaScript и DOM были тесно связаны, но впоследствии они развились в различные сущности. Содержимое страницы хранится в DOM и может быть доступно и изменяться с использованием JavaScript, поэтому мы можем записать это в виде приблизительного равенства:
API (веб либо XML страница) = DOM + JS (язык описания скриптов)
DOM спроектирован таким образом, чтобы быть независимым от любого конкретного языка программирования, обеспечивая структурное представление документа согласно единому и последовательному API. Хотя мы всецело сфокусированы на JavaScript в этой справочной документации, реализация DOM может быть построена для любого языка, как в следующем примере на Python:
Для подробной информации о том, какие технологии участвуют в написании JavaScript для веб, смотрите обзорную статью JavaScript technologies overview.
Каким образом доступен DOM?
Вы не должны делать ничего особенного для работы с DOM. Различные браузеры имеют различную реализацию DOM, эти реализации показывают различную степень соответствия с действительным стандартом DOM (это тема, которую мы пытались не затрагивать в данной документации), но каждый браузер использует свой DOM, чтобы сделать веб страницы доступными для взаимодействия с языками сценариев.
При создании сценария с использованием элемента
Реактивные интерфейсы на ванильном JavaScript — Часть 1: Чистый функциональный стиль
20 апреля Крис Койер написал пост, исследуя вопрос: «При каких условиях проекту нужен React?». Другими словами, когда преимущества использования React (или другого веб-фреймворка для приложений с нетривиальной логикой), вместо серверных шаблонов и jQuery, перевешивают сложность настройки требуемого инструментария, процесса сборки, разрешения зависимостей и так далее? Через неделю Саша Грайф выразил в своей статье противоположное мнение о преимуществах постоянного использования такой структуры для каждого веб-проекта. Его аргументы состояли в том, что фреймворк обеспечивает устойчивую расширяемость, упрощенный рабочий процесс от проекта к проекту (единую архитектуру, отсутствие необходимости в сопровождении нескольких типов структур проекта) и улучшенный пользовательский интерфейс благодаря рендерингу на стороне клиента, даже если контент меняется не часто.
В этой паре статей пробуем найти золотую середину: написание пользовательского интерфейса в реактивном стиле в ванильном JavaScript — без фреймворков, без препроцессоров.
Существует два способа создания компонентов React.
Первый вариант более полезен для больших сложных приложений с динамичным интерфейсом, а второй является элегантным способом отображения информации, при отсутствии сложного динамического состояния. Если вы когда-либо использовали шаблонный движок, например Handlebars или Swig, их синтаксис довольно похож на функциональный код React.
В этой серии статей наша цель — статичные сайты, которые при использовании рендеринга на основе JavaScript получат определенные преимущества в случае отсутствия накладных расходов на создание такой структуры, как React. Блоги, форумы и так далее. Поэтому этот первый пост будет посвящен функциональному подходу к написанию пользовательского интерфейса на основе компонентов, поскольку такой интерфейс будет более практичным для такого сценария. Второй пост будет скорее экспериментом: я постараюсь расширить грани того, как далеко мы можем продвинуться без фреймворка, пытаясь максимально точно скопировать структуру компонентов на классах React, используя только ванильный JavaScript (возможно, за счет небольшой потери практичности).
О функциональном программировании
За последние пару лет функциональное программирование стремительно развивалось, по большей части в Clojure, Python и React. Полное объяснение понятия функционального программирования выходит за рамки этой публикации. Актуальная для нас часть — это концепция величин, которые являются функциями других величин.
Скажем, ваш код должен представлять концепцию прямоугольника. Прямоугольник имеет ширину и высоту, но также имеет площадь, периметр и другие атрибуты. Сначала можно представить прямоугольник следующим объектом:
Сразу видно, что есть проблема. Что произойдет, если ширина изменится? При этом мы должны изменить площадь и периметр, иначе они будут неверны. Возможно будут конфликтующие значения, которые нельзя просто изменить, не обновляя что-то еще. Это называется наличием множественных источников истины.
В примере с прямоугольником решение в функциональном стиле состоит в том, чтобы сделать область и периметр функциями прямоугольника:
Таким образом, если изменяется ширина или высота, нам не нужно вручную изменять что-либо еще, чтобы отразить этот факт. Площадь и периметр просто всегда верны. Это называется наличием единственного источника истины.
Сила этой идеи также проявляется, когда вместо длины и ширины прямоугольника — данные вашего приложения, а вместо площади и периметра — HTML. Если вы можете сделать HTML функцией от данных, заботиться нужно будет только об их изменении, а DOM отобразится на странице неявным способом.
UI компоненты как функции
Мы хотим сделать HTML функцией от наших данных. Давайте рассмотрим пример сообщения в блоге:
Хорошо. Мы создали функцию объекта сообщения, возвращающую строку HTML, которая отображает наше сообщение в блоге. На самом деле это пока не компонентно. Это — единый большой шаблон. Что делать, если мы хотим отобразить все наши сообщения в блоге последовательно на главной странице? Что делать, если мы хотим повторно использовать этот заголовок на разных страницах? К счастью, можно легко построить функции из других функций. Это называется композиция:
Так гораздо приятнее. Нам не пришлось дублировать заголовок для домашней страницы и у нас есть единственный источник истины для этого HTML-кода. Если мы захотим отобразить сообщение в другом контексте, мы сможем легко это сделать.
Достаточный синтаксис с шаблонами
Хорошо, но эти конкатенации ужасны. Их нудно печатать, и они затрудняют чтение. Должен быть лучший способ, не так ли? Люди в W3C опережают нас в этом. Они создали шаблонные литералы, которые, хотя и относительно новы, уже имеют довольно хорошую поддержку в браузерах. Просто оберните свою строку в обратные кавычки и она получит пару дополнительных сверхспособностей.
Первая суперсила — это способность охватывать несколько строк. Наш компонент BlogPost может стать таким:
Намного лучше. Сейчас это похоже на JSX. Наш полный пример с шаблонными литералами теперь выглядит так:
Больше, чем просто заполнение пробелов
Таким образом, мы можем подставить значения переменных и даже другие компоненты через функции, но иногда необходима более сложная логика. Иногда нам нужно перебирать данные или отвечать на изменение состояния. Давайте рассмотрим некоторые функции JavaScript, упрощающие выполнение более сложного рендеринга в функциональном стиле.
Тернарный оператор
Это все… не идеально. Мы добавляем много строк для несложной логики и отделяем код рендеринга от его места в остальной части HTML. Это связано с тем, что классический оператор if-else решает, какие строки кода запускать, а не какое значение вычислять. Это важное для понимания различие. Вы не можете вставить последовательность в шаблонный литерал, только одно выражение.
Array.map()
Вы возможно уже поняли, почему такой способ эффективен для нас. Ранее мы определили концепцию: значение — функция от другого значения. Array.map() позволяет нам получить целый массив, для которого каждый элемент является функцией соответствующего элемента в другом массиве. Допустим, у нас есть массив сообщений в блогах, которые мы хотим отобразить:
Перерисовка
Теперь мы можем неявно генерировать HTML из входных данных, компоновать и использовать этот код для других данных, и все это на стороне клиента. Но как обновлять HTML при изменении данных? Как вообще понять в какой момент произошли изменения? Этот вопрос является одним из самых сложных и горячо обсуждаемых в сообществе фреймворков JavaScript. Осуществление частых обновлений DOM — удивительно сложная проблема, над которой инженеры из Facebook и Google работают уже много лет.
К счастью, наш сайт — это всего лишь блог. Содержание ощутимо меняется только при просмотре другого сообщения в блоге. Нет множества взаимодействий для отслеживания, нам не нужно оптимизировать операции с DOM. Когда мы загружаем новое сообщение, мы можем просто удалить DOM и перестроить его.
Мы могли бы сделать это немного лучше, обернув в функцию:
Теперь, когда мы загружаем данные сообщения, просто вызываем update() и отображается нужный HTML. Если бы наше приложение было достаточно сложным и его нужно было бы часто перерисовывать (например, пару раз в секунду), оно быстро начало бы тормозить. Можно написать сложную логику, чтобы определять, какие части страницы действительно нуждаются в обновлении, учитывая конкретное изменение данных, и обновлять только их, но это как раз тот случай, когда надо просто использовать фреймворк.
Не только для контента
На данный момент почти весь наш код рендеринга использовался для определения фактического содержимого HTML и текста внутри элементов, но мы не должны останавливаться на достигнутом. Поскольку мы просто создаем HTML-строку, туда можно добавить кое-что еще. Классы CSS?
Сделано. Не стесняйтесь проявлять творческий подход. Подумайте о своих данных и подумайте о том, как все различные их аспекты должны быть представлены в разметке и пишите выражения, превращающие одно в другое.
Итоги
Надеюсь, что эта статья дает вам хороший набор инструментов для написания простых реактивных веб-интерфейсов, управляемых данными, без накладных расходов в лице каких-либо инструментов или фреймворков. Этот тип кода намного проще писать и поддерживать, чем jQuery лапшу, и нет никакого препятствия для использования его прямо сейчас. Все, о чем мы говорили здесь, поддерживается всеми достаточно современными браузерами, без дополнительных библиотек.
Во второй части основное внимание будет уделено классам, компонентам с состоянием, которые будут на грани сложного и разумного использования нативного JavaScript. Но мы все равно попробуем, и это будет интересно.
Простой JavaScript: разбираемся с mocking, stubbing и интерфейсами
Простой JavaScript позволяет писать понятный и гибкий код. Рассмотрим основные концепции программирования и способы их применения в JavaScript.
Mocking, stubbing и mutating
Для тестирования кода можно использовать самописные библиотеки: они медленные и с их помощью сложно смоделировать реально работающую ФС. А можно воспользоваться библиотеками Proxyquire или Sinon. Proxyquire позволяет переопределить импорт файла, а Sinon может мутировать методы. Для упрощения тестирования удобно использовать оба инструмента, но между ними есть различие.
Предположим, что у вас есть модуль «a», импортирующий модуль «b». Proxyquire импортирует модуль «а» и переопределит модуль «b». Это не повлияет на импорт модуля «b» в других местах программы. Sinon повлияет на экспорт модуля «b» по всему коду – вы должны это помнить.
Почему stubs – это плохо?
Описанные выше варианты не идеальны, т. к. они включают мутацию. При разработке ПО следует избегать мутаций, поскольку они ухудшают предсказуемость поведения приложения.
Одна маленькая мутация не создаст большой проблемы, но когда в коде их много, становится трудно отследить, какое значение изменяет та или иная функция, и когда выполняется каждая мутация.
Есть неприятный момент – блокировка. Как Proxyquire, так и Sinon попросят вас обновить свои тесты, если вы измените библиотеку fs на fs-extra-promise. Вы по-прежнему будете использовать функцию readFileAsync, а Sinon и Proxyquire будут пытаться переопределить fs.readFile.
Простой JavaScript: альтернативы?
Идеально подойдет принцип инверсии зависимостей. Вместо того, чтобы создавать собственные зависимости, код будет ожидать, что ему их передадут.
Код получился компактным и без применения мутаций. Теперь модуль принимает readFileAsync, а не создает эту функцию самостоятельно. Такой подход лучше тем, что он не перегружен лишним функционалом.
Куда ведет зависимость?
Импортируемые зависимости следует размещать в коде как можно ниже. Желательно импортировать их однократно в точке входа.
В примере показаны зависимости, перемещенные в точку входа приложения. Все, кроме index.js “осело” в интерфейсе. Это позволяет приложению быть гибким, легко изменяемым и тестируемым.
На что еще способна инверсия зависимостей?
Интерфейс – это набор методов и свойств. Когда он реализуется в коде, вы можете использовать этот модуль с несколькими реализациями данного интерфейса. Поэтому говоря, что модуль реализует интерфейс, подразумеваем, что модуль реализует объект, реализующий набор методов и свойств. Предполагается, что интерфейсы реализуют разные функции аналогичным образом.
Примером общего интерфейса является компонент React. В TypeScript он может выглядеть так:
Этот React-компонент имеет предсказуемый набор методов и свойств, которые можно использовать для создания множества различных компонентов.
Переходим к принципу «открытости / закрытости». В нем говорится, что наше программное обеспечение должно быть открыто для расширения, но закрыто для модификации. Этот процесс, возможно, вам знаком, если вы создавали программное обеспечение на Angular или React. Они обеспечивают общий интерфейс, который можно расширить для создания программного обеспечения.
Вместо того, чтобы использовать сторонние интерфейсы, вы можете начать писать свои для создания собственного ПО.
При написании CRUD-приложения можно создать интерфейс, предоставляющий стандартные функции работы с базой. Модулями можно расширять этот интерфейс для реализации бизнес-логики и различных сценариев.
Если вы создаете приложение, управляющее задачами, можно создать интерфейс с общими функциональными блоками. Каждая задача может использовать этот интерфейс или расширять его.
Инверсия зависимостей и принцип «открытости/закрытости» позволяют писать повторно используемый, хорошо тестируемый и «предсказуемый» софт. Простой JavaScript не будет включать беспорядочный код, модули станут функционировать единой группой, разработанной и функционирующей по одному шаблону.
Множественная реализация
Еще одно преимущество в применении интерфейса – реализация различными способами.
Допустим, что у нас есть интерфейс, реализующий хранилище в БД. Если через время процесс чтения / записи станет медленным, можно написать более быструю реализацию, использующую Redis или Memcached для улучшения времени ответа. Единственное изменение, которое вам нужно сделать, это написать новый интерфейс без необходимости обновлять логику.
Похожим образом работает React и React-Native. Оба фреймворка используют один и тот же компонент и интерфейсы, но реализуют их по-разному. Внутри React Native есть функционал для работы как с IOS, так и с Android. Несколько реализаций позволяют писать логику один раз и выполнять ее различными способами.
Вместо точки
Теперь, когда вы узнали, как простой JavaScript позволяет работать с инверсией зависимостей и принципом «открытости / закрытости», можно применить его в коде:
Вы будете медленно, но уверенно создавать свое лучшее приложение. Удачи!