Как стать автором
Обновить
0
HTML Academy
Обучаем веб-разработке и меняем жизни

Хороший плохой манкипатчинг

Время на прочтение 4 мин
Количество просмотров 12K

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


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



Сегодня вопрос про разработку от Сергея, отвечает наш преподаватель Игорь Алексеенко:


Манкипатчинг — почему это так плохо или не так уж и плохо?

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


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


Array.prototype.shuffle = function() {
  const i = this.length;
  while (i--) {
    fisherYatesShuffle(this, i);
  }
};

[1, 2, 3].shuffle();

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


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


const initNewTimeout = function() {
  const initialTimeout = window.setTimeout;
  window.setTimeout = function(fn, timeout, ctx) {
    initialTimeout(function() {
      fn.call(ctx);
    }, timeout);
  }
};

initNewTimeout();

setTimeout(tickInContext, 100, this);

Конечно, в вашем коде setTimeout будет работать так, как вам нужно, но вы не можете гарантировать, что в других местах, где он используется всё будет работать так же гладко. Есть и более экстремальные примеры, например, раньше в JavaScript можно было переопределить даже undefined и window.


Получается, что с манкипатчингом нужно быть очень осторожным и придерживаться определённых правил:


  • Добавлять новое лучше, чем изменять старое.


    Изменять поведение уже встроенных в язык методов плохо, потому что они могут использоваться где-то ещё кроме вашего кода. А вот, добавить что-то новое, чем кто-то другой вряд ли додумается воспользоваться — относительно безопасно. Например, добавить в массивы метод их перемешивания. Правда, через какое-то время, в массиве может появиться такой метод — стандарты развиваются, а браузеры быстро их подхватывают.


  • Нужно тщательно тестировать патчи.


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


  • Лучше использовать патчи как временные решения.


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



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


Кажется, что полифилы — это хорошая идея: подключаешь полифил и вне зависимости от того, какой у пользователя браузер, в коде можно использовать новые штуки, например, Fetch для HTTP-запросов, Promise или Object.entries для итерирования по объектам.


<script src="./promise-polyfill.js"></script>
<script src="./whatwg-fetch.js"></script>
<script>
  fetch('/api/request')
    .then(resp => resp.json())
    .then(json => render);
</script>

Но и в этом подходе есть проблемы:


  • Надо что-то делать с теми браузерами, которые уже поддерживают то, что вы патчите.


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


  • Соответствие стандартам.


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



В таких ситуациях лучше использовать функции-обёртки, которые иногда называются понифилами. В принципе, они позволяют делать то же самое что и полифилы, но явно. А ещё у них нет проблем со стандартами: например, популярная библиотека Lodash выросла как раз из обёртки над неработающими итераторами в массивах. Ребята добавили в библиотеку forEach, map и прочие some, every, но не привязывались к стандарту и поэтому у них были изначально развязаны руки. Через какое-то время они добавили другие удобные методы для массивов и коллекций, такие как shuffle, unique, flatten и другие. Несмотря на то что итераторы в массивах поддерживаются уже давно, Lodash успешно развивается.


// полифил
[1, 2, 3].map(it => it / 2);

// понифил
arrayMap([1, 2, 3], it => it / 2);

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


Ещё в разной среде ваши тесты будут работать по-разному, потому что в одних средах патч сработает, в других — нет. У понифилов таких проблем нет: вы всегда знаете что тестируете, они подключаются и работают явно.


Подытожим


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


Материалы по теме



Видеоверсия



Вопросы можно задавать здесь.

Теги:
Хабы:
+7
Комментарии 2
Комментарии Комментарии 2

Публикации

Информация

Сайт
htmlacademy.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
Евгений Шкляр

Истории