Pull to refresh
16
0
Dmitry @Riim

User

Send message

Тут просто разные типы мышления. Любители повсеместного const используют его для заявления фактической константности, а любители повсеместного let, для заявления идеологической константности. Одним больше помогает одно, другим другое. Большинство исходных утверждений от которых вы отталкиваетесь и делаете какие-то выводы ложны для меня. Вот например:


Просто сам факт того, что ответ уже есть и не надо его искать

зачем его искать я хз, никогда этим не занимался. Видя незнакомый мне код я пытаюсь понять его суть и суть того, что лежит в переменных. Лишние (идеологически) const меня именно сбивают.
И так далее по остальным приведённым аргументам.


Ещё один уже объективно ложный аргумент любителей const (вы его не приводили, но он уже есть выше нашего разговора), это то, что используя let можно выстрелить себе в ногу. Если у вас let тоже стреляет (или стрелял и вы перешли на const), то вы пишете кривой код. Без обид)). Смотрите как это происходит:


class SomeView {
  onBtnClick() {
    let btn = this.$('btn');
    btn.disable();
    getSomeData().then(res => {
      btn.enable();
      // ...
    });

    // Здесь другой программист решил ещё логики добавить заиспользовав существующую переменную.
    // Он забыл учесть, что обрабатывающий запрос колбек ещё не выполнен (может не заметил его не став подробно разбираться в коде, которого часто больше чем в примере), а когда будет выполнен, в нём окажется неправильная кнопка.
    btn = this.$('other-btn');
    // ...
  }
}

Только так стреляет let. Почему этот код кривой? Потому что нет возможности при наследовании переопределить код обрабатывающий запрос. Как минимум нужно переписать так:


class SomeView {
  ready() {
    this.btn1 = this.$('btn');
  }

  onBtnClick() {
    let btn = this.btn1;
    btn.disable();
    getSomeData().then(this.onSomeData.bind(this));

    // Здесь другой программист решил ещё логики добавить заиспользовав существующую переменную.
    // Всё у него будет норм)).
    btn = this.$('other-btn');
    // ...
  }

  onSomeData(res) {
    this.btn1.enable();
    // ...
  }
}

И вот let уже никуда не стреляет и так во всех подобных случаях.


Если же есть желание написать именно с использованием колбека, то опять же let выигрывает, потому что его просто не будет: программист использующий осознанный const и знающий о ловушке обязательно сделает эту переменную константой предупредив коллегу в будущем. У него просто есть такая возможность, ведь в проекте с осознанным использованием const эти const просто так не расставляются. Другой программист увидев const задумается зачем он здесь и заметит колбек. При бездумном const этого не происходит: в 99.9% случаев замена const на let ничего не ломает и программисты настолько к этому привыкают, что совершенно перестают задумываться о такой ловушке. Const бездумно меняется на let, колбек не замечается и здрасте новый баг. И такой баг я не раз чинил в проектах с бездумным const.
Вот и получается, что в реальности, при грамотном коде, стреляет именно const, а не let.

Некоторые решения на просторах npm предлагают замену скролла отступом или блоком, который стилизован под скролл (простая серая полоска), много магии, но проблему они не исправляют.

у меня добавление отступа исправляет проблему, что я делаю не так? Да и магии в таком решении явно не больше чем в предложенном. Сейчас попробовал на действующем проекте после скролла страницы в инспекторе добавлять на body:


position: fixed;
overflow-y: scroll;
top: -100px;

куча разных артефактов вылазит. Колбасит элементы уже имеющие position: fixed (явно не по причине несовпадения top: -100px с проскроленным значением) и сжимает body по ширине. Со вторым не проблема, нужно ещё width: 100% на body добавлять, а вот что происходит с фиксированными элементами нужно разбираться, но добавление отступа на body проблем не создавало.

Ещё одна статья на эту тему: Как меня задолбало противопоставление хренова const чертову let.
Ключевая на мой взгляд мысль:


Действительно ли вы хотели сообщить, что ответ никогда не должен меняться, или просто так совпало, что вы нигде его не меняли?

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

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

Всё только начинается)

Array.splice это Array.splice — статический метод класса Array. Если нужно кратко записать метод экземпляра (Array.prototype.splice), то обычно используется запись Array#splice.

Секция scripts в package.json.

Зачем вообще показывать состояние фокуса, если пользователь не прикасался к клавише Tab? Это лишняя информация для него. Нужно делать так:
На body висит класс _noFocusHighlight который прячет всё (почти всё, про исключения ниже) отображение фокуса, при нажатии на Tab он снимается и пользователь видит состояние фокуса, раз нажал на Tab — значит оно ему нужно. При любом клике, после которого document.activeElement указывает на body, возвращается класс _noFocusHighlight. Возможны некоторые исключения, например, текстовые поля, состояние фокуса на которых отображается даже если было получено мышкой.
Вот код: тыц.

Интересная идея с возможностью извлекать статический тип из валидатора. Надо будет попробовать так сделать.

Реализовал оба варианта. keypath подставляется сам когда есть вложенность. Вместо message можно использовать type, в таком случае сообщение об ошибке будет сформировано с учётом .or:


om(om.custom({ validator, type: 'type1' }).or.custom({ validator, type: 'type2' }), type3);
// бросит TypeError('Expected "type1" or "type2"')

Примеры в сообщении выше тоже рабочие.

Привет. Можно научить понимать возвращаемую валидатором строку как сообщение об ошибке при неудачной проверке:


om.number.and.custom(value => value > 18 || 'Вы ещё слишком маленький')

Можно в этой строке некоторые простые замены делать, например, {keypath} заменять на место где случилась ошибка.


Ещё вариант — научить .custom() понимать не только функцию, но и объект с функцией и строкой ошибки:


om.number.and.custom({
    validator: value => value > 18,
    message: 'Вы ещё слишком маленький ({keypath})'
});

Если нужно такое, создайте issue чтобы я не забыл. Сделаю в скором времени.

Ну да, просто тестировать имеет смысл на реалистичных сценариях.

ну там вполне реалистично, 1-2 зависимости, можно увеличить до 1-3, но не более, это будет похоже на 99% ячеек в реальном приложении. А про глубину нет смысла думать, как я уже говорил, ячейке пофиг на какой она глубине, на скорости её обработки никак не отражается, это просто способ сделать их много.


Ну там долго расписывать, какая именно часть его не понятна?

в общих чертах вроде понял, вопрос уже другой: это реально даёт результат в плане ускорения или это пока просто эксперимент? Чем больше понимаю алгоритм, тем большее ощущение, что это никак не должно быть быстрее использования Set и тем более массива при малом числе зависимостей.

Разные реализации по разному справляются с разным числом зависимостей. Ну грубо говоря indexOf на большом числе зависимостей может начать тормозить.

так и я о том же. Глубину то ты зачем уменьшить хочешь? Ты не понимаешь, что увеличивать число зависимостей можно не трогая глубину?


трекинг происходил как можно быстрее

ну это понятно, я про идею алгоритма спрашивал.

а в худшем — что-нибудь ломается капитально

ok, на самом деле я немного о другом случае описанном здесь. А то о чём говоришь ты похоже из этой серии. Странно, но со мной такого ни разу так и не случилось, может мне очень повезло, а может что-то в моём фреймворке не даёт этому происходить. В любом случае хорошо, что ничего подобного больше не случится ни с $mol_atom, ни с cellx.


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

так я и не спорю про разное число зависимостей, я про то, что замена большей глубины на большую ширину без изменения числа зависимостей ничего не даст. Так зачем ты это требуешь?


но без indexOf

выглядит довольно запутанно, плюс отталкивает slaves с разными типами значений (в masters как я понял тоже самое) и лишние итерации при переборе masters (if( !master ) continue). Set#has конечно чуть медленнее, но неужели вся эта дополнительная возня действительно даёт результат? Можешь поверхностно объяснить идею?

Про глубину в очередной раз ответил чуть раньше.


Чтоб можно было на полученные от бека данные вешать реактивные поля, и потом не париться тем, что перед JSON.stringify обратно на сервер эти реактивные поля нужно будет вычищать.

я для подобного использую декоратор NonEnumerable.

но когда стреляло — отрывало руки по локоть

можно пример? Я находил у себя в приложении пару мест с таким лишним вычислением, там всё гладко было. Я именно намеренно искал, никаких проблем не возникало.


И надобности в сильно глубоких деревьях мне встречать не приходилось

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


Трекинг большого числа зависимостей
Инвалидация большого числа зависимых

я вижу у тебя для хранения родительских и дочерних ячеек используется Set, has на котором, при достаточно большом количестве айтемов, будет заметно быстрей, чем indexOf на массиве (https://jsperf.com/array-indexof-vs-set-has/). Наверно, в таком кейсе твой вариант действительно будет быстрее. Я же выбрал массив, тк. при малом числе айтемов уже indexOf быстрее, плюс нативный for-of тогда ещё рано было использовать, а Set#forEach был заметно медленнее обычного цикла. Малое число зависимостей — это 99.9% случаев. Мой бенчмарк показывает как ведут себя библиотеки в этих 99.9%, ты же предлагаешь мне бенчмарк под 0.1% заявляя, что он будет более адекватным. Мне кажется ты всё же не прав.

Корректность всё же важнее производительности

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


Или есть какие-то новые более адекватные бенчмарки?

Не понимаю почему ты не веришь в адекватность такого бенчмарка. Ну вот уменьшу я глубину (число слоёв) одновременно увеличив количество ячеек в каждом слое и что дальше? Если количество вычисляемых ячеек по которым пройдёт сигнал будет тем же, то и результат будет абсолютно тем же.
Все бенчмарки для такой библиотеки, скорей всего, можно разделить на два типа: 1 — скорость создания экземпляра ячейки, 2 — скорость прохождения сигнала по вычисляемым ячейкам. Остальное практически не имеет какого-либо смысла. Что ты предлагаешь ещё замерить? Скорость чтения не вычисляемой ячейки? Зачем?

Начиная с v1.8 алгоритм тот же, что и в mobx. А на счёт менее продвинутого я бы поспорил, да в старом алгоритме есть один мелкий нерешаемый недостаток, но зато он минимум в 3 раза быстрее. В три раза медленнее — это лучшее, что я смог получить с нового алгоритма избавившись всего лишь-то от одного недостатка с которым вполне нормально жилось. Довольно сомнительное улучшение.

получаете поле объекта, а в python — это-таки поле класса

ок, в общем-то я и и предлагаю использовать поля класса, на js будет так:


class BaseTooltip {
    static template = 'baseTemplate'
    constructor(content) {
        this.render(content)
    }
    render(content) {
        console.log('render:', content, this.constructor.template)
    }
}

new BaseTooltip('content')

class SpecialTooltip extends BaseTooltip {
    static template = 'otherTemplate'
}

new SpecialTooltip('otherContent')
// render: content baseTemplate
// render: otherContent otherTemplate

Всё зависит от того — хочет ли он этот самый template, в какой-то момент, менять.

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

что человек его не знает

не претендую.


Это, вроде как, не совсем то, чего хотел топикстартер

почему? Вроде именно этого он и хотел. Какие недостатки у такого решения для его задачи?

Делить на ноль действительно плохо, не делайте так.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity