Comments 273
В ответ на https://t.co/aAvOuymZXQ сразу гиперссылку https://t.co/UBD4CnkFFu дают, и это очень правильно как аргумент в пользу микромодулей.
— Mithgol (@FidonetRunes) 24 марта 2016 г.
Перевод на Хабре
Small modules: it’s not quite that simple
Ну и даже в комментариях к самой статье много разумных аргументов.
Small modules: it’s not quite that simple
Ну и даже в комментариях к самой статье много разумных аргументов.
Ситуацию с npm мне всегда хочется проиллюстрировать этой чудесной фотографией:
А что на этом фото происходит? Хотя бы приблизительно? Кто это? Чем они тут занимаются?
Программируют же! Вы разве не видите ноутбук у самого главного?
UFO just landed and posted this here
Да, это индийский военный парад, там много разных «фигур высшего пилотажа» было кроме той, что на фотографии. И вишенка на торте: индийцы этот парад еще Обаме с его женой с гордостью демонстрировали, видео гуглится.
UFO just landed and posted this here
очень странно всё-таки не хотеть хотя бы примерно знать как это должно работать, хотя бы одним глазком взглянуть на исходник, особенно если нам намекают, что там творится какая-то магия!Хочется — взгляните, кто ж вам мешает? Мне, например, не хочется. Мне хочется, чтобы работало и бизнесовая логика быстрее писалась.
UFO just landed and posted this here
знаем/загуглили про Array.isArray/[object Array], сразу пишем в коде Array.isArray/[object Array]
А где именно вы это пишете? В отдельном файле
utils.js
? И в следующем проекте вы тоже будете его копипастить? Это как-то не очень здорово, если честно.У меня для таких вещей стоит зависимость от
lodash
, а у кого-то она будет излишней и зависимость от конкретного isArray
будет весьма кстати.P. S. Это же Unix-way в чистом виде.
Ок. В одном проекте написали от руки свой привычный однострочник, повторили его в другом, в третьем, в пятом, в десятом. А в одиннадцатом обнаружили вдруг в этом привычном однострочнике баг. Ваши действия?
Ок. Подключили в зависимость однострочник, использовали его в одном, другом, в третьем, в пятом, в десятом. А в одиннадцатом обнаружили что вдруг в этом привычном однострочнике баг, и автор выпустил новую версию. Ваши действия?
Идти обновлять зависимости сопоставимо с обновлением кода этого однострочника. Если разработчик не понимает что он пишет, то проще нагуглить готовое решение, чем городить велосипед. Такому коду место в gist.github.com, но никак не в пакетах.
Идти обновлять зависимости сопоставимо с обновлением кода этого однострочника. Если разработчик не понимает что он пишет, то проще нагуглить готовое решение, чем городить велосипед. Такому коду место в gist.github.com, но никак не в пакетах.
/весело/
Создать новый npm пакет (… богу NPM...)
Создать новый npm пакет (… богу NPM...)
Исправить один раз и дополнить юнит-тесты. Тем более он уже много лет как в utils.js или аналоге, если, конечно, это не первый Hello, World! программиста.
Пишу код, который ищёт все вхождения выражения и заменяет на другое. Многие IDE имееют такую функциональность изкоробки. Пишу жалобный (хабра)пост о мудаках в комитетах стандартизации, которые при переходе на новую версию js поломали обратную совместимость.
Примерно такой алгоритм действий был при переходе со второго на третий питон.
Примерно такой алгоритм действий был при переходе со второго на третий питон.
Проблема в том, что документация к пакету занимает больше места, чем содержимое пакета. Лучше было бы эту строчку разместить в документации, и пусть все желающие утаскивают её к себе в проект.
Да пусть занимает, на что это влияет?
На время, которое потратит программист, использующий этот пакет. Вы же не будете использовать пакет, не прочитав документации?
А что быстрее – прочитать документацию, или написать документацию? Вы же не будете писать свою функцию без документации?
Буду, конечно. Нет нужды комментировать очевидные вещи.
Тогда к чему ваш вопрос про документацию?
Чтобы использовать пакет, надо прочитать документацию. Потому что если ты всё знаешь о тонкостях js, ты сам напишешь этот кода, а если не знаешь, то должен откуда-то узнать, что есть сложности. То есть что-то прочитать, скорее всего ту самую документацию.
Тогда гораздо проще в документации сразу указать нужный однострочник, чем давать ссылку на установку пакета.
Тогда гораздо проще в документации сразу указать нужный однострочник, чем давать ссылку на установку пакета.
Нет нужды комментировать очевидные вещи.
Чтобы использовать пакет, надо прочитать документацию
Странная логика. Для очевидных вещей документацию писать не надо, но читать надо. Откуда же она будет браться, если её не надо писать?
toString.call(arr) == '[object Array]' — неужели так некрасиво в js определяется тип? Что будет если в будущем поменяется функция преобразования объекта в строку?
В ES5 Array.isArray, поэтому и существуют шимы/полифиллы/мини-модули.
Возможно это просто костыль, ввиду особенностей поведения typeof:
typeof ''
«string»
typeof []
«object»
typeof {}
«object»
toString.call('')
"[object String]"
toString.call([])
"[object Array]"
toString.call({})
"[object Object]"
arr instanceof Array. Не?
Да, и это будет быстрее.
Вариант typeof в данном случае реализован не корректно, но тем ни менее.
Call to function isArray1(obj)
{
return obj instanceof Array;
} took 10.195000000000022 milliseconds.
Call to function isArray2(obj)
{
return (typeof obj == «object»);
} took 12.25 milliseconds.
Call to function isArray3(obj)
{
return Array.isArray(obj);
} took 26.909999999999968 milliseconds.
Call to function isArray4(obj)
{
return toString.call(obj) == '[object Array]';
} took 1597.9850000000001 milliseconds.
Вариант typeof в данном случае реализован не корректно, но тем ни менее.
Функция
function isArray2(obj) {
return (typeof obj == «object»);
}
бесполезна чуть более чем полностью. isArray2({}) //true
function isArray2(obj) {
return (typeof obj == «object»);
}
бесполезна чуть более чем полностью. isArray2({}) //true
С фреймами не пройдет. Если необходима универсальная проверка то либо toString() либо isArray(). (
Дли тех, кто не понял что имеется в виду или почему не пройдёт (вроде меня), вот в деталях: http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
Там еть и некоторые другие странные способы проверить имеем ли мы дело с массивом или нет.
Хотя стоит заметить, что лично мне проще проверить существование необходимых мне в последующем коде методов.
Там еть и некоторые другие странные способы проверить имеем ли мы дело с массивом или нет.
Хотя стоит заметить, что лично мне проще проверить существование необходимых мне в последующем коде методов.
После прочтения этого лишь укрепилась вера в убогость языка, где приходится так извращаться ради простых вещей, включая is-positive-integer.
Даже на php это делается проще и логичнее — if ((int) $value == $value && $value > 0)
Банально, padding во многих языках решается через sprintf, но его почему-то в javascript нет.
Даже на php это делается проще и логичнее — if ((int) $value == $value && $value > 0)
Банально, padding во многих языках решается через sprintf, но его почему-то в javascript нет.
isArray() работает как надо, не нужно извращаться.
is-positive-integer можно также записать в вашем стиле и на js (parseInt(val) === val && val > 0)
но это не значит что это единственное и главное всеобъемлющее решение.
Безусловно js не лишен проблем, как и любой язык, впринципе, особенно если пытаться использовать его не по назначению.
Но убог? Както через чур, мне кажется.
is-positive-integer можно также записать в вашем стиле и на js (parseInt(val) === val && val > 0)
но это не значит что это единственное и главное всеобъемлющее решение.
Безусловно js не лишен проблем, как и любой язык, впринципе, особенно если пытаться использовать его не по назначению.
Но убог? Както через чур, мне кажется.
var isPosInt = (val) => val + 0 === val && val > 0
Чёрт, забыл, что нужно ещё и на int проверить. :)
var isPosInt = (val) => Math.trunc(val + 0) === val && val > 0
var isPosInt = (val) => Math.trunc(val + 0) === val && val > 0
Bitwise приведение к int: var isPosInt = (x) => (~~x) === x && x > 0
Есть даже чистый bitwise:
http://stackoverflow.com/questions/3912375/check-if-a-number-x-is-positive-x0-by-only-using-bitwise-operators-in-c
Есть даже чистый bitwise:
http://stackoverflow.com/questions/3912375/check-if-a-number-x-is-positive-x0-by-only-using-bitwise-operators-in-c
Чёрт, это же С и тип заранее задан. Там только проверка на positive, без int. У кого-нибудь есть идеи как сделать чистый bitwise is int на JS? -_-
UFO just landed and posted this here
Не совсем понимаю что вы хотите, сами же пример привели чуть выше. Если целиком у меня вышло както так:
var isPosInt = (val) => ~~val === val && !(((val >> 31) << 1) | !val)
var isPosInt = (val) => ~~val === val && !(((val >> 31) << 1) | !val)
Чистый bitwise подразумевает полное отсутствие каких-либо иных логических операторов. С === и && я и сам могу. :)
Кстати, alexkunin выше дал более коректное решение для проверки на положительное значение. Оно не привязано к разрядности переменной.
Кстати, alexkunin выше дал более коректное решение для проверки на положительное значение. Оно не привязано к разрядности переменной.
isPosInt(2147483648)
false
false
UFO just landed and posted this here
В JavaScript нет Int32, можно сказать, что есть Int54, и от функции is*Int(eger) ожидаешь проверки именно на Int54. Если ограничиваться Int32, то и именовать нужно соответствующе.
На счёт именования согласен. Решение не универсальное и тут уже играет роль важна ли нам скорость или работа с большими числами. Ещё стоит заметить, что числа больше Number.MAX_SAFE_INTEGER не целые по-определению.
Ну так Number.MAX_SAFE_INTEGER и есть "Int54.MaxValue" (в .Net нотации)
Я, кагбэ, и не говорил, что это не оно. Просто более крупные значения в JS представляется в формате double-precision floating-point и тут уже результат проверки скорее зависит от точки зрения. Данные хранятся в не целочисленном формате, но число получается целое так-как дробная часть с такой точностью не влезает и в этот формат.
UFO just landed and posted this here
UFO just landed and posted this here
Именно это я и имел в виду, когда сказал, что результат зависит от точки зрения. Значение-то целочисленное получается, хоть и хранится в формате для дробных значений и часть данных теряется просто потому, что их негде хранить. И да, я в курсе, что там есть специальная функция для проверки, только именуется она просто isSafeInteger.
Кстати, со строгим ограничением на SafeInteger (и без bitwise, естественно) можно вот так вот:
var isSafePositiveInteger = x => Number.isSafeInteger(x) && x > 0;
Кстати, со строгим ограничением на SafeInteger (и без bitwise, естественно) можно вот так вот:
var isSafePositiveInteger = x => Number.isSafeInteger(x) && x > 0;
UFO just landed and posted this here
Я думаю для понимания автора модуля достаточно взглянуть на это вот:
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991
UFO just landed and posted this here
А разве у isSafeInteger не та же беда? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger
Вот и изобретает велосипеды.
Ну и раз сделал isPositiveInteger, то нужно ж было этот велосипед как-то задействовать? Запихивать Number.isSafeInteger?: и, тем более if в isSafePositiveInteger явно не хотелось, а через || этот isSafeInteger всунуть некуда так-как isPositiveIngeter оно не заменит, а для проверки x <= MAX_SAFE_INTEGER будет избыточным.
Вот в isPositiveInteger и правда можно (и нужно, наверное) было бы попробовать воспользоваться Number.isInteger если есть в наличии.
Вот и изобретает велосипеды.
Ну и раз сделал isPositiveInteger, то нужно ж было этот велосипед как-то задействовать? Запихивать Number.isSafeInteger?: и, тем более if в isSafePositiveInteger явно не хотелось, а через || этот isSafeInteger всунуть некуда так-как isPositiveIngeter оно не заменит, а для проверки x <= MAX_SAFE_INTEGER будет избыточным.
Вот в isPositiveInteger и правда можно (и нужно, наверное) было бы попробовать воспользоваться Number.isInteger если есть в наличии.
Если кратко, то это ES6 :)
UFO just landed and posted this here
{
const src = [1,2,3,4,5];
const wrong = { foo: 1 };
const arr1 = it => typeof it[Symbol.iterator] === 'function';
const arr2 = it => it instanceof Array;
const arr3 = it => Array.isArray(it);
const arr4 = it => toString.call(it) == '[object Array]';
Array.prototype.forEach.call([ arr1, arr2, arr3, arr4 ], (f, i) => {
const fname = `arr${i+1}`;
console.log(`----- ${fname} -----`);
console.time(fname);
const result = f(src);
console.timeEnd(fname);
console.assert(result === true);
console.assert(f(wrong) === false);
});
}
/*
----- arr1 -----
arr1: timer started
arr1: 0.63ms
----- arr2 -----
arr2: timer started
arr2: 0.55ms
----- arr3 -----
arr3: timer started
arr3: 0.53ms
----- arr4 -----
arr4: timer started
arr4: 1.2ms
*/
Извините за глупый вопрос, но не могу не переспросить:
Определение типа таким способом "toString.call(obj) == '[object Array]';" занимает больше 1.5 секунд?
Определение типа таким способом "toString.call(obj) == '[object Array]';" занимает больше 1.5 секунд?
Этот вариант не сработает, если массив был создан в другой глобальной области видимости.
typeof obj[Symbol.iterator] === 'function'
это работает не всегда — если, скажем, массив создан в web-worker'e, то это дело вернёт false.
Сколь я помню, это не гарантирует истинности. Если arr пришел из другого окна например, то будет false.
Типы — это давняя боль. В первой версии языка вообще не было массивов (поэтому arguments — не массив), их эмулировали с помощью объектов с ключами 0..n. Отсюда все эти ноги растут. А еще вот такое счастье:
Ну а вообще в 2016 есть Array.isArray. В крайнем случае, для легаси окружений, можно и полифилл поставить.
typeof null === 'object'
.Ну а вообще в 2016 есть Array.isArray. В крайнем случае, для легаси окружений, можно и полифилл поставить.
А если так?
return !![].forEach(или любая другая функция, имеющаяся только у массива)
return !![].forEach(или любая другая функция, имеющаяся только у массива)
UFO just landed and posted this here
Ну, прям крайность GNU ) Вырожденная модульность, чтобы в любой момент пользователь мог заменить зависимую библиотеку на более любимую)
Ну а вообще проблема в бедной стандартной библиотеке. Вместо того, чтобы починить, например, Date и принять String#padLeft и прочее, что можно легко заполифиллить и снять эти идиотские проблемы, TC39 занимается… чем-то другим.
Им уже предлогают String.prototype.padStart и String.prototype.padEnd: github.com/tc39/proposal-string-pad-start-end
Мне кажется, что подобное(втягивание пустяковых зависимостей) происходит в первую очередь из-за того, что кодерам не до перфекционизма. Цель — выкатить решение.
UFO just landed and posted this here
Так это ж три этапа развития разработчика (на правах полу-шутки):
1) Копипастишь.
2) Не копипастишь, а переиспользуешь.
3) Понимаешь, когда копипастить можно, а когда не нужно.
Много разработчиков остаются на втором уровне понимания (отчасти, я думаю, из-за перфекционизма, типа модули, переиспользование кода, красота же).
1) Копипастишь.
2) Не копипастишь, а переиспользуешь.
3) Понимаешь, когда копипастить можно, а когда не нужно.
Много разработчиков остаются на втором уровне понимания (отчасти, я думаю, из-за перфекционизма, типа модули, переиспользование кода, красота же).
Именно, когда (возможно этого и не случится) вдруг бизнес повернет на курс создания надёжных, продуманных продуктов то ситуация сама собой исправится. Сейчас все гоянятся как на скачках не понятно куда.
Чистить зависимости вручную, то еще удовольствие, особенно когда их набирается с десяток. Выход, нужен инструмент для выявления неиспользуемых зависимостей, иначе эта куча будет только расти.
https://github.com/dylang/npm-check Весьма неплохо справляется.
Есть еще https://github.com/depcheck/depcheck но мне лично он нравится меньше.
Есть еще https://github.com/depcheck/depcheck но мне лично он нравится меньше.
Нет ничего плохого в маленьких модулях, в модулях из 1 строки и даже из 0 строк (модуль без кода, представляет собой коллекцию полезных зависимостей, например). Это очень хорошо, что люди используют проверенные решения даже для примитивных задач, потому как есть немало шансов, что даже модуль из трёх строк спасет программистов от багов, возможныз при самописной реализации той же проверки на массив, встречающихся в очень редких ситуациях, т.к. "у меня же работает!".
Плохо в npm и во всей этой экосистеме с фреймворками друг на друге это их огромнейшая раздутость, 28000 файлов, вот это вот всё. Реально нужный и используемый код из всего этого — это доли процентов чаще всего. Но кому до этого есть дело, в смартфонах уже по 8 ядер, анимация почти не тормозит!)
Плохо в npm и во всей этой экосистеме с фреймворками друг на друге это их огромнейшая раздутость, 28000 файлов, вот это вот всё. Реально нужный и используемый код из всего этого — это доли процентов чаще всего. Но кому до этого есть дело, в смартфонах уже по 8 ядер, анимация почти не тормозит!)
>люди используют проверенные решения даже для примитивных задач
к сожалению, большинство npm-модулей отнюдь не проверенные решения.
к сожалению, большинство npm-модулей отнюдь не проверенные решения.
Именно так. Приведённая функция leftpad крайне неоптимальна: она имеет сложность O(N^2). Но на это обратили внимание только сейчас, когда поднялась шумиха:
github.com/azer/left-pad/issues/15
То есть автор написал функцию для своих нужд. Возможно, ему требовалось быстрое и надёжное решение для строк небольшой длины, а оптимизацию для длинных строк он решил оставить на потом, о чём благополучно забыл. А другие взяли и стали его функцию использовать, не особо вникая в то, как эта функция работает.
github.com/azer/left-pad/issues/15
То есть автор написал функцию для своих нужд. Возможно, ему требовалось быстрое и надёжное решение для строк небольшой длины, а оптимизацию для длинных строк он решил оставить на потом, о чём благополучно забыл. А другие взяли и стали его функцию использовать, не особо вникая в то, как эта функция работает.
И это аргумент, почему лучше использовать готовый модуль, а не самописную функцию (или, вообще копипаст).
Вот смотрите:
1. Народ обратил внимание на то, что сложность O(N^2).
2. Грамотный чувак сделал из неё оптимизированную O(N) и бросил пулл-реквест.
3. Автор принял пулл-реквест и обновил репозиторий.
4. С этого момента миллионы чуваков делают npm update (или как там) и у них код начинает работать быстрее и эффективнее, без усилий и рефакторинга с их стороны. И пролетают те, кто вместо использования готового лепит велосипеды и забивает на них. Тут можно возразить, что без тестов может что-то поломаться. Ну те, кто не пишут тесты на свой код — ССЗБ.
Вся мощь модулей в том, что вы можете отдать части логики на опенсорс-аутсорс, где она дотачивается и оптимизируется. И иметь возможность быстро обновиться до актуальных версий. Чего не скажешь о самопале, глубоко зарытом в коде проекта. Даже маленьких модулей, которые вынуждены покрывать крайнюю нищету и скудость стандартной библиотеки. Непонятно, чем занимаются авторы ES-стандартов, если такие нужные каждый день в быту однострочные вещи приходится подтягивать из npm-репы.
Вот смотрите:
1. Народ обратил внимание на то, что сложность O(N^2).
2. Грамотный чувак сделал из неё оптимизированную O(N) и бросил пулл-реквест.
3. Автор принял пулл-реквест и обновил репозиторий.
4. С этого момента миллионы чуваков делают npm update (или как там) и у них код начинает работать быстрее и эффективнее, без усилий и рефакторинга с их стороны. И пролетают те, кто вместо использования готового лепит велосипеды и забивает на них. Тут можно возразить, что без тестов может что-то поломаться. Ну те, кто не пишут тесты на свой код — ССЗБ.
Вся мощь модулей в том, что вы можете отдать части логики на опенсорс-аутсорс, где она дотачивается и оптимизируется. И иметь возможность быстро обновиться до актуальных версий. Чего не скажешь о самопале, глубоко зарытом в коде проекта. Даже маленьких модулей, которые вынуждены покрывать крайнюю нищету и скудость стандартной библиотеки. Непонятно, чем занимаются авторы ES-стандартов, если такие нужные каждый день в быту однострочные вещи приходится подтягивать из npm-репы.
Народ обратил внимание на это только после привлечения внимания к этому модулю. Из-за чего у меня сразу возникают вопросы:
- Что мешало грамотному чуваку это сделать на год-два раньше?
- Почему все бездумно используют модули, но не смотрят, что у них находится под капотом?
- Почему принято считать, что велосипед всегда будет хуже, чем ранее написанный код? Кстати, в велосипеде проблемы нет: ведь тесты-то уже написаны!
- Что делать, если автор умер и не больше не поддерживает свои библиотеки?
Ну а к самописной функции вообще никогда внимание бы не обратилось.
- ровно то же, что может помешать разработчику велосипеда увидеть более оптимальное решение
- потому что, по-идее, для обычного использования достаточно смотреть документацию. Вот когда вопрос стоит в оптимизации/дебаггинге – тогда да, без ковыряния в коде не обойтись (если затык в конкретном модуле).
- потому что "ранее написанный код" уже работает и так или иначе проверен, а велосипед – нет. Вместо написания велосипеда лучше обновить "ранее написанный код" (пулл-реквесты и т.д.)
- форк сделать, например. В чём проблема?
Есть люди, которые занимаются написанием, вылизыванием и поддержкой стандартных библиотек. Это их основная задача. Их код можно и нужно использовать.
А когда дело касается модулей, которые представляют из себя точно такие же самописные велосипеды, только выложенные в репозиторий, в качестве кода возникают сомнения. Но всегда находятся программисты, которые считают, что пусть и плохой, но выложенный в репозиторий код — это благо.
А когда дело касается модулей, которые представляют из себя точно такие же самописные велосипеды, только выложенные в репозиторий, в качестве кода возникают сомнения. Но всегда находятся программисты, которые считают, что пусть и плохой, но выложенный в репозиторий код — это благо.
- Автор модуля пулл-реквест может не принять или принять не сразу, а изменения нужно внести прямо сейчас, что делать?
- Проблема в том, что миллионам разработчиков придётся переправлять зависимости на новый форк.
Что мешало грамотному чуваку это сделать на год-два раньше?А зачем?
Почему все бездумно используют модули, но не смотрят, что у них находится под капотом?Потому что люди так устроены. Они не роботы и не хотят делать то, чего можно не делать.
Почему принято считать, что велосипед всегда будет хуже, чем ранее написанный код?Потому что велосипед нужно написать, очевидно же.
Суть в том, что пункт 1 произошел, в общем-то, случайно. У сотен и тысяч подобных модулей (а у более сложных — так тем более) это не случится никогда.
Неправда. Если это действительно такое тормозное и отъедающее много времени место, то первый же сеанс профилирования покажет, что именно в этом месте алгоритм надо оптимизировать, и при достаточной чистоплотности — выложить в open source форк/pull request.
UFO just landed and posted this here
Обычно да, так всё и происходит. :) Неоптимальный код заливают баблом на железо. Но это бывате только там, где что железо дешевле времени разработчика. Если было бы наоборот — сидели бы все безвылазно в профайлерах. :)
Ну и если совсем уж всё плохо и пара часов времени разработчика дешевле двух сотен серваков для хайлоад-проекта — то запустят-таки и исправят. Вон, фейсбук и вконтакт дальше пошли — то компилируемый PHP изобретут, то из этого PHP всё тормозящее ООП повыкидывают, то на C++ с ассемблерными вставками перепишут критичные сервисы.
Ну и если совсем уж всё плохо и пара часов времени разработчика дешевле двух сотен серваков для хайлоад-проекта — то запустят-таки и исправят. Вон, фейсбук и вконтакт дальше пошли — то компилируемый PHP изобретут, то из этого PHP всё тормозящее ООП повыкидывают, то на C++ с ассемблерными вставками перепишут критичные сервисы.
Конкретный практический пример показал, что не случился ни у кого "первый же сеанс профилирования". А если и случился, то скорее всего, никто не стал заморачиватся доработками и пулл-реквестами, а просто нашел что-то другое.
Да, но бонус в том, что если в этой библиотеке починят и оптимизируют — вы тоже будете в выигрыше, если обновитесь.
На самом деле, там O(N) и предложено решение O(log(N)).
> потому как есть немало шансов, что даже модуль из трёх строк спасет программистов от багов,
> возможныз при самописной реализации той же проверки на массив,
Точно так же есть немало шансов (мне сдаётся, что их там даже больше), что найденный по потребности и добавленный в зависимости модуль — это нифига не проверенное решение, и имеет свои подводные камни, фичи и баги. Как по мне, если кусок кода тривиален и прост, его нужно иметь в своём решении, а не тянуть как зависимость. По крайней мере, скопировать, а не переписать с нуля, раз уж он такой хороший.
> возможныз при самописной реализации той же проверки на массив,
Точно так же есть немало шансов (мне сдаётся, что их там даже больше), что найденный по потребности и добавленный в зависимости модуль — это нифига не проверенное решение, и имеет свои подводные камни, фичи и баги. Как по мне, если кусок кода тривиален и прост, его нужно иметь в своём решении, а не тянуть как зависимость. По крайней мере, скопировать, а не переписать с нуля, раз уж он такой хороший.
То, что используют миллион программистов всяко более оттестированно, чем то, что вы напишете сами.
… и любая проблема, сознательно или несознательно вносимая автором, сразу ломает миллион проектов.
Я бы не был настолько уверен насчёт качества тестов. Программист написал какие-то тесты и забыл. А миллионы программистов смотрят на модуль: код есть, тесты есть, можно пользоваться.
Напомню про платную программу под ms-dos, состоявшую из 0 байт и позволявшую быстро запустить предыдущую запущенную программу (трюк состоял в том, что вызывался предыдущий загруженный в память код).
Вопрос не в размере кода, а его продуманности и удобстве. Переиспользование кода — благо.
Вопрос не в размере кода, а его продуманности и удобстве. Переиспользование кода — благо.
Уточнение интересующимся про программу: https://habrahabr.ru/post/147075/
Переиспользование кода — благо
С некоторыми уточнениями:
- В общий код легко добавлять новые вещи, очень тяжело менять существующие и совсем тяжело, что то удалять. Что бы обеспечивать обратную совместимость, этот код обычно замусоривается.
- Любое изменение в коде, даже баг фикс требует регрессионное тестирование в коде, который переиспользует этот общий код. Почему? потому что даже если это баг, возможно, что бы его обойти, пристроили костыль и теперь, без бага, этот код не будет работать корректно.
Конкретный пример из npm, есть проект который использует angular2 и для него нужно поставить еще несколько пакетов, у всех пакетов стояла версия с префиксом ^ (версия такая то или совместимая) после npm update апликация перестала работать, выдавая странные ошибки, пришлось вручную перебирать версии, пока не нашли работающую комбинацию.
"переиспользование кода" должно иметь разумную границу.
Не вчитывался в каждый комментарий тут, но вроде только в одной ветви люди задались вопросом — почему такие элементарные и настолько массово используемые вещи, не внесены в стандартную библиотеку до сих пор?
Не вчитывался в каждый комментарий тут, но вроде только в одной ветви люди задались вопросом — почему такие элементарные и настолько массово используемые вещи, не внесены в стандартную библиотеку до сих пор?
Стандартная библиотека в данном случае — тянущаяся с собой каждый раз или встроенная в браузер?
Если первое — тут я тоже не понимаю, что мешает.
Если второе — ну, у каждого разработчика браузеров будет своё видение "стандартной библиотеки", пока они согласуют свои представления, пока заимплементят, пока вся юзер-база перейдёт на версии, которые имеют в себе эту самую библиотеку...
Если первое — тут я тоже не понимаю, что мешает.
Если второе — ну, у каждого разработчика браузеров будет своё видение "стандартной библиотеки", пока они согласуют свои представления, пока заимплементят, пока вся юзер-база перейдёт на версии, которые имеют в себе эту самую библиотеку...
"с собой или в браузере" — не знаю. Не настолько глубоко погружен в JS, что бы даже версию выдвинуть.
Но очевидно, что наиболее популярные вещи не должны оставаться "независимым пакетом", и кто-то, кто близок к разработке стандарта языка, должен следить и за содержимым стандартной библиотеки, втягивать их "внутрь", покрывать тестами, оптимизировать и так далее. От этого прямо зависит популярность и удобство инструмента.
Что там у нас сейчас самое популярное — java? Сколько сил вложено в стандартную библиотеку и в наиболее популярные библиотеки/фреймворки? Следующее C++? Тоже не нужно искать примеры, насколько лучше, когда язык и стандартная библиотека идут за потребностями разработчиков.
Но очевидно, что наиболее популярные вещи не должны оставаться "независимым пакетом", и кто-то, кто близок к разработке стандарта языка, должен следить и за содержимым стандартной библиотеки, втягивать их "внутрь", покрывать тестами, оптимизировать и так далее. От этого прямо зависит популярность и удобство инструмента.
Что там у нас сейчас самое популярное — java? Сколько сил вложено в стандартную библиотеку и в наиболее популярные библиотеки/фреймворки? Следующее C++? Тоже не нужно искать примеры, насколько лучше, когда язык и стандартная библиотека идут за потребностями разработчиков.
Но очевидно, что наиболее популярные вещи не должны оставаться «независимым пакетом», и кто-то, кто близок к разработке стандарта языка, должен следить и за содержимым стандартной библиотеки, втягивать их «внутрь», покрывать тестами, оптимизировать и так далее. От этого прямо зависит популярность и удобство инструмента.Они как раз начали этим заниматься и теперь довольно плодотворны на обновления языка.
Что там у нас сейчас самое популярное — java?JavaScript
Фам Нювен несколько лет провел, обучаясь программировать и исследовать. Программирование восходило к началу времен. Как та навозная куча за замком отца. Когда ее промыло ручьем на десять метров в глубь, обнаружились искореженные корпуса машин – летающих машин, как говорили крестьяне, еще от тех великих дней колонизации Канберры. Но та навозная куча была чистой и свежей по сравнению с тем, что лежало в локальной сети «Репризы». Были программы, написанные пять тысяч лет назад, когда человечество еще не покинуло Землю. И самое чудесное (самое ужасное, как говорила Сура) было то, что, в отличие от бесполезных обломков прошлого Канберры, эти программы все еще работали! И через миллион миллионов запутанных нитей наследования многие из старейших программ все еще выполнялись во внутренностях системы Кенг Хо. Например, методы слежения за временем у торговцев. Поправки вносились неимоверно сложно – но на самом дне лежала крошечная программа, которая гоняла счетчик. Секунду за секундой отсчитывала система Кенг Хо с того момента, как нога человек ступила на Луну Старой Земли. Но если приглядеться еще пристальнее… начальный момент был миллионов на сотню секунд позже; момент «ноль» одной из первых компьютерных операционных систем Человечества.
// Виндж, «Глубина в небе».
UFO just landed and posted this here
>> мы разучились программировать?
>> return toString.call(arr) == '[object Array]';
Скорее, не научились программировать на JS. Конкретный пример — исключительно фактологическое знание, не фундаментальное.
>> return toString.call(arr) == '[object Array]';
Скорее, не научились программировать на JS. Конкретный пример — исключительно фактологическое знание, не фундаментальное.
Напоминает http://youmightnotneedjquery.com/, где предлагают заменить
на
или
на
То бишь я сажусь писать новый проект и пишу 10000 строк кода с хелперами потому что умею прогать, зашибись.
$.getJSON('/my/url', function(data) {});
на
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
var data = JSON.parse(request.responseText);
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
или
$(el).fadeIn();
на
function fadeIn(el) {
el.style.opacity = 0;
var last = +new Date();
var tick = function() {
el.style.opacity = +el.style.opacity + (new Date() - last) / 400;
last = +new Date();
if (+el.style.opacity < 1) {
(window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
}
};
tick();
}
fadeIn(el);
То бишь я сажусь писать новый проект и пишу 10000 строк кода с хелперами потому что умею прогать, зашибись.
Думается приведенные в статье примеры скорей нужно если и вендорить то путем копирования кода под реп.
Вот конкретно данный функционал нет смысла писать самому, так как эти функции не являеются отдельными зависимостями, но частью одного целого.
Т.е. если на все приложение нужно сделать в 3 местах запросы на получение JSON, то правильнее будет загружать jQuery?
Ну, если ваше время и время тех, кто это будет потом поддерживать, бесконечно, то — нет, не правильнее.
Если это одноразовое приложение, у которого не будет поддержки по каким-либо причинам, то тоже — нет, не правильнее.
В остальных случаях — да, правильнее загрузить jQuery.
Если это одноразовое приложение, у которого не будет поддержки по каким-либо причинам, то тоже — нет, не правильнее.
В остальных случаях — да, правильнее загрузить jQuery.
UFO just landed and posted this here
А где граница между чужим проверенным кодом, который точно будет лучше (быстрее и/или надежнее) чем свой, и кодом непонятно откуда взятых NPM модулей с зависимостями от других непонятных модулей?
Она ведь у каждого своя? И основана на собственном опыте/умениях/целях?
По ссылке выше прямо в адресе сказано «вы _можете_ обойтись без». :)
Она ведь у каждого своя? И основана на собственном опыте/умениях/целях?
По ссылке выше прямо в адресе сказано «вы _можете_ обойтись без». :)
А не лучше тогда уже 1 раз написать код, который будет выдёргивать из необходимых вам либ реально используемый вами код и выгружать это всё дело в какой-нибудь deps.min.js? Многие и так держат у себя локальную копию того же jQuery, так что следить за обовлениями локальных копий не должно составить труда.
UFO just landed and posted this here
https://developers.google.com/closure/compiler/ — уже проделано до нас. Скажем спасибо корпорации зла.
UFO just landed and posted this here
Разумеется, в документации указаны требования к стилю кодинга, соблюдение которого гарантирует безопасность преобразований. ИЧСХ, эти требования очень часто соблюдаются, если js код генерирует не человек, а транслятор из программы, написанной на другом языке программирования.
Доброго времени суток
Использую Closure Compiler как корректор, иногда полезно :)
А корекцию вашего примера я понимаю так.
Переменные локальны и в именах нет особой необходимости он и сделал их анонимными.
Если хотите оставить имена используйте, --compilation_level=SIMPLE, правда и коррекция будет послабей.
Имена переменным, еще до Closure, давал a, b и т.д.
Использую Closure Compiler как корректор, иногда полезно :)
А корекцию вашего примера я понимаю так.
Переменные локальны и в именах нет особой необходимости он и сделал их анонимными.
Если хотите оставить имена используйте, --compilation_level=SIMPLE, правда и коррекция будет послабей.
Имена переменным, еще до Closure, давал a, b и т.д.
- слишком много времени уходит, на подбор лаконичного имени,
- после оптимизации или тестирования, часть их вовсе не нужны.
UFO just landed and posted this here
Содержимое
Не массив, объект
не являющиеся элементами цикла— пример можно о таком не слышал
Не массив, объект
Содержимое
Так это, привычка?
От вредных привычек можно избавляться, если счетчик задается задолго до цикла например: параметром функции, или в другом цикле?
От вредных привычек можно избавляться, если счетчик задается задолго до цикла например: параметром функции, или в другом цикле?
UFO just landed and posted this here
Содержимое
Простите но вы не ответили, на вопрос.
Я думал мы обсуждаем, Google® Closure Compiler, а не переходим на личности, или у Вас есть аргументы по поводу
Тогда лучше в приват.
но однобуквенные переменные, не являющиеся элементами цикла, вам не удастся протащить через линтер
— пример можно о таком не слышал
Иначе мы просто повторим комментарии к вашим публикациям с тем же нулевым результатом.
Я думал мы обсуждаем, Google® Closure Compiler, а не переходим на личности, или у Вас есть аргументы по поводу
с тем же нулевым результатом
Тогда лучше в приват.
Содержимое
— Если функция, должна выполниться для элементов с [параметр] и до последнего элемента.
— Если в цикле обрабатываю строку но хочу пропустить пару символов, которые определил в родительском, цикле.
Ну и где здесь душок?
Если я плыву против течения, это не значит что я не прав, может мне просто нужно в другую сторону
А Google® Closure может потому у меня не вызывает вопросы, что умею читать переменные по разному если нужно и без привязки.
Грубить даже не пытался, поправил, насчет массива? Но и я мог описаться и не раз.
Тему о Closure поднимали вы я просто высказал свое мнение и даже говорить пытался шепотом когда заметил ваши высказывания о моем мнении, хотя так хотелось убрать спойлер,
Ну в общем разговор не о чем.
Думаю, что ответил на ваш вопрос о Closure.
Вот эти вот «параметром функции» и «в другом цикле» — это признаки «кода с душком».
— Если функция, должна выполниться для элементов с [параметр] и до последнего элемента.
— Если в цикле обрабатываю строку но хочу пропустить пару символов, которые определил в родительском, цикле.
Ну и где здесь душок?
ваши представления о правильном и хорошем коде очень сильно различаются с общепринятыми
Если я плыву против течения, это не значит что я не прав, может мне просто нужно в другую сторону
А Google® Closure может потому у меня не вызывает вопросы, что умею читать переменные по разному если нужно и без привязки.
На личности я не переходил. До меня уже перешли, вроде, а я сразу открестился от дальнейшего обсуждения
Грубить даже не пытался, поправил, насчет массива? Но и я мог описаться и не раз.
Тему о Closure поднимали вы я просто высказал свое мнение и даже говорить пытался шепотом когда заметил ваши высказывания о моем мнении, хотя так хотелось убрать спойлер,
Ну в общем разговор не о чем.
Думаю, что ответил на ваш вопрос о Closure.
А я-то гадал чем они генерируют свои адовы скрипты для GMail и всего остального.
Тссс, строго между нами
$.getJSON('/my/url', function(data) {});
уже можно заменить на
fetch('/my/url').then(function (response) {});
$.getJSON('/my/url', function(data) {});
уже можно заменить на
fetch('/my/url').then(function (response) {});
fetch ещё не вошёл ни в один стандарт ecmascript
Хм, стандарт html это в смысле стандарт DOM API?
И может это для кого-то элементарно, но всё же: по ссылке https://fetch.spec.whatwg.org указано что это «living standard».
Что это вообще значит? Означает ли это что стандарт ещё не стабильный в будущем в нём могут произойти изменения ломающий обратную совместимость?
И может это для кого-то элементарно, но всё же: по ссылке https://fetch.spec.whatwg.org указано что это «living standard».
Что это вообще значит? Означает ли это что стандарт ещё не стабильный в будущем в нём могут произойти изменения ломающий обратную совместимость?
Полифиллы на что? https://github.com/github/fetch
Вполне закономерная ситуация, и проблеме не в npm, сотнях однострочных модулях и зависимостях, а в том, что у js очень бедная стандартная библиотека, люди начали решать ее отсутствие такими вот костылями чтобы не писать в каждом проекте isArray вручную, в конечном счете как это обычно и бывает, костыль поднялся и ударил людей по лбу.
Мне кажется, что вся работа программиста в экосистеме NPM сводится к написанию как можно меньшего количества кода, чтобы связать вместе существующие библиотеки, чтобы создать нечто новое, функционирующее уникальным образом для личных или коммерческих нужд.
А разве это не цель, для которой пишутся программы? Не Ваша цель, как программиста, а цель написания программы?
А разве это не цель, для которой пишутся программы? Не Ваша цель, как программиста, а цель написания программы?
UFO just landed and posted this here
Мы не разучились программировать, просто сейчас программирование выглядит именно так, что ты должен выпустить продукт как можно быстрее. Поэтому моя работа скатилась из программиста в собирателя модулей, это нормально сейчас на js проектах, устанавливаешь bower/npm пакет, и просто вставляешь его, своего кода в проекте 20%-30% и то половина этого это в целом работа с пакетами. В целом я уже забыл когда я хотя бы часов 5 программировал, а не имплементил пакеты. Что грусно.
Ситуацию бы исправили более-менее вменяемые библиотеки наиболее востребованных функций. Чтото вроде Glibc (из linux) или stdlib…
Они есть, но никому не нужны, т.к. всем важен размер яваскрипта. Сильно влияет на юзабилити сайта.
Что действительно нужно яваскрипту — так это оптимизирующий минификатор, способный выкидывать неиспользующийся код. Вопрос в том, как это сделать в таком языке, как яваскрипт...
Что действительно нужно яваскрипту — так это оптимизирующий минификатор, способный выкидывать неиспользующийся код. Вопрос в том, как это сделать в таком языке, как яваскрипт...
Внешняя утилита? Или как часть статического анализатора кода (Который тож будет не лишним).
Как-то компилятор/линковщик умудряется вставлять в окончательный бинарник прошивки для микроконтроллера не вообще всю библиотеку, а только реально используемые функции. Это что, принципиально невозможно в JS?
Малость мешает отсутствие статической строгой типизации. Никогда нельзя точно сказать, что реально используется, а что нет.
Именно! Приведу очень простой пример:
if (false){
var x = 0;
}
«x» in window; // true
Вот, есть ветка которая вообще никогда не выполнится, так как проверяется литеральная константа. Если мы её выпилим, то получим в выражении снизу уже не «true», а «false»!
if (false){
var x = 0;
}
«x» in window; // true
Вот, есть ветка которая вообще никогда не выполнится, так как проверяется литеральная константа. Если мы её выпилим, то получим в выражении снизу уже не «true», а «false»!
C ES-модулями это возможно. Погуглите rollup и tree-shaking.
Уже есть Underscore и Lodash
Мне кажется, проблема с маленькими модулями в том, что никогда не знаешь, как они поведут себя друг с другом и в каком стиле они вообще сделаны. Что будет, если вместо входной строки подать undefined? Или null? Будет ли исключение или молча превратится в "undefined"/"null"? Вы взяли left-pad и привыкли к одному поведению. Завтра вам понадобится right-pad, а его написал другой человек, у которого другие представления о граничных случаях. И ещё окажется, что порядок аргументов другой. Другое дело, если есть какой-нибудь string-utils, где сто функций с общим стилем, где всегда знаешь, как библиотека отреагирует на нетривиальный ввод и даже используя функцию первый раз можешь предположить, в каком порядке передавать параметры.
Ещё важный момент — это тестирование. В нашем воображаемом string-utils все функции покрыты тестами и нормально совместимы друг с другом: вывод одной можно подать на вход другой без всякого нежданчика. А если что-то случится, то фиксать будет одна команда разработчиков. А не так, что «совместимость с чужим пакетом пусть обеспечивают они, а не я».
Ещё важный момент — это тестирование. В нашем воображаемом string-utils все функции покрыты тестами и нормально совместимы друг с другом: вывод одной можно подать на вход другой без всякого нежданчика. А если что-то случится, то фиксать будет одна команда разработчиков. А не так, что «совместимость с чужим пакетом пусть обеспечивают они, а не я».
А потом конечный JS бандл раздуется до 10 мб.
А делов-то: нужно всего-навсего написать программу, которая будет выбрасывать неиспользуемый код, как это делают линкеры компилируемых языков.
Но, боюсь, для JS это будет совсем нереально из-за особенностей саомго языка.
Но, боюсь, для JS это будет совсем нереально из-за особенностей саомго языка.
webpack --optimize-minimize
Вам в помощь
Достаточно использовать микромодульный подход к написанию библиотек. Тогда в пакет включаются исключительно те микромодули, что реально необходимы. При этом размер самой библиотеки может быть сколь угодно большим.
Да ладно! Пять лет назад никого не беспокоило подклеить к проекту весь jQuery ради какой-нибудь одной шняги типа
Опять же если остро стоит такой вопрос, можно делать зонтичные проекты. Типа string-utils — это список зависимостей на string-utils-core, string-utils-regex, string-utils-formatting и т. д. Не надо всё — укажите, что конкретно надо. Суть в том, что всё под одним именем, пишется одной командой в одном стиле и тестируется вместе.
$(".blahblah").height("100%")
. Теперь каналы стали меньше? Вы таки уверены, что в собранном бандле каждая строчка вам приносит пользу и строго необходима?Опять же если остро стоит такой вопрос, можно делать зонтичные проекты. Типа string-utils — это список зависимостей на string-utils-core, string-utils-regex, string-utils-formatting и т. д. Не надо всё — укажите, что конкретно надо. Суть в том, что всё под одним именем, пишется одной командой в одном стиле и тестируется вместе.
Странно, что у автора этой заметки, ведущего инженера Stack Overflow, нет претензий к дичайшему гавнокоду в указанном "ключевом модуле" и что никто до сих пор его не выправил. Делать в цикле конкатенации по количеству необходимых символов с генерацией каждый раз нового String объекта на каждой итерации вместо "return ch.repeat(len — str.length) + str" — это какой-то эпикфейл.
String.prototype.repeat() поддерживается только в ES6+
Можно и без String#repeat сделать более оптимально.
Да, Вы правы. Тогда push в массив и join. Но никак не тот лютый трындец в сырце.
Вот тут уже подсуетились — https://github.com/azer/left-pad/pull/11
В волшебной стране javascript даже join тормозит, на самом деле.
В волшебной стране javascript даже join тормозит, на самом деле.
Ух жесть. Битовый сдвиг и конкатенация строки на себя же чтобы немного уменьшить алгоритмическую сложность и нагрузку на GC, но оставив по-сути проблему треша на своём месте… Мир JS жесток и беспощаден. )))
UFO just landed and posted this here
вместо того чтобы потратить 2 минуты и написать эту базовую функцию самому
Если бы я занимался переписыванием базовых функций, на основную работу времени бы не оставалось.
Плюс этим пришлось бы заниматься каждому разработчику, вместо использования уже готового решения.
Если бы я занимался переписыванием базовых функций, на основную работу времени бы не оставалось.
Плюс этим пришлось бы заниматься каждому разработчику, вместо использования уже готового решения.
UFO just landed and posted this here
результат стратегии NPM по решению проблемы dependency hell — каждому модулю своя копия всех зависимостей, нужной версии. (ничего ж не путаю? оно так устроено?)Нет, ужé не «копия всех зависимостей»: npm, начиная с третьей версии, складывает все зависимости в кучу в подкаталог node_modules первого уровня до тех пор, пока два модуля не потребуют одну и ту же зависимость разных версий (и тогда она, и только она, достанется каждому такому модулю в виде своей копии нужной версии). Экономия.
Объясните пожалуйста, где можно применить модуль leftpad и для каких задач он вобще нужен? Что-то нигде не нашёл...
UFO just landed and posted this here
Правда где-то посередине.
Нет, микромодули это замечательно. Пусть в модуле будет всего одна строка, но
— эта строка не дублируется в каждом проекте
— эта строка просматривается бòльшим числом глаз чем она просматривалась бы в одном проекте
— эта строка имеет меньшую вероятность внести ошибку в проект нежели написанная с нуля, особенно неискушённым разработчиком
— при нахождении бага в этой строке он будет исправлен сразу во всех проектах, использующих модуль
Кроме того, не надо забывать что эта строка вполне может развиться в сотню.
Проблему, наоборот, представляют собой крупные модули, которые добавляются в зависимости ради минимального функционала. И это как раз значит что большой модуль нужно разбить на маленькие.
Проблема npm и других новомодных пакетных менеджеров в другом — зависимости никак не верифицируются, а зачастую даже не фиксируются по версиям. В лучшем случае любое обновление или новая установка может всё сломать (что и было успешно продемонстрировано, хотя на деле происходит постоянно), а если задуматься то по npm|pip|bower|cargo|… прилетает вообще неизвестно что — код может быть подменён в любой точке от автора до последней мили и вы об этом не узнаете, нет никакой возможности убедиться что сейчас прилетело то же что неделю назад, или вам прилетело то же что и Васе. Или Пете, который провёл аудит кода. И постфактум, когда катастрофа уже случилась, концов не найти.
— эта строка не дублируется в каждом проекте
— эта строка просматривается бòльшим числом глаз чем она просматривалась бы в одном проекте
— эта строка имеет меньшую вероятность внести ошибку в проект нежели написанная с нуля, особенно неискушённым разработчиком
— при нахождении бага в этой строке он будет исправлен сразу во всех проектах, использующих модуль
Кроме того, не надо забывать что эта строка вполне может развиться в сотню.
Проблему, наоборот, представляют собой крупные модули, которые добавляются в зависимости ради минимального функционала. И это как раз значит что большой модуль нужно разбить на маленькие.
Проблема npm и других новомодных пакетных менеджеров в другом — зависимости никак не верифицируются, а зачастую даже не фиксируются по версиям. В лучшем случае любое обновление или новая установка может всё сломать (что и было успешно продемонстрировано, хотя на деле происходит постоянно), а если задуматься то по npm|pip|bower|cargo|… прилетает вообще неизвестно что — код может быть подменён в любой точке от автора до последней мили и вы об этом не узнаете, нет никакой возможности убедиться что сейчас прилетело то же что неделю назад, или вам прилетело то же что и Васе. Или Пете, который провёл аудит кода. И постфактум, когда катастрофа уже случилась, концов не найти.
Резюме: микромодули помогают избавиться от включения неиспользуемого кода в JavaScript, тем самым уменьшив размер файла. Но иногда это может привести к проблемам.
К сожалению часто микромодуль противоречит вот этому:
такие вещи начинают использовать не задумываясь. Кроме того у JS есть серьёзные проблемы со сборкой и получением JS нужных размеров и нарезанных нужным образом… (1 Mb JS файл часто не вариант качать, как и 50-60 мелких файлов)
Я короче в JS для Frontend отказался от любых сборочных систем, текущая ситуация меня не устраивает.
— эта строка просматривается бòльшим числом глаз чем она просматривалась бы в одном проекте
— эта строка имеет меньшую вероятность внести ошибку в проект нежели написанная с нуля, особенно неискушённым разработчиком
такие вещи начинают использовать не задумываясь. Кроме того у JS есть серьёзные проблемы со сборкой и получением JS нужных размеров и нарезанных нужным образом… (1 Mb JS файл часто не вариант качать, как и 50-60 мелких файлов)
Я короче в JS для Frontend отказался от любых сборочных систем, текущая ситуация меня не устраивает.
И как показала ситуация все это не шибко работает. Никто особо не просматривал этот left-pad, не считал оптимальность и не искал баги. Просто взяли и использовали. Потому что люди, которые готовы это делать обладают квалификацией, что написать самостоятельно. Остальные просто подключают.
И источник проблемы указан верно: слабая стандартная библиотека. И тут силами коммьюнити объединять общепринятые решения в библиотеки, как например Underscore, но многие предпочитают решать конкретную проблему и делать микромодули.
И источник проблемы указан верно: слабая стандартная библиотека. И тут силами коммьюнити объединять общепринятые решения в библиотеки, как например Underscore, но многие предпочитают решать конкретную проблему и делать микромодули.
Вот только к этому и стремились в сообществе node.js: не нужно писать свои велосипеды используй уже готовое. Поэтому сама ситуация не на столько ужасна, и первая на моей памяти. Единственное — раньше была проблема с папкой node_modules и то, что вес и вложенность превышала все разумные пределы.
С каких это пор «переиспользование кода» = «разучился программировать»? Очередное нытьё на тему «мы разучились программировать, мы все умрём». С какой стати использующие простой 11-строчный модуль по умолчанию приравниваются к тупым индусам? Вполне нормальный сценарий: человеку надоело копипастить эти 11 строк из проекта в проект, вот и заюзал модуль. «Проблема третьих лиц»? Что мешает проверить код этого микромодуля? Тем более всего 11 строк! А вот то, что у вас всё ломается при исчезновении какого-либо модуля из центрального репозитория — это проблема совсем не модулей-в-одну-строчку.
Да ладно вам, дайте людям поныть — повод же есть.
Проблема не в микросервисах и не в повторном использовании, просто в ноде нет качественной стандартной библиотеки. Нет скелета, который мог бы обрастать сторонними модулями. Была в начале года такая резонансная статья https://medium.com/@wob/the-sad-state-of-web-development-1603a861d29f, автор мог бы сейчас сказать "а я вас предупреждал"
вместо того чтобы потратить 2 минуты и написать эту базовую функцию самому
Если каждый разработчик сэкономит эти 2 минуты при решении своей задачи, то вся индустрия в целом сэкономит много человеко-часов. А таких функций может быть довольно много. На мой взгляд, автор просто не хочет замечать других проблем: отсутствие стандартизированной процедуры для верификации/ревью пакетов и ненадежная политика хранения пакетов.
Если каждый разработчик сэкономит эти 2 минуты при решении своей задачи, то вся индустрия в целом сэкономит много человеко-часов. А таких функций может быть довольно много. На мой взгляд, автор просто не хочет замечать других проблем: отсутствие стандартизированной процедуры для верификации/ревью пакетов и ненадежная политика хранения пакетов.
И эти люди еще косо смотрят на PHP.
В node_modules иногда и вовсе страшно заглядывать.
В node_modules иногда и вовсе страшно заглядывать.
А зачем вы туда заглядываете?
Всё же лучше злоупотреблять микромодулями на JavaScript из-за небольшой стандартной библиотеки, нежели злоупотреблять массивами на PHP из-за невозможности написать простой код (наподобие «{a: "b", c: 0xd}») для создания объекта на лету. (Да и удобство стандартной библиотеки PHP настолько не на высоте, что уж лучше она была мала и поощряла создание микромодулей.)
Есть мнение, что JS это новый PHP.
Доброго времени суток
Некогда не понимал зачем писать обертку для того, что есть и/или пишется одной строкой.
На мой взгляд подобный код не имеет смысла оборачивать в функции.
Некогда не понимал зачем писать обертку для того, что есть и/или пишется одной строкой.
На мой взгляд подобный код не имеет смысла оборачивать в функции.
function isArray(a){
return a && a.constructor === Array;
}
function pading(a, b) {
return Array(b).join(" ") + a;
}
Вот вы и ошиблись, isArray не все тесты проходит отсюда. Код для проверки возвращает:
Вместо четырёх true и остальных false.
true true true true undefined false null undefined false false false false true
Вместо четырёх true и остальных false.
Возможно, но первые четыре true, а остальные false, просто не boolean, но false.
А если нужно boolean, хотя это и не имеет смысла, допишите:
А если нужно boolean, хотя это и не имеет смысла, допишите:
function isArray(a){
return a && !!(a.constructor === Array);
}
Извиняюсь забыл сказать о последней проверке:
==> 5 // Небольшой факт: Array.prototype сам является массивом:
==> 5 // Небольшой факт: Array.prototype сам является массивом:
Кажется, вы хотели написать выше:
Последний тест этот:
Это собственно говорит, что не всё так просто.
function isArray(a){
return !!(a && a.constructor === Array);
}
Последний тест этот:
Array.isArray({ __proto__: Array.prototype });
не пройден. У правильной функции там false. Единственно верный способ там указан:if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
Это собственно говорит, что не всё так просто.
Извините, наверное мы говорим о разном, в стандартных ситуациях хватает и запроса к свойству 'constructor'
В не стандартных ситуациях, для получения значения 'class' тоже использую '{}.toString.call()':
Но сути дела это не меняет:
В не стандартных ситуациях, для получения значения 'class' тоже использую '{}.toString.call()':
function getTypeOf(a) {
return (void 0 === a || null === a ? String(a) : {}.toString.call(a).replace(/\[.+?(\w+)\]/, '$1').toLowerCase()) || '';
}
Но сути дела это не меняет:
зачем писать обертку для того, что есть и/или пишется одной строкой.
UFO just landed and posted this here
Спасибо
Спасибо, за внимание, не понял вашего совета.
где и что вы предлагаете дописать,
и что делать регуляркой, возможно вы не мне.
function isArray(a){
return !!(a && a.constructor === Array);
}
где и что вы предлагаете дописать,
и что делать регуляркой, возможно вы не мне.
UFO just landed and posted this here
Спасибо
Теперь понятней, полностью с вами согласен
Хотя, так можно оборачивать и команду print.
P.S. Когда то увидел, как на asm двумя байтами перезагрузить комп. не поленился сохранил как инклюд, чтоб не забыть, хотя и глупо это выглядело.
что на самом деле эти строки — это кусочек знания (о массивах, об исключительных случаях, и т.д.)
Хотя, так можно оборачивать и команду print.
P.S. Когда то увидел, как на asm двумя байтами перезагрузить комп. не поленился сохранил как инклюд, чтоб не забыть, хотя и глупо это выглядело.
Еще вариант
"undefined" === typeof Array.prototype.isArray && (Array.prototype.isArray = true);
Array.isArray || (Array.isArray = function(arg) {return arg.isArray;});
UFO just landed and posted this here
А если так,
Но это не принципиально, здесь пишу, как функцию только для понимания,
хота сам использую только
или
Модули и лоадеры удобно использовать только на этапе наброска.
А на этапе тестирования, отладки и оптимизации обычно стараюсь избавиться от зависимостей.
Но это не означает, что я их не использую.
function pading(a, b, c) {
return Array(b).join(c) + a;
}
Но это не принципиально, здесь пишу, как функцию только для понимания,
хота сам использую только
var str+=Array(2).join("0");
или
var str=Array(2).join("0") + str;
Модули и лоадеры удобно использовать только на этапе наброска.
А на этапе тестирования, отладки и оптимизации обычно стараюсь избавиться от зависимостей.
Но это не означает, что я их не использую.
UFO just landed and posted this here
Что то не так, вопрос не в варианте,
Написание модуля — функции, дает понимание законченности.
Дробление своей задачи на модули — функции, общее представление алгоритма.
Модули удобно использовать для демонстраций и изучения.
Но когда доходит до оптимизации ...;)
Это как в жизни, чем меньше зависимостей, тем легче дышится.
И т.д и т.п.
function pading(a, b, с) {
return (Array(b).join(c) + a).substr(-1*b);
}
Написание модуля — функции, дает понимание законченности.
Дробление своей задачи на модули — функции, общее представление алгоритма.
Модули удобно использовать для демонстраций и изучения.
Но когда доходит до оптимизации ...;)
Это как в жизни, чем меньше зависимостей, тем легче дышится.
И т.д и т.п.
зачем писать обертку для того, что есть и/или пишется одной строкой.
UFO just landed and posted this here
function pading(a, b, с) {
return a.length < b ? (Array(b).join(c) + a).substr(-1*b): a;
}
Я наверное не правильно, выражаюсь, все мои примеры только импровизация на коленке, для подтверждения возможностей JavaScript.
И любую задачу при желании можно описать одной строкой — если понимаю как, когда не понимаю ищу пример модуль или функцию изучаю, и если целесообразно добавляю фрагмент или вызов.
UFO just landed and posted this here
Проверка длинны 'a.length < b', намного быстрей чем 'a.length' + 'Math.max' + 'Array.join'
Но в целом, для решении любой задачи существует два варианта, либо что-то делать для ее решения либо нет.
А программист добавит, пока все работает, ничего не меняй ;)
function pading(a, b, с) {
return (b+=1,a.length < b ? (Array(b).join(c) + a).substr(-1*b): a);
}
Но в целом, для решении любой задачи существует два варианта, либо что-то делать для ее решения либо нет.
А программист добавит, пока все работает, ничего не меняй ;)
Я когда после java начал разбираться со зверинцем этим фронтэнд-разработчика тоже тихо прифигевал от этого садомазо с зависимостями для сокращения двух символов.
Например, модуль keyMirror, который встречал постоянно у других. Зачем?
писать keyMirror({blue: null, red: null});
вместо {blue: "blue", red:"red"}
Какой здесь чужой проверенный опыт?
Например, модуль keyMirror, который встречал постоянно у других. Зачем?
писать keyMirror({blue: null, red: null});
вместо {blue: "blue", red:"red"}
Какой здесь чужой проверенный опыт?
Вот недавно чинил велосипед с регуляркой для парсинга url от "умеющих" программировать программистов.
парсинг урл? регуляркой? еретики!
думаете, эти 1300 строк просто так занимают место в JRE?
Про ситуацию с библиотеками для работы со временем вообще молчу...
думаете, эти 1300 строк просто так занимают место в JRE?
Про ситуацию с библиотеками для работы со временем вообще молчу...
UFO just landed and posted this here
Вот вот, и я так считаю, но программисты подумали, а что такого спарсить хост из урла и пропустили вполне валидные урлы типа http://example.com?ref=http://example.com а в сочетании с специфическим поведением ie7 при присвоении атрибута frame.src — это дало весьма занятный баг :)
http://left-pad.io/ теперь для этого есть сервис
А что такое npm? Я вот не пользуюсь и бед не знаю.
Никогда не понимал вот эту ситуацию с «28000 файлов». Каждый раз когда использую node.js и ставлю какой-то модуль, потом ужасаюсь тому, сколько всего он за собой потянул и сколько у меня теперь на винте файлов. А когда надо что-то найти, это вообще мрак.
Статья понятна, логична, правдива. Но это не поможет. Потому, что человек ленив, и вместо того, чтобы думать своей головой — предпочтет использовать готовое решение. Даже, если это повышает шанс отказа (о проблемах никто не думает — пока они не случаются). Даже, если готовое решение подходит плохо (забьют молотком).
UFO just landed and posted this here
Я бы не стал мешать JS и .NET.
В JS очень велики накладные расходы от включения в код неиспользуемых функций на стороне клиента, тогда как в Java и .NET я не вижу проблемы включения в зависимости довольно большой сборки с точки зрения производительности.
Впрочем, чужие библиотеки я тоже стараюсь использовать как можно реже, а если и использую, то просто включая их код в свой проект, а не создавая зависимость.
Из последних извращений:
В JS очень велики накладные расходы от включения в код неиспользуемых функций на стороне клиента, тогда как в Java и .NET я не вижу проблемы включения в зависимости довольно большой сборки с точки зрения производительности.
Впрочем, чужие библиотеки я тоже стараюсь использовать как можно реже, а если и использую, то просто включая их код в свой проект, а не создавая зависимость.
Из последних извращений:
- Потратил 2.5 дня на попытку подключить C++ MySQL адаптер и заставить его работать без глюков. Успеха не добился.
- Потратил 1.5 дня на написание собственного адаптера на C++, используя документацию с описанием сетевого протокола.
- Потом ещё пару дней на перевод написанного на C# с полной асинхронной реализацией написанного кода.
- Допиливание сторонней библиотеки, реализующей LinqToMySql, для использования с асинхронным кодом.
UFO just landed and posted this here
Считаю проблема поставлена некорректно. Обратимся к .NET и менеджеру NuGet: систем принципиально не дает удалить пакет или конкретную его версию из репозитория пакетов. Надо чтобы пакет не было видно? unlisting поможет убрать его из поиска, но пакет всегда можно будет установить как зависимость другого. И вопрос микропакетов тут совсем непричем, тоже самое может случиться и с довольно популярными библиотеками.
Хорошо, что просто удалил, а если бы внедрил вредоносный код?
Доброго времени суток
Пару дней назад я здесь написал:
Сейчас, дошло.
Бездумное использование сторонних модулей без учета отказоустойчивости — по сути меня и тревожило.
P.S. Вспомнил, сколько трачу времени на подбор и проверку подключаемых модулей.;)
Пару дней назад я здесь написал:
Некогда не понимал зачем писать обертку для того, что есть и/или пишется одной строкой.Долго упирался, и не мог сформулировать, почему?
На мой взгляд подобный код не имеет смысла оборачивать в функции.
Сейчас, дошло.
Бездумное использование сторонних модулей без учета отказоустойчивости — по сути меня и тревожило.
P.S. Вспомнил, сколько трачу времени на подбор и проверку подключаемых модулей.;)
Хочется разбавить разговор своим скромным мнением. Я программист со стажем 20+, а последние 6 лет еще и компанию свою развиваю как собственник и директор. Так вот хочется из мира бизнеса аналогию привести.
Если собственник свои ключевые компетенции полностью делегировал сотрудникам и при этом не знает, как они это делают, — он попадает в полную зависимость от них. Выстроить процессы так, чтобы все были маленькими винтиками и делали свою маленькую работу можно. Вроде бы здорово все, все работает, можно не переживать. Но увольнение или болезнь ключевого сотрудника — беда.
А выход какой? Выход в том, что собственник должен как минимум уметь выполнять сам все ключевые функции. Поруководить цехом, продать клиенту услугу и так далее. В бизнесе все это известно уже лет 100, так почему в программировании должно быть иначе?
На мой взгляд умение искать аналогии в окружающем мире и использовать их на пользу проекту/продукту/компании и есть один из главных признаков высокой квалификации. А вовсе не умение найти в гугле функцию на 3 строки. Поэтому я никогда не доверяла экосистеме Руби и Node.js. Просто второе бомбануло раньше в силу более бурного роста.
Также все вышесказанное заставляет меня глубоко сомневаться в успехе ИТ-компаний, во главе которых не стоят программисты с опытом. Непрограммист смотрит на программистов как на чудаковатых волшебников и совершенно теряется, если кто-то из них не может или не хочет что-то делать, а он сам — собственник — не может стряхнуть пыль и расчехлить, чтобы временно заменить бойца. Не то, чтобы надо было постоянно бегать и тушить пожары, это как раз плохо. Но надо иметь возможность. Не терять хватку помогает обучение новых сотрудников и студентов — и в процесс не лезешь, и квалификацию не теряешь.
Если собственник свои ключевые компетенции полностью делегировал сотрудникам и при этом не знает, как они это делают, — он попадает в полную зависимость от них. Выстроить процессы так, чтобы все были маленькими винтиками и делали свою маленькую работу можно. Вроде бы здорово все, все работает, можно не переживать. Но увольнение или болезнь ключевого сотрудника — беда.
А выход какой? Выход в том, что собственник должен как минимум уметь выполнять сам все ключевые функции. Поруководить цехом, продать клиенту услугу и так далее. В бизнесе все это известно уже лет 100, так почему в программировании должно быть иначе?
На мой взгляд умение искать аналогии в окружающем мире и использовать их на пользу проекту/продукту/компании и есть один из главных признаков высокой квалификации. А вовсе не умение найти в гугле функцию на 3 строки. Поэтому я никогда не доверяла экосистеме Руби и Node.js. Просто второе бомбануло раньше в силу более бурного роста.
Также все вышесказанное заставляет меня глубоко сомневаться в успехе ИТ-компаний, во главе которых не стоят программисты с опытом. Непрограммист смотрит на программистов как на чудаковатых волшебников и совершенно теряется, если кто-то из них не может или не хочет что-то делать, а он сам — собственник — не может стряхнуть пыль и расчехлить, чтобы временно заменить бойца. Не то, чтобы надо было постоянно бегать и тушить пожары, это как раз плохо. Но надо иметь возможность. Не терять хватку помогает обучение новых сотрудников и студентов — и в процесс не лезешь, и квалификацию не теряешь.
Sign up to leave a comment.
NPM и left-pad: мы разучились программировать?