class: center, middle # Microapplications With EmberJS ### Deliver Awesome Stuff Fast ### Jon Johnson  Slides at: https://jrjohnson.dev/talks/2017-03-microapps.html
jrjohnson
jrjohnson
jrjohnson_
--- # Who am I? - Full stack web developer (PHP, Javascript) - Technical lead for the Ilios Project open source curriculum management system for health science education. (http://iliosproject.org) .center[] ??? ## I get paid to write open source software by UCSF and I love my job --- # Who am I? - Full stack web developer (PHP, Javascript) - Technical lead for the Ilios Project open source curriculum management system for health science education. (http://iliosproject.org) .center[] -- ### https://tinyurl.com/are-work --- # What is UCSF? - 149 years old - Focused entirely on health sciences - Second largest employer in San Francisco with 24K+ staff and faculty - Ranked 3rd in research and 3rd for primary care, making it the only medical school to achieve a top-5 ranking in both categories. - Nobel Prizes: 1989, 1997, 2009, 2012 ??? I guess that means we're hiring! --- # What is Ilios - An ambitious web application - Curriculum management system for health science education. (http://iliosproject.org) - Deployed at dozens of medical schools on 5 continents - A product of UCSF School of Medicine and the MedBiquitous Consortium .center[] ??? - Open API - We interconnect with a lot of other systems on campuses and with organizations like the American Association of Medical Colleges so having an open and well documented API allows data to flow - Community - We provide Ilios for Free to other medical schools around the world --- class: center, middle # What is a microapp? -- ## That map was one: .center[] --- ### app/templates/components/world-map.hbs ```handlebars {{#g-map as |context|}} {{#each (await codedLocations) as |obj|}} {{g-map-marker context lat=obj.lat lng=obj.lng}} {{/each}} {{/g-map}} ``` ### app/components/world-map.js ```javacript codedLocations: computed('locations.[]', function(){ return new Promise(resolve => { const locations = this.get('locations'); map(locations, location => { return this.getLatLongForAddress(location); }).then(data => { resolve(data); }); }); }), ``` --- class: center, middle # OK, umm... so what? --- class: center # Profound and Unstoppable Power of Yes .center[] ??? - UCSF has been going around telling people we say yes! - As developers we want to say yes - As people we want to help other people - The developer life cycle has taught us to be cautious. --- class: center # Developer Life Cycle .center[] --- class: center # Developer Life Cycle .center[] --- class: center # Developer Life Cycle .center[] --- class: center # Developer Life Cycle .center[] --- class: center # Developer Life Cycle .center[] --- class: center # Developer Life Cycle .center[] --- class: center # Developer Life Cycle .center[] --- class: center # Developer Life Cycle .center[] --- # Why are we stuck in this loop? .left-column[ ## Proof of Concept ] .right-column-focus[ It isn't possible nor should it be necessary for everyone to understand the difference between proof of concept code and production code. ] ??? - The people who think this aren't dumb. - Our first pass has to be very nearly production ready. --- # Why are we stuck in this loop? .left-column[ ## MVP ## Proof of Concept ] .right-column-focus[ Get our ideas in front of people immediately ] ??? ## Minimum Viable Product --- # Why are we stuck in this loop? .left-column[ ## RAT ## MVP ## Proof of Concept ] .right-column-focus[ Before we invest too heavily in any one idea we must find and test our riskiest assumptions. ] ??? ## Riskiest Assumption Test --- class: center # How can we get off this ride?  --- class: center # Microapps! That's How!  --- class: center, middle # Do you mean Microservices? --- .strike[ # Microservices? ] # Microapps - Take advantage of existing data through APIs - Single Responsibility Principle - Throw away things that don't work - Low cost of enhancement - Freedom to choose different technologies --- class: center # What makes an app micro?  ??? Credit: https://calisphere.org/item/3fe65b42-122e-48de-8e4b-bc8dcf531216/ --- .left-column[ ## Infrastructure code ] .right-column[ - Build System - Request Handling - Testing - Configuration - Continuous Integration - Deployment ] ??? - Taking us on a little detour to talk about Infrastructure Code - Can't understand microapps without it. --- .left-column[ ## Infrastructure code ## Build System ] .right-column[  ] ??? - compile - transpile - preprocess - bundle - minify - fingerprint --- .left-column[ ## Infrastructure code ## Request Handling ] .right-column[  ] --- .left-column[ ## Infrastructure code ## Request Handling (for realz) ] .right-column[  ] --- .left-column[ ## Infrastructure code ## Request Handling (for realzy realz realz) ] .right-column[  ] --- .left-column[ ## Infrastructure code ## So Much More ] .right-column[  ] --- class: center # Very Ambitious Application  --- class: center # Ambitious Application  --- class: center # Small Application  --- class: center # Microapp  --- class: center # Microapps .minibox[] .minibox[] .minibox[] .minibox[] .minibox[] .minibox[] .minibox[] .minibox[] --- class: center, middle # Too Far Dude! --- # Cognitive Load for EVERY Application .square[ ### Getting Started - Project Structure - Build Pipeline - Dependency Loading - Test runner / testing pattern - Feedback Loop ] -- .square[ ### Active Development - Request Routing - Assets - Error / Loading States - #### Solve The Actual Problem ] -- .bigsquare[ ### Production / Maintenance Mode - Deployment - QA / Feature Testing - Continuous Integration - Stay up to date - Apply Security fix - Support new Browsers - Improve Performance - Why is this even here? - Who wrote this shit? - Damn I wrote this shit. 2015 me was an idiot! - #### Add New Features ] --- class: center, middle  ??? ## Since I stole the concept for thsi problem from Yehuda it's only fair that we steal his solution as well. --- class: center, middle # Ember (An SDK for the Web) -- class: emberbackground .square[ ### Getting Started -
Project Structure -
Build Pipeline -
Dependency Loading -
Test runner / testing pattern -
Feedback Loop ] .square[ ### Active Development -
Request Routing -
Assets -
Error / Loading States - ####
Solve The Actual Problem ] .bigsquare[ ### Production / Maintenance Mode -
Deployment -
QA / Feature Testing -
Continuous Integration -
Stay up to date -
Apply Security fix -
Support new Browsers -
Improve Performance -
Why is this even here? -
Who wrote this shit? -
Damn I wrote this shit. 2015 me was an idiot! - ####
Add New Features ] ??? - Semantic versioning lets us skip versions without worrying about issues - Deprecations make it possible to prepare for upgrade with spare cycles - Share common functionality in addons - Connect to any API with adapters --- class: center, middle # Because we have standardized our platform we can standardize our tooling --- class: toolsbackground # Platform Tooling .square[ ### Getting Started -
Project Structure -
Build Pipeline -
Dependency Loading -
Test runner / testing pattern -
Feedback Loop ] .square[ ### Active Development -
Request Routing -
Assets -
Error / Loading States - ####
Solve The Actual Problem ] .bigsquare[ ### Production / Maintenance Mode -
Deployment -
QA / Feature Testing -
Continuous Integration -
Stay up to date -
Apply Security fix -
Support new Browsers -
Improve Performance -
Why is this even here? - ####
Add New Features ] ??? - Travis - green keeper - netlify - heroku - ember-cli makes onboarding new team members supser fast - Standardizing makes it easy to farm out work because you know what you will get back. --- # Simple Commands ```bash $ ember generate component new-feature ``` -- ## Can ensure consistency - Code structure - Test Structure - Implementation and Test Skeleton -- ## and Maintainability - Tests document functionality - Consistency in approach allows you to focus on the problem --- # Simple Commands ```bash $ ember test ``` -- ## Can do many things - Build App - Load test fixtures - Start a browser session - Keep track of failures --- # Simple Commands ```bash $ ember deploy production ``` -- ## Can hide complicated details - Ship assets to AWS / send index.html to Redis - Send everything to server via ssh - Convert index.html into JSON and ship assets to azure - Deploy to PageFront --- class: center, middle # Some Examples --- # Data Visualization (Map of Ilios Schools)  --- .left-column[ ### Ilios map ### Plain Old Web ] .right-column[ ```html
```  ] --- .left-column[ ### Ilios map ### Plain Old Web ### Add Some Markers ] .right-column[ ```html
```  ] ??? # Getting out of hand - How do I figure out coordinates for each school - What school do each latitude and longitude represent - Keep having to press refresh - ## Where do I store the API key? --- .left-column[ ### Ilios map ### As an Ember Microapp ] .right-column[ ```bash $ ember new map $ cd map $ ember generate component schools-map $ ember add ember-g-map $ ember serve ``` ```handlebars {{#g-map as |context|}} {{#each (await codedLocations) as |obj|}} {{g-map-marker context lat=obj.lat lng=obj.lng}} {{/each}} {{/g-map}} ``` ] --- .left-column[ ### Ilios map ### As an Ember Microapp ] .right-column[ ```javascript export default Component.extend({ locations: [ 'SF,ca', ], codedLocations: computed('locations.[]', function(){ return new Promise(resolve => { map(this.get('locations'), location => { return this.getLatLongForAddress(location); }).then(data => { resolve(data); }); }); }), getLatLongForAddress(address){ return new Promise(resolve => { let request = `${uri}/geocode/json?&key=${key}&address=${address}`; $.getJSON(request, (response) => resolve({ response.results[0].geometry.location.lat,response.results[0].geometry.location.lng})); }); }, }); ```  ] ??? # Same map - Using city name instead of lat / long - Lots of ember stuff - promises - computed properties - template separation - Ember cli stuff - live reload - ember server - project structure - linting - Options to store the key # Ember isn't your only choice for this - but it is a really good one --- .left-column[ ### Ilios map ### As an Ember Microapp ### Next steps ] .right-column[ ### Keep it - Add Labels - Different markers for Consortium members - Data from external source ### Throw it away? ] --- # Data Visualization (Ilios Team)  ??? # Built for this talk to make a point ## If you don't have the ability to contribute fixes this probably isn't for you --- .left-column[ ### Team Ember Contributions ### Route ] .right-column[ ```javascript export default Route.extend({ async model(){ let users = []; for (let i = 0; i < this.users.length; i++) { const username = this.users[i]; const repositoryNames = await this.getRepositoriesForUser(username); let user = Object.create({ username, repositoryNames }); users.push(user); } return users; }, }); ``` ] --- .left-column[ ### Team Ember Contributions ### Visualization ] .right-column[ ```javascript export default Component.extend({ tagName: 'svg', didReceiveAttrs() { run.scheduleOnce('render', this, this.draw); }, draw(){ const svg = select(this.element); // set the ranges const x = scaleBand().range([0, chartWidth]).padding(0.1); const y = scaleLinear().range([chartHeight, 0]); svg.append("g").attr("transform", "translate(" + 40 + "," + 20 + ")"); x.domain(dataOrArray.map(d => d.username)); y.domain([0, max(dataOrArray, d => d.repositoryNames.length)]); // append the rectangles for the bar chart svg.selectAll(".bar").data(dataOrArray) .enter().append("rect") .attr("class", "bar") .attr("x", d => x(d.username)) .attr("width", x.bandwidth()) .attr("y", d => y(d.repositoryNames.length)) .attr("height", d => chartHeight - y(d.repositoryNames.length)) .attr('fill', d => color(d.username)); svg.append("g").attr("transform", "translate(0," + chartHeight + ")").call(axisBottom(x)); svg.append("g").call(axisLeft(y)); }, }); ``` ] ---  ## https://copy-writer-crab-43023.netlify.com/ ## https://github.com/jrjohnson/team-contributions --- .left-column[ ### Team Ember Contributions ### Next steps ] .right-column[ ### Keep it - Loading Indicator - Handle Errors - Authenticate User to get an API key - Cache Results ### Throw it away? ] --- # An accidental example  --- # Demoing a Feature: Ilios Todo https://ilios-todo.herokuapp.com/  ??? - Highly requested feature, but not clear understanding of the problem - Threw together on a plane as a demo of what open APIs can mean - Has allowed us to have a discussion about what this feature actually is --- class:center  ??? - The less code you are responsible for the more problems you can solve Credit: www.veryfunnypics.eu --- class: center, middle ## Discussion / Questions?  Slides at: https://jrjohnson.dev/talks/2017-03-microapps.html
jrjohnson
jrjohnson
jrjohnson_
??? # Thanks - to the LinkedIn and the SF Ember group for the opportunity to speak - to the UCSF library for giving me the time to do this and other open source work - and the Ilios team who picked up a lot of slack as I started to panic about getting this talk finished.