# Понедельник 67 твитов
всем привет, эту неделю с вами будет @deepsweet. меня зовут Кир, кто-то может помнить меня по Яндексу, для остальных я просто JS-разработчик
2:32т.к. у меня GMT+7 и вы скорей всего спите, я пока поспамлю темами, на которые мне было бы интересно поговорить :)
2:33webpack, Babel, React, Flux, BEM (в хорошем смысле), изоморфность, фотки тупых людей, иммутабельность, парное программирование, Вьетнам.
2:38@jsunderhood GMT +7 это какой город?)2:42
.@ivan_krivonos Хошимин
2:42на текущей работе есть всё из этого списка, очень красиво переплетённое. да-да, React + BEM :) с наследованием по уровням переопределения.
2:49@jsunderhood уже смотрели в сторону CSS Modules? Может ли этот концепт заменить BEM? Насколько вообще оно практично?3:19
.@alexeyraspopov да, смотрели ещё с первых коммитов в css-loader – сама идея уникального локального скоупа для стилей компонента заманчивая.
3:23.@alexeyraspopov но лично мне совсем не нравится подход к внедрению этого в React – github.com/css-modules/cs… – когда компонент думает о теме.
3:24для всех – тема CSS Modules началась примерно отсюда github.com/webpack/css-lo…, и развивается дальше здесь github.com/css-modules
3:24идея в чём-то гениальна: css-loader для webpack превращает классы из стилей в хэши, которые потом экспортируются как из обычного js-модуля.
3:30дальше где-то, где эти стили нужны (в том же react-компоненте), они импортируются, и появляется доступ к маппингу "класс -> хэш".
3:32но для уникальных хэшей всё равно нужны уникальные классы, и для этого внутри стилей вполне можно использовать то же BEM-именование.
3:38в итоге получается такая себе автоматизированная связка BEM + <style scoped> без лишней боли по поводу конфликтов и пересечений.
3:43@jsunderhood разве уникальные? Можно использовать одни и те же имена в разных файлах и они будут разруливаться без конфликтов3:44
.@alexeyraspopov я имею в виду, что внутри файлов стилей всё равно нужно как-то именовать классы, и идея BEM (например) здесь очень подходит
3:45.@alexeyraspopov я ведь правильно понял, что одни и те же селекторы из разных файлов будут иметь одни и те же одинаковые хэши?
3:47@jsunderhood нет, разные. В это вся фишка — никакого конфликта имен между файлами3:52
.@alexeyraspopov а если у меня стили для одного компонента находятся в разных файлах? судя по докам берётся хэш от внутренностей :local()…
3:55@jsunderhood У вас есть где-то снаружи project-stub или мини-проект, где можно увидеть как именно это красиво переплетено?4:59
.@toivonens "стаба" нет, мы слишком ленивые и занятые. есть только все нужные технологии github.com/yummies/yummies + github.com/yummies/babel-…
5:00кстати, как вам затея с эмоджи в коммитах? github.com/yummies/genera… 😼
5:02@jsunderhood @toivonens мне вот этот стартер кит понравился из последних github.com/cdebotton/reac… там есть css modules5:05
собственно, основная идея React + BEM в том, что JSX – говно, а BEMJSON – добро github.com/yummies/yummie…
5:11дальше – наследование github.com/yummies/core-c…, ещё дальше – "уровни переопределения" или, как мы их называем, "слои" github.com/yummies/babel-…
5:12BEM-модификатор – это класс, который (автоматически) наследуется от класса react-компонента и до/переопределяет BEMJSON из его render()'а.
5:15про это всё определённо нужна отдельная статья + отдельный стартер-кит, но я уже даже не решаюсь давать обещания, всё тянется уже с мая.
5:17самое крутое, что это в принципе никак не отменяет ни компоненты высшего порядка, ни декораторы, ни прочие подходы. очень удачно уложилось.
5:22уже в черновиках статья. в целом – Flux может быть абсолютно любым. RT @RusAlexander: @jsunderhood на чью реализацию похож ваш #flux ?
5:58завтра будет день Flux: иммутабельные деревья, единое состояние, курсоры, GraphQL-like декларативность, префетчинг на сервере, изоморфность.
6:03@jsunderhood как вы относитесь к @WebComponents ? Правда ли что появление #react есть следствие провала компонентов ?6:10
.@RusAlexander личное моё мнение – это мертворожденная технология, которую зря пытаются форсить. React появился из-за общей убогости DOM.
6:14.@RusAlexander с другой стороны, возможно ещё просто не пришло время, и появление "shady DOM" вместо полноценного Shadow DOM тому пример.
6:22@jsunderhood Как уровни переопределения работают в этой связке? В html.6:36
.@operatino в конечном итоге импортируется фабрика уже собранного и склеенного по всем уровням реакт-компонента.
6:37.@operatino можно до/переопределять что угодно, как в BEMHTML, хоть тэг, хоть внутренности.
6:38довольно интересная концепция получилась с "темами" – тема просто является отдельным слоем, начиная с темы "reset" github.com/yummies/theme-…
6:41@jsunderhood То есть это кастомная реализация сборки с мерджем компонентов? Без БЭМ шаблонизаторов? Какие тулзы замешаны?6:42
.@operatino основа – webpack + Babel, кастомной сборки как таковой нет, всё нужное уже есть в webpack + немного магии через babel-плагин.
6:42пример корневого `.yummies.yml` из внутреннего проекта gist.github.com/deepsweet/15c8…
6:46видимо эта неделя наконец-то заставит нас с @mistadikay сделать starter-kit.
6:47магия заключается в спец. #-импорте:
import Example from '#example';
import ExampleTypeTestSizeBig from '#example?_type=test&_size=big';
Babel-плагин матчится на символ `#` в импорте и начинает искать файлы по слоям из конфига. находит – включает в цепочку наследований.
6:51в конечном итоге в Example попадает обычная фабрика реактового компонента, который отнаследован по очереди от класса каждого слоя.
6:52пример модификатора github.com/yummies/core-c… – `super.render()`
6:55@jsunderhood много времени уже прошло, не сожалеешь? :)7:05
.@silentroach 1) не сожалею, по-моему я ушёл очень вовремя 2) уже жалею :) но опыт жизни в Азии всё равно очень интересный и бесценный.
7:08@jsunderhood Почему жалеешь? Что не так с Вьетнамом?7:09
.@verkholantsev это страна, в которой уровень экономического развития слишком резко и быстро обогнал уровень сознания. со всеми вытекающими.
7:10@jsunderhood что думаешь про redux?7:11
.@silentroach Redux – крутой, но меня не покидает ощущение, что это какой-то мимолётный промежуточный этап, как и webpack HMR в целом.
7:13@jsunderhood @andrey_sitnik @silentroach а как быть тогда, какую flux либу использовать?8:46
.@thought_sync @andrey_sitnik @silentroach сегодня – Redux :) мой ответ был немного не о том, что Redux не надо использовать.
8:46Flux хорош именно тем, что это сначала концепция, а уже потом – реализация. мы на первом проекте делали с нуля руками, чтобы прочувствовать.
8:48главное сильно и навсегда не залипнуть на "каноническом" Flux, это лишь начало :) завтра будут стримы, а послезавтра одно лишь телевидение.
8:51@yuritkachenko @jsunderhood смотря что называть мимолетным. Для кого-то - 5 лет. Для фронтенда год-два быть в топе - очень круто.8:51
@jsunderhood почему Въетнам? Как там ощущения вне офиса (или где вы работаете)? Долго там уже?9:13
.@beshur почему – без понятия, просто было интересно :) вне офиса круглый год душное и влажное лето лето. вот уже почти год как живём.
9:14.@beshur почему – без понятия, просто было интересно :) вне офиса круглый год душное и влажное лето. вот уже почти год как живём.
9:15быстро набросал кое-какой Starter Kit github.com/yummies/starte… 🔥
10:04уже не представляю как можно жить без "Object Rest/Spread Properties" github.com/sebmarkbage/ec… – даже если не войдёт в ES7, буду юзать плагин
11:08вообще, колонка Stage в ES7+ пока выглядит довольно печально github.com/tc39/ecma262
11:11Create random JSON objects using json-spawn and Chance.js github.com/luisfarzati/js…
12:31Awesome list of Redux examples and middlewares github.com/xgrommx/awesom…
14:15совсем забыл, со мной можно говорить про Diablo 2.
14:18@jsunderhood Еще вот мои наработки по коллекционировании ресурсов об реактивности xgrommx.github.io/rx-book/conten… также тут есть видео, лекции и тд.14:31
# Вторник 92 твита
доброе утро. вчера спрашивали какое Flux решение мы используем… начну немного издалека, а закончу постом в медиум со ссылкой на репозиторий.
4:04хорошее интро в Immutable Data на примере Immutable.js всё от того же фейсбука youtube.com/watch?v=I7IdS-…
4:06а что если представить одно большое дерево данных, в котором хранится всё состояние приложения, от нажатости чекбокса до запрошенных данных.
4:10это дерево иммутабельное, т.е. каждое изменение влечёт за собой новую версию дерева, отличную от старой.
4:12в типичном приложении в дереве будет не так много основных явных веток, типа products list, product info и т.п.
4:14"курсор" – это своеобразная ссылка на ветку данных в дереве. простой пример на основе всё того же Immutable.js github.com/facebook/immut…
4:15"cursor path" – это путь к этой ветке или к конечным данным. обычно представляется в виде массива, [ 'products', ID, 'details', 'price' ].
4:17для дерева и курсоров мы используем Baobab github.com/Yomguithereal/… – ничего лишнего, всё довольно просто и прозрачно.
4:19дерево эмитит событие `update`, на основе которого можно и нужно обновлять, например, курсоры, т.к. дерево уже новое, а ссылки старые.
4:23событие `update` есть и у самих курсоров – изменились данные по конкретному пути в дереве.
4:27сначала мы делали так: всё дерево помещается в локальный стэйт корневого компонента. по подписке на update стэйт обновляется новый деревом.
4:28от корневого компонента прямо через пропсы в рендере детям разливались курсоры на ветки данных, которые им нужны.
4:30это было очень удобно: каждый нвоый рендер самообновлял курсоры. получался такой водопад данных сверху вниз, который ещё и саморазливался.
4:31из минусов: жёсткая связанность компонентов через иерархию: компонент C зависел от курсора, который ему даст B, а тот в свою очередь от A.
4:32"лишние" рендеры довольно легко отсекались через shouldComponentUpdate(), как и было завещано.
4:33но потом моё внимание привлекла очень интересная особенность Baobab: есть событие `get` – были запрошены данные по такому-то пути. геттер.
4:34т.е. в теории можно было узнать, что запрошены данные, которых ещё нет в ветке. и сделать замозаполняющееся дерево :)
4:36Declarative data fetching in React components with Baobab medium.com/@mistadikay/de…
4:37компоненты – максимально тупые. они просто рисуют данные как будто эти есть и всегда были. почти каждый компонент сам знает свой cursor path
4:38в рутовом компоненте идёт подписка на геттер из дерева – если данных, которые запрошены отрисовкой компонента ещё нет, то дёргается экшн…
4:38…который, как в самом обычном Flux, диспатчит событие, которое ловит стор, который складывает эти данные по нужному cursor path в дерево.
4:40компонент по событию `update` от своего курсора самообновляется и перерисовывается. profit.
4:41по ссылке ниже есть более подробное описание и даже тестовый репозиторий с простым, но в том же время полноценным примером.
4:43самый жир затеи – github.com/mistadikay/rea… – декларативный "запрос" данных. что-то вроде того же GraphQL, только поверх обычного Rest.
4:45т.е. компонент просто декларативно описывает откуда в дереве брать данные. а как, когда и почему они там оказались – не важно. просто рисуй.
4:46ещё одна интересная особенность – в дереве есть две осовных ветки – data и ui. в data собственно данные, а в ui – визуальные состояния…
4:49типа выбранного пункта, нажатости чекбокса и т.д. это позволяет практически забесплатно сделать "историю" – отматывание всего состояния.
4:50т.к. иммутабельное дерево создаёт новую версию на каждое изменение, ни что не мешает сохранять эти версии и сделать историю как в фотошопе.
4:51@jsunderhood Правда про CLJS, но отлично про иммутабельность, историю из оной и вообще. youtube.com/watch?v=lDkrXT… youtube.com/watch?v=tUtLe1…4:56
@jsunderhood А в вашем случае "дерево" — это BEMJSON или ещё над ним абстракция?5:06
.@toivonens нет, не BEMJSON, произвольная структура данных, в ветки которой чаще всего складываются данные от сервера as is.
5:06.@toivonens но твою идею я понял :)
5:07@jsunderhood Просто ты упоминал до этого BEMJSON, и я пытаюсь понять, куда вы его там встроили.5:08
.@toivonens это никак не связано с Yummies и BEM. пример в репозитории специально написан на JSX :) просто концепция, применимая везде.
5:09кажется ведущий @jsunderhood отпросился от работы на неделю :) столько твиттов, хотя только вторник!5:11
@jsunderhood не могу избавиться от ощущения что что-то с GraphQL и подобными решениями не так. Rest более лучше, конечно, но как-то тоже <_<6:37
.@silentroach мы (пока) взяли только ту часть GraphQL, которая про декларативность в компоненте. а вот бэкендовый кусок – да, необычный.
6:37два поста в тему: Your First GraphQL Server medium.com/@clayallsopp/y… / Moving from REST to GraphQL medium.com/@frikille/movi…
6:38на данном этапе меня смущает даже сам синтаксис graphQL Query, но это просто с непривычки. с самой идеей по-моему всё в порядке.
6:40@jsunderhood а как у вас дела с бэкендом? прослойка на ноде между клиентом и бэкендом на чем-то богомерзком? :)6:43
.@silentroach обычный богомерзкий PHP, одни и те же REST-ручки которого "изоморфно" дёргаются нодой на сервере и аяксом на клиенте.
6:44@jsunderhood Вопрос из зала: что лучше использовать Angular 2.0alpha (es6) или же React + ...) или есть еще хорошие альтернативы?6:49
@jsunderhood интересно. как насчет отдельных констант типа pretty_name => path_in_tree, чтобы компонент не знал о структуре дерева6:50
@jsunderhood на самом деле, если разобраться - баобаб тянет кучу всего лишнего. свой апи, курсоры, кучи методов (push, get). Нет даже has6:50
@jsunderhood ну и основная идея - чистые функции, невозможна, set не возвращает новое дерево - он меняет текущее.даже если внутри это другое6:50
.@milk_is_my_life а какие альтернативы? меня Baobab не смущает вообще ни чем. has есть в виде exist в @V2
6:51@jsunderhood как относишься к сорхусу и его идее на каждую мелочь создавать по модулю?6:52
.@silentroach :) забавный персонаж. в идее модульности нет ничего плохого, даже в таком, доведённом до абсурда виде. я даже что-то юзал.
6:53.@silentroach но я примерно понимаю почему это может раздражать.
6:54(речь о github.com/sindresorhus и его модулях типа github.com/sindresorhus/c…)
6:58@jsunderhood идея - заменить путь к данным в дереве более семантичной константой6:59
.@_cloudo вполне нормальная идея :) импортировать это из тех же constants, по аналогии с именами событий.
7:00.@_cloudo но это не работает с динамическими путями типа github.com/mistadikay/rea…
7:00@jsunderhood буквально вчера об это спросил @dan_abramov оказалось сделать это самому гораздо проще, чем кажется github.com/gaearon/redux/…7:01
.@milk_is_my_life в моём мире set и не должен напрямую возвращать новое дерево, всё летает по кругу почти как в каноническом Flux.
7:04@jsunderhood ещё вопрос. Для бем дерева вы данные подготавливаете прямо в шаблоне или где-то раньше? (что-то типа своего bemtree)7:18
.@MaximSukharev а нет как такового бем-дерева, как и шаблона :) сырые данные идут напрямую в ветку дерева, оттуда компонент рисует как хочет
7:20.@MaximSukharev в смысле нет одного большого BEMTREE -> BEMJSON, всё немного иначе.
7:21а какое Flux решение используете вы и какие у него основные минусы и сложности?
8:05@jsunderhood alt.js.org всё чётко8:14
@jsunderhood Пробовал Альт; теперь хочу попробовать Редакс.8:45
@sapegin @jsunderhood @jsunderhood тоже используюем alt.js. попробовать redux интересно.8:56
@jsunderhood делал в свое время анализ флаксов для заказщика, в результате и перешел на redux docs.google.com/spreadsheets/d…9:09
@jsunderhood Если у кого есть комментарии, критика к документу - это крайне желательно. Буду править)9:12
@jsunderhood использовал reflux, alt, flummox и теперь пробую redux9:34
@jsunderhood reflux — дурацкие экшены, нет единого диспатчера, alt — странный api, flummox — все ок, но есть redux :-), redux пока радует9:34
@pomidore @jsunderhood только flux, только классика, только хардкор.9:37
@jsunderhood понравилось использовать baobab вместо сторов.9:43
brace yourself, завтра изоморфность.
10:46о да. жду адептов секты правильных слов :) RT @lapanoid: @jsunderhood универсальность ;)
10:47@jsunderhood vanilla js + свои сторы github.com/alexeyraspopov…10:48
@jsunderhood У вас есть i18n? Кто как решает эту задачу с React?10:50
@roman01la @jsunderhood использовал github.com/yahoo/react-in… все ок.10:53
@dimchez @jsunderhood @roman01la метод translate прокидывался в компоненты как props.12:25
@roman01la @jsunderhood использую github.com/piranha/puttext:12:39
парсинг вызовов -> *.po -> *.json -> puttext(require('*.json'))
@roman01la @jsunderhood Polyglot.js от airbnb + своя привязка к Redux14:15
@olebedev @jsunderhood @roman01la +1 к puttext, просто и сердито14:16
Фронтаны, а может кто поможет найти решение или лучшие практики для smooth parallax scrolling? кто как делает @jsunderhood14:42
коллеги на работе подходят с вопросами потому что нагуглили мои модули. удобно.
15:00Все что обсуждал с @ir4y_ix и планировал запилить на прошлых выходных, сегодня рассказывает @deepsweet в @jsunderhood. Супер!15:22
ооок, в CSS есть outline-offset codepen.io/SitePoint/pen/…
15:33@jsunderhood А ещё он может быть отрицательным! В опере удобно было вёрстку так отлаживать, пока нормальный дебаггер не появился15:39
минутка ванильной вёрстки закончилась.
15:42какое название вашей должности/профессии наиболее полно отражает реальность и в целом вас устраивает?
15:51моё "Senior Front-End Developer" уже явно вносит больше путаницы в головы менеджеров, чем что-либо проясняет.
15:52@jsunderhood яжпрограммист15:52
@jsunderhood просто js web dev, без аутсорсной энтерпрайзной софтверной инженерии 😤16:38
@mr_mig_by @jsunderhood меня устраивает классическое software engineer.16:38
@jsunderhood JavaScript Engineer16:39
@jsunderhood разработчик интерфейсов16:39
@jsunderhood Frontend Developer или разработчик интерфейсов. не люблю деление на Junior/Senior — оно искусственное.16:45
# Среда 81 твит
A modular, progressive, and beautiful Markdown and HTML editor github.com/bevacqua/woofm…
3:16могу расписать по шагам идею изоморфности на примере того же реакта, начиная со сборки. интересно/актуально?
3:42готовых starter kit'ов и прочих стабов хватает, например github.com/RickWong/react… / github.com/webpack/react-… / github.com/DavidWells/iso…
5:18суть одна: один и тот же "изоморфный" код должен строить начальный HTML на сервере и продолжать работать дальше на клиенте.
5:20в React для этого предусмотрены обычный DOM `render()` и "серверные" `renderToString()` / `renderToStaticMarkup()` facebook.github.io/react/docs/top…
5:23к слову, в react@0.14 их даже разнесут по разным модулям facebook.github.io/react/blog/201…
5:24обычно webpack'ом делают одновременно два билда с двумя наборами бандлов на выходе: серверный и клиентский.
5:27точками входа в каждый из бандлов являются своеобразные конструкторы роутеров, которые ждут текущий запрощенный URL в виде аргумента.
5:30на сервере это обычный `request.url` из Express / Koa (koajs.com, наш выбор) / whatever, на клиенте – HTML5 History API.
5:31стандартом де-факто является react-router github.com/rackt/react-ro…
5:32на сервере:
5:36грубо говоря, роутер по переданному URL через таблицу роутов определяет, какой именно компонент нужно рендерить.
5:39через renderToStaticMarkup() (чтобы не было лишних атрибутов data-reactid, "чистый" HTML) строится руками доктайп, <head> и <body>.
5:40через renderToString() вытягивается строка HTML из компонента, который решил рендерить роутер, и dangerouslySetInnerHTML вставляется в body.
5:42вся эта портянка отправляется обратно в Express в виде ответа на запрошенный URL. казалось бы всё, наш HTML jт сервера готов.
5:43но 1) чаще всего ваше приложение не статическое, и рутовый компонент и всё последующее строится на основе данных, запрашиваемых с бэкенда.
5:45а render() у реакта синхронный, и сам по себе ждать каких-то там экшенов и сторов не может и не будет.
5:47для решения этой задачи мы выбрали способ, в котором данные запрашиваются после осознания нужного роута, но до фактического рендера.
5:48придумали маппинг соответствия роута и экшна(ов) – серверный роутер дёргает нужный экшн и ждёт ответа от стора, пока тот не заполнится.
5:51пришёл ответ – рендерим. передав данные через пропсы, или просто тупо, если всё построено на дереве, из которого компонент возьмёт всё сам.
5:52Ajax with less suck - (and node.js HTTP client to match)
visionmedia.github.com/superagent/ – чуть не забыл, "изоморфный ajax".
@jsunderhood И все это быстро?5:55
@jsunderhood почему Koa?5:56
.@vladimore because we can :) генераторы, вот это всё. судя по стресс-тестам распределение нагрузки более равномерное.
6:09очень важно для осознания: componentDidMount() не происходит "на сервере", т.к. ничего никуда не маунтится.
6:11поэтому подписки на обновление сторов или дёргание каких-нибудь экшнов в этом методе будут проигнорированы renderToString()'ом.
6:12и ровно из-за этого же использовать условия с `typeof window` или, прости господи, process.env.BROWSER и пр. – плохо.
6:14весь чистый client-side компонента должен быть описан исключительно в его componentDidMount().
6:15итак. на сервере теперь для нужного роута дёргаются нужные данные и вытягивается HTML-строка из нужных компонентов.
6:16когда на клиенте активируется наш собранный клиентский бандл, он (как я представляю) построит VDOM и начнёт матчить с HTML по `data-reactid`
6:19т.к. никаких данных, которые были запрошены на сервере, у клиента нет, то React просто построит diff относительно пустых данных и всё сотрёт
6:19отсюда интересная проблема: даже если на клиенте заново дёрнуть такие же экшны по роуту, как и на сервере, не факт, что они будут идентичны.
6:20это будет два разных несвязанных друг с другом запроса, пусть даже за одним и тем же. мало ли там какой timestamp или другая уникальность.
6:21мы не придумали ничего лучше (а затем нашли подтверждение правильности своей идеи в других Flux рещениях), чем передать данные в HTML.
6:22ведь если подумать, то между сервером и клиентом нет абсолютно никакой связи, кроме как HTML, и только так можно связать "сессию".
6:23@jsunderhood а почему нельзя:6:24
React.render(<Handler />, document);
?
т.е. при серверном рендеринге, куда-нибудь в <body>:
<script id="_bootstrap" type="application/json">{ ololo: true }</script>
6:26для клиентского бандла точкой входа является клиентский конструктор роутера, который, если есть "bootstrap", возьмёт оттуда данные.
6:29сложит их в стор и сделает самый обычный React.render(…). в этой точке всё дальнейшнее управление роутами уходит в клиентский react-router.
6:30теперь строка HTML от сервера полностью идентична тому, что построит реакт на клиенте. нулевой diff, profit.
6:31дальнейший переход на другую страницу будет перехвачен роутером и выполнен только на клиенте. только в этом случае будет дёрнут экшн…
6:32т.к. данных для другой страницы в "boostrap" нет, ведь сервер рендерил только текущую страницу. начинается обычный Flux data flow.
6:34если очень кратко: самые начальные данные клиент берёт из HTML, а дальше всё как обычно, никаких ограничений.
6:37грабли, на которые мы наткнулись практически сразу: неучтённые синглтоны и `on`-подписки вместо `once` на сервере.
6:39результат: расшаренные сессии и сторы между разными клиентами :) следите за этим.
6:41извиняюсь за возможную сумбурность, старался излагать максимально последовательно. вопросы?
6:41~@jsunderhood @listochkin как то говорил в чате что нельзя так, так как экстеншены могут мjдифицировать DOM.6:42
.@olebedev @listochkin буду очень рад узнать альтернативное решение
6:42@jsunderhood Как по мне, тут чейнинг используется только ради чейнинга. Какой профит по сравнению с window.fetch(url, {…})?6:42
.@subzey github.com/matthew-andrew… для любителей.
6:43@jsunderhood на клиенте используете тот же маппинг или другой подход к работе с данными?6:43
я в целом большой поклонник метода "сделай с нуля, или не поймёшь до конца". но это не значит, что не нужно использовать готовые решения.
6:45хотя бы издалека понимать принцип работы такой не самой простой штуки уже полезно.
6:46@jsunderhood есть react native для андроида?6:46
@jsunderhood данные для render нужно заранее готовить и в отдельном от React месте. Я вот для этого либу написал bit.ly/1TPnKSn6:48
@jsunderhood В твитере всё равно поток сознания получается :-) Но в целом всё понятно.6:48
разница между серверным и клиентским webpack-бандлами небольшая: разные точки входа, и упрощённый процессинг на сервере, без стилей и т.п.
6:53в серверный бандл так же можно не включать всё вендорное, чтобы мучать зря файл на пару мегабайт – webpack.github.io/docs/library-a…
6:56@jsunderhood НЕ мучать, идиот.
6:59Надо будет взять кофейку и перечитать @deepsweet в роли @jsunderhood . Не будет какой-нибудь ссылочно-резюмешечного текста по итогам?7:04
@sbmaxx @deepsweet @jsunderhood В профиле аккаунта же есть ссылка jsunderhood.ru7:04
@jsunderhood ого, какая печалька (почитал дальше). Какая-то так себе изоморфность получается. Неужто более лучше ничего нет?7:25
.@silentroach github.com/facebook/react… когда-нибудь…
7:25этот наш роут -> экшн(ы) маппинг плюс ко всему позволяет довольно легко решить, какой компонент рендерить на сервере, а какой на клиенте.
7:27если для чисто клиентского компонента не дёргается экшн в серверном роутере, то он просто отрисуется пустым.
7:28на клиенте в своём componentDidMount() компонент посмотрит, что данных в сторе (от бутстрапа) нет, и сам дёрнет свой экшн. даже изящно.
7:29Вопрос к залу: поддон для посудомойки обязательно нужен? Как подобрать подходящий, какие у них параметры? Забыла заказать вместе с машинкой.7:35
@kra1g0 @jsunderhood стоит ли вообще инвестировать время в него сейчас? есть ли серьезные разработки на нем?7:52
@adaniliuk @jsunderhood @kra1g0 У фейсбука два приложения нативных (ads и groups) - react native. Все очень серьезно.7:58
@jsunderhood Читаю ваши твиты про реакт и не двупляю почти ничего. Чем крут реакт? Киллерфича перед ангуларом? ☺️8:48
@ymatuhin @jsunderhood фича в том, что ты можнешь думать о приложении, как о функции. В математическом смысле слова.8:49
@jsunderhood а если таких компонента два? оба дернут?9:55
.@slonoed мы сделали isRequesting на уровне экшна, чтобы одновременно не было двух одинаковых. всё равно в стор попадёт в одно и то же место
9:56а у кого сейчас какой pet project? :)
16:38# Четверг 69 твитов
появились подвижки в мёрдже isparta в istanbul github.com/douglasduteil/… – покрытие оригинального ES6 кода через sourcemaps от Babel.
5:25к слову, лоадеры к вебпаку для обоих – github.com/deepsweet/ista… / github.com/deepsweet/ispa…
5:27Approaches to testing React components reactkungfu.com/2015/07/approa… – а как вы тестируете реакт-приложения?
5:29у нас (пока) jsdom github.com/tmpvar/jsdom + старая добрая mocha github.com/rstacruz/mocha… + TestUtils facebook.github.io/react/docs/tes…
5:32@jsunderhood используя Shallow Rendering facebook.github.io/react/docs/tes…7:09
@jsunderhood такой же набор + sinon7:09
@jsunderhood ну а дальше mocha, chai с параметром —compilers js:babel/register7:14
@jsunderhood почему не Karma? Для браузера же пишете, jsdom - читерство7:58
.@silentroach а какие именно браузерные отличия ты хочешь тестировать кармой? то, как работает сам реакт? :)
7:59.@silentroach правда. но что это меняет? внутри Flux тоже нечего такого специфичного тестировать… приведи пример, я не могу придумать :)
8:02.@silentroach мы начали с кармы, и на первом проекте она даже до сих пор крутится. даже под Sauce Labs. а потом подумали "а зачем?".
8:03@jsunderhood :) хороший довод. Но проект же состоит не только из реакт-компонентов, правда же?8:05
@jsunderhood так любой js-код. Все же js в ноде от того, что есть в chrome и ff разных версий отличается. Дело же не только в dom.8:06
.@silentroach смотрю на проект и пытаюсь найти что-нибудь такое :) я понимаю о чём ты, но одновременно не попускают мои доводы.
8:07@jsunderhood тот же babel спокойно может зарелизить версию с косяками и зафиксить только через пару часов, какое тут доверие к зависимостям?8:10
.@silentroach по-моему это путь в ад, тестировать "не свой" код. так можно тестировать правильно ли вебпак реквайрит модули, например.
8:11@jsunderhood а это тестировать и не надо, надо тестировать работоспособность своего проекта :) которая может быть сломана зависимостями, да8:13
@jsunderhood насколько я понял и подход и даже частично реализация совпадает с вот этим примером: github.com/erikras/react-…, верно?8:19
.@afitiskin очень может быть, конкретно на это я не смотрел. идея у всех плюс-минус одна.
8:20@jsunderhood получение данных на серверной стороне (наполнение стора) там изящно реализовано, рекомендую обратить на него внимание8:25
@silentroach @jsunderhood так можно же локально тестировать через jsdom, а в CI запускать те же тесты в браузере8:27
@vslinko @jsunderhood @silentroach а как тестировать e2e? Хочу, чтобы перед деплоем основные сценарии проверялись: логин, оплата, ...9:58
@subzey @jsunderhood для fetch получается слишком много лишнего кода типа установки хедеров и тд, в итоге я пришёл к superagent и доволен10:00
@milk_is_my_life @vslinko @jsunderhood @silentroach @jsunderhood мы начинаем прикручивать pioneerjs.com посмотрим , что получится10:00
@adaniliuk @milk_is_my_life @jsunderhood @silentroach я не понял, чем он лучше cucumber.js?10:10
@jsunderhood немного опоздал, но вот небольшой пример isomorphic app (github.com/ShpuntiK/isomo…) с идеями, которые ты описывал (1/2)10:12
@jsunderhood shpuntik.github.io/isomorphic-app… - и презентация на основе этого кода (2/2)10:13
@jsunderhood про синглотоны очень верно :) сам долго осознавал эту проблему10:18
@milk_is_my_life @jsunderhood @silentroach так и тестировать — писать e2e тесты, локально запускають через jsdom, на сервере через selenium10:18
@vslinko @milk_is_my_life @jsunderhood @silentroach хороший вопрос, я пока не знаю. по зависимостям pioneer ссылается на форк cucumberjs.10:20
@adaniliuk @milk_is_my_life @jsunderhood @silentroach понял, это враппер над ним, с e2e API. Но мне больше нравится webdriver.io10:24
Babylon is a JavaScript parser used in Babel github.com/babel/babel/tr…
10:40кажется решились на babel-plugin-typecheck, по крайней мере простые вещи. ненавижу JSDoc. github.com/codemix/babel-… + flowtype.org/docs/quick-ref…
10:48хочется как в Babel – github.com/babel/babel/bl… – комменты комментами, а типы через flow type annotations.
10:50(TypeScript для бедных)
10:51Turn flow type annotations into comments github.com/babel-plugins/…
11:07@jsunderhood Все задаю вопрос почему flow? Почему не typescript?12:10
пруф или не было :) RT @roman01la: @jsunderhood @xgrommx уже и с ES7
12:17на сегодня так github.com/mistadikay/rea…, мы над этим работает. RT @roman01la: @jsunderhood У вас своя реализация query в компонентах?
12:19@jsunderhood о-да! Суперагент очень крутой! Я даже написал для него REST-моккер который работает прямо в браузере github.com/rambler-digita…12:19
@jsunderhood Вот их roadmap github.com/Microsoft/Type…12:19
хм, ок. тогда почему не TypeScript?
12:20@jsunderhood он умеет искать по полям в объектах? типа: хочу объект из массива в котором id: 512:22
.@roman01la да, стандартными средствами Baobab. мы когда осознали, кажется взвизгнули.
12:23github.com/Yomguithereal/… RT @roman01la: @jsunderhood ану покаж!
12:24btw, скоро Baobab@v2 github.com/Yomguithereal/…
12:26@jsunderhood Круто! А как быть с динамическими query? Например листы. Как вы расширяете query?12:28
.@roman01la по ссылке на наш пример видно, что query – это функция, принимающая props и state :)
12:28@jsunderhood Я написал новый ридми для Redux: github.com/gaearon/redux/…. Фидбэк вэлкам! (Доки пока не готовы)12:28
@jsunderhood @roman01la А что о github.com/mquan/cortex скажете?12:28
@jsunderhood @roman01la Вообще есть целый список github.com/enaqx/awesome-…12:32
@jsunderhood Хм, вижу. А что, если часть динамического query зависит от данных из глобального состояния?12:33
.@roman01la ммм… в общем случае оно может быть в пропсах, мы так ID из роута протягивали. ещё вариант – context. есть конкретный пример?
12:36на сегодня это тянется в пропсах, но уже есть кое-какие намёки. RT @roman01la: @jsunderhood вот я про роут и id как раз и хотел сказать :)
12:38@jsunderhood Это не ломает проверку SCU? Или у вас и пропсы и данные по курсору сравниваются в SCU?12:42
.@roman01la не совсем понял как тут сломается SCU. мы сравниваем ID в componentWillReceiveProps и при отличии обновляем свои курсоры.
12:43.@roman01la т.е. данные компонента обновляются на новую ветку с новым ID.
12:43.@roman01la query-функция вызывается заново с новыми пропсами, и получается новый cursor path. ну ты наверное уже понял :)
12:46немного забегая вперёд скажу, что мы уже всё чуть переосмыслили и оформляем в виде небольшого модуля на декораторах. для своих нужд.
12:51а скиньте примеры своего кода на ES6 с JSDoc.
12:53хохма последней недели – "самовозбуждающийся стор"
12:55@roman01la @jsunderhood а почему бы это состояние не хранить в самом tree? )13:05
.@__fro @roman01la именно это мы и собираемся попробовать. в каком-то виде :)
13:05@jsunderhood @roman01la глянул, очень круто ). А это github.com/tonsky/datascr… - следующая итерация идеи @nikitonsky13:06
@jsunderhood я это в своем slt как раз имел ввиду ). Короче, состояние целостно только в случае, когда все причины хранятся в нем же13:08
@jsunderhood и тут основаная моя претензия к flux.Вызов экшена никак не фиксируется,теряются причины.В #redux такая же проблема @dan_abramov14:00
↓ и дальше по реплаям.
14:00JSCity is an implementation of the Code City metaphor for visualizing source code github.com/aserg-ufmg/JSC… 😻
14:30# Пятница 40 твитов
Пс, парень, немного рекурсии не желаешь? pic.twitter.com/tw4p65bqnB1:06![]()
@jsunderhood расскажи вот что про реакт. Как люди валидируют пользовательский ввод в формах, трансформируют его и так далее?2:29
@jsunderhood ибо формы, по-моему, это головная боль на реакте в отличие от того же ангуляря. В ангуляре это прям великолепно сделано2:29
.@iSnifer мы не придумали ничего лучше, чем заюзать validator github.com/chriso/validat… с кастомным выводом ошибок.
2:33.@iSnifer пробовали даже нативную HTML5 валидацию html5rocks.com/en/tutorials/f…, но это просто ад. более невменяемого API я не помню.
2:33тема лично для меня всё ещё актуальная, может есть что-то очевидное и крутое?
2:34@iSnifer @jsunderhood что по поводу github.com/gcanti/tcomb-f… и github.com/insin/newforms?2:50
@iSnifer @jsunderhood tcomb интересный, был небольшой опыт, но newforms поддерживают isomorphic2:53
@iSnifer @jsunderhood А еще в ангуляре есть великолепнейшая либа angular-formly.com3:07
coveralls в read-only, ну круто status.coveralls.io – видимо с этим же связаны последние затупы с pending очередью /@toivonens
3:46.@__fro @roman01la первая попытка, по-моему получилось круто github.com/mistadikay/rea… – cursor path как часть другого cursor path
3:59.@__fro @roman01la до того как делать баобабовый select мы подготавливаем cursor path через рекурсивный поиск вложенных массивов.
4:01.@__fro @roman01la на любой глубине как и раньше могут быть части props/state из функции, в скоупе которой это всё происходит.
4:02@jsunderhood А тогда скажи, форма для тебя должна быть smart- (с внутренним состоянием) или dumb-компонентом (с состоянием в сторе)?4:03
.@mista_k у нас получилось что-то между: у формы есть своё внутреннее состояние, которое можно менять внешними пропсами.
4:07@jsunderhood для валидации форм использую github.com/christianalfon…6:13
Всем привет ) Меня зовут Денис @denisfedosov и люблю верстать. Работаю удаленно в ⚑ Passenger.me.6:13
@jsunderhood а поделись годными материалами про spa (на стек пофиг) :)6:28
@jsunderhood ну ок, кастомный вывод ошибок нормальная тема. А что на счет модификации пользовательского ввода onkeyup? Как $filter в angular7:13
@iSnifer @jsunderhood могу сделать простенький gist для поля ввода номера кредитки, там все очень просто7:21
@jsunderhood @roman01la вроде норм. А в чем смысл использовать state вместо props?7:27
.@__fro @roman01la просто на всякий случай :) у нас такого примера нет, но локальный стэйт компонета всё равно пробрасывается. мало ли.
7:27.@__fro @roman01la а, кажется ты про другое. мы не делали через higher-order component по некоторым причинам, но в целом можно.
7:29.@__fro @roman01la как раз сейчас пишем довольно подробный README. всё будет.
7:29@jsunderhood @roman01la да не, я имел ввиду что вообще нафиг state не нужен ). То есть ну вообще ).7:36
.@__fro @roman01la в идеальном случае – да, согласен. он просто удобен "в виде хранилища" тем, что при обновлении дёргает рендер сам.
7:37@iSnifer @jsunderhood собственно вот: gist.github.com/afitiskin/a65c…7:38
@afitiskin @iSnifer @jsunderhood onchange в Реакте - это только change, или он другие какие-то события подмешивает?7:48
@Chudesnov @iSnifer @jsunderhood любое изменение в input триггерит реактовский onchange, на мобилках должно работать так же7:48
оформили наш подход к работе со стэйтом в реакте github.com/mistadikay/doob, по мотивам поста medium.com/@mistadikay/de… 🔥
7:56@__fro @jsunderhood @mista_k я просто чувствую, что с большим количеством форм ты не работал и не понимаешь всех трудностей
горячий тред :) RT @__fro: @jsunderhood @iSnifer @mista_k , не? )
@__fro @jsunderhood @mista_k я просто чувствую, что с большим количеством форм ты не работал и не понимаешь всех трудностей
9:54
@xgrommx @jsunderhood это все какие-то библиотеки, которые подменяют привычное написание элементов форм. Фу на такое9:57
@jsunderhood @xgrommx ща покажу, как раз взялся зафиксировать это9:59
совсем забыл про важную фишку иммутабельности – сохранение ссылок на объекты. простейший shouldComponentUpdate без shallow-equal костылей.
10:22в том же Baobab два курсора на одни и те же данные будут равны через `===`, как и результат их `.get()`а.
10:22@jsunderhood ну просто, для ясности :) вообще да, идея с баобабом заразительна. Особенно то, как это на флакс ложится.10:35
@milk_is_my_life @jsunderhood да не нужен тебе флакс е-мае )). Там же можно на изменения данных подписываться ))10:35
извините, у вас есть минутка поговорить о баобабе? RT @milk_is_my_life: @__fro @jsunderhood точно, не заметил. нафиг флакс, всем по баобабу!
10:42A Virtual DOM based AngularJS view renderer designed to be used with immutable data structures github.com/teropa/angular…
14:12# Суббота 53 твита
So true2:23// = "oh hey, by the way,"
/* = "please take a seat."
в ESLint@1.0.0-rc-3 наконец-то сделали reset по умолчанию eslint.org/blog/2015/07/e…, т.е. нужно заполнять конфиг с нуля вдумчиво и руками.
2:56если вы по какой-то странной причине всё ещё используете JSHint, то самое время перейти с выходом ESLint@1.0.0.
2:58у инструмента, который связан с парсингом ES6, нет практически никаких шансов выжить без Babel. Себастиан не просто так выделил Babylon.
3:11@jsunderhood Так что выжить без Babel для парсинга ES6 очень даже легко (и он будет скорее оверкиллом).5:14
.@RReverser расскажи это какому-нибудь JSCS
5:14@jsunderhood Esprima, собственно, тоже уже догоняет, тем более что общую спецификацию мы уже написали.5:15
.@RReverser на ES7 уйдёт ещё год догонов github.com/estree/estree. парсер Babel хорош именно тем, что он bleeding edge.
5:16@jsunderhood И тем же одновременно и плох, так как использует внутренние типы нод, которые внешние либы могут принять за стандартные.5:17
.@RReverser но на его основе потом и обсуждается формат для ESTree. кому-то нравится теория, а мне нужно использовать ещё вчера.
5:18.@RReverser я начал говорить о конкретных инструментах типа ESLint/JSCS, а ты про глобальное. совершенно очевидно, что есть эсприма и акорн.
5:20.@RReverser про esprima-fb нужно напоминать? :) да, оно когда-нибудь будет стабильное и покрывающее всё-всё. но не сегодня.
5:22.@RReverser вот тебе факты: 1) от JSCS я отказался на следующий день после осознания отсутствия поддержки всего, что мне нужно.
5:23.@RReverser 2) если бы не появился babel-eslint, я бы жил вообще без линтера.
5:23@jsunderhood На чьем формате? Бабеля? Нет. Он в этой сфере относительно недавний игрок, и больше консьюмер чем задающий правила.5:24
@jsunderhood Это не о теории, а о стабильности тулз и фич. Тем более, что все эти ES7 штуки легко реализовать как плагины для акорна.5:24
@jsunderhood Я тоже очень даже о конкретных. ESLint (Espree) мы вон тоже потихоньку на Акорн переводим.5:24
@jsunderhood Не понял посыла про esprima-fb. В том-то и суть, что стабильным оно может и не стать, и быть по-тихому удалено с ядра.5:24
@jsunderhood Это основная политика Бабеля - можно экспериментировать с новыми фичами, но мы их в любой момент можем убрать.5:24
.@RReverser ты снова про какую-то абстрактную теорию. у тебя есть живой проект на ES6/ES7, который нужно, например, линтить? похоже, что нет
5:25.@RReverser можно сколько угодно обсуждать инструмент в вакууме, но если бы не появился babel-eslint, ваш "ESPree" до сих пор бы тужился.
5:26@jsunderhood Ладно, это бессмысленно :( В который раз описываю как конкретно это работает прям сейчас изнутри, а ты называешь теорией :(5:26
@jsunderhood babel-eslint - временный хак, в том числе Себ это признает и хочет изменить в сторону стандартов. Он крут, но все же временный.5:28
.@RReverser я ни разу это не отрицал, если ты не заметил. временный, НО АКТУАЛЬНЫЙ. это куда важнее для проекта, который УЖЕ ЕСТЬ.
5:29.@RReverser Esprima и Acorn без сомнений сделают полную поддержку ES6 и даже ES7. но когда? сколько месяцев мне ещё не использовать тулзы?
5:30@jsunderhood Прочти первый свой твит из которого собственно все началось :)5:31
.@RReverser сегодня у инструментов всё ещё мало шансов. что не так-то? JSCS переводят на babel-jscs просто так?
5:31.@RReverser как итог – у тебя бомбануло не по теме :)
5:33@jsunderhood Аргументировал достаточно, и почему ES6 тулзам Babel как парсер вообще не критичен, а ты в ответ начал мне про эксперименты :)5:35
.@RReverser дай мне рабочие ESLint и JSCS без Babel. аргументировал он :)
5:35@jsunderhood Ммм... я среди тех, кто это в том числе строит в тимке Babel-а.5:36
.@RReverser такие аргументы никогда не волновали и не будут меня волновать вообще никак :) будь ты хоть Крокфордом.
5:36@jsunderhood Очень рад, что человек, использующий тулзы, обясняет, как надо строить эти самые тулзы :) Удачи!5:38
.@RReverser когда придумаешь ответ на мои доводы про ESLint и JSCS, приходи. я как не мог их толком использовать полгода назад,так и не могу
5:39.@RReverser пока ты скатился только "а я авторитет, и кажется знаю, о чём говорю"
5:40спор математика и инженера, блин.
5:52@jsunderhood Та да. Причем, почему-то кажется, каждый из нас видит математика в другом :)5:57
@jsunderhood а в чем принципиальные отличия, чтобы прям взять все бросить с перейти?9:50
.@tvii нормальная архитектура, нормальные названия правил, выбор между предупреждением и ошибкой, бурное развитие, плагины, сообщество.
9:56@jsunderhood а есть смысл переходить, если пишешь на es5 и не на react? мне это видится переходом ради перехода10:23
.@baxxabit помимо ES6 и прочих JSX смысл есть уже просто потому, что это новое поколение знакомого инструмента eslint.org/docs/rules/
10:35@baxxabit @jsunderhood можно новое начать писать на ES610:36
@baxxabit @jsunderhood А причём тут React?10:36
.@freiksenet @baxxabit заметили, как мощно React/JSX зафорсили ES6, что иногда даже одно без другого уже кажется странным? :)
10:37(по большому счёту и JSCS не нужен, codestyle-правил в ESLint по крайней мере для меня уже достаточно)
10:43(с одной стороны, разделение обязанностей это хорошо, с другой – два разных инструмента это слишком)
10:45btw, husky – "Prevents bad commit or push (git hooks, pre-commit, pre-push and all that stuff…)" github.com/typicode/husky
10:47когда кто-то всерьёз говорит "ES2015" вместо "ES6" [gif] replygif.net/i/100.gif
10:54перестал следить за Node.js + io.js с момента анонса "foundation". что там? мёрдж? роадмапы?
13:56homebrew-rmtree – remove a formula and its unused dependencies github.com/beeftornado/ho…
14:25# Воскресенье 116 твитов
@jsunderhood привет! вы проверяете в компонентах propTypes? если да, то есть какой-то регламент (что проверять, насколько глубоко и тд)?2:08
.@alexfedoseev привет. по-хорошему конечно нужно проверять :) это даже ни столько для валидации, сколько для наглядного представления данных
2:24.@alexfedoseev но если у тебя компонент напрямую рисует глубокую структуру данных, то такой компонет явно стоит разбить на несколько.
2:25(мы даже сделали в Yummies безумный экстенд отдельных файлов с propTypes по слоям, но пока так ни разу не воспользовались)
2:26был хороший issue в тему github.com/facebook/flow/… – propTypes на фоне нормальной типизации кажется костылём, хоть в нём и есть свои фишки.
2:30(Flow, конечно, хорош, но он статический "типизатор". по поводу динамической типизации я всё ещё верю в штуки типа github.com/codemix/babel-…)
2:41@jsunderhood сон не нужен? (:2:43
задумка простая: перед тем как удалять, превращать все flow types annotations в инлайновые ассерты. только в dev-режиме, конечно же.
2:47@jsunderhood и да, typescript тащит!2:49
@backendsecret @jsunderhood @rubyunderhood думаю, картинка будет полезна pic.twitter.com/6tkRlf8CqN3:09![]()
1/6 A young developer approached me after a conf talk and said, “You must feel really bad about the failure of object-oriented programming.”7:36
2/6 I was confused. I said, “What do you mean that object-orient programming was a failure. Why do you think that?”7:36
3/6 He said, “OOP was supposed to fix all of our software engineering problems and it clearly hasn’t."7:36
4/6 He continued: "Building software today is just as hard as it was before OOP. came along.”7:36
5/6 I said: “Have you ever look at the programs we were building in the early 1980s? At how limited their functionality and UIs were?”7:36
6/6 OOP has been an incredible success. It enabled us to manage complexity as we grew from 100KB applications to today’s 100MB applications.7:36
промежуток времени, через который собственный код уже кажется корявым, стал измеряться не годом, а месяцем. мозг постоянно нагрет.
7:44это точно устаканится в каком-то своём правильном балансе, но хотелось бы, чтобы сам процесс в целом не останавливался никогда.
7:45хуже всего, это когда ты явно застрял, но этого не осознаешь и даже отрицаешь. со стороны обычно очень явно видно, но это редко помогает.
7:53(я разлогинюсь где-то в 19 по МСК, если осталось что обсудить или спросить – самое время)
7:55@jsunderhood когда месяц - это хорошо или плохо?7:56
.@RusAlexander "минус" – постоянная тяга к рефакторингу. если откровенно запустить, то будет плохо, и не только тебе самому.
7:57.@RusAlexander если подойти осознанно и извлечь из этого свои плюсы, то можно действительно улучшить код не просто ради факта переписывания.
7:58@jsunderhood ну ведь принцип "работает не трогай" всегда останавливает от преждевременного рефакторинга.7:58
.@RusAlexander как я заметил, это довольно сильно зависит от проекта. есть такие, где даже думать о рефакторинге нельзя, чтобы не сломать.
7:59.@RusAlexander "преждевременный рефакторинг" – это подростковость :) и рано или поздно проходит, сам таким был ещё недавно.
8:00@jsunderhood у меня под это определение попадает любой рабочий и приносящий доход проект8:00
.@RusAlexander именно поэтому я и говорю, что зависит от проекта. можно сопротивляться сколь угодно, то всё равно придётся разделять […]
8:01.@RusAlexander […] "бизнес" и "гик". на каком-то этапе стартапа может показаться, что это одно и то же, но это ловушка.
8:01@jsunderhood согласен. Но ту точку где рефакторинг необходим, нам надо как-то обозначить в этом треде8:02
.@RusAlexander для меня такой точкой часто является факт "блин, надо поправить казалось бы мелочь, но всё так плохо, что даже это страшно".
8:03.@RusAlexander если ОЧЕНЬ сложно вносить изменения в работающий проект, то нужно хотя бы подумать о том, чего будет стоить новая архитекрута
8:04.@RusAlexander *иногда* в это удачно можно вплести "бизнес", аргументировав тем, что затраты на поддержку в текущем виде дороже рефакторинга
8:04учусь определять зрелость разработчика (как человека в том числе) по его код-стайлу. в этом есть свои отчётливые закономерности.
8:07@jsunderhood вот здесь полностью согласен. Рефакторинг ценен только тогда когда ты вносишь требуемые изменения в проект.8:07
это отражение внутреннего состояния, как если бы вы рисовали картины для психолога. и программиста-подростка,которому уже за 30, сразу видно
8:08@jsunderhood Какие?8:09
.@gxoptg_ умение думать о других. не тупо "специально" писать слишком вербозный код, а иметь как личное качество на привычном обычном уровне
8:12.@gxoptg_ обилие вложенных тернарных операторов и прочие однострочники от тех, кто не наигрался в своё время на 140byt.es
8:13.@gxoptg_ отсутствие даже единственной строчки с комментарием под предлогом "нормальный программист и так поймёт".
8:13@jsunderhood однажды я добавлял на страницу кнопку больше недели.8:14
@jsunderhood А как от такого избавляться?8:14
.@gxoptg_ научиться допускать, что если ты слышишь о своей проблеме более, чем от одного человека, то возможно в этом что-то есть.
8:15самый треш – "кто не понял как работают мои выглядящие как перл три строчки кода, тот тупой и просто не дотягивает до моего уровня".
8:16@sevaisnotcow @jsunderhood как объяснили это заказчикам, если это был enterprise ?8:17
ультрагиком хорошо быть, когда ты мальчишка, и все вокруг тебя тоже мальчишки, и вы меряетесь странными для обычных людей письками.
8:18@RusAlexander @jsunderhood это был крупный соцсервис, с миллионом а/б тестов, из за них это и произошло, и из за отсутствия чего то типа бэм8:20
@RusAlexander @jsunderhood кнопочку то я вставил быстро, неделю я делал так что бы она одинаково везде работала8:21
чаще всего такие люди физически не способны доводить начатые проекты до конца, т.к. одно дело набросать прототип с однострочными while [...]
8:22[…] циклами без "лишних скобок", а другое дело жить с этим, думать про внешний API и т.п… быть ответственным, вот.
8:23вспомните своих коллег, у каждого такой есть :)
8:24@sevaisnotcow @jsunderhood ха. у нас на поддержке старый гос. интерпрайз. Кнопочку туда месяц как-то вставляли.8:24
Я КНОПОЧКУ ДО СИХ ПОР ВСТАВЛЯЮ, УЖЕ 30 ЛЕТ ЖИВУ.
8:24@RusAlexander @jsunderhood если рефакторинг снижает стоимость владения продуктом в дальнейшем, то вот и точка.9:06
@jsunderhood вот глянул код полугодовалой давности..9:06
@jsunderhood даже не знаю, у меня такого нет, причины почему код был написан так или иначе мне как-то понятны..9:06
@jsunderhood Причем всегда известно, какие есть опции по улучшению/изменению. Но чаще объективных причин менять нет.9:06
@jsunderhood код должен быть выразительным и без мусора.9:07
@jsunderhood Даже очень краткий код может быть хорошо понимаем без комментариев (при достаточной квалификации)9:07
.@__fro может, когда это действительно искусное владение. а может и нет, когда это 1) самоцель 2) ЧСВ
9:08.@__fro причины-то понятны. я наверное больше про то, что я пока ещё явно не постиг все паттерны и не всегда умею писать сразу "правильно".
9:10@jsunderhood и такое бывает )). По себе знаю, иногда приходится бороться с порывами повыпендриваться ).9:10
@jsunderhood иногда нужно просто отложить вставлялку в сторону и отпустить в продакшен.9:10
@vladimore @jsunderhood если любишь отпусти9:12
@jsunderhood надо перестать заморачиваться, оно само придет ). Главное грамотная постановка задачи (тесты), а способ найдется.9:13
@jsunderhood @__fro Вот да, всегда уважаю людей которые могут понять задачу до написания кода, чтобы на неё написать тесты.9:17
@freiksenet @jsunderhood это и есть итеративный подход. Нет идеальной схемы, это как лепка из пластилина )9:23
@__fro @jsunderhood Ну вот похоже скилл программиста это сколько тебе надо итераций, чтобы сделать правильно какую-то фичу.9:23
@__fro @jsunderhood Правильно - это чтобы соответствовало внешним требованиям и не сгнило после того как они совсем поменялись.9:23
@jsunderhood к сожалению, в коммерческой разработке инженеру не доносят задачу цельно. Поэтому и цель размывается. И качество страдает (9:24
@freiksenet @jsunderhood А вот те, кто не мыслит итерациями, на самом деле они находятся внутри одной бесконечной итерации ))9:31
.@__fro @freiksenet так, у нас тут один словил МакКонахи, вызывайте помощь.
9:31@freiksenet @jsunderhood то есть профессионалу нужно смириться со своим несовершенством и только тогда выйдет что-то стоящее9:32
а как вам такое – "преждевременный отказ от копипасты"
9:42@__fro @freiksenet @jsunderhood мне помогли в этом книги о физиологии мозга. Ошибки - обязательная часть обучения.9:47
@jsunderhood преждевременный отказ от говнокода9:59
@vladimore @__fro @jsunderhood Да меня не пугают мои ошибки, меня восхищают люди которые их делают меньше чем я при схожей продуктивности.9:59
.@mistadikay оттягивание коммита "it just works"
10:08@jsunderhood проблема большинства программистов - инфантелизм. Отсюда и бескончные размышления о коде как о высшей ценности.10:21
@jsunderhood когда N обработчиков с 80% копипаста лучше, чем один обработчик c декларацией параметров для них ?10:59
jsfiddle.net/trnt/savrdygy/
.@apostololeg когда один обработчик становится слишком полиморфным и сложным
10:59@jsunderhood Мастерство, это когда не только сам пишешь хорошо, но когда ты senior, и все в команде пишут как надо (пусть не с первого раза)10:59
@jsunderhood Как делать TDD на фронтенде? И вообще как хорошо тестировать фронтенд?11:00
.@freiksenet karma + mocha + chai + sinon
11:00.@freiksenet + istanbul. dev-режим с вотчером в карме прекрасен, как раз для вывода на отдельный монитор при TDD.
11:01@jsunderhood Ну технологии я знаю. Меня интересует процесс, как сделать тест не имея ещё, например, реакт компонента.11:03
@jsunderhood Насколько полезно мерить code coverage? Мы не меряем, хотя и стараемся хорошо тестировать и требовать тесты в ревью.11:13
@jsunderhood Что нам даст code coverage?11:13
.@freiksenet даст понимание, какие условия, циклы и даже целые методы не покрыты тестами вообще никак.
11:14.@freiksenet без визуального представления связь тестов с реальным кодом слабовата даже у автора кода. сложно представить каждую мелочь.
11:15.@freiksenet задрачивать покрытие на 100% рационально разве что на небольших проектах. задача №1 – убедиться, что покрыто то, что должно.
11:17ну или если это действительно критично github.com/babel/babel/is…
11:20.@freiksenet код Babel довольно сильно меняется, отсюда потребность сразу видеть то, что из нового или переделанного старого не покрыто.
11:27.@freiksenet т.е. тесты после рефакторинга могут и не валиться, но это ещё не идеальный результат.
11:28прикрутить покрытие тестов к нормальному проекту можно и за полчаса, а *потенциальный* профит куда круче.
11:30@jsunderhood Когда у тебя очевидный ввод и вывод в программе, как в babel, то тестировать не так сложно.11:32
чем умнее программист, тем тупее его функции pic.twitter.com/Fw3a6BSZqk
@jsunderhood нормальному?11:38
.@superv1s0r ну в смысле прикрутить к проекту новый инструмент не составляет труда :) бывает же всякое.
11:39@jsunderhood @freiksenet что про tape думаете/знаете?12:09
.@illbullet @freiksenet знал, что он есть, и что это в каком-то смысле альтернатива mocha. вот пошёл читать подробно medium.com/javascript-sce…
12:10.@illbullet @freiksenet а можно преимущества в своих двух словах?
12:10@jsunderhood помню, как один БЭМ-разработчик, слово в слово такое выдавал.12:11
.@mostolovista потом его конечно в дурку забрали?
12:11@jsunderhood о, да! Однажды я решил что ифы не нужны — есть же тернарки. Потом правда одумался, но 2 проекта так написал @gxoptg_12:14
эту забавную неделю с вами был @deepsweet. надеюсь, что было интересно, спасибо всем за общение :) логи будут здесь jsunderhood.ru/deepsweet
13:49часто говоря "мы" я имел в виду себя и @mistadikay – моего коллегу, напарника по парному программированию и просто хорошего трансгендера.
13:50@jsunderhood в штанах у тебя трансгендер13:52
так и живём :)
13:52ещё увидимся в каком-нибудь cljsunderhood. логаут.
13:56# Ссылки
github.com
- https://github.com/css-modules/css-modules/blob/master/examples/theming.md#theming
- https://github.com/webpack/css-loader#local-scope
- https://github.com/css-modules
- https://github.com/yummies/yummies
- https://github.com/yummies/babel-plugin-yummies
- https://github.com/yummies/generator-yummies-repo/blob/master/app/templates/CONTRIBUTING.md#commit-emojis
- https://github.com/cdebotton/react-universal
- https://github.com/yummies/yummies#overview
- https://github.com/yummies/core-components/blob/master/components/input/_type/search/index.es6
- https://github.com/yummies/theme-reset
- https://github.com/yummies/babel-plugin-yummies#mods
- https://github.com/yummies/starter-kit
- https://github.com/sebmarkbage/ecmascript-rest-spread
- https://github.com/tc39/ecma262
- https://github.com/luisfarzati/json-chance
- https://github.com/xgrommx/awesome-redux
- https://github.com/facebook/immutable-js/tree/master/contrib/cursor
- https://github.com/Yomguithereal/baobab
- https://github.com/mistadikay/react-auto-fetching-example/blob/master/src/components/products-list/index.es6#L9-L23
- https://github.com/sindresorhus
- https://github.com/sindresorhus/cat-names
- https://github.com/mistadikay/react-auto-fetching-example/blob/master/src/components/products-list/index.es6#L14-L16
- https://github.com/gaearon/redux/blob/improve-docs/docs/store.md
- https://github.com/alexeyraspopov/flux-stateful
- https://github.com/yahoo/react-intl
- https://github.com/piranha/puttext
- https://github.com/bevacqua/woofmark
- https://github.com/RickWong/react-isomorphic-starterkit
- https://github.com/webpack/react-starter
- https://github.com/DavidWells/isomorphic-react-example
- https://github.com/rackt/react-router
- https://github.com/matthew-andrews/isomorphic-fetch
- https://github.com/facebook/react/issues/3009
- https://github.com/douglasduteil/isparta/issues/31#issuecomment-123894638
- https://github.com/deepsweet/istanbul-instrumenter-loader
- https://github.com/deepsweet/isparta-loader
- https://github.com/tmpvar/jsdom
- https://github.com/rstacruz/mocha-jsdom
- https://github.com/erikras/react-redux-universal-hot-example
- https://github.com/ShpuntiK/isomorphic-app-sample
- https://github.com/webdriverio/webdrivercss
- https://github.com/babel/babel/tree/master/packages/babylon
- https://github.com/codemix/babel-plugin-typecheck
- https://github.com/babel/babel/blob/master/packages/babel/src/util.js
- https://github.com/babel-plugins/babel-plugin-flow-comments
- https://github.com/rambler-digital-solutions/superagent-mocker
- https://github.com/Microsoft/TypeScript/wiki/Roadmap
- https://github.com/Yomguithereal/baobab/wiki/Select-state
- https://github.com/Yomguithereal/baobab/tree/v2
- https://github.com/gaearon/redux/tree/rewrite-docs
- https://github.com/mquan/cortex
- https://github.com/enaqx/awesome-react#data-managing
- https://github.com/tonsky/datascript
- https://github.com/aserg-ufmg/JSCity/wiki/JSCITY
- https://github.com/chriso/validator.js
- https://github.com/gcanti/tcomb-form
- https://github.com/insin/newforms
- https://github.com/mistadikay/react-auto-fetching-example/blob/doob/src/components/product/index.es6#L8-L17
- https://github.com/christianalfoni/formsy-react
- https://github.com/mistadikay/doob
- https://github.com/teropa/angular-virtual-dom
- https://github.com/babel/babel-eslint
- https://github.com/babel/eslint-plugin-babel
- https://github.com/yannickcr/eslint-plugin-react
- https://github.com/estree/estree
- https://github.com/typicode/husky
- https://github.com/beeftornado/homebrew-rmtree
- https://github.com/facebook/flow/issues/277#event-338421297
- https://github.com/gcanti/flowcheck
- https://github.com/gaearon/flowcheck-loader
- https://github.com/babel/babel/issues/1851
other
- https://gist.github.com/deepsweet/15c8f2eb3a85004adad0
- https://gist.github.com/afitiskin/a65c26ff923d13788980
- https://www.reddit.com/r/slashdiabloevents/
- http://slashdiablo.wikia.com/wiki/Slashdiablo_Wiki
- http://xgrommx.github.io/rx-book/content/similar_libraries/index.html
- https://www.youtube.com/watch?v=I7IdS-PbEgI
- http://www.youtube.com/watch?v=lDkrXTDwbJQ
- http://www.youtube.com/watch?v=tUtLe1VlkYc
- https://medium.com/@mistadikay/declarative-data-fetching-in-react-components-with-baobab-e43184c43852
- https://medium.com/@clayallsopp/your-first-graphql-server-3c766ab4f0a2
- https://medium.com/@frikille/moving-from-rest-to-graphql-e3650b6f5247
- https://medium.com/javascript-scene/why-i-use-tape-instead-of-mocha-so-should-you-6aa105d8eaf4
- http://alt.js.org/
- https://docs.google.com/spreadsheets/d/1TZPdUYDx6D1NWBXp_6NNtJ-NeVW6pudx3C9SkYSXI18/edit#gid=0
- http://funkyimg.com/i/ZkVp.png
- http://codepen.io/SitePoint/pen/VLXyZw
- https://facebook.github.io/react/docs/top-level-api.html
- https://facebook.github.io/react/blog/2015/07/03/react-v0.14-beta-1.html
- https://facebook.github.io/react/docs/why-react.html
- https://facebook.github.io/react/docs/test-utils.html
- http://koajs.com/
- http://visionmedia.github.com/superagent/
- http://bit.ly/1TPnKSn
- https://webpack.github.io/docs/library-and-externals.html
- https://jsunderhood.ru/
- https://jsunderhood.ru/deepsweet
- http://jlongster.com/Removing-User-Interface-Complexity,-or-Why-React-is-Awesome
- http://reactkungfu.com/2015/07/approaches-to-testing-react-components-an-overview/
- http://pioneerjs.com/
- http://shpuntik.github.io/isomorphic-apps-presentation
- http://webdriver.io/
- http://flowtype.org/docs/quick-reference.html
- http://www.html5rocks.com/en/tutorials/forms/constraintvalidation/
- http://angular-formly.com/
- http://status.coveralls.io/
- http://eslint.org/blog/2015/07/eslint-1.0.0-rc-3-released/#reset-is-now-the-default
- http://eslint.org/docs/rules/
- http://replygif.net/i/100.gif
- http://www.140byt.es/
- https://jsfiddle.net/trnt/savrdygy/
- https://www.google.ru/search?q=%D0%B1%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9+%D1%83%D0%B1%D0%BB%D1%8E%D0%B4%D0%BE%D0%BA&tbm=isch#newwindow=1&tbm=isch&q=%D0%B1%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9+%D1%83%D0%B1%D0%BB%D1%8E%D0%B4%D0%BE%D0%BA+50+%D0%BE%D1%82%D1%82%D0%B5%D0%BD%D0%BA%D0%BE%D0%B2