89 подписчиков
Что такое полимофризм?
В одном из комментариев в постах про паттерны, кто-то сказал что совсем не въезжает в полиморфизм. Тогда я понял что надо немного откатиться и рассказать, так как концепция важна и без нее понимание многих вещей, например, тех же паттернов, будет нереальным. Так что садитесь по удобнее и слушайте)
Сначала договоримся что под словом полиморфизм здесь мы понимаем полиморфизм подтипов или сабтайпинг, это то что называется полиморфизмов в ооп. Кроме него есть и другие, о которых, может быть, в другой раз (например, дженерики это пример параметрического полиморфизма)
Если в двух словах, то полиморфизм позволяет нам подменять реализацию без необходимости переписывать код. Проявляется это по разному в разных ситуациях и чтобы увидеть картинку целиком, нужно разобрать эти типовые ситуации.
Но есть проблема, если у бекендеров полиморфизм по всюду хотят оно того или нет, то у фронтендеров его мало если это не angular, где он вшит через контейнер во фреймворк. Попробуем, все же, зайти через фронтенд, надеюсь будет понятно.
Допустим мы работаем с беком по апи и для этого используется спец либа, а не просто fetch запросы. У гитхаба есть подобная либа: https://github.com/octokit/rest.js Дальше вы решили написать тесты к своему коду и столкнулись с проблемой, что в тестах улетают запросы на реальный github, что не правильно. В тестах во внешние системы не ходят (кстати вы знаете почему?). Как выйти из этой ситуации?
• Либа может сама содержать такую функциональность. Ставится какой-нибудь флаг и она не шлет запросы
• Подход, который довольно популярен в JavaScript (и Ruby) это манки патчинг. С помощью либы https://github.com/nock/nock которая патчит низкоуровневый код и подменяет его фейком, который не делает никаких запросов.
• С помощью ифов
• Как развитие предыдущего пункта, с помощью полиморфизма
Поговорим о последних двух. Мы легко могли бы расставить по коду проверки на окружение:
if (process.env.NODE_ENV === ‘testing’) {
// ничего не делаем
} else {
// реальный запрос
}
Однако, этот код ведет к двум проблемам. Во-первых вызов кода по условию скрывает возможные ошибки и делает код сложнее. Тут легко напортачить и получить работающий тест, но не работающий код. Во-вторых, представьте что у вас таких вызовов десятки, а то и сотни. Во что превратиться код?
Выйти из этой ситуации можно с помощью применения полиморфизма. Для этого понадобится продублировать библиотеку octokit/rest.js но внутри, вместо реальных запросов, например, складывать данные в свойства объекта-библиотеки. Дальше, в отдельном файле пишем:
let octokit;
if (process.env.NODE_ENV === ‘testing’) {
octokit = new OctokitFake();
} else {
octokit = new Octokit();
}
export octokit;
Вуаля, импортируем файл где надо и используем его не думая ни про какую тестовую среду. Конечно при этом фейковый объект должен иметь возможность настраиваться снаружи, чтобы возвращать нужные данные в нужных условиях.
В итоге мы получаем единообразный способ работы, с точки зрения приложения не существует никакого фейкового варианта либы. И если что-то меняется, то код приложения не меняется, изменения идут либо в либах, либо в этом отдельном файле. Это и есть полиморфизм подтипов (а объяснение последнего слова требует отдельного погружения в системы типов).
p.s. Мастхев для чтения: https://guides.hexlet.io/ru/usefull-twitter-threads/#мифы-вокруг-ооп
p.s.s. Требуется ли для полиморфизма подтипов наличие ооп?)
2 минуты
25 марта 2024