├── .gitignore
├── .nojekyll
├── LICENSE
├── README.md
├── abbr
├── index.html
├── offline.js
├── readme-en.md
└── readme.md
├── absurd
├── absurd.svg
├── cantor.png
├── cl2.png
├── contra.png
├── fire.jpg
├── fl4.png
├── gedel1.png
├── gedel2.png
├── index.html
├── non-stop.png
├── offline.js
├── order.png
├── predicates.png
├── readme.md
├── santa.png
├── self-exclude.png
├── stop.png
├── table.png
├── this-is-absurd.png
├── this-is-false.png
├── this-is-true.png
└── ways.png
├── business
├── index.html
├── offline.js
├── readme.md
└── readme0.md
├── consensus
├── byzantine.svg
├── concurrency.svg
├── consensus.svg
├── convergence.svg
├── dead-lock.svg
├── discord.svg
├── disjoint.svg
├── full.svg
├── inconsistency.svg
├── index.html
├── offline.js
├── optimistic.svg
├── order.svg
├── pessimistic.svg
├── readme.md
├── readme1.md
├── semi-order.svg
├── short.svg
└── unorder.svg
├── css-in-ts
├── index.html
├── offline.js
└── readme.md
├── cvrdt
├── crdt-clock-logical.svg
├── crdt-clock-real.svg
├── crdt-counter.svg
├── crdt-crowd.svg
├── crdt-dead-forget.svg
├── crdt-dead-tombstone.svg
├── crdt-diff-tree.svg
├── crdt-lseq.svg
├── crdt-lww-reg.svg
├── crdt-map.svg
├── crdt-mv-reg.svg
├── crdt-oracle.svg
├── crdt-p2p.svg
├── crdt-set.svg
├── crdt-treedoc.svg
├── crdt-woot.svg
├── crdt-yata.svg
├── index.html
├── offline.js
└── readme.md
├── dragon-way
├── index.html
├── offline.js
└── readme.md
├── escobar
├── hysteresis.png
├── index.html
├── kano.png
├── multikano.png
├── nekano.png
└── readme.md
├── fibers
├── async-only.png
├── cache-1.svg
├── cache-2.svg
├── call-back.jpg
├── de-serialization.jpg
├── fiber-stack.png
├── flame-chart.png
├── idemp-1.svg
├── idemp-2.svg
├── index.html
├── lotus.jpeg
├── low-fps.gif
├── no-concurrency.gif
├── no-escape.jpg
├── offline.js
├── quants.gif
├── react-debug.jpg
├── react-everywhere.jpg
├── react-logic.png
├── react-only.gif
├── react-stack.png
├── react-trap.jpg
├── readme.md
├── server-chart.png
├── stop.jpg
├── sync-0.svg
├── sync-1.svg
└── worker-logic.png
├── mobility
├── index.html
├── offline.js
└── readme.md
├── mol
├── angular-vs-react.jpg
├── bloat.jpg
├── bus-factor.jpg
├── dumb-framework.jpg
├── hard-choice.png
├── hyip.jpg
├── index.html
├── library.jpg
├── mol-deps.svg
├── mol-deps.xml
├── mol-goo.png
├── no-templates.jpg
├── offline.js
├── pain.jpg
├── readme.md
├── readme.pdf
├── rich-framework.png
├── siziph.png
├── tinkoff-office.jpg
└── vecicle.jpg
├── monopoly
├── index.html
├── offline.js
└── readme.md
├── orp
├── all_deps.png
├── angular_1.png
├── angular_2.png
├── angular_3.png
├── angular_4.png
├── angular_5.png
├── channels_1.png
├── channels_2.png
├── channels_3.png
├── company.png
├── fc.png
├── flux_1.png
├── flux_2.png
├── flux_3.png
├── index.html
├── linear.png
├── linear_log.png
├── mol.svg
├── not_on_my_shift.png
├── offline.js
├── ofr_p.png
├── only_visible.png
├── readme.md
├── render_html.png
├── render_orp.png
├── render_vdom.png
├── shit.png
├── toys.png
├── toys_filtered.png
├── toys_sorted.png
└── user_front_back.png
├── package.json
├── reactivity
├── index.html
├── offline.js
├── reactivity-actions.svg
├── reactivity-auto.svg
├── reactivity-cascade.svg
├── reactivity-cycle-allow.svg
├── reactivity-cycle-fail.svg
├── reactivity-cycle-limbo.svg
├── reactivity-cycle-unreal.svg
├── reactivity-defer.svg
├── reactivity-error-revert.svg
├── reactivity-error-stop.svg
├── reactivity-error-store.svg
├── reactivity-error-unstable.svg
├── reactivity-instant.svg
├── reactivity-interactive.svg
├── reactivity-invariants.svg
├── reactivity-lazy.svg
├── reactivity-manual.svg
├── reactivity-order-code.svg
├── reactivity-order-deep.svg
├── reactivity-order-event.svg
├── reactivity-order-subscribe.svg
├── reactivity-pull.svg
├── reactivity-push.svg
├── reactivity-reactions.svg
├── reactivity-reactive.svg
├── reactivity-reactivity.svg
├── reactivity-runtime.svg
├── reactivity-snowboll.svg
├── reactivity-stable.svg
├── reactivity-states.svg
└── readme.md
├── slides
├── batman.png
├── cat.gif
├── index.html
├── keys.png
├── offline.js
├── offline.png
├── piterjs.png
├── print.png
├── readme.md
└── touch.png
├── sourcemap
├── index.html
├── offline.js
└── readme.md
├── templates
├── index.html
├── offline.js
└── readme.md
├── testing
├── index.html
├── offline.js
├── readme.md
├── readme1.md
└── readme2.md
├── tree
├── index.html
├── offline.js
├── readme.md
└── standarts.png
├── turing-ts-types
├── index.html
├── offline.js
└── readme.md
├── ui-kit
├── design-binom.svg
├── design-blocks.svg
├── design-cards.svg
├── design-fixed.svg
├── design-flex.svg
├── design-font.svg
├── design-grid.svg
├── design-header.svg
├── design-line.svg
├── design-matreshka.svg
├── design-paragraph.svg
├── design-symmetry.svg
├── design-table-big.svg
├── design-table-cards.svg
├── design-table-small.svg
├── fc.svg
├── index.html
├── offline.js
└── readme.md
├── virt
├── after.png
├── anchor.png
├── atomic.png
├── before.png
├── column.png
├── gaps.png
├── grids.png
├── index.html
├── inside.png
├── nothing.png
├── offline.js
├── overlap-bottom.png
├── overlap-top.png
├── readme.md
├── render.png
├── row.png
├── stack.png
├── timeslice.png
└── wrap.png
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /package-lock.json
3 |
--------------------------------------------------------------------------------
/.nojekyll:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 nin-jin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Мои слайды для конференций
2 |
3 | ## [Как программисты дурят бизнес?](https://page.hyoo.ru/#!=swfl3g_y3okjr)
4 |
5 | Рассказ о том, как программисты вынуждают бизнес тратить кучу денег и времени ради сомнительных веловипедов и отказываться от действительно эффективных технологий.
6 |
7 | ## [Что не так с сорсмапами и как с ними не связываться?](sourcemap) 
8 |
9 | Рассказ про устройство source maps, их подводные камни и про пайплайн для формата tree, позволяющий легко и просто разрабатывать свои DSL.
10 |
11 | ## [Quantum Mechanics of Calculations](fibers) 
12 |
13 | Рассказ о реализации кроссплатформенных псевдофайберов на основе перезапусков, позволяющих разбивать вычисления на кванты по 8мс, приостанавливать на асинхронных операциях и отменять их до полного завершения.
14 |
15 | ## [Автоматическая виртуализация рендеринга произвольной вёрстки](virt) 
16 |
17 | Рассказ про полностью виртуальный рендеринг, гарантирующий отзывчивость приложения независимо от размера страницы, и не требующий от прикладного разработчика дополнительных приседаний.
18 |
19 | ## [Разбираемся в сортах реактивности](https://github.com/nin-jin/slides/tree/master/reactivity) 
20 |
21 | Глубокий анализ основных аспектов моделей реактивности, выработка наиболее практичного подхода, и сравнение существующих библиотек на предмет близости к идеалу.
22 |
23 | ## [Объектное Реактивное Программирование](orp) 
24 |
25 | Рассказ о парадигме программирования, где правила взаимосвязей частей приложения описываются в простой и естесственной форме, а вся рутина по оптимальной организации потоков данных берёт на себя автоматика.
26 |
27 | ## [Фрактальное тестирование](testing) 
28 |
29 | Рассказ про прагматичный подход к тестированию, позволяющий добиться максимальной надёжности минимумом усилий, путём отказа от модульных и системных тестов.
30 |
31 | ## [$mol - лучшее средство от геморроя](mol) 
32 |
33 | Рассказ об идеях, положенных в основу компактного высокоуровневого веб-фреймворка $mol.
34 |
35 | ## [Презентация приложения для проведения презентаций](slides) 
36 |
37 | Рассказ про приложение, через которое я показываю слайды на всех своих выступлениях.
38 |
39 | ## [Tree - единый AST чтобы править всеми](tree) 
40 |
41 | Рассказ про крайне простой, человекочитаемый, но компактный формат представления произвольных структур данных, который уделывает XML, JSON, YAML, TOML и остальных по всем фронтам.
42 |
43 | ## [Продвинутый CSS-in-TS](css-in-ts) 
44 |
45 | Рассказ про максимально статическую типизацию стилей, учитывающюю реальную иерархию компонент.
46 |
--------------------------------------------------------------------------------
/abbr/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/abbr/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/absurd/cantor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/cantor.png
--------------------------------------------------------------------------------
/absurd/cl2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/cl2.png
--------------------------------------------------------------------------------
/absurd/contra.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/contra.png
--------------------------------------------------------------------------------
/absurd/fire.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/fire.jpg
--------------------------------------------------------------------------------
/absurd/fl4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/fl4.png
--------------------------------------------------------------------------------
/absurd/gedel1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/gedel1.png
--------------------------------------------------------------------------------
/absurd/gedel2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/gedel2.png
--------------------------------------------------------------------------------
/absurd/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/absurd/non-stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/non-stop.png
--------------------------------------------------------------------------------
/absurd/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/absurd/order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/order.png
--------------------------------------------------------------------------------
/absurd/predicates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/predicates.png
--------------------------------------------------------------------------------
/absurd/santa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/santa.png
--------------------------------------------------------------------------------
/absurd/self-exclude.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/self-exclude.png
--------------------------------------------------------------------------------
/absurd/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/stop.png
--------------------------------------------------------------------------------
/absurd/table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/table.png
--------------------------------------------------------------------------------
/absurd/this-is-absurd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/this-is-absurd.png
--------------------------------------------------------------------------------
/absurd/this-is-false.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/this-is-false.png
--------------------------------------------------------------------------------
/absurd/this-is-true.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/this-is-true.png
--------------------------------------------------------------------------------
/absurd/ways.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/absurd/ways.png
--------------------------------------------------------------------------------
/business/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/business/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/consensus/concurrency.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/consensus/consensus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/consensus/convergence.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/consensus/discord.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/consensus/disjoint.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/consensus/inconsistency.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/consensus/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/consensus/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/consensus/readme1.md:
--------------------------------------------------------------------------------
1 | # Алгоритмы консенсуса
2 |
3 | ## Документ
4 |
5 | - 200 страниц
6 | - 50K слов
7 | - 300К символов
8 |
9 | ## Негативный сценарий
10 |
11 | > Несколько клиентов в оффлайне внесли изменения и хотят синхронизоваться
12 |
13 | ## Описание дерева
14 |
15 | - сверху вниз
16 | - снизу вверх
17 |
18 | ## Разрешение конфликтов
19 |
20 | - Ручное
21 | - Автоматическое
22 |
23 | ## Автоматическое слияние
24 |
25 | - Гарантия сходимости в конечном счёте
26 | - Предсказуемый для пользователя результат
27 | - Предугадать желания пользователей
28 |
29 | ## Оракул
30 |
31 | - Сервер может хранить больше информации, чем клиенты
32 | - Гарантирует сходимость состояний
33 | - Единая точка отказа
34 |
35 | ## Алгоритмы синхронизации
36 |
37 | | Что передаётся | Строгий порядок (Naive) | Частичный порядок (CROWD) | Произвольный порядок (RDT)
38 | |----------------|----------------------------|---------------------------|--------------------------------
39 | | Состояния | Full State Replacement | CROWD Register / Ordered Set | ConVergent Replicated Data Type
40 | | Операции | Operational Transformation | | CoMutative Replicated Data Type
41 | | Разница | | CROWD Counter / Onordered Set / Tagged Union / Tuple / Dictionary / Text / Json | Delta Replicated Data Type
42 |
43 | ### Full State Replacement
44 | ### ConVergent Replicated Data Type
45 |
46 | ### Operational Transformation
47 | ### CoMutative Replicated Data Type
48 |
49 | ### Difference Stream
50 | ### Delta Replicated Data Type
51 |
52 | ### Выбор алгоритма
53 |
54 | | Свойство | FSR | OT | DS | CvRDT | CmRDT | dRDT
55 | |----------|-----|-------|----|-------|----|------
56 | | Непересекающиеся правки сливаются без потерь | ❌ | ✅ | ✅ | ✅ | ✅ | ✅
57 | | Независимость хранимого объёма от числа изменений | ✅ | ❌ | ✅ | ✅ | ❌ | ❌
58 | | Независимость хранимого объёма от числа пиров | ✅ | ✅ | ✅ | ❌ | ✅ | ❌
59 | | Порядок прихода событий не важен | ❌ | ❌ | ❌ | ✅ | ✅ | ✅
60 | | Стойкость к дублированию событий | ✅ | ❌ | ✅ | ✅ | ❌ | ❌
61 | | Независимость размера события от размера документа | ❌ | ✅ | ✅ | ❌ | ✅ | ✅
62 | | Время наложения патча не зависит от его древности | ✅ | ❌ | ✅ | ✅ | ✅ | ✅
63 |
--------------------------------------------------------------------------------
/css-in-ts/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/css-in-ts/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/cvrdt/crdt-lww-reg.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/cvrdt/crdt-map.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/cvrdt/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/cvrdt/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/dragon-way/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/dragon-way/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/escobar/hysteresis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/escobar/hysteresis.png
--------------------------------------------------------------------------------
/escobar/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/escobar/kano.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/escobar/kano.png
--------------------------------------------------------------------------------
/escobar/multikano.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/escobar/multikano.png
--------------------------------------------------------------------------------
/escobar/nekano.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/escobar/nekano.png
--------------------------------------------------------------------------------
/escobar/readme.md:
--------------------------------------------------------------------------------
1 | # Выбор из двух зол
2 |
3 | Как принимать наименее фатальные решения в условиях противоречивых требований.
4 | Не интуитивно наобум, а рационально и прагматично.
5 | При этом учитывая субъективные впечатления пользователей.
6 | Поговорим о фундаментальных принципах простым языком.
7 | Так что и продвинутый словит пару инсайтов, и новичок не растеряется.
8 |
9 | # todo
10 |
11 | - тезис через весь доклад (уменьшение негатива превыше увеличения позитива)
12 | - Менее спорные примеры для тезисов
13 | - Негатив: уменьшение, подслащение, перенаправление
14 | - wsjf
15 |
16 | ## Кто здесь?
17 |
18 | - Я тут случайно
19 | - Вообще, я программист
20 | - Поделюсь взглядом со своей перспективы
21 | - Пруфов не будет
22 |
23 | ## Дима, сделай нам редактор
24 |
25 | - Поспрашивай людей, узнай, что им надо
26 | - Нарисуй красивый роадмап
27 | - Сделай, чтобы всё было заечно
28 | - И только попробуй проемелить сроки
29 |
30 | ## Все хотя разного
31 |
32 | - Противоречивые требования
33 | - Скрытые требования
34 | - Фальшивые требования
35 |
36 | ## Каждому по продукту?
37 |
38 | - Нужно много рук
39 | - Нужно много времени
40 | - На 90% они будут похожи
41 |
42 | ## Универсальный продукт?
43 |
44 | - Совмещение ужа и ежа
45 | - Нужно хорошо всё продумать
46 | - Легко кастомизировать
47 |
48 | ## Модель Кано
49 |
50 | 
51 |
52 | # Деконструкция Кано
53 |
54 | - Сначала минимизация негатива
55 | - Потом максимизация позитива
56 |
57 | ## Модель НеКано
58 |
59 | 
60 |
61 | ## Гистерезис впечатлений
62 |
63 | 
64 |
65 | # Частота использования
66 |
67 | - Базовые должны быть даже если редко используются
68 | - Редкий негатив бьёт сильнее, чем частый позитив
69 |
70 | ## Умный против глупого
71 |
72 | - Все любят умные системы
73 | - Но только пока они не умнее самого пользователя
74 |
75 | ## Кейс с лентами новостей
76 |
77 | - Пользователь не понимает как строится лента
78 | - Видит много нерелевантного
79 | - Перестаёт пользоваться лентой
80 | - Вводятся всё более "интеллектуальные" алгоритмы
81 | - Всё более не понятно
82 | - Обострение реакции на нерелевантное
83 | - Пропускает важные для него записи
84 | - Подписки -> Колокольчики -> ...
85 |
86 | ## Противоречащие фичи
87 |
88 | Всё это, конечно, хорошо, но фичи нередко взаимосвязаны.
89 |
90 | ## Взаимозаменяющие фичи
91 |
92 | - Одна включает другую
93 | - Одна заменяет другую
94 | - Одна исключает другую
95 |
96 | ## Оптимум Парето
97 |
98 | Улучшить нельзя не ухудшив другого.
99 |
100 | ## Деградация позитива
101 |
102 | Восхищающая -> Желаемое -> Базовое
103 |
104 | ## Обострение негатива
105 |
106 | Терпимо -> Отвращающее -> Зашквар
107 |
108 | ## Закон больших чисел
109 |
110 | - Постоянно кто-то будет вляпываться в негатив
111 | - Каждый постояннный пользователь неизбежно столкнётся с негативом
112 |
113 | ## Направление негатива
114 |
115 | - На систему
116 | - На другого пользователя
117 |
118 | Непрозрачная система создаёт впечатление глючной, даже если предельно корректна.
119 |
120 | ## Фальшивые ожидания
121 |
122 | - Спрашиваешь - пользователю надо
123 | - Наблюдаешь - пользователь не пользуется
124 |
125 | ## Изменение ожиданий
126 |
127 | - Лояльность пользователей
128 | - Уверенность в решении
129 | - Отсутствие выбора
130 | - Минимизация негатива от изменения привычек
131 |
132 | Хорошее решение вирусно распространяется на конкурентов, но вы уже лидер.
133 |
134 | ## Ожидание и реальность
135 |
136 | Приятный сюрприз лучше неприятного.
137 |
--------------------------------------------------------------------------------
/fibers/async-only.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/async-only.png
--------------------------------------------------------------------------------
/fibers/cache-1.svg:
--------------------------------------------------------------------------------
1 |
126 |
--------------------------------------------------------------------------------
/fibers/cache-2.svg:
--------------------------------------------------------------------------------
1 |
127 |
--------------------------------------------------------------------------------
/fibers/call-back.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/call-back.jpg
--------------------------------------------------------------------------------
/fibers/de-serialization.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/de-serialization.jpg
--------------------------------------------------------------------------------
/fibers/fiber-stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/fiber-stack.png
--------------------------------------------------------------------------------
/fibers/flame-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/flame-chart.png
--------------------------------------------------------------------------------
/fibers/idemp-1.svg:
--------------------------------------------------------------------------------
1 |
165 |
--------------------------------------------------------------------------------
/fibers/idemp-2.svg:
--------------------------------------------------------------------------------
1 |
167 |
--------------------------------------------------------------------------------
/fibers/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/fibers/lotus.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/lotus.jpeg
--------------------------------------------------------------------------------
/fibers/low-fps.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/low-fps.gif
--------------------------------------------------------------------------------
/fibers/no-concurrency.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/no-concurrency.gif
--------------------------------------------------------------------------------
/fibers/no-escape.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/no-escape.jpg
--------------------------------------------------------------------------------
/fibers/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/fibers/quants.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/quants.gif
--------------------------------------------------------------------------------
/fibers/react-debug.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/react-debug.jpg
--------------------------------------------------------------------------------
/fibers/react-everywhere.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/react-everywhere.jpg
--------------------------------------------------------------------------------
/fibers/react-logic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/react-logic.png
--------------------------------------------------------------------------------
/fibers/react-only.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/react-only.gif
--------------------------------------------------------------------------------
/fibers/react-stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/react-stack.png
--------------------------------------------------------------------------------
/fibers/react-trap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/react-trap.jpg
--------------------------------------------------------------------------------
/fibers/server-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/server-chart.png
--------------------------------------------------------------------------------
/fibers/stop.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/stop.jpg
--------------------------------------------------------------------------------
/fibers/sync-0.svg:
--------------------------------------------------------------------------------
1 |
125 |
--------------------------------------------------------------------------------
/fibers/sync-1.svg:
--------------------------------------------------------------------------------
1 |
112 |
--------------------------------------------------------------------------------
/fibers/worker-logic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/fibers/worker-logic.png
--------------------------------------------------------------------------------
/mobility/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/mobility/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/mobility/readme.md:
--------------------------------------------------------------------------------
1 | # Разработчик без дизайнера
2 |
3 | * Быстрый результат
4 | * UX и UI ниже плинтуса
5 | * Заточено под один форм-фактор
6 | * Много работы по адаптивности - дорого
7 |
8 | # Дизайнер в деле
9 |
10 | * Долго отрисовывает все экранчики - дорого
11 | * Неконсистентность в макетах
12 | * Заточено под один форм-фактор
13 | * Много работы по адаптивности - дорого
14 | * Синхронизация работ разных отделов - долго
15 |
16 | # Цели
17 |
18 | * Создание опрятных приложений без дизайнера
19 | * Максимальное переиспользование кода
20 | * Один разработчик - все платформы
21 |
22 | # Десктоп
23 |
24 | * Стационарное использование
25 | * Много места, хорошо бы потратить его с пользой
26 | * Приложение может быть открыто не на весь экран
27 | * Управление мышью, пальцем, пером
28 |
29 | # Ноутбук
30 |
31 | * То же, что и десктоп, но мобильный
32 | * Управление мышью, пальцем, пером
33 |
34 | # Телефон
35 |
36 | * Мобильное использование
37 | * Мало места, не должно быть ничего лишнего
38 | * Приложение всегда полноэкранное
39 | * Управление пальцем
40 |
41 | # Планшет
42 |
43 | * Мобильное использование
44 | * Куча форм-факторов от телефона до десктопа
45 | * Управление пальцем, пером
46 |
47 | # К чему пришли
48 |
49 | * Универсальные UI и UX метафоры на всех платформах
50 | * Универсальное управление любым доступным средством ввода
51 | * Текущий код, как эталонный макет
52 | * Перекрёстное опыление дизайнер-разработчик
--------------------------------------------------------------------------------
/mol/angular-vs-react.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/angular-vs-react.jpg
--------------------------------------------------------------------------------
/mol/bloat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/bloat.jpg
--------------------------------------------------------------------------------
/mol/bus-factor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/bus-factor.jpg
--------------------------------------------------------------------------------
/mol/dumb-framework.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/dumb-framework.jpg
--------------------------------------------------------------------------------
/mol/hard-choice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/hard-choice.png
--------------------------------------------------------------------------------
/mol/hyip.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/hyip.jpg
--------------------------------------------------------------------------------
/mol/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/mol/library.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/library.jpg
--------------------------------------------------------------------------------
/mol/mol-deps.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/mol/mol-deps.xml:
--------------------------------------------------------------------------------
1 | 5VjJbtswEP0aXQuJlBT3mDhpCrQFCuTQ5lQwEi0xoTQGRW/9+pIitVu2m8TOFgMB+WY40rx5HAp08DRbXwsyT39ATLmD3Hjt4EsHoYnvqv8a2Bgg8M4MkAgWG8hrgBv2l1rQrksWLKZFx1ECcMnmXTCCPKeR7GBECFh13WbAu0+dk4QOgJuI8CH6i8UytWmhsMG/Upak1ZO98LOx3JHoIRGwyO3zHIRn5Z8xZ6SKZRMtUhLDqgXhKwdPBYA0o2w9pVxTW9Fm1n0ZsdbvLWguD1kwsa8hN1XqNFZM2CkImUICOeFXDXpRpkd1AFfNUplxNfTUkK6Z/K3hT4Gd3VaWXIpNy6SntzbAPZVyYyVAFhIU1Dz3O8DcxphBLq0b0usKKeChLg+qkSlwEGUu+KL8KcuQFstUAQsR2cyRFRoRCbVegYE0J61llsprChlViSgHQTmRbNlVD7EiTGo/u/RcCLJpOcyB5bJo10kNWvEbqKzeSOnRUUrZKmSrdrWpLmRpe82lDE9cShv5pwaUw7qqkt34tjF6fm9/7vHHE7enE/MGj1XNMzeAk2hjayEfIwn8RAV0dusukk2IJeELWh0Lfgb8z5JR1fvPlU1V1f12MahFw7SmZpUySW/mpExppQ7eLvv1WaJpSzgpCjuOIGORHffpJZwluZpEijsqdvC9hd4lFZKunV27qbKGPdlXsl41p2tJgsbS1slafUg8if7gOIfc2egp5x1f/nvUjk/QAA/mPzwO/+ht8f/s3xKH8o93tR9k+g963/3H91+w/3jegNc3/JF9kPz9V9R+/DH5EwmZUT9+3+rvn75ockr1uwNe37v6g6H6/ZdSfzCm/oxa8XsfTPzuCcUfjrEPd/flvdUHLAAOT/ntf7alAv12lMfn+s5QzXLIdfuJSZHWzLdY7hM4ys7efd7KPdiSeoX932XE4PbAd7vU+31KTdeyq3ZcQ/QDTXpxTKsbxNl/IaGmzWWncW8ulPHVPw==
--------------------------------------------------------------------------------
/mol/mol-goo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/mol-goo.png
--------------------------------------------------------------------------------
/mol/no-templates.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/no-templates.jpg
--------------------------------------------------------------------------------
/mol/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/mol/pain.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/pain.jpg
--------------------------------------------------------------------------------
/mol/readme.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/readme.pdf
--------------------------------------------------------------------------------
/mol/rich-framework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/rich-framework.png
--------------------------------------------------------------------------------
/mol/siziph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/siziph.png
--------------------------------------------------------------------------------
/mol/tinkoff-office.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/tinkoff-office.jpg
--------------------------------------------------------------------------------
/mol/vecicle.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/mol/vecicle.jpg
--------------------------------------------------------------------------------
/monopoly/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/monopoly/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/monopoly/readme.md:
--------------------------------------------------------------------------------
1 | # Фрактальные моно-поли-репозитории
2 |
3 | Организуем кодовую базу так, чтобы она легко и плавно масштабировалась от одной библиотеки, поддерживаемой одним человеком, до фрактальной экосистемы библиотек и приложений, поддерживаемой кучей команд из разных компаний.
4 |
5 | # Типичный путь развития проекта
6 |
7 | ## Поли-репо
8 |
9 | - Каждая библиотека в своём репозитории.
10 | - Изменил зависимость - изволь опубликовать и обновить версии в зависимых.
11 | - Зависимость от инфраструктуры при локальной разработке.
12 | - Пуш в поли-репо не атомарен.
13 |
14 | ## Моно-репо
15 |
16 | - Все библиотеки сваливаются в кучу в один репозиторий.
17 | - Пуш всегда атомарен.
18 | - Разработчики толкаются локтями, работая с одним репо.
19 | - Трудности с разграничением прав доступа.
20 | - Трудности с бранчеванием одной библиотеки без влияния на другие.
21 | - Не помещается на локальной машине целиком - нужен спец тулинг.
22 |
23 | ## Мульти-моно-репо
24 |
25 | - Каждой команде свой моно-репо.
26 | - Работаешь и там, и там - получаешь проблемы поли-репо.
27 | - С бранчеванием проблемы остаются.
28 | - Пуш сноова не атомарен.
29 |
30 | ## Что не так с этим путём?
31 |
32 | - Каждый переход - большая работа по изменению кода и тулинга.
33 | - Решаются одни проблемы - открываются другие.
34 | - Решаются другие - открываются первые.
35 |
36 | # Моно-поли-репо
37 |
38 | - Изначально репо одно.
39 | - Директория разрослась - в отдельный репо.
40 | - Рекурсивная декомпозиция порождает дерево репо.
41 | - Сам код остаётся неизменным.
42 | - Локальная разработка не зависит от инфраструктуры.
43 | - Не засоряется реестр пакетов промежуточными версиями.
44 | - Не фиксируются версии.
45 | - Простой тулинг.
46 |
47 | ## Композиция
48 |
49 | - Клонирование по необходимости.
50 | - В каждом репо - реестр вложенных репо.
51 | - В корневом репо - никакого кода.
52 |
53 | - `git submodules` - фикс ревизии
54 | - `git merge-tree` - фикс ревизии
55 | - `git clone | hg clone` - последняя ревизия
56 |
57 | ## Отделение кода от рабочего окружения
58 |
59 | - Настройки рабочего окружения - отдельное репо.
60 | - В рамках одного окружения работа со множеством проектов.
61 | - Настройки тулинга едины - приходят в корневом репо.
62 | - Централизованный рефакторинг всех репо.
63 |
64 | # Версионирование
65 |
66 | ## SemVer
67 |
68 | - Версия фиксируется по некоторому правилу.
69 | - Минорные версии тоже могут всё сломать.
70 | - Нельзя использовать сразу несколько версий.
71 | - Нет гарантий, что использована единая версия.
72 | - Нельзя выразить одну версию через другую.
73 | - Лок файлы для библиотек бесполезны.
74 | - Фрагментация экосистемы по версиям.
75 |
76 | ## VerLess
77 |
78 | - Версии не фиксируются.
79 | - Везде и всеми используется единая версия - последняя.
80 | - Непрерывная интеграция актуальных версий.
81 | - Изменения API - новый модуль, а не версия старого.
82 | - Старый модуль может быть выражен через новый.
83 |
84 | # Безопасность
85 |
86 | | | SemVer | VerLess
87 | |-|--------|--------
88 | | Диверсии | случаются (нужны тесты) | случаются (нужны тесты)
89 | | Фиксы безопасности | могут долго буксовать | уже при следующем релизе
90 |
91 | # Моно-поли-репо в дикой природе
92 |
93 | - [MAM: сборка фронтенда без боли]( https://habhub.hyoo.ru/#!author=nin-jin/repo=HabHub/article=18) - наш девтул.
94 | - [$hyoo](https://github.com/orgs/hyoo-ru/repositories?type=all) - наш моно-поли-репо.
95 | - [$psb_portal](https://github.com/MolDevHack) - пример фрактального микрофронтенда.
96 | - [Фрактальное тестирование](https://github.com/nin-jin/slides/tree/master/testing) - выступление на TechLeadConf.
97 |
98 | # Больше информации
99 |
100 | - [SemVer-vs-VerLess](https://github.com/hyoo-ru/mam_mol/wiki/SemVer-vs-VerLess) - про версионирование.
101 |
102 | ---
103 |
104 | - Добавить проблемы с зависимостями какие встретили и как они решаются.
105 | - Глянуть, что намутили в го-модулях.
--------------------------------------------------------------------------------
/orp/all_deps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/all_deps.png
--------------------------------------------------------------------------------
/orp/angular_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/angular_1.png
--------------------------------------------------------------------------------
/orp/angular_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/angular_2.png
--------------------------------------------------------------------------------
/orp/angular_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/angular_3.png
--------------------------------------------------------------------------------
/orp/angular_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/angular_4.png
--------------------------------------------------------------------------------
/orp/angular_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/angular_5.png
--------------------------------------------------------------------------------
/orp/channels_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/channels_1.png
--------------------------------------------------------------------------------
/orp/channels_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/channels_2.png
--------------------------------------------------------------------------------
/orp/channels_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/channels_3.png
--------------------------------------------------------------------------------
/orp/company.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/company.png
--------------------------------------------------------------------------------
/orp/fc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/fc.png
--------------------------------------------------------------------------------
/orp/flux_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/flux_1.png
--------------------------------------------------------------------------------
/orp/flux_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/flux_2.png
--------------------------------------------------------------------------------
/orp/flux_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/flux_3.png
--------------------------------------------------------------------------------
/orp/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/orp/linear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/linear.png
--------------------------------------------------------------------------------
/orp/linear_log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/linear_log.png
--------------------------------------------------------------------------------
/orp/not_on_my_shift.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/not_on_my_shift.png
--------------------------------------------------------------------------------
/orp/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/orp/ofr_p.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/ofr_p.png
--------------------------------------------------------------------------------
/orp/only_visible.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/only_visible.png
--------------------------------------------------------------------------------
/orp/render_html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/render_html.png
--------------------------------------------------------------------------------
/orp/render_orp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/render_orp.png
--------------------------------------------------------------------------------
/orp/render_vdom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/render_vdom.png
--------------------------------------------------------------------------------
/orp/shit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/shit.png
--------------------------------------------------------------------------------
/orp/toys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/toys.png
--------------------------------------------------------------------------------
/orp/toys_filtered.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/toys_filtered.png
--------------------------------------------------------------------------------
/orp/toys_sorted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/toys_sorted.png
--------------------------------------------------------------------------------
/orp/user_front_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/orp/user_front_back.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "local-static-server": "^2.2.0"
4 | },
5 | "scripts": {
6 | "start": "local-server"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/reactivity/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/reactivity/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/reactivity/reactivity-cycle-unreal.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/reactivity/reactivity-interactive.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/reactivity/reactivity-reactive.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/reactivity/reactivity-reactivity.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/reactivity/reactivity-states.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/slides/batman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/slides/batman.png
--------------------------------------------------------------------------------
/slides/cat.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/slides/cat.gif
--------------------------------------------------------------------------------
/slides/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/slides/keys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/slides/keys.png
--------------------------------------------------------------------------------
/slides/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/slides/offline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/slides/offline.png
--------------------------------------------------------------------------------
/slides/piterjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/slides/piterjs.png
--------------------------------------------------------------------------------
/slides/print.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/slides/print.png
--------------------------------------------------------------------------------
/slides/touch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/slides/touch.png
--------------------------------------------------------------------------------
/sourcemap/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/sourcemap/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/templates/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/templates/readme.md:
--------------------------------------------------------------------------------
1 | # Скрипты в шаблонах или теги в скриптах или?
2 |
3 | Вы можете открыть эти слайды в [интерфейсе проведения презентаций](https://nin-jin.github.io/slides/templates/) или [читать их как статью](https://github.com/nin-jin/slides/blob/master/templates/).
4 |
5 | > Что такое "шаблоны", чем они так хороши и почему они не нужны?
6 |
7 | # Скрипты в шаблонах?
8 |
9 | Что выбрать? Подход Angular с оживлением вёрстки с помощью директив?
10 |
11 | > ```html
12 | >
13 | > - ng-repeat="name in names | orderBy:'length' track by $index"
15 | > >
16 | > {{name}}
17 | >
18 | >
19 | > ```
20 |
21 | # Теги в скриптах?
22 |
23 | Или подход React c винегретом из двух языков?
24 |
25 | > ```jsx
26 | > function Names( props ) {
27 | > return (
28 | > {
29 | > props.names.slice()
30 | > .sort( ( a , b )=> a.length < b.length )
31 | > .map( name => (
32 | > - { name }
33 | > ) )
34 | > }
35 | > )
36 | > }
37 | > ```
38 |
39 | Или...
40 |
41 | # Что такое шаблон?
42 |
43 | Пример с подстановкой текста в строку
44 |
45 | > ```js
46 | > "Hello, ${name}!"
47 | > ```
48 |
49 | # А если обобщить?
50 |
51 | Пример со вставкой дерева в дерево
52 |
53 | > ```
54 | >
55 | >
56 | >
57 | >
58 | >
59 | >
60 | >
61 | >
62 | > ```
63 |
64 | # Зачем нужны шаблоны?
65 |
66 | > Шаблон:
67 | >
68 | > ```js
69 | > "Hello, ${name}!"
70 | > ```
71 |
72 | > Не шаблон:
73 | >
74 | > ```js
75 | > "Hello" + name + "!"
76 | > ```
77 |
78 | Шаблон позволяет буквально видеть результат, опуская вариативные детали.
79 |
80 | # Но как добиться динамики?
81 |
82 | Некоторые части шаблона могут быть опциональными и зависеть от входящих данных.
83 |
84 | # По шаблону на вариант?
85 |
86 | Будет много шалонов с копипастой. Будет комбинаторный взрыв числа шаблонов.
87 |
88 | # Помечать опциональные части?
89 |
90 | > ```
91 | >
92 | > {{#if isAdmin}}
93 | >
94 | > {{/if}}
95 | > {{ name }}
96 | >
97 | > ```
98 |
99 | В простых случаях это ещё работает.
100 |
101 | # А если сложная логика?
102 |
103 | Но по мере усложнения шаблона мы теряем возможность видеть результат, так как нам приходится в уме вычислять все условные выражения, чтобы понять, каков реально будет результат.
104 |
105 | > ```
106 | >
107 | > {{#if isAdmin}}
108 | >
109 | > {{else}}
110 | >
111 | > {{/if}}
112 | > {{ name }}
113 | >
114 | > ```
115 |
116 | # А что если вообще без логики?
117 |
118 | > ```
119 | >
120 | >
121 | >
122 | > {{ name }}
123 | >
124 | > ```
125 |
126 | Казалось бы, мы сделали шаг назад и потеряли всю динамику. Однако, обратите внимание на то, что каждому блоку мы присвоили уникальный идентификатор.
127 |
128 | # А как же логика?
129 |
130 | А для описания логики есть специально предназначенные языки:
131 |
132 | > ```
133 | > function Ecma_user_link( dom ) {
134 | > return {
135 | > ... dom ,
136 | > link_ : props => [
137 | > props.isAdmin ? dom.icon_admin : dom.icon_member ,
138 | > dom.name ,
139 | > ] ,
140 | > }
141 | > }
142 | > ```
143 |
--------------------------------------------------------------------------------
/testing/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/testing/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/tree/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/tree/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/tree/standarts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/tree/standarts.png
--------------------------------------------------------------------------------
/turing-ts-types/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/turing-ts-types/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/turing-ts-types/readme.md:
--------------------------------------------------------------------------------
1 | # Программирование на TypeScript типах
2 |
3 | | Дмитрий Карловский @ PiterJS#? |
4 | |--------------------------------|
5 |
6 | Вы можете [открыть это в интерфейсе проведения презентаций](https://nin-jin.github.io/slides/turing-ts-types/)
7 |
8 | # Иерархия типов TS
9 |
10 | 
11 |
12 | # Типотернарник
13 |
14 | ```typescript
15 | type A = 5 extends number ? true : false // true
16 |
17 | type B = number extends 5 ? true : false // false
18 | ```
19 |
20 | # Типофункции
21 |
22 | ```typescript
23 | type IsSubType< Low , High > = Low extends High ? true : false
24 |
25 | type A = IsSubType< 5 , number > // true
26 | type B = IsSubType< number , 5 > // false
27 | ```
28 |
29 | # Наивное сравнение типов
30 |
31 | ```typescript
32 | type Equal< A , B > =
33 | A extends B
34 | ? B extends A
35 | ? true
36 | : false
37 | : false
38 |
39 | type A = Equal< 5 , number > // false =)
40 | type B = Equal< Object , object > // true =(
41 | type C = Equal< any , object > // boolean =\
42 | ```
43 |
44 | # Железное сравнение типов
45 |
46 | ```typescript
47 | type Equal< A , B > =
48 | (
49 | ()=> X extends A ? 1 : 2
50 | ) extends (
51 | ()=> X extends B ? 1 : 2
52 | )
53 | ? unknown
54 | : never
55 | ```
56 |
57 | # Тесты для типов
58 |
59 | ```typescript
60 | type Assert<
61 | Actual,
62 | Expected extends Equal<
63 | Actual,
64 | Expected,
65 | >,
66 | > = Actual
67 | ```
68 |
69 | ```typescript
70 | // compile time error
71 | type UnknownAny = Assert< unknown , any >
72 |
73 | // boolean
74 | type BooleanUnion = Assert<
75 | Equal< boolean , true | false >,
76 | unknown,
77 | >
78 | ```
79 |
80 | # Типы-отображения
81 |
82 | ```typescript
83 | type KeysAsValues< Obj > = {
84 | [ Key in keyof Obj ]: Key
85 | }
86 | ```
87 |
88 | ```typescript
89 | type StrangeThing = Assert<
90 |
91 | KeysAsValues<{
92 | foo: 1
93 | bar: 2
94 | }>,
95 |
96 | {
97 | foo: 'foo'
98 | bar: 'bar'
99 | },
100 |
101 | >
102 | ```
103 |
104 | # Туда и обратно
105 |
106 | ```typescript
107 | type KeyOf1< Obj > = {
108 | [ Key in keyof Obj ]: Key
109 | }[ keyof Obj ]
110 |
111 | type KeyOf2< Obj > = keyof Obj
112 | ```
113 |
114 | ```typescript
115 | type StrangeThing = Assert<
116 |
117 | KeyOf1<{
118 | foo: 1
119 | bar: 2
120 | }>,
121 |
122 | KeyOf2<{
123 | foo: 1
124 | bar: 2
125 | }>,
126 |
127 | >
128 | ```
129 |
130 | # Поиск ключей по типу значения
131 |
132 | ```typescript
133 | type Keys< Obj , Upper > =
134 | {
135 | [ Key in keyof Obj ]
136 |
137 | : unknown extends Obj[ Key ]
138 | ? never
139 |
140 | : Obj[ Key ] extends never
141 | ? never
142 |
143 | : Obj[ Key ] extends Upper
144 | ? Key
145 |
146 | : never
147 | }[ keyof Obj ]
148 | ```
149 |
150 | ```typescript
151 | type Trash = {
152 | foo: ()=> void
153 | bar: new()=> {}
154 | lol: 5
155 | }
156 |
157 | type MethodNames = Assert<
158 | Keys< Trash , Function >,
159 | 'foo' | 'bar',
160 | >
161 | ```
162 |
163 | # Фильтрация объекта по типу свойств
164 |
165 | ```typescript
166 | type MyPick< Obj , Type > = Pick<
167 | Obj,
168 | keys< Obj , Type >
169 | >
170 |
171 | type MyOmit< Obj , Type > = Omit<
172 | Obj,
173 | keys< Obj , Type >
174 | >
175 | ```
176 |
177 | ```typescript
178 | type Trash = {
179 | foo: ()=> void
180 | bar: new()=> {}
181 | lol: 5
182 | }
183 |
184 | type Methods = Assert<
185 | MyPick< Trash , Function >,
186 | {
187 | foo: ()=> void
188 | bar: new()=> {}
189 | }
190 | >
191 | ```
192 |
193 | # Поиск всех подклассов
194 |
195 | ```typescript
196 | namespace $ {
197 | export class $mol_view {}
198 | export class $my_app extends $mol_view {}
199 | export class $mol_time_moment {}
200 | }
201 |
202 | const AllViews = MyPick< typeof $ , $mol_view >
203 |
204 | Assert< AllViews , {
205 | $mol_view : typeof $mol_view
206 | $my_app : typeof $my_app
207 | } >
208 | ```
209 |
210 | # Рекурсивные типы
211 |
212 | ```typescript
213 | type Styles< View > =
214 | & Properties
215 | & {
216 | [ Key in Keys< View , ()=> $mol_view > ]:
217 | Styles< ReturnType< View[ Key ] > >
218 | }
219 | & {
220 | [ Key in keyof AllViews ]:
221 | Styles< InstanceType< AllViews[ Key ] > >
222 | }
223 | ```
224 |
225 | ```
226 | function defineStyle<
227 | View extends typeof $mol_view,
228 | Config extends Styles< View >
229 | >(
230 | view : View,
231 | config : Config
232 | )
233 | ```
234 |
235 | # Типогуарды
236 |
237 | ```typescript
238 | type StylesGuard< View , Config > =
239 | & Properties
240 | & {
241 | [ Key in keyof Config ]
242 |
243 | : key extends keyof Properties
244 | ? unknown
245 |
246 | : key extends keyof AllViews
247 | ? StylesGuard<
248 | Extract<
249 | ResultType< AllViews[ Key ] > ,
250 | $mol_view,
251 | >,
252 | Config[ Key ]
253 | >
254 |
255 | }
256 | ```
257 |
258 | ```
259 | function defineStyle<
260 | View extends typeof $mol_view,
261 | Config extends StylesGuard< View , Config >
262 | >(
263 | view : View,
264 | config : Config
265 | )
266 | ```
267 |
268 | # Типошибки
269 |
270 | ```
271 | : key extends keyof View
272 | ? View[ key ] extends ( id? : any )=> infer Sub
273 | ? Sub extends $mol_view
274 | ? StylesGuard< Sub , Config[ key ] >
275 | : Error<[ 'Wrong Property' , key ]>
276 | : Error<[ 'Property is not Element' , key ]>
277 |
278 | : Error<[ 'Unknown Property' , key ]>
279 |
280 |
281 | type Error< Message > = 'Error' & { $mol_type_error : Message }
282 | ```
283 |
284 | # Уникальные типы
285 |
286 | `unique symbol`
287 |
288 | # Брендированные примитивные типы
289 |
290 | `string&{}`
291 |
--------------------------------------------------------------------------------
/ui-kit/design-binom.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/ui-kit/design-fixed.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/ui-kit/design-flex.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/ui-kit/design-font.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/ui-kit/design-grid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/ui-kit/design-paragraph.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/ui-kit/design-symmetry.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/ui-kit/fc.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
26 |
--------------------------------------------------------------------------------
/ui-kit/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/ui-kit/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/virt/after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/after.png
--------------------------------------------------------------------------------
/virt/anchor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/anchor.png
--------------------------------------------------------------------------------
/virt/atomic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/atomic.png
--------------------------------------------------------------------------------
/virt/before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/before.png
--------------------------------------------------------------------------------
/virt/column.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/column.png
--------------------------------------------------------------------------------
/virt/gaps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/gaps.png
--------------------------------------------------------------------------------
/virt/grids.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/grids.png
--------------------------------------------------------------------------------
/virt/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
--------------------------------------------------------------------------------
/virt/inside.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/inside.png
--------------------------------------------------------------------------------
/virt/nothing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/nothing.png
--------------------------------------------------------------------------------
/virt/offline.js:
--------------------------------------------------------------------------------
1 | if( typeof window === 'undefined' ) {
2 |
3 | self.addEventListener( 'install' , ( event )=> {
4 | self['skipWaiting']()
5 | } )
6 |
7 | self.addEventListener( 'activate' , ( event )=> {
8 | self['clients'].claim()
9 | console.info( '$mol_offline activated' )
10 | } )
11 |
12 | self.addEventListener( 'fetch' , ( event )=> {
13 | event.respondWith(
14 |
15 | fetch( event.request )
16 | .then( response => {
17 |
18 | caches.open( 'v1' )
19 | .then( cache => cache.put( event.request , response ) )
20 |
21 |
22 | return response.clone()
23 |
24 | } )
25 | .catch( error => {
26 |
27 | return caches.match( event.request )
28 | .catch( error2 => { throw error } )
29 |
30 | } )
31 |
32 | )
33 | })
34 |
35 | } else {
36 | if( navigator.serviceWorker ) navigator.serviceWorker.register( 'offline.js' )
37 | else if( location.protocol === 'http:' ) console.warn( 'HTTPS is required for service workers.' )
38 | else console.warn( 'Service Worker is not supported.' )
39 | }
40 |
--------------------------------------------------------------------------------
/virt/overlap-bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/overlap-bottom.png
--------------------------------------------------------------------------------
/virt/overlap-top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/overlap-top.png
--------------------------------------------------------------------------------
/virt/render.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/render.png
--------------------------------------------------------------------------------
/virt/row.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/row.png
--------------------------------------------------------------------------------
/virt/stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/stack.png
--------------------------------------------------------------------------------
/virt/timeslice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/timeslice.png
--------------------------------------------------------------------------------
/virt/wrap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nin-jin/slides/661dc8ca6379d3142d52a0b7cc5b28b7aaf991e9/virt/wrap.png
--------------------------------------------------------------------------------