deepsweet

20 июля 2015, Saint Petersburg, Russia

# Понедельник 67 твитов

всем привет, эту неделю с вами будет @deepsweet. меня зовут Кир, кто-то может помнить меня по Яндексу, для остальных я просто JS-разработчик

2:32

т.к. у меня GMT+7 и вы скорей всего спите, я пока поспамлю темами, на которые мне было бы интересно поговорить :)

2:33

webpack, 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 modules
5:05

собственно, основная идея React + BEM в том, что JSX – говно, а BEMJSON – добро github.com/yummies/yummie…

5:11

дальше – наследование github.com/yummies/core-c…, ещё дальше – "уровни переопределения" или, как мы их называем, "слои" github.com/yummies/babel-…

5:12

BEM-модификатор – это класс, который (автоматически) наследуется от класса 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';

6:50

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:46

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

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:11

Create random JSON objects using json-spawn and Chance.js github.com/luisfarzati/js…

12:31

Awesome 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:36

Declarative 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

.@_cloudo можно чуть подробнее? не совсем уловил.

6:50
@jsunderhood на самом деле, если разобраться - баобаб тянет кучу всего лишнего. свой апи, курсоры, кучи методов (push, get). Нет даже has
6: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 и теперь пробую redux
9: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 У вас есть i18n? Кто как решает эту задачу с React?
10:50
@dimchez @jsunderhood @roman01la метод translate прокидывался в компоненты как props.
12:25
@roman01la @jsunderhood использую github.com/piranha/puttext:
парсинг вызовов -> *.po -> *.json -> puttext(require('*.json'))
12:39
@roman01la @jsunderhood Polyglot.js от airbnb + своя привязка к Redux
14:15
@olebedev @jsunderhood @roman01la +1 к puttext, просто и сердито
14:16
Фронтаны, а может кто поможет найти решение или лучшие практики для smooth parallax scrolling? кто как делает @jsunderhood
14: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 Engineer
16: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:52

Ajax with less suck - (and node.js HTTP client to match)
visionmedia.github.com/superagent/ – чуть не забыл, "изоморфный ajax".

5:55
@jsunderhood И все это быстро?
5:55

.@lyxdenv ни чем не должно отличаться от похода за данными на бэкенд в любой другой системе.

5:56
@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 а почему нельзя:
React.render(<Handler />, document);
?
6:24

.@olebedev можно и нужно, вот только сторы пустые.

6:25

т.е. при серверном рендеринге, куда-нибудь в <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

.@snejink абсолютно тот же расшаренный маппинг роут -> экшн(ы).

6:44

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

6:45

хотя бы издалека понимать принцип работы такой не самой простой штуки уже полезно.

6:46
@jsunderhood есть react native для андроида?
6:46

.@kra1g0 afaik нет, но они очень обещают. без чётких сроков, как обычно у Facebook.

6:47
@jsunderhood данные для render нужно заранее готовить и в отдельном от React месте. Я вот для этого либу написал bit.ly/1TPnKSn
6:48

.@__fro можно в двух словах основной принцип?

6: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.ru
7: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

.@slonoed компонент не должен о таком думать

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:27

Approaches 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 такой же набор + sinon
7:09
@jsunderhood ну а дальше mocha, chai с параметром —compilers js:babel/register
7: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, на сервере через selenium
10:18
@vslinko @milk_is_my_life @jsunderhood @silentroach хороший вопрос, я пока не знаю. по зависимостям pioneer ссылается на форк cucumberjs.
10:20
@adaniliuk @milk_is_my_life @jsunderhood @silentroach понял, это враппер над ним, с e2e API. Но мне больше нравится webdriver.io
10: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:51

Turn flow type annotations into comments github.com/babel-plugins/…

11:07
@jsunderhood Все задаю вопрос почему flow? Почему не typescript?
12:10

.@xgrommx а TypeScript уже разве полностью синхронизировался с ES6?

12:16

пруф или не было :) 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

хм, ок. тогда почему не TypeScript?

12:20
@jsunderhood он умеет искать по полям в объектах? типа: хочу объект из массива в котором id: 5
12:22

.@roman01la да, стандартными средствами Baobab. мы когда осознали, кажется взвизгнули.

12:23

btw, скоро 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/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… - следующая итерация идеи @nikitonsky
13:06
@jsunderhood я это в своем slt как раз имел ввиду ). Короче, состояние целостно только в случае, когда все причины хранятся в нем же
13:08
@jsunderhood и тут основаная моя претензия к flux.Вызов экшена никак не фиксируется,теряются причины.В #redux такая же проблема @dan_abramov
14:00

↓ и дальше по реплаям.

14:00

JSCity is an implementation of the Code City metaphor for visualizing source code github.com/aserg-ufmg/JSC… 😻

14:30

# Пятница 40 твитов

Пс, парень, немного рекурсии не желаешь? pic.twitter.com/tw4p65bqnB
1: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 tcomb интересный, был небольшой опыт, но newforms поддерживают isomorphic
2:53
@iSnifer @jsunderhood А еще в ангуляре есть великолепнейшая либа angular-formly.com
3: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 в angular
7: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
@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

.@iSnifer @xgrommx покажи уже ангуларовый рай для создания и валидации форм

9:58
@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:42

A Virtual DOM based AngularJS view renderer designed to be used with immutable data structures github.com/teropa/angular…

14:12

# Суббота 53 твита

So true

// = "oh hey, by the way,"
/* = "please take a seat."

2:23

в 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

.@tvii всё бросать сразу точно не стоит, но попробовать – однозначно.

9:58
@jsunderhood а есть смысл переходить, если пишешь на es5 и не на react? мне это видится переходом ради перехода
10:23

.@baxxabit помимо ES6 и прочих JSX смысл есть уже просто потому, что это новое поколение знакомого инструмента eslint.org/docs/rules/

10:35
@baxxabit @jsunderhood можно новое начать писать на ES6
10:36
@baxxabit @jsunderhood А причём тут React?
10:36

.@freiksenet @baxxabit заметили, как мощно React/JSX зафорсили ES6, что иногда даже одно без другого уже кажется странным? :)

10:37

(по большому счёту и JSCS не нужен, codestyle-правил в ESLint по крайней мере для меня уже достаточно)

10:43

(с одной стороны, разделение обязанностей это хорошо, с другой – два разных инструмента это слишком)

10:45

btw, 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:56

homebrew-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

.@Kern_0 у меня уже почти 10 утра

2:43

задумка простая: перед тем как удалять, превращать все flow types annotations в инлайновые ассерты. только в dev-режиме, конечно же.

2:47
@jsunderhood и да, typescript тащит!
2:49
@backendsecret @jsunderhood @rubyunderhood думаю, картинка будет полезна pic.twitter.com/6tkRlf8CqN
3: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

.@__fro вот трушный TDD – пока мечта. это явный показатель очень высокого уровня.

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 декларацией параметров для них ?
jsfiddle.net/trnt/savrdygy/
10:59

.@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

11:37
@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

other