inspirational sources:
- book: Essentialism by Greg McKeown
key concepts:
- essentialism is about getting the right things done
- doing more by doing less
- make your users do less
- focus on the essential task
- take time to think
ux examples:
- Netflix “skip intro” button
- Apple “Face ID” feature
- Medium “article page ux”
code examples:
- lodash.sample
- react button component + analytics logging
closing thoughts:
- find the seams
- build what you understand
- just say no
- slides: http://kristen.codes/forwardjsottawa.pdf
- twitter: @kristencodes
- Lead Instructor, @HackerYou
inspirational sources:
- book: the 4-hour chef, Timothy Ferriss, “minimum effective dose”
- book: the talent code, Daniel Coyle, “deep practice”
problems:
- too many junior devs on the market
- too hard to recruit senior developers
solutions:
- close the on boarding process gap / cost
key concepts:
-
mentorship is just as important as writing code
-
cut out the noise
- what is the minimum effective dose for our code
- you don’t need to know everything
- learners: focus on the fundamentals, look for patterns, once you figure something out try to explain it to someone else (solidifies learning)
- mentors: isolate fundamentals and explain them well, as dev to explain things back to you
-
repeat repeat repeat
- with repetition, the brain can start to identify and learn patterns
- make mistakes, fix them, rinse repeat
- learners: build a lot of small projects, memorize syntax so you can focus on logic
- mentors: have frequent planned feedback on the schedule, bring devs into code reviews for other peoples PR’s, assign similar tasks and let the brain figure out the pattern
-
value context
- learners: look at other code / mimic to start, find or make starter files (don’t get caught up on the tools)
- mentors: paired programming, keep the first few tasks clear and small in scope
-
have empathy
- being at the beginning of the learning journey is a very vulnerable place to be
- ie: learning a new instrument, starting a fitness journey, dating someone new
- learners & mentors: be kind (to yourself and others), remember what it’s like
-
remember, we’re all learning
-
How I learned to stop worrying, and love standards
-
angular, ember, react, vue, ....
-
a lack of cross framework compatibility leads to duplicated (code, efforts) and an over abundance of choices with no clear difference in tools
-
what if, there was a way we could do this with standards
-
Enter Web Components...
-
vanilla js, easy to polyfill, built into the browser, part of the standard
-
custom elements, x-tag
-
template element: client-side templating
-
shadow dom
-
example: github.com/pearlbea/better-img
-
stenciljs, another framework?
-
compiler for web components
book: the new kingmakers, stephen o'grady
State of JS
- js is #1
Compilation vs Transpilation
- compilation: transforming source from one language to another (normally a language with a lower level of abstraction)
- transpilation: compilation between languages with similar levels of abstraction
Why Transpilation?
- abstraction is our friend
- the more ways there are to write js, the more people will write js
Where did Transpilation come from? Where are we now? What's the future of JS / Transpilation?
- secrets grant Authentication (AuthN) or Authorization (AuthZ) to a system
Secret Sprawl
- secrets ending up in the wrong places
- source code, VCS (Github, BitBucket), configuration management (chef, puppet, ansible, etc..)
Issues with Secrets
- when were they last accessed?
- who has access?
- what if we want to change them?
Desired State for Secrets
- encryption in rest and transit
- decrypted only in memory
- access control
- rotation & revocation
Shamir Secret Key Sharing
-
teachablemachine.withgoogle.com
-
what? ("supervised machine learning")
- AI - science of getting computers to perform human tasks (ie: alphago, robotics)
- ML - an approach to achieve AI through a system that can learn from experience to find patterns in data
- DL (deep learning) - a technique to implement ML through structures called neural networks (NN)
- deep learning drives machine learning, which can then enable artificial intelligence
- the main goal of ML is prediction / inference
- models: regression (line chart) vs classification (picture of cat)
- machines: predict, change (to reduce errors), try
-
why? do we care as js developers
-
we have a direct connection to the users on the other end of the screen - interactive machine learning
-
JS ML frameworks
- as of jan 2010, 1
- as of apr 2018, 8
-
-
how?
-
brain.js
- open source lib, two types of NN's (feedforward) and recurrent that can remember previous actions
- easy to train models and inference
- usage
- data is organized in an object containing an input and an output (features and labels)
- input has to be an array or object of values between 0 and 1, so we translate our data
-
"underfitting": not enough knowledge to create generalizations
-
"overfitting": result of training our data based on outliers, undesirable
-
tensorflow.js
- previously deeplearn.js, developed by Google Brain
- based off tensorflow for python, written in typescript
- hardware accelerated
- data has to be fed as tensors, a data structure which represents an n-dimensional array
-
-
cool example projects:
- melody mixer
- styletransfer
- tensorfire
- cyborg writer
- webcam pacman
- emoji scavenger hunt
-
idea: squint detector which automatically increases font-size
-
"Go programmers should not fear first class functions" (Dave Cheney, dotGo 2016)
-
what is first class?
- all operations can generally be applied to it:
- passed as argument
- assigned as variable
- returned from function
- modified
- all operations can generally be applied to it:
-
learners need to think of functions as values
-
"smart speakers" vs "voice assistants"
-
what would you want to know about voice UI development?
- what can i actually make?
-
history: timeline
- nov 2014, amazon echo
- 2015, alexa
- 2016, google assistant, google home
- 2017, samsung bixby, microsoft cortana
- 2018, apple homepod
-
each player in the game seems to have gone through a natural evolution
-
- add voice activation to existing app ecosystem (apple, samsung)
-
- add content via RSS feeds (microsoft)
- 2.5 home automation, another type of custom skill like IFTTT
-
- add support for custom "skills" (amazon, google)
-
-
conclusions:
- amazon has a 2-year lead
- only amazon and google have fully developed systems
- a big focus is adding access to news and podcasts via RSS
- home automation is secondary
-
- what can i actually make?
-
is it possible to build one app for amazon echo, google home, and apple homepod?
- can you build one "skill" to rule them all?
- alexa + google
- heavily leverage their existing cloud infrastructure
- AWS lambda + google cloud functions
- can build a traditional REST API accessed by their services
- heavily leverage their existing cloud infrastructure
- the future is "serverless"
- let's assume we want to use lambda or cloud functions
- node.js wins
- the official SDKs are pretty good
- let's assume we want to use lambda or cloud functions
- all manufacturers agreed to use SSML speech sensitive markup language
- limitations / challenges
- text-to-speech (TtS) is still king
- google didn't even add support for their native audio player until feb 2018
- no access to the user's location
- error handling is interesting
- user might not even trigger your skill
- text-to-speech (TtS) is still king
conclusions:
- the code is not hard
- understanding platform limitations and user expectations are hard
- apple is a bit of a wildcard
open source opportunities:
- would it be helpful to have a formalized framework?
- not really in practice, code isn't too hard
- what we struggle with the most: QA
- we need something like selenium or nightwatch.js for voice UI
- book: Responsive Web Design, Ethan Marcotte
- book: Building Progressive Web Apps
Progressive Web Apps are just web pages
- works for every user regardless of browser choice because it's built with progressive enhancement as a core tent.
- responsive:
- fits any form factor: desktop, mobile, tablet, or whatever is next
- connectivity independent:
- enhanced with service workers to work offline or on low-quality networks
- app like:
- feels like an app, because the app shell model separates the application functionality from the content
- safe:
- served via https to prevent snooping and to ensure content hasn't been tampered with
- re-engageable:
- makes re-engagement easy through features like push notifications
- installable
- allows users to add apps to their home screen without an app store
- linkable
- easily share the application via URL, does not require complex installation
- discoverable:
- is identifiable as an "application" thanks to W3C manifest and service worker registration scope, allowing search engines to find it
Tools: - workbox: https://developers.google.com/web/tools/workbox/ - lighthouse: https://developers.google.com/web/tools/lighthouse/
Confusing terms surrounding "Event Loop"
- call stack, v8 engine, libuv, event loop, task queue
What happens when our code runs?
- call stack, push/pop, FILO
Node under the hood
- v8 & libuv
v8
- transpiles js into c++ -> assembly -> machine code
- optimizations like GC and Malloc
libuv (unicorn velociraptor library)
- written in C++, focused on async I/O
- processes async tasks through OS or its own thread pool
event loop breakdown
- timers (setInterval, setTimeout)
- i/o (setImmediate, close)
- idle, prepare
- poll (incoming connections, data, etc..)
- check
- close callbacks
performance node timing
const { performance } = require('perf_hooks')
setTimeout(() => { process.on('exit', () => { console.log('settimeout', performance.nodeTiming); }) }, 1000)
^ yields loopStart
and loopExit
times
history of design systems
- 2011, twitter bootstrap
- 2014, google material design
- 2018, everyone and their ancestors are making a design system
boring problems we're solving right now
- blog post: josh clark, the most exciting design systems are boring, 2017
- "the more common the problem, the better. Design systems should prioritize the mundane."
- scaling a type scale: Mike Riuthmeiler equation
- switching barriers (covered by css gridish, opensource tool: https://github.com/IBM/css-gridish)
- "There is such a thing as over-designing, however, it has nothing to do with the capabilities of the browser. You can design for the future of your medium."
things we want today
- variation with variable fonts (coming soon™)
- a single file with all weights of a typeface can reduce total data downloaded and the number of requests
- effortless use via element queries
- element queries would allow css to be applied to an element based on the current width and height of that particular element.
css-in-js makes design better
- velocity in transition-duration variables
- react with eventlistener ripples
- skeletons with Math.random() states (the RAIL model from google)
Douglas Riches, Rangle.io, @froosh_ca, [email protected]
- resource: micro-frontends.org
-
tool: cypress.io
-
manual tests
- stuck in a repetitive workflow
- for just one simple field, like an email address
- tester: tests feature, detects defect
- qa lead: validates the defect
- dev: validates defect, fixes
- for just one simple field, like an email address
- stuck in a repetitive workflow
-
automated tests
- let testers do what they do best
- represent your site users
- find unexpected functionality or errors
- let machines handle the boring repetitive stuff
- let testers do what they do best
-
mystery tests
- shift testing "left"
- makes sure tests are included with the code before it gets merged
- won't this take longer? how do we make this work?
- takes the same amount of time, but you verify by testing earlier to save headaches
- shift testing "left"
-
environment disparity
- test/dev/qa envs aren't the same as prod
- solve via containers to get closer to the same environment as prod for our tests to run
-
resources: https://github.com/ericadamski/forwardjs-2018-async-struggle
-
why consider different async options?
-
handle async, chainable, multi-value, cancellable
-
callbacks: only handle async
-
promises: handle async, chainable
-
observable stream programming paradigm: does all the things
-
libs:
- RxJS
- XStream
- Callbag
-
- resources: halyard.js, enigma, nhl.com api
Upgrading a 100+ page legacy webapp to a single page React app without slowing development or compromising user experience
Hofstadter's Law software development always takes longer than you expect, even when you take into account Hofstadter's Law
-
technical goals
- single page app
- react + redux
- typescript
- stateless backend API
- meta goal: easy to do the right thing, hard to do the wrong thing
- maintain feature development velocity
-
approach 1: dom snatcher
ReactRouter newRoute1 newRoute2 *oldRoute* -> DomSnatcher to re-inject server-side content div#app (new client-rendered content) div#content (old server-rendered content)
- wrap new and old pages in a react ui so the overhead for creating new pages with react is lower
- downsides:
- mixes new and old patterns
-
approach 2: dom snatcher after dark
- "everything the light touches is the new codebase"
- write a new dashboard from the ground up
- convert the old dashboard into an API to serve legacy pages
- steps:
- static asset urls need to be updated (webpack can help rewrite urls)
- scripts from the legacy page need to be loaded (create a script element, inject it into the page)
- links need to be converted to react router (
el.querySelectorAll('a')
and modify thehref
attribute) - form submission needs to be ajax'ified (hook
form.onSubmit
and redirect to the legacy proxy)
- downsides:
- lots of edge cases in the 10% phase, took a lot of effort to deal with random hacks
- very difficult to develop on the legacy codebase
the first 90% of the code accounts for the first 90% of the development time the remaining 10% of the code accounts for the other 90% of the development time
-
approach 3: d2 (dashboard 2) :P
- write a new dashboard from the ground up and run it alongside the old dashboard, proxy requests as needed
- benefits:
- could still develop on the old dashboard (aka: trashboard)
- no changes to legacy codebase
- ended up being the simplest approach codewise
- whole team contributed to upgrading pages
- feature development speed increases
- downsides:
- hard page reloads when using the trashboard pages
-
key takeaways
- clear "right path"
- can be done as slowly or quickly as needed
- carrot (modern dev practices) & the stick (old trashy repo name, clunky old api, code reviews :P)
- can be as easy as starting with a proxy and a url list
-
book: Practical Object Oriented Design in Ruby, Sandi Metz
-
message-oriented design instead of object-oriented design
-
concepts:
- single responsibility principle
- more singular responsibility leads towards more easily changeable code
- SRP is fractal (at the class level, at the method level, zooming down...)
- dependencies
- thoughts:
- still violates CQS, dependencies in chaining make for really hard to test code
- punching a whole w/ react context both couples an unstable api and still doesn't solve changeability
- thoughts:
- single responsibility principle
JSX Gotchas
- react attributes are camelCase, but aria-* and data-* are exempt from this
- reserved words for html attritubtes
for
->htmlFor
,class
->className
- self closing elements require a forward-slash to close (img, meta, input)
Setting a page title
- updates the browsers tab, so users understand where they are in the app
- SEO
- page title is the first content announced by screen readers
document.title = 'Some Page Title';
or some pre-existing components:- react-document-title
- react-helmet (created by the NFL)
Live Announcements
- announces when data is being loaded, and finishes, and announces how many items are now being displayed on the screen
aria-live="polite"
-> assistive technology will wait until other messages are announced before announcing thisaria-atomic="true"
-> ensures all content, not just the changed content, will be announced<Announcements message={this.state.message} />
- other existing components:
- react-aria-live
- react-a11y-announcer
Focus Management
-
critical to a comfortable UX
-
jquery
$(el).focus()
-
react:
<div ref={ (loadingMessage) => { this.loadingMessage = loadingMessage; } } tabIndex=-1 > Loading... </div>
used via:
componentDidMount() { this.loadingMessage.focus(); } -
-
why manage focus when loading a new page?
- React Router
<Link/>
- SPA's load pages quickly, but people who need assistive tech need an indicator that the page has changed, shifting focus helps with this
- React Router
-
use fragments to avoid generating invalid HTML,
React.Fragment
or<></>
Reacts Accessibility Linter
- eslint-plugin-jsx-a11y (comes with Create React App), outputs errors to the browser console
Semantic HTML in React
- how semantic your components are is up to you, React does not prevent this
- if there are any a11y issues, it's your fault
- why code reviews?
always code as if the guy who ends up maintaining your code is a violent psychopath?always code as if the guy who ends up maintaining your code is YOU
-
fewer bugs
-
reducing technical debt
-
knowledge transfer between team members
-
happier clients
-
getting buy-in
- allow time to streamline the process
- automate as much as possible (lint, prettier, etc..)
- establish standards as a team (shared ownership)
- build a culture of trust
-
practical examples
- steer clear of generic terms like "item", "element", or "unit"
- don't invent terminology
- use semantic html
- comments
- write why not how
- too many comments? => refactor the code
- keep comments up to date or delete them
- functions
- named(?), when is it appropriate to use anonymous functions, -> conversation with team
- do one thing
- reusable
-
harder to quantify things
- performance/maintainability
- is there an existing feature for this in the codebase?
- sass mixins
- event listeners (right place? scope? cleaning up after done?)
!important
(not great, force page layout)- DOM (minimize or batch DOM updates)
- image sizes and formats (can we use svg)
- security
- user input, sanitized?
- url parameters, secure? vulnerable?
- cookies, extra scrutiny
- is a 3rd party dependency appropriate? do we need this? are we vulnerable?
- other considerations
- test coverage
- documentation
- es6
- performance/maintainability
Getting the Most out of CR's
when you give people agency, it makes it harder for them to avoid doing what you want them to do
- give the entire team a say in the process
- use linters and tests to reinforce code standards
- write PRs with knowledge sharing in mind
- allow everyone to be a reviewer
- negotiate feedback styles
-
react-native threads
- main thread | (no link between this threads)
- javascript thread (runs a js engine in this thread, in ReactNative, JSCore from Safari (even in Android))
- if you want to communicate between threads, you need a bridge (async bridge that sends serialized messages)
-
react-native uses the same fundamental native UI building blocks as iOS and Android
-
tools for react-native:
- react-navigation
- react-native-navigation
- detox (end to end testing)
- react-native-elements (ui toolkit)