Как стать автором
Обновить
9
4
Андрес Ковалев @andres_kovalev

Разработчик

Отправить сообщение

Не так важно, но там не меня забанили, а именно того самого небезызвестного участника хабра.

Тем более это свои и типа сплочение, я там не знаю, солидарность проявить можно же?

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

Про контрибьют - как описано в статье, в основном нам не хватало функционала, который зачастую в принципе противоречил концепции эффектора (динамическое создание и уничтожение сторов). Поэтому такие костыли остались в нашей кодовой базе.

(дальше может быть не точно)

По поводу финансирования - как у любой топ-корпорации все финансовые вопросы четко планируются. На сколько мне известно, на определенном этапе планирования бюджета на финансирование этот вопрос поднимался, но так вышло что это примерно совпало с нашей "стадией принятия".

Спасибо за ссылки. У нас поверх MobX накручена своя архитектура, поэтому многие вопросы уже решены или должны решаться на ее уровне. Но вот асинхронные компьютеды мы как раз обсуждаем, поэтому смотрим на разные варианты решения, в том числе mobx-stateful-fn.

Читал Все Ваши статьи на хабре, спасибо за то что собрали в компактном виде большое количество полезной информации и интересные идеи. Моя любимая - про act :)

Конкретно в этой статье не со всеми пунктами и определениями согласен, но все равно было полезно почитать)

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

Конкретно про пункт с линтерами/тестами для MobX - если не ошибаюсь, это о том, что в MobX нет из коробки инструментов типа fork/allSettled. Как сказано в статье - мы тогда на волне хайпа тяготели к тому, чтобы выбрать Effector, поэтому многие критерии оценивали с этой позиции - если нет чего-то, что есть в Effector, то это минус.

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

Спасибо за Ваш труд. Все три материала нам знакомы и информация из них была очень полезна на этапе анализа проблем.

Здравствуйте. Спасибо, что прочитали. Мы конечно же приходили со всеми вопросами в чат, когда не могли найти ответа в документации. В блоке с историей я рассказываю, что на этапе повторного анализа я отдельно пришел в чат со всеми моментами, описанными выше (ссылки на переписку есть в статье). В итоге для каких-то проблем мы решения нашли, но на большую часть - нет. Например, так необходимая нам динамика пока что реализуется с помощью громоздкого key-value (ждем модели), а циклические зависимости не обнаруживаются и авторы пишут что это невозможно.

Чат гораздо оперативнее и удобнее, поэтому отдали предпочтение ему перед issues. Там почти на каждый вопрос отвечали в том числе лично создатели. По многим важным вопросам они сами создавали issue. Но в наших вопросах ничего особо нового не было и они в основном относились к одному из следующих случаев:

  • проблема известна, мы над этим работаем (тут issue уже не нужно)

  • проблема легко решается / это не проблема эффектора / это не проблема вообще (тут issue как будто не имеет смысла)

Пример в статье немного не соответствует описанию - спасибо что обратили внимание. Акцент был на том, что:

Функция filter в семпле принимает на вход два аргумента...

Т.е. проблема возникает в случаях, когда TypeGuard'ы нужны и для clock и для source :

sample({
  clock: event,
  source: store$,
  filter: (value, payload) => isSmth(value) && isSmth(payload),
  fn: (value, payload) => ???,
  target: ...
});

Здравствуйте. Я рассчитывал получить от Вас комментарий =)

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

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

const incr = createEvent();

const counter$ = createStore(0)
  .on(incr, value => value + 1);

const handleTitleChange = createEvent();
const updateTitle = handleTitleChange.map(e => e.target.value)

const title$ = createStore('title')
  .on(updateTitle, (_, value) => value);

Учитывая, что в современном FE разработчики (почему-то) избегают классы и предпочитают react-like код, я допускаю что мнения сторонних наблюдателей по поводу приведенных примеров может разделиться.

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

Странная подборка аргументов. Откуда она?
Всё, что есть в ООП, уже давно есть в других парадигмах

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

ООП не запрещает создавать объекты без состояния, ровно как и объекты без поведения.
Наследование закрепощает программу, делает трудным внесение изменений

Как и любой другой инструмент, может быть губительным не в тех руках. Возможно, речь о том, что наследование — очень сильная связь от общего к частному, а с сильными связями стоит быть осторожным. Уж точно наследование существует не для «выделения общих методов в базовый класс». Это как с KISS, который многие ошибочно считают призывом выносить все похожие участки кода в отдельный метод.
Инкапсуляция не имеет смысла

Нет, у данных аргументов правда существует какой-то источник?
Если не предполагается расширять родительский класс третьим классом — такое наследование попросту бессмысленно. Если вы создаёте магазин спиртных напитков, то классы Beer, Vodka и Vine можно унаследовать от класса Alcohol, но совершенно не нужно создавать ещё и класс Drinks, если только вы не хотите продавать ещё и, скажем, парагвайский чай.

Кроме классов существуют еще и интерфейсы, которые с точки зрения SOLID как раз желательно сегрегировать.
Но ведь никто не мешает создать, например, иерархию, где все реки мира (Конго, Сена, Темза, Амазонка, Колыма и т.д.) являются объектами одной всеобъемлющей «Реки», которой присущи свойства (например, состоит из воды) и действия (например, течёт), а уже она будет наследоваться от «Водоёма», который тоже состоит из воды, а от «Водоёма» можно унаследовать ещё и «Озеро», объектами которого будут отдельные озёра (Байкал, Каспийское море, Титикака и т.д.).

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

Это, вроде как, про одно и то же. Кстати, пример с человеком очень хорошо показывает, что наследование не может заменить композицию (иногда и наоборот). Как вы имплементируете человека, который играет в футбол от человека, который плавает, сделаете его наследником человека? А что нужно сделать, чтобы получить человека футболиста-пловца? Обычно, в таком случае композиция выиигрывает. Вообще, Composition over inheritance — один из основных принципов ООП, описанный еще в небезизвестной Design Patterns от GoF.
Но даже миллионы мух не убедят нас, что навоз — это вкусно

В целом статья получилась сумбурная, как это бывает обычно, когда она пишется «чтобы было». Цель Автора, вроде как, понятна, но для этого было достаточно прочитать последний абзац без всей воды с сомнительными аргументами и нечеткими контраргументами.
Ваше желание поделиться новыми для Вас знаниями можно понять, но почему хабр? Не достаточно ли было показать это своим друзьям или выложить на каком-нибудь форуме? Мало того, что статья на уровне «объясню как понял» (с примером из документации), так еще и код в ней, как говорится, с душком — учить такому совершенно не стоит торопиться:
Для начала нам нужен менеджер пакетов. Я выбрал npm, а он есть в Node.js
На самом деле для запуска Вам нужен Node.js, а без менеджера пакетов даже можно обойтись. Но судя по статье — нода, это просто что-то, где есть npm.
this – текущий класс
this не текущий класс, а контекст. В Вашем случае — экземпляр класса.
Далее стандартная обработка конструктора родительского класса super(props)
Конструктор не обрабатывается, а вызывается.

Ну и по коду.
const INTERVAL = 100;
На самом деле это не интервал, интервал в Вашем случае — 1000/INTERVAL (в описании Вы и сами пишете, что это частота).
this.stopTimer = this.stopTimer.bind(this);
В комментариях уже упоминались стрелочные функции и proposal class properties.
this.setState({value: this.state.value + 1})
Также в комментариях уже упоминалось о возможности асинхронного обновления состояния, в связи с чем оф. документация рекомендует использовать использовать функциональный стиль.
stopTimer(){
	this.setState({stopped: !this.state.stopped});
		if(this.state.stopped){
			clearInterval(this.timerID);
		}
		else
		{
			this.timerID = setInterval(() => this.increment(), 1000/INTERVAL);
		};
	}
}
Судя по названию метод должен останавливать таймер, но он его и запускает. Не должен ли он тогда называться toggleTimer()?
this.timerID = setInterval(() => this.increment(), 1000/INTERVAL);
и
clearInterval(this.timerID);
Повторяющийся код в данном случае можно вынести в отдельную функцию.
if (this.state.stopped) document.title = "Таймер";
Вы выносите в отдельную переменную value, но не stopped. Подобные обращения на несколько уровней вложенности тяжело читать. Сделать код читабельнее и короче Вам поможет деструктуризация.
Math.floor(value/INTERVAL/60/60)+":"+Math.floor(value/INTERVAL/60) % 60+":"+Math.floor(value/INTERVAL) % 60;
Подобные выражения лучше предварительно вычислять и сохранять в соответствующие переменные, тем более что их значения по коду используются несколько раз (для отображения в заголовке окна и в самом таймере).
{value % INTERVAL < 10 ? '0' : ''}{value % INTERVAL}
Для добавления ведущих нулей обычно используется padStart(), преимущества которого особенно заметны в тех случаях, когда ведущих нулей больше одного. Интересно, что ведущие нули есть только у децисекунд. Если Вам было лень дублировать ту же логику для секунд/минут/и т.д. могли бы выделить ее в отдельную функцию.
Также надо исправить метод increment(), чтобы он останавливался, когда stopped = true:
Разве не для этого был остановлен таймер?
<div class="container-fluid align-items-center">
Оф. документация любезно просит использовать className вместо class, о чем React сигнализирует в консоли разработчика своими warning'ами.
&nbsp;
Совместно с flexbox'ом выглядит очень прогрессивно =)

Даже после исправления всех этих упрощений и ошибок (в т.ч. орфографических) статья все еще не сможет называться «Изучаем реакт», скорее «Изучаем еще один способ сделать таймер с применением реакта». Пожалуйста, не торопитесь делиться тем, в чем еще сами не до конца разобрались, тем более на ресурсе такого уровня. Подобных статей на хабре итак много, что превращает его в помойку из выброшенных велосипедов.

Для тех же, кому действительно хотелось бы изучить реакт за один день, могу посоветовать данный материал, в котором все по порядку объясняется на доступном языке и наглядном примере (есть продолжения про redux и router). И да, дня вполне хватит, чтобы его прочитать и попрактиковаться. повторив все действия автора.

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

От себя хотел добавить, что Ваши оппоненты делают упор на том, что условия контракта были несправедливы или неадекватны (слишком большое задание, слишком мало времени). Но ведь никто не заставлял их принимать. А если автор принял, то уже не важно, как он бы хотел, важно как договорились.

...остановите планету, я сойду...

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

В последнем вопросе ответ неправильный - чтобы что-то вывелось, надо App срендерить, а там он просто экспортируется)

Спасибо за интересный материал. Вопрос к автору библиотеки - поддерживает ли она в каком-либо виде асинхронность?

А как быть со случаями, когда пропы компонента меняются и коллбек должен об этом знать? Создавать в замыкании переменные, через которые прокидывать пропы?

```

export const clear = () => instances.clear()

```

=/

Это уже не первая библиотека, которая прячет за "хуками" использование глобальной переменой спрятанной в самой библиотеке (`instances`). Примерно так же поступает бОльшая половина библиотек "убийц редакса" (я не поклонник редакса, просто отметил).

Вопрос из зала - как Вы это тестируете?

Поясните, что хотели сказать этим комментарием? Ведь typeof null на самом деле не объект.

Я не имел в виду реализацию, я имел в виду в принципе его наличие. DI на фронте не очень популярен в других библиотеках и фреймворках. Я не поклонник Angular, но вариант с вынесением логики в сервисы и внедрение их в компоненты мне нравится и я думаю, как бы это объединить с прелестями React'а. Вы наверняка скажете, что эта проблема уже давно решена в $mol, причем более изящно, но так уж вышло, что я в нём не силен (хоть и читал почти все Ваши статьи про него) :)

Информация

В рейтинге
1 026-й
Откуда
Ухта, Коми, Россия
Дата рождения
Зарегистрирован
Активность