├── .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) ![](https://holyjs.ru/favicons/favicon-16x16.png) 8 | 9 | Рассказ про устройство source maps, их подводные камни и про пайплайн для формата tree, позволяющий легко и просто разрабатывать свои DSL. 10 | 11 | ## [Quantum Mechanics of Calculations](fibers) ![](https://holyjs.ru/favicons/favicon-16x16.png) 12 | 13 | Рассказ о реализации кроссплатформенных псевдофайберов на основе перезапусков, позволяющих разбивать вычисления на кванты по 8мс, приостанавливать на асинхронных операциях и отменять их до полного завершения. 14 | 15 | ## [Автоматическая виртуализация рендеринга произвольной вёрстки](virt) ![](https://holyjs.ru/favicons/favicon-16x16.png) 16 | 17 | Рассказ про полностью виртуальный рендеринг, гарантирующий отзывчивость приложения независимо от размера страницы, и не требующий от прикладного разработчика дополнительных приседаний. 18 | 19 | ## [Разбираемся в сортах реактивности](https://github.com/nin-jin/slides/tree/master/reactivity) ![](https://secon.ru/favicon-16x16.png) 20 | 21 | Глубокий анализ основных аспектов моделей реактивности, выработка наиболее практичного подхода, и сравнение существующих библиотек на предмет близости к идеалу. 22 | 23 | ## [Объектное Реактивное Программирование](orp) ![](https://frontendconf.ru/i/frontendconf/2018/favicon.ico) 24 | 25 | Рассказ о парадигме программирования, где правила взаимосвязей частей приложения описываются в простой и естесственной форме, а вся рутина по оптимальной организации потоков данных берёт на себя автоматика. 26 | 27 | ## [Фрактальное тестирование](testing) ![](https://techleadconf.ru/i/techlead_conf/moscow/2020/favicon.ico) 28 | 29 | Рассказ про прагматичный подход к тестированию, позволяющий добиться максимальной надёжности минимумом усилий, путём отказа от модульных и системных тестов. 30 | 31 | ## [$mol - лучшее средство от геморроя](mol) ![](https://favicon.yandex.net/favicon/piterjs.org?color=0,0,0,0&size=16&stub=1) 32 | 33 | Рассказ об идеях, положенных в основу компактного высокоуровневого веб-фреймворка $mol. 34 | 35 | ## [Презентация приложения для проведения презентаций](slides) ![](https://favicon.yandex.net/favicon/piterjs.org?color=0,0,0,0&size=16&stub=1) 36 | 37 | Рассказ про приложение, через которое я показываю слайды на всех своих выступлениях. 38 | 39 | ## [Tree - единый AST чтобы править всеми](tree) ![](https://favicon.yandex.net/favicon/piterjs.org?color=0,0,0,0&size=16&stub=1) 40 | 41 | Рассказ про крайне простой, человекочитаемый, но компактный формат представления произвольных структур данных, который уделывает XML, JSON, YAML, TOML и остальных по всем фронтам. 42 | 43 | ## [Продвинутый CSS-in-TS](css-in-ts) ![](https://favicon.yandex.net/favicon/piterjs.org?color=0,0,0,0&size=16&stub=1) 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
Concurrency
Concurrency
Optimistic

Lock-Free
2Phase Commit
Optimistic...
Pessimistic

Mutex
Critical Section
Pessimistic...
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /consensus/consensus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Consensus
Consensus
Concurrency

Transaction
Atomics
Consensus Protocols
Concurrency...
Convergence


Wait-Free
Eventual Consistency
Convergence...
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /consensus/convergence.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Consensus
Consensus
Convergence
Convergence
Ordered

OT
Ordered...
Unordered

CvRDT
Unordered...
Semi-Ordered

CmRDT
Semi-Ordered...
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /consensus/discord.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Man
Man
Man
Man
Man
Man
Helicopter
Helicopter
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /consensus/disjoint.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Man
Man
Man
Man
Woman
Woman
Woman
Woman
Man
Man
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /consensus/inconsistency.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Parent
Parent
Alice
Alice
Parent
Parent
Bob
Bob
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /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 |
42
42
Bet
Bet
3
3
Amy
Amy
Cat
Cat
Text is not SVG - cannot display
-------------------------------------------------------------------------------- /cvrdt/crdt-map.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
jin
jin
6
6
Name
Name
123
123
9
9
Age
Age
Text is not SVG - cannot display
-------------------------------------------------------------------------------- /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 | ![](kano.png) 51 | 52 | # Деконструкция Кано 53 | 54 | - Сначала минимизация негатива 55 | - Потом максимизация позитива 56 | 57 | ## Модель НеКано 58 | 59 | ![](nekano.png) 60 | 61 | ## Гистерезис впечатлений 62 | 63 | ![](hysteresis.png) 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 | 2 | 3 | 59 | 60 | Code 61 | 62 | 63 | 64 | 65 | 66 | const step = $mol_fiber_func( name => { 67 | console.log( name , 'begin' ) 68 | // 20 ms of work 69 | return name 70 | } ) 71 | 72 | const walk = $mol_fiber_func( ()=> { 73 | console.log( 'start' ) 74 | console.log( step( 'first' ) , 'done' ) 75 | console.log( step( 'second' ) , 'done' ) 76 | console.log( 'finish' ) 77 | } ) 78 | 79 | Console 80 | 81 | 82 | 83 | 84 | 85 | start 86 | first begin 87 | first done 88 | 89 | start 90 | first done 91 | second begin 92 | second done 93 | finish 94 | 95 | Cache 96 | 97 | void 98 | 99 | 100 | 101 | 102 | walk 103 | 104 | 105 | 'first' 106 | 107 | 108 | 109 | 110 | 111 | 112 | 0: step 113 | 114 | 115 | promise 116 | 117 | 118 | 119 | 120 | 121 | 122 | 1: step 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /fibers/cache-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 59 | 60 | Code 61 | 62 | 63 | 64 | 65 | 66 | const step = $mol_fiber_func( name => { 67 | console.log( name , 'begin' ) 68 | // 20 ms of work 69 | return name 70 | } ) 71 | 72 | const walk = $mol_fiber_func( ()=> { 73 | console.log( 'start' ) 74 | console.log( step( 'first' ) , 'done' ) 75 | console.log( step( 'second' ) , 'done' ) 76 | console.log( 'finish' ) 77 | } ) 78 | 79 | Console 80 | 81 | 82 | 83 | 84 | 85 | 86 | start 87 | first begin 88 | first done 89 | 90 | start 91 | first done 92 | second begin 93 | second done 94 | finish 95 | 96 | Cache 97 | 98 | void 99 | 100 | 101 | 102 | 103 | walk 104 | 105 | 106 | 'first' 107 | 108 | 109 | 110 | 111 | 112 | 113 | 0: step 114 | 115 | 116 | 'second' 117 | 118 | 119 | 120 | 121 | 122 | 123 | 1: step 124 | 125 | 126 | 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 | 2 | 3 | 59 | 60 | Code 61 | 62 | 63 | 64 | 65 | 66 | const step = $mol_fiber_func( name => { 67 | console.log( name , 'begin' ) 68 | // 20 ms of work 69 | return name 70 | } ) 71 | 72 | const log = $mol_fiber_func( console.log ) 73 | 74 | const walk = $mol_fiber_func( ()=> { 75 | log( 'start' ) 76 | log( step( 'first' ) , 'done' ) 77 | log( step( 'second' ) , 'done' ) 78 | log( 'finish' ) 79 | } ) 80 | 81 | Console 82 | 83 | 84 | 85 | 86 | 87 | start 88 | first begin 89 | 90 | first done 91 | second begin 92 | second done 93 | finish 94 | 95 | Cache 96 | 97 | void 98 | 99 | 100 | 101 | 102 | walk 103 | 104 | 105 | void 106 | 107 | 108 | 109 | 110 | 111 | 112 | 0: log 113 | 114 | 115 | 'first' 116 | 117 | 118 | 119 | 120 | 121 | 122 | 1: step 123 | 124 | 125 | promise 126 | 127 | 128 | 129 | 130 | 131 | 132 | 2: log 133 | 134 | 135 | 'second' 136 | 137 | 138 | 139 | 140 | 141 | 3: step 142 | 143 | 144 | void 145 | 146 | 147 | 148 | 149 | 150 | 151 | 4: log 152 | 153 | 154 | void 155 | 156 | 157 | 158 | 159 | 160 | 161 | 5: log 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /fibers/idemp-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 59 | 60 | Code 61 | 62 | 63 | 64 | 65 | 66 | const step = $mol_fiber_func( name => { 67 | console.log( name , 'begin' ) 68 | // 20 ms of work 69 | return name 70 | } ) 71 | 72 | const log = $mol_fiber_func( console.log ) 73 | 74 | const walk = $mol_fiber_func( ()=> { 75 | log( 'start' ) 76 | log( step( 'first' ) , 'done' ) 77 | log( step( 'second' ) , 'done' ) 78 | log( 'finish' ) 79 | } ) 80 | 81 | Console 82 | 83 | 84 | 85 | 86 | 87 | 88 | start 89 | first begin 90 | 91 | first done 92 | second begin 93 | second done 94 | finish 95 | 96 | Cache 97 | 98 | void 99 | 100 | 101 | 102 | 103 | walk 104 | 105 | 106 | void 107 | 108 | 109 | 110 | 111 | 112 | 113 | 0: log 114 | 115 | 116 | 'first' 117 | 118 | 119 | 120 | 121 | 122 | 123 | 1: step 124 | 125 | 126 | void 127 | 128 | 129 | 130 | 131 | 132 | 133 | 2: log 134 | 135 | 136 | 'second' 137 | 138 | 139 | 140 | 141 | 142 | 143 | 3: step 144 | 145 | 146 | void 147 | 148 | 149 | 150 | 151 | 152 | 153 | 4: log 154 | 155 | 156 | void 157 | 158 | 159 | 160 | 161 | 162 | 163 | 5: log 164 | 165 | 166 | 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 | 2 | 3 | 63 | 64 | Code 65 | 66 | const step = name => { 67 | console.log( name , 'begin' ) 68 | // 20 ms of work 69 | return name 70 | } 71 | 72 | 73 | 74 | 75 | const walk = ()=> { 76 | console.log( 'start' ) 77 | console.log( step( 'first' ) , 'done' ) 78 | console.log( step( 'second' ) , 'done' ) 79 | console.log( 'finish' ) 80 | } 81 | 82 | 83 | 84 | 85 | 86 | 87 | Console 88 | 89 | 90 | 91 | start 92 | first begin 93 | first done 94 | second begin 95 | second done 96 | finish 97 | 98 | 99 | 100 | 101 | 102 | 103 | Cache 104 | 105 | 106 | 107 | walk 108 | 109 | 110 | 111 | 112 | 113 | 0: step 114 | 115 | 116 | 117 | 118 | 119 | 1: step 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /fibers/sync-1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 59 | 60 | Code 61 | 62 | 63 | 64 | 65 | 66 | const step = name => { 67 | console.log( name , 'begin' ) 68 | // 20 ms of work 69 | return name 70 | } 71 | 72 | const walk = ()=> { 73 | console.log( 'start' ) 74 | console.log( step( 'first' ) , 'done' ) 75 | console.log( step( 'second' ) , 'done' ) 76 | console.log( 'finish' ) 77 | } 78 | 79 | Console 80 | 81 | 82 | 83 | 84 | 85 | start 86 | first begin 87 | first done 88 | second begin 89 | second done 90 | finish 91 | 92 | Cache 93 | 94 | 95 | 96 | walk 97 | 98 | 99 | 100 | 101 | 102 | 0: step 103 | 104 | 105 | 106 | 107 | 108 | 1: step 109 | 110 | 111 | 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_view: 0 KB
$mol_view: 0 KB
$mol_view2: 2 KB
$mol_view2: 2 KB
$mol_atom: 3 KB
$mol_atom: 3 KB
$mol_mem: 1 KB
$mol_mem: 1 KB
$mol_object: 1 KB
$mol_object: 1 KB
-------------------------------------------------------------------------------- /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 |
Next
Next
7
7
Next = Prev + 1
Next = Prev + 1
Prev
Prev
6
6
Prev = Next + 1
Prev = Next + 1
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /reactivity/reactivity-interactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Jin
Jin
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /reactivity/reactivity-reactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Jin
Jin
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /reactivity/reactivity-reactivity.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /reactivity/reactivity-states.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Name
Name
Jin
Jin
Count
Count
3
3
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /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 | > 19 | > ``` 20 | 21 | # Теги в скриптах? 22 | 23 | Или подход React c винегретом из двух языков? 24 | 25 | > ```jsx 26 | > function Names( props ) { 27 | > return ( 28 | > 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 | ![](https://habrastorage.org/webt/jg/fv/nq/jgfvnq3cka9i4sgxslxoomo7el4.png) 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 |
Lorem Ipsum Dolor sit
Lorem Ipsum Dolor sit
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /ui-kit/design-grid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /ui-kit/design-paragraph.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Lorem Ipsum Dolor sit
Lorem Ipsum Dolor sit
Lorem Ipsum Dolor sit
Lorem Ipsum Dolor sit
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /ui-kit/design-symmetry.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Lorem..
Lorem..
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /ui-kit/fc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 14 | 15 | 16 | FrontendConf 17 | 2021 18 | 19 | 20 | 23 | 24 | 25 | 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 --------------------------------------------------------------------------------