POPULARITY
Fredrik talks to Balint Erdi about the web framework Ember. Where did Ember come from, what stands out about it today, how do new features get into the framework, and how is development being made more sustainable? Plus: Balint’s experiences organizing Emberfest, and quite a bit of appreciation for the Ruby and Ember communities in general. The episode is sponsored by Cursed code - a half-day conference with a halloween mood taking place on October 31st, in central Gothenburg. Thank you Cloudnet for sponsoring our VPS! Comments, questions or tips? We a re @kodsnack, @tobiashieta, @oferlund and @bjoreman on Twitter, have a page on Facebook and can be emailed at info@kodsnack.se if you want to write longer. We read everything we receive. If you enjoy Kodsnack we would love a review in iTunes! You can also support the podcast by buying us a coffee (or two!) through Ko-fi. Links Balint JSP - Java server pages ZODB - Python object database Ruby Ruby on rails Convention over configuration ORM Active record Ember Angular Yehuda Katz Emberfest Balint’s (first!) book - Rock & roll with Ember.js Ember data Support us on Ko-fi! Classes in Javascript Internet explorer 6 Handlebars Glimmer Controllers in Ember Ember addons Ember RFC:s Codemods React native Tree shaking Webpack Embroider Vite Cursed code - sponsor of the episode Poppels cursedcode.se - to read more and buy tickets The Embroider initiative The Ember initiative Ember CLI Ember core teams Emberconf devjournal.balinterdi.com Ember community links Ember guides Ember checkup - Balint’s productized consulting service Titles These two decades I’m a web guy Just one thing It’a always useful Rails carried me over Ember was in flux Javascript didn’t have classes Emberisms Nowadays I like explicitness more Everything needs to be imported A change they would like to see in the framework (The) Emberfesting Fellow emberino We don’t do drama
As Chris Thoburn (otherwise known as runspired) began prepping for his own Whiskey Web and Whatnot, he found himself driving along to Chris Manson's episode from a few weeks prior. Nodding along as Chris explained his point of view on all things Ember, runspired suddenly slammed on the brakes after hearing one pivotal sentence. At the center of his break slam and today's fierce disagreement? The value of TypeScript and its place in the Ember community. Fortunately, Chris and Chris have the same end goal: to encourage more developers to use Ember and contribute to Ember projects. But how do we keep Ember contributor-friendly while keeping contributions careful? One of them yearns for a happy medium and the other feels that balance is forever impossible. In this episode, runspired and Chris Manson battle it out, discussing TypeScript's place in the Ember community and balancing the volume of Ember contributors with the accuracy of developer edits. Key Takeaways [02:49] - A whiskey review. [09:55] - What whiskey and NFTs have in common. [11:37] - Runspired explains the source of his smackdown with Chris Manson. [15:38] - Where Chris Manson and runspired stand on TypeScript. [19:29] - Chris Manson's side of the story. [20:02] - How runspired and Chris Manson think we'll get more developers contributing to Ember. [29:09] - Where runspired and Chris Manson actually agree. [37:18] - Where Chris Manson stands on TypeScript. [40:56] - How to balance contributor-friendly with contributor careful. [44:58] - The problem with Ember sponsorships and Ember advocates. [01:02:53] - Some closing thoughts on today's smackdown, Peaky Blinders, and an NFT-themed whatnot. Quotes [26:19] - “The more that we've adopted TypeScript, the more I've seen people capable of making a contribution without my assistance that had the right fix.” ~ runspired [43:20] - “I see Ember Learn, the org, and all of the things that we maintain, as kind of a gateway drug to becoming an Ember CLI contributor, a framework contributor, an Ember Data contributor. It's like a training ground.” ~ Chris Manson [44:58] - “What we really need is a developer advocate for Ember. We need, as a community, to find some pool of funding, to hire somebody, to be 100% focusing on that pipeline that I'm talking about: getting people in at the bottom, finding ways for them to get from the bottom to the middle grounds, identifying the projects, project managing people up that scale, and getting them to (runspired's) door when they are ready.” ~ Chris Manson Links Chris Manson runspired Chuck on Twitter Whiskey Web and Whatnot: Ember vs. React, Jamstack, and Holes in the Hiring Process with Chris Manson Whiskey Web and Whatnot: Discovering Ember, Adopting Orbit, and Unlocking Optimization with Chris Thoburn (runspired) Whiskey Web and Whatnot: Work-Life Balance, React, and Why Accessibility is Everything with Melanie Sumner Jos. A. Magnus & Co. Murray Hill Club Buffalo Trace Distillery Redbreast 12 Year Old Glendalough Whiskey Booker's Bourbon Jim Beam 1787 Coworking Juan Palomino TypeScript Ember.js Ember Data Ember Core Team FourLoop Thinking, Fast and Slow by Daniel Kahneman Depreciations Ember.js Open Collective Tilde Inc Hades Ember Conf Gary Vaynerchuk Damien Hirst Damien Hirst's NFT Bored Ape Yacht Club NFT Connect with our hosts Robbie Wagner Chuck Carpenter Ship Shape Subscribe and stay in touch Apple Podcasts Spotify Google Podcasts Whiskey Web and Whatnot Top-Tier, Full-Stack Software Consultants This show is brought to you by Ship Shape. Ship Shape's software consultants solve complex software and app development problems with top-tier coding expertise, superior service, and speed. In a sea of choices, our senior-level development crew rises above the rest by delivering the best solutions for fintech, cybersecurity, and other fast-growing industries. Check us out at shipshape.io.
Встречайте 135-й выпуск подкаста. У меня в гостях Андрей Листочкин, CTO в компании Viravix. Очень давно мы собирались пообщаться с Андреем, но свершилось это вот только сейчас. Так что тем для обсуждения накопилось порядочно и выпуск получился длинным, но от этого не менее интересным! Андрей рассказал про свой долгий и ветвистый путь в Айти: работу в компании Opera, IP-телефонию, разработку медицинского софта и заканчивая системами промышленного оборудования в пищевой промышленности. Мы поговорили про эволюцию веба, развитие браузеров и внедрение новых браузерных API, подискутировали о инструментах фронтенда, таких как сборщики, вспомнили jQuery и Firebug! Андрей рассказал про то, как он стал амбассадором Ember.js в русскоязычном сообществе. Мы подискутировали о фреймворках, платформах, их идеях и устаревании, vanilla js и легаси. Обсудили то, как изменились вопросы, задаваемые фронтенд-разработчикам на собеседованиях. Поговорили про команды, ресурсы, фуллстек разработчиков и аутсорс, решаемые задачи и используемые для их решения технологии, выбор стэка, платформ и всего остального. Андрей рассказал про свою роль СТО в компании, чем он занимается и какие решает задачи. Андрей, как активный член различных программных коммитетов конференций и сообществ рассказал и про эту сферу своей деятельности. Мы обсудили конференции, преподавание и менторство: зачем, для чего и ради каких целей ими занимаемся. Ссылки на ресурсы по темам выпуска: * Ранний фронтенд и веб: * Firebug (https://en.wikipedia.org/wiki/Firebug_(software)) * Joe Hewitt, автор Firebug и iUI (https://en.wikipedia.org/wiki/Joe_Hewitt_(programmer)) * Ролик про Opera Mini 5 & Mobile 10 (https://www.youtube.com/watch?v=wWHIGGjiamA), над которыми работал Андрей * Тот самый вопрос на SO про X-UA-Compatible (https://stackoverflow.com/questions/11095319/how-to-fix-document-mode-restart-in-ie-9/11096186#11096186) * KnockoutJS - первый популярный фреймворк с интерактивным туториалом (http://learn.knockoutjs.com/#/?tutorial=intro) * Туториал Джона Резига (автора jQuery) о том, как работает Function.prototype.bind (https://johnresig.com/apps/learn/) * Книги и доки: * Literate Programming (https://en.wikipedia.org/wiki/Literate_programming) * Annotated Version of the Original jQuery Release (https://johnresig.com/blog/annotated-version-of-the-original-jquery-release/) * Docco (http://ashkenas.com/docco/) is a quick-and-dirty documentation generator * Аннотированные исходники underscore.js (https://underscorejs.org/docs/underscore-esm.html) * Ответ Андрея про использование CoffeeScript на SO (https://softwareengineering.stackexchange.com/questions/72569/what-are-the-pros-and-cons-of-coffeescript/113208#113208) * Ember JS: * Broccoli.js (https://broccoli.build/) * The Ember CLI (https://cli.emberjs.com/release/) * Первый доклад Андрея про Ember с JavaScript Framework Day'14 (https://www.youtube.com/watch?v=cXb1aFczAbo) * Post-SPA фреймворки: * Hotwire (https://hotwired.dev/) * TwinSpark (https://kasta-ua.github.io/twinspark-js/) * Строчка кода, заработавшая компании миллион (https://www.freeswitch.org/confluence/display/FREESWITCH/mod_dptools%3A+deflect) * Сообщества и конференции: * https://fwdays.com/ * http://kharkivjs.org/ * http://kyivjs.org/ * https://kottans.org/ * Фреймворки и платформы: * https://nestjs.com/ * Про “Async iterators and generators” (https://jakearchibald.com/2017/async-iterators-and-generators/) от Джейка Арчибальда * https://rxjs.dev/ Понравился выпуск? — Поддержи подкаст на patreon.com/KSDaemon (https://www.patreon.com/KSDaemon), звёздочками в iTunes (https://podcasts.apple.com/ru/podcast/software-development-podcast/id890468606?l=en) или своём подкаст-плеере, а так же ретвитом или постом! Заходи в телеграм-чат SDCast (https://t.me/SDCast), где можно обсудить выпуски, предложить гостей и высказать свои замечания и пожелания!
Aaron is the author and co-maintainer of the popular Ember addon, EmberCLI Deploy, which has become the defacto addon for shipping Ember applications. He has spent the past 5 years evolving deployment patterns for JS web applications to allow faster shipping with more confidence, using patterns such as parallel deployments that leverage tools such as Redis. By day, Aaron is a tech lead at Phorest where he helps lead the development of their salon management software built in Ember.js and loves to ship at 4pm on Fridays :)“What do you do?” (1:25)“What is Ember?” (1:53)“What is Ember CLI deploy?” (3:35)Multiple versions of app“What inspired you to create it?” “4:30”Team member saw it used at squareWeb server looks for parameter“What are patterns are you interested in these days?” (10:40)Immutable deployments – normal on the backend, but not normal on the front end“Where do you use Redis?” (12:35)“S3 (assets), CDN & Redis (store links, version to files in Redis)” (15:10)“Patterns to make dev easy” (14:35)JavascriptCSSImages“Parallel Deployments” (19:15)“How do you integrate with other app code?” (20:00)RELATED LINKS:https://twitter.com/grandazzhttps://cli.emberjs.com/release/basic-use/deploying/#emberclideployhttps://immutablewebapps.orghttps://www.phorest.com
Luke Melia, Aaron Chambers, and Mattia Gheda john Taras and Charles to discuss all things deployment! Luke Melia: Luke has been working with Ember since it was under early development as Sproutcore 2.0. Ember.js powers a SaaS company he co-founded, Yapp, and they funded their business for a couple of years doing Ember consulting under the Yapp Labs moniker. They're full-time on product now, and his engineering team at Yapp (currently 3 people) maintains around 6 Ember apps. Luke helps to maintain a bunch of popular addons, including ember-cli-deploy, ember-modal-dialog, ember-wormhole, ember-tether, and more. He started the Ember NYC meetup in 2012 and continues to co-organize it today. Aaron Chambers: Aaron Chambers: Aaron is the co-author of EmberCLI Deploy and is currently an Engineer at Phorest Salon Software, helping them move their desktop product to the web platform. He's been using Ember for 5 years and maintains a number of plugins in the EmberCLI Deploy ecosystem. Aaron loves trying to work out how we can ship JS apps faster, more reliably and with more confidence. Mattia Gheda: Mattia is a Software Engineer, Ember hacker, Ruby lover and Elixir aficionado. Currently he works as Director of Development for Precision Nutrition where Ember, Ruby and Elixir power several applications. He loves meetups, organizes Ember.js Toronto and co-organizes Elixir Toronto. Resource: Immutable Web Apps Please join us in these conversations! If you or someone you know would be a perfect guest, please get in touch with us at contact@frontside.io. Our goal is to get people thinking on the platform level which includes tooling, internalization, state management, routing, upgrade, and the data layer. This show was produced by Mandy Moore, aka @therubyrep of DevReps, LLC. Transcript: CHARLES: Hello and welcome to The Frontside Podcast, a place where we talk about user interfaces and everything that you need to know to build them right. My name is Charles Lowell, a developer here at the Frontside. With me also co-hosting today is Taras Mankovsky. Hey, Taras. TARAS: Hello, everyone. CHARLES: Today, we have three special guests that we're going to be talking to. We have Aaron Chambers, Luke Melia, and Mattia Gheda who originally met collaborating on fantastic open source library that we, at the Frontside, have used many, many times that saved us countless hours, saved our clients hundreds of thousands of dollars, if not more. ember-cli-deploy. We're gonna be talking not about that library in particular but around the operations that happen around UI. So, welcome you all. LUKE: Thanks, it's great to be here. CHARLES: Like I said, I actually am really excited to have you all on because when we talk about the platform that you develop your UI on, something that often gets short shrift in communities outside of the Ember community is how do I actually deliver that application into users' hands. Because obviously, we don't want it to be working just on our laptop. We want it to be delivered to our users and there are myriad ways that that can happen and it's only gotten more complex since the last time we talked which must have been like three or four years ago. I kind of just have to ask, I think that what you all were talking about then was cutting edge is still cutting edge now but there must have been some pretty incredible developments like in the last three or four years. What have been kind of the new insights that you all have? LUKE: I think that what we realized as we got started with ember-cli-deploy and a project kind of came together as a combination of a few different open source efforts, something that Aaron was working on, something that our collaborator Mike was working on. We decided to come together under one umbrella, joined forces. And what we realized pretty soon is that deployment needs vary a ton between companies. And so, we are coming from this background in Ember community where we had this attitude where nobody is a special snowflake. We all kind of have the same needs for 90% of what we do. And that's true. I really believe in a lot of that Ember [ethos]. But when it comes to deployment, you know what? A lot of companies are special snowflakes or it's at least is much more fragmented than kind of our needs around on the JavaScript side. And so, what we decided to do was to try to evolve ember-cli-deploy into a platform essentially, an ecosystem that could let people mix and match plug-ins to do in their organization without locking them into an opinion that might simply be a non-starter in their org. CHARLES: It's hard enough to have opinions just around the way that your JavaScript code is structured but when it comes to rolling out your app, it really does encompass the entire scope of your application. So, it has to take account of your server. It has to take account of your user base. It has to take account of all the different processes that might be running all over, distributed around the Internet. Maybe somewhere on AWS, maybe somewhere on Legacy servers but it has to consider that in its entirety. So, it's having opinions that span that scope is particularly difficult. LUKE: Yes. And so, you mentioned a bunch of technical details which are absolutely forcing factors for a lot of words in how they do their deployments but what we found in talking to people that there are also people in political aspects to deployment in many cases. Engineers kind of own the JavaScript code that's running within their app, more or less. But when it comes to pushing the app into the world and a lot of companies, that means they're interacting with sysadmins, ops folks, people who have very strong opinions about what is an allowable and supportable way to get those deployments done and to have that stuff exist in production. And so, we needed to come up with an architecture that was going to support all these kind of varied use cases. And so, we came up with this system of essentially a deployment pipeline and plugins that can work at various stages of that pipeline. And that ecosystem has now grown quite a bit. It's actually, I don't know Aaron if you and Mattia would agree but I think it's probably the best decision that we made in this project because that ecosystem has grown and evolved without us needing to do a ton of work in maintenance. And it's been really great. I think Mattia, you pulled some of the current numbers there. MATTIA: Yeah. I pulled some numbers just yesterday and we have currently 150 different plugins attached to themselves, to different parts of the pipeline. So some of them are about how to build the assets, some of them are about how to compress them, some of them are about shipping. And they allow people to ship it with different ways like we are seeing [inaudible] with just simply Amazon APIs or Azure APIs and some of them even are about just how to visualize data about your deployments or how to give feedback to the user about what was deployed and represent the information. And then this is kind of a bit more detail, probably specific to us but we also added this idea of plugin packs. So, in order to help people define their deployment story, we created this ideal of plugin packs. Plugin packs are simply group of plugins. So, plugins grouped together. As a user, if you want to implement what we call a deploy strategy, you can simply install a plugin pack and that will give you all the plugins that allow you to deploy in a specific way. And that's kind of like an optimization that we added just to make it easier for people to share deployment strategies, share ways of deploying applications. CHARLES: Right. It's almost like an application within the framework. MATTIA: Yeah, exactly. But to stay on the community side, I think that the interesting part about what Luke was saying which was a great success for us is that all we maintain as the core team for this project is the core infrastructure, so the pipeline and a thousand of plugins. Everything else is community-based. And often, even in my day-to-day work, I end up using plugins that I didn't write and that I don't even maintain. But because the underpinning of it were designed especially by Luke and I are flexible enough. It just like has been very, very stable and very, very reliable for many years. So, I will say definitely the idea of like in the spirit of what Ember is, I guess, creating a shared ecosystem where people can add what they want and extend what was provided has been the one single biggest win of this project. CHARLES: One of the things that I'm curious about is we've talked about how you're allowing for and kind of embracing the fragmentation that happens in people's kind of the topology of their infrastructure. What do you see is the common threads that really bind every single good deployment strategy together? MATTIA: My biggest thing here, and we actually have some shared notes about this, but my biggest thing about this is the idea that building and deploying an application for me is divided into three parts. There's building part where you have to decide how to compile your JavaScript application and how to produce some sort of artifact. There is the shipping part where it's about deciding where you're going to put the artifact. And then there is the serving part which is how you show it and deliver it to your users. I think that these three are the underpinnings of any deploy strategy. What we did with this project is just acknowledging that and give each one of these a place. And so, the entirety of what we do in what Luke defined as a pipeline is simply give you a way to customize how you build, customize how you ship, and then customize how you serve. So yeah, I think that that's kind of the root. And the question that everybody that wants to deploy a modern JavaScript application have to ask themselves is how do I want to build it, how do I want to ship it, and how will I serve it to my users. And these things are completely independent one from the order in the sense that you can have something build it, something ship it and something serve it, and that's what we end up doing in most of our deployments, I find. CHARLES: It's good to think about those things as soon as you possibly can and make sure that you have all three of those bases covered really before you start adding a whole ton of features. TARAS: Sprint 0, right? LUKE: In Agile, we call Sprint 0 the phase the thing you do right in the beginning. You've got a skeleton of an app and then you get the deployment infrastructure going, you have the test infrastructure going, so that there is no task within your actual feature development where you have to do those things. And I think that can be a valuable concept to embrace. I would just add to Mattia's three points that for deployments, to me, some very simple qualities of a good deployments are repeatability. You need to be able to reliably and consistently run your deployment process. Sounds simple but there's plenty of operations that have run up way too long on manual deployments. So, we don't want to see those rollback capabilities if you have a deployment that you realize was a mistake right after it gets into production. I'm sure none of us have ever experienced that. CHARLES: That never happens to me. LUKE: You want to have a method to roll that code back. That's something that can be remarkably complex to do. And so, having some guardrails and some support mechanisms to do that like ember-cli-deploy provides can be really useful. But whatever your approach is, I think that's a necessary quality. And then I think we start to step into kind of more advanced capabilities that a good deployment architecture can provide when we start to think about things like personalization, A/B testing, feature flags, these kinds of things. And that requires more sophistication, but you cannot build that on a deployment foundation that's not solid. AARON: I think for me, one of the things I've been really thinking about a lot lately, it's a bit of a mindset shift, I think, to get to where the things Mattia was talking about separating those different parts of deployment. And so, I really start to realize the traditional mindset around deployments like I build some stuff and I ship it to the server and then the users get it. But if we can actually stop and actually split our understanding of deployment into two separate phases. One is the building and the physical shipping of the files; and the other one's actually making them available to people. You open up this whole world of our features that you wouldn't normally have. So to be able to actually physically put stuff in production but not yet have it active, as in users don't see it yet but you can preview those versions in production against production databases. And then at some point after the fact, decide, "Okay, I'm now going to route all my users to this new thing," And to be able to do that really easily is massively, massively powerful. And so, to me, the thing I've been thinking about lately is it is a small mindset shift away from packaging everything up and pushing and overwriting what's currently there to being something, again like Luke said, immutable deployments where everything we build and ship sits next to all the other versions and we just decide which one we want to use to look at it any time which leads into then, I guess, A/B testing, feature flags and things. So I guess deployment really is not so much about the physical shipping, that's one part of it. To me, deployment now is shipping of stuff, as in physical deployment and then the releasing it or enabling it or activating it to users. CHARLES: Or routing it. Sounds like what you're describing is an extraordinarily lightweight process. AARON: It is, yeah. CHARLES: To actually route traffic to those files. AARON: It is. It's incredibly lightweight. That's the amazing thing about it. When you think about it, you're building a few JavaScript files and CSS files and images and putting them on a CDN, and then you just need a tiny web server that basically decides which version of the app you want to serve to people. There's not much to it at all, really. CHARLES: I mean that's absolutely fascinating, though the capability that you have when you have the ability to have these versions, the same versions or different versions of your application sitting along next to each other and being able to route traffic. But it also seems to me like it introduces a little bit of complexity around version matching because only certain versions are going to be compatible with certain versions of your API. You have different versions of your API talking to the -- so the simplicity of having kind of mutable deployments, so to speak, is that everything is in sync and you don't have to worry about those version mismatches. Is that a problem or this could just be me worrying about nothing? But that's kind of the thing that just immediately jumps out to me is like are there any strategies to manage that complexity? LUKE: To me, what you're describing, I kind of think of as a feature not a bug. And what I mean by that is that it is very simple to have a mental model of, "Oh, I have a version of my JavaScript code that works with this version of my API." And as long as I kind of deploy those changes together, I'm good to go. The reality is that that's impossible. The JavaScript apps that we write today, people are using anywhere from two seconds at a time to two days at a time. It's not uncommon these days to have some of these dashboard apps. People literally live-in for their job eight hours a day, nine hours a day, keep the browser tab open and come in the next morning and continue. And so, obviously there are some mechanisms we could use to force them to reload that kind of thing. But at some point in most apps, you're going to have a slightly older version of your JavaScript app talking to a slightly newer version of your API for either the span of a minute or perhaps longer depending on their strategies. So to me, the process of thinking about that and at least being aware of that as an engineer thinking about how your code is going to get from your laptop into the world, I think it's an important step that we not paper over that complexity and that we kind of embrace it and say, "Hey, this is part of life." And so, we need to think about just like we need to think about how your database migrations get into production. That's not something that you can paper over and just have a process that it's going to take care of for you. It requires thought. And I think that this, in the same token, how different versions of your JavaScript app are going to interact with your API requires thought. An exact parallel also had different versions of a native mobile app that go into the app store. How did those interact with different versions of your API? So, I think you're right. There's complexity there. There's ways that we can try to mitigate... CHARLES: Keep repeating ourselves if we think that that [inaudible] actually doesn't exist even in the simple case? MATTIA: Yeah. I think that that's to reiterate what Luke is saying. That's exactly the point. You can pretend it's not there but it is and you have no way to avoid it. Once you ship something to a browser, you have no control over it anymore. And so, you have to assume that somebody is going to be using it. LUKE: Aaron, I think you too, I don't know if you can share it. But you recently told us some stories about kind of what you encountered in your work about this and of how long people were using versions and stuff. AARON: Yeah. Something that we hadn't sort of put a lot of thought into. But the last place I worked at, we had quite a long lived app and we're using feature flags and we're using launch [inaudible] something and it gives you a list of flags and when they were last requested. And there were also flags that we removed from the code and it was just a matter of waiting until all the users had the most current version of the app and weren't requesting the flag anymore. But this one flag just kept getting requested for months and we just could not work out why. It really sort of opened my eyes up to this exact problem that these long lived apps set in the browser and if you have someone that just doesn't reload the browser or restart the machine or anything, your app can live a lot longer than maybe you actually realize it is. So we're shipping bug fixes, we're shipping new features, and we're all patting ourselves in the back. We fixed this bug but have we really? If your users haven't reloaded the app and gotten the latest version, then you haven't actually fixed the bug for some number of people. And it's really hard to tell them as you think about this and put things in place, really hard to tell what versions are out in the world, how many people are using this buggy version still. CHARLES: Yeah, that's an excellent point. I haven't even thought about that. I mean, what is the countermeasure? AARON: We hadn't made it until we came across [crosstalk]. CHARLES: It's nothing quite like getting smacked in the face of the problem to make you aware of it. AARON: That's right. CHARLES: So, what's the strategy to deal with that? AARON: I guess for me, my learnings from that would be from very early on thinking about how we're going to encourage people to reload, to start with, and maybe even have the ability to force a reload and what that means but then that has gotchas as well. You don't want to just reload something when a user is in the middle of writing a big essay or something like that. But definitely thinking about it from the start is one of the things you've got to think about from the start. But I guess something that I'd like to implement and I've kind of thought through but not really explored yet, but the ability to see what versions are out there in the world and there are things I've been thinking about in terms of this little server that serves different versions. Maybe we can start having that kind of tracking what versions are out there and who's using what and being able to see because it would be great to be out to see a live chart or a dashboard or something that sort of shows what versions are out there, which ones we need to be aware of that are still there and even what users are using and what versions they can maybe even move them on, if we need to. But there's definitely a bunch of things that aren't immediately obvious. And I don't know how many people actually think about this early on, but it's critical to actually think about it early on. MATTIA: Yeah. I was going to share what we do which is very similar to what Aaron said just maybe for the listeners to have some context. The first thing you can do is basically what Gmail does, which is every time a web app sends a request, an [inaudible], it will send the version of the app with the request and the backend can check. And the backend can check if you are sending a request from the same version that is the most recent deployed version. And if it's not, this sends back a header and the same way that Gmail does, it will display a pop up that is like, "Hey, we have a new version if you want reload." And on top of that [inaudible] is that we have a dead man's switch. So if we accidentally deploy a broken version, a part of this process, the frontend application tracks in the headers. And if a special header is sent, it force reloads, which is not nice for the user but it's better and sometimes is critical to do so. CHARLES: Right. I remember that was that case where Gmail released something. They were doing something with broken service workers and the app got completely and totally borked. I remember that my Twitter blew up, I don't know, about a year ago I think, and one of the problems I don't think they had was they did not have that capability. MATTIA: I mean, you learned this the hard way sadly. But I think these two things are definitely crucial. And the third one, [inaudible]. I thought, Luke, you had the ability that Aaron was talking about like tracking versions in the world. And I think that's more useful for stats so that you know how often your users update. And then you can make the design decisions based on that and based on how much you want to support in the past. LUKE: Yeah. We haven't implemented that but it reminds me whenever there's a new iOS version, we do a bunch of mobile work in the app and we're always looking at that adoption curve that's published. A few different analytic services publish it and say, "OK. How fast is iOS 12 adoption? How fast are people leaving behind the old versions?" And that helps to inform how much time you're spending doing bug fixes on old version versus just telling people, "Hey, this is fixed in the new OS. Go get it." But if you are able to see that for your own JavaScript apps, I think that would be pretty hot. CHARLES: Yeah. Crazy thought here but it almost makes me wonder if there's something to learn from the Erlang community because this is kind of a similar problem. They solved 20 years ago where you have these very, very long running processes. Some of them there's some telephone servers in Sweden. They've been running for over a decade without the process ever coming down. And yet they're even upgrading the version of Erlang that the VM is running. And they have the capability to even upgrade a function like a recursive function as it's running. And there's just a lot of -- I don't know what the specific lessons are but I wonder if that's an area for study because if there's any community that has locked in on hot upgrade, I feel like it's that one. LUKE: That's a terrific analogy. I bet we could learn a ton. Just hearing that kind of makes me think about how kind of coursed our mental model is about updates to our JavaScript apps. We talked to Aaron, we're talking about kind of this idea of a mutable apps and you have different versions side by side. But the idea of being able to kind of hot upgrade a version with running code in a browser, now that's an ambitious idea. That's something I'd say, "Wow! That kind of thing would be a game changer." CHARLES: Yeah. AARON: Makes me feel like we got a whole bunch of work to do. CHARLES: We welcome them. I'm always happy to give people plenty more work to do. No, but how they manage even being able to do migrations on the memory that's running. I don't know if it's something that's going to be achievable but it sounds kind of like that's the direction that we're heading. LUKE: It does, as these apps get more complex and they continue to live longer. The idea, the work arounds that Mattia mentioned about kind of showing a message and having a dead man's switch, these are all certainly useful. And today, I would say even like the best practice but they were not what you would want to do if you could magically design any system. If you're taking a magical approach, the app will just be upgraded seamlessly as a user was using it. And they would be none the wiser, the bugs would be fixed. End of story. There's no interruption to their workflow. At least for me personally, I don't really think about that as a possibility but I love the Erlang story and analogy and to say maybe that is a possibility, what would it take? I would obviously take a collaboration across your JavaScript framework, perhaps even JavaScript language features and browser runtime features as well as your backend and deployment mechanism. But I think it's a great avenue for some creative thinking. CHARLES: I'm curious because when we're talking about this, I'm imagining the perfect evergreen app but there's also feels like there's maybe even a tension that arises because one of the core principles of good UI is you don't yank the rug out from underneath the user. They need to, at some point and we've all been there when the application does something of its own agency, that feels bad. It feels like, "Nope, this is my workspace. I need to be in control of it." The only way that something should move from one place to the other without me being involved is if it's part of some repeatable process that I kicked off. But obviously, things like upgrading the color of a button or fixing a layout bug, those are things that I'm just going to want to have happen automatically. I'm not going to worry about it. But there is this kind of a gradation of features and at what point do you say, "You know what? Upgrading needs to be something that the user explicitly requires," versus, "This is something that we're just going to push. We're going to make that decision for them." LUKE: Yeah, it's a great question. One of the things that I'm curious what you all think is when you think about the mental model that our users have of working in a browser app, do you think that there is a mental model of, "Oh, when I refresh, I might get a new version." Do people even think about that? Or are they just like your example about a button color changing as kind of a minor thing. I don't even know if I could endure stack. We've all been I think in situations where you do a minor redesign and all of a sudden, all hell breaks loose and users are in revolt. Take the slack icon. So, I think it's a fascinating question. CHARLES: I don't know. What's the answer? Do you always ask for an upgrade just observing? I don't have any data other than observing people around me who use web applications who don't understand how they actually work under the covers. I don't think it's the expectation that this code, this application is living and changing underneath their feet. I think the general perception is that the analogy to the desktop application where you've got the bundled binary and that's the one you're running is that's the perception. AARON: I'd say the difference there is that, and with all these new ways of deploying, we're shipping small things faster in multiple, multiple times a day or even an hour. So it's not the sort of thing you really want time to use. There has been an update, need to upgrade as well. And that's the difference between the desktop mentality. And if that's the mentality they have, it sits quite a bit of a shift, I guess. MATTIA: It makes me think that one of the tools that the users -- if you take a look at the general public, there's probably one tool that everybody can relate to which is Facebook. So, I think if there is a way to say what do people generally expect. There is a business user which I think we are often most familiar with but the general public, probably what they're most familiar with is what happens in Facebook. And I don't use Facebook almost. I haven't used it for a couple of years but I wonder how much of what people experience in Facebook actually impacts the expectations around how applications should behave. LUKE: I think that's a really good question. I do think your underlying point of you have to know your own users I think is an important one also. Obviously, some folks are going to be more technical than others or some audiences will be more technical than others. But I would even question, Charles, your suggestion that people think of it kind of as like a binary that it stays the same until you refresh. I think people have an idea that web apps improve over time or sometimes they get bugs but hopefully that they improve and change over time, and that there is a tradeoff there that means sometimes there's something new to learn but at the same time, you get new features. But I don't know that people necessarily associate that with and it happens when I hit reload or it only happens when I open a new browser, like I don't know that it's that clear for people in their head. CHARLES: Right. I can see that. But the question is if the evolution is too stark, I think people tend to get annoyed. If they're in the middle of a workflow or in the middle of a use case and something changes, then it gives it a feeling of instability and non-determinism which I think can be unsettling. LUKE: Definitely. We all value, as engineers, we value getting into that flow state so much of like, "Oh man, I'm being productive. I don't have any distractions." And you kind of owe that to your users also to be able to let them get into that state with your app and not be throwing up, "Hey, there's new stuff. Reload." "I'm in the middle of something. Sorry." CHARLES: Yeah. I definitely do the same thing. Sometimes, I let iOS be bugging me to upgrade for a month until I finally start to feel guilty about security and actually do the upgrade. LUKE: Right. CHARLES: Although once they started doing it at night, it actually made it a lot better. LUKE: That's an interesting idea, too. I think there's a natural tension between the lower integration risk that we have as the engineering teams of shipping very frequently. Aaron mentioned shipping a dozen times a day. We certainly have been there and done that as well. I would say on average, we ship a few times a day. But the reason that we do that is because we know the faster we get code into production, the faster we can trust it. So it passes all your tests, it passes your [inaudible], but you don't really know if you're being honest. You don't really know until there's thousands of people using it in production. And yet, this conversation makes me think about there is a tension between how frequently you do that versus your users' kind of comfort level and expectations. CHARLES: And maybe there is a thing where you can kind of analyze on a per user basis how often they're active in the application and try to push updates on times that are customized to them. LUKE: Like when a user has been idle for 30 minutes or something like that. CHARLES: Yep. Or even like track trends over months and see when they're most likely to be idle and schedule it for them. LUKE: Good point. CHARLES: Something like that. TARAS: I have an idea. We should introduce screen savers into web apps. And so when the user stops using the app, just turn on screen saver and do the upgrade. LUKE: I can see the VC patch. It's after dark but for the web. CHARLES: Enter install flying toaster. AARON: It does that to open up the idea as well of that automated checking that things are okay well after the fact because it's all right to sit there maybe activate something and sit there even for an hour and make sure there's no bug request coming in. But if no one's actually received your app, then of course it's not going to come in. And it's very easy to kind of move onto the next thing and forget about that. I guess it's not something that I've ever put a lot of time in and I haven't worked anywhere that's had really great automated checking to see is everything still okay. And I guess it's an interesting thing to start thinking about as well an important thing. CHARLES: Like actually bundling in diagnostics in with your application to get really fine grained information about kind of status and availability inside the actual app. AARON: I'm not exactly sure, really. I guess I maybe wasn't thinking about inside the app but I don't know what it looks like exactly. But there is that element of shipping fast and getting stuff out there. But are we really making sure it all works later on when everyone's actually using it. LUKE: Yeah. This by the way, I just wanted to say when we were talking earlier what are the essential qualities around deploying an app. And this reminds me that one thing that we didn't mention but is very simple is your app should have a version. And it should be unique and traceable back to what was the GitHub, git commit that was the origin of that code. It's just a very simple idea but if you're going to be analyzing errors in production when you have multiple different versions of your JavaScript app running, you're going to need to know what version caused this error and then how do I trace it back and make sure that the code that I'm trying to debug is actually the code that was running when this error happened. CHARLES: Do you only use just [inaudible] or do you assign like a build number or using SemVer? What's a good strategy? LUKE: In our case, we use git tags. And so, our CI deployment process for our Ember apps basically looks like this is we work on a PR, we'll merge it to master. If it builds, the master gets deployed into our QA environment automatically using ember-cli-deploy from our CI server. And then once we're happy with how things are on QA, we do git tag or actually I use an ember addon called ember release that does that tagging for me and I'll tag it either in patch minor or major, roughly [inaudible] although it doesn't matter that much in the case of apps. When there is a new tag that builds green on CI, that gets deployed automatically into production by ember-cli-deploy. And so, that's kind of a basic flow. That tagging, just to be clear, the SemVer tag is just going to be number.number.number. You can get more sophisticated than that and I think both Aaron and Mattia have a system where even in the PR stage, there's automatic deployments happening. So maybe one of you want to mention that. AARON: We're slightly different. Every time we push the pull request, that gets deployed to production. We're able to preview up pull requests in production before we even merge into master which we find super useful to send out links to stakeholders and maybe people that have raised bugs just to get them to verify things are fixed. And then at the point that it's all Google merged, the pull request to master which will automatically do another deploy which is the thing we'll ultimately activate, we activate it manually after the fact. We just do a little bit of sanity checking but we could automatically activate that on merge to master as well. But yeah, the being able to preview a pull request in production is super powerful for us. CHARLES: That is definitely a nice capability. It's hard. It's one of those certain workflows or patterns or tools that you remember life before them and then after them and it's very hard to go back to life before. I would definitely say kind of the whole concept of preview applications is one of those. AARON: Absolutely. It's a daunting concept if you're not there, previewing something that's essentially a work in progress and production. And there are some things you want to be careful with, obviously. But for the most part, it's a super valuable thing. As you say, it's a world where once you're there, it's very hard to step back and not be there again. CHARLES: So I had a question about, we talked about I think it was 162 plugins around the ember-cli-deploy community. What for you all has been the most surprising and delightful plugin to arrive that you never imagined? MATTIA: That is a good one. I'm pulling up the list. What I can tell you, for me, it's not about a specific plugin. The surprising part was the sheer amount of different strategies that people use for the shipping part. At least, I found that the build part is similar for most people, like most people want to do the things that you're supposed to do. So, you want to build your application and then you want a minify it in some way. And there's a bunch of options there from gzip to more recent technologies. But the way people deliver it to servers and the difference in the solutions, that I think for me has been the biggest thing, where people that ship [inaudible] are people that ship directly to Fastly, people that use FTP files, people that use old FTP, people that use our sync, people that do it over SSH. We have people that ship stuff directly to a database because some databases actually have great support for large files. So we even use it as a storage. We have people that do it in MySequel, people that do it in [inaudible]. CHARLES: It's actually storing the build artifacts inside of a database? MATTIA: Yes, I've seen them in that. It's kind of interesting like the solutions that people ended up using. And so for me, I think that that's been the most fascinating part. Because as we were saying at the beginning, I'm just seeing now, we even have one for ZooKeeper. I don't have an idea what this does but it's probably related to some sort of registration around the seven-day index. That, to me, I think has been the biggest surprise. Everybody ends up working in a different environment. And so, that flexibility that users need has been by far the most surprising one. AARON: I think that's also been one of the challenging things, one of the enlightening things for me. I think in the Ember ecosystem, addons and even just Ember itself, it's all about convention of configuration and doing a lot of the stuff that you do for you. I think people expect them to see a lot of point to do the same thing. But the key thing here is it just really automates all the things you would do manually and you need to understand exactly what you want your deployment strategy to be before use them to see a lot of [inaudible] could do for you. You need to decide do I want to install my assets on a CDN and do I want to install my index in Redis or in console or in S3 bucket. You need to know all these things and have decided on all these things and then ember-cli-deploy will make that really easy for you. And this is one of the educational things, I think we still haven't even nailed because there are always people that want to know why this doesn't work. But deployments are complex thing and as what you were saying Mattia, there are so many different variables and variations on doing this that there's no sensible configuration ember-cli-deploy could really provide out of the box, I guess. And so, that's why we ended up with a pipeline that gives you the tools to be flexible enough to support your strategy. LUKE: I think the closest that we come to the convention is that if any app is using ember-cli-deploy, you can run ember deployment targets or ember deploy prod and ember deploy QA and you can expect that that's going to work. What you don't know is how has it happened to be configured in this project. Charles, your question about kind of the most surprising thing that's come out of the ecosystem. For me, I would say -- Mattia mentioned plugin packs earlier which are groups of plugins that kind work together well. And so, we've seen some plugin packs like you might expect, like an AWS pack for deploying to AWS. But the more interesting ones to me that we've seen a lot of, companies open source their plugin packs. So what you naturally fall into as a company that's adopting ember-cli-deploy that has multiple ember apps is that you are going to develop your own plugin pack for internal use because generally speaking, companies follow the same deployment pattern for each of their apps. There's usually not any reason to vary that. So then the new thing that happen on top of that is people said, "Why don't I make this open source so other people can kind of see how we do it?" And that's been a really delightful part of the process to kind of get a peek into how other organizations are orchestrating their deployments. And if people are curious about kind of looking at that themselves, you can go on NPM and look for keyword ember-cli-deploy-plugin-pack and pull up all of those. And you can kind of poke around and see what different companies have open source there. CHARLES: I actually love all three of those answers because it really is for me when you have a constellation of people around a particular problem, it's the surprising solutions that emerge that are some of the most exciting that would have lain hidden otherwise. It would have been kind of buried beneath the source of company A or company B or company C but actually having it all out in the open so that you can inspect it and say, "Wow, where has this solution been all my life?" Something that you have never imagined yourself. LUKE: It's so funny that you mentioned that because that actually is the origin story way back, I'm talking like 2013 probably when we were very early Ember adopters and we were trying to figure out how do we deploy this thing. We're deploying it with our Rails app, like literally deploying the Ruby code and the JavaScript code together which took forever which is a disaster. And I heard through the grapevine, just exactly what you're saying Charles, where the good ideas are kind of hidden inside of a company. I heard through the grapevine that Square had this approach that they were using where they would deploy their JavaScript assets and then deploy their index HTML file, the contents of that file, into a database, it's Redis in their case, and serve then it out of there. And it empowered all of these interesting situations of like having multiple versions, being able to preview the release, et cetera. And so we then set out to copy that idea because there was nothing open source. So we had to create it ourselves which we did in Ruby which we made it inaccessible to many JavaScript shops in the first place. Then the evolution of that kind of over time and of Mattia and Aaron and Mike and the rest of the community kind of talking together has now moved this into the open source sphere where these ideas are more accessible and we've created an ecosystem encouraging these ideas to stay out in the open. It's so true that there's just gems of ideas that have been created by really brilliant engineers inside of companies that could be benefiting so many people, they just haven't seen the light of day yet. CHARLES: Yeah, that leads me to my next question. I would say most of the ideas that we've been talking about today really, except for the build part, how Ember specific are they? Obviously, the ember-cli is a great resource and has a lot of great opinions for actually building the JavaScript assets themselves. But the second two phases of the pipeline really can vary freely, if I understand correctly. And so, have you all ever thought about trying to maybe kind of abstract these processes and these plugins so that these same ideas don't remain not just inside of a company but inside a community that spans a set of companies so that it's available for a wider audience? How integrated is it with Ember and what kind of effort would that be? LUKE: That's a great question. Aaron or Mattia, one of you guys wanna talk a little bit about the history here? MATTIA: Yeah, sure. We've been thinking about this as well. In the past, a guy on the ember-cli-deploy team, Pepin, has actually started this effort and it kind of prototyped this very idea of separating the ember-cli-deploy part from Ember CLI itself and make it a bit more generic. And he started a project called Deploy JS which I can give you a link for the show notes later. I don't think that the project is currently maintained but definitely the start of the effort is there. And the funny thing is that it was surprisingly easy. I think that we didn't get there mostly because we just all use Ember at work. As you know, open source is mostly motivated by the needs that an individual or a group of people have. But if any of the listeners were very interested in this, I think they should definitely get in touch and we will be happy to talk to them and see what can be done here. AARON: And also if you look, there's actually a plugin called ember-cli-deploy-create-react-app and there's also ember-cli-build-view. So it can and is being used to deploy non-Ember apps which I think is super interesting because the only real Ember part of it is just using the CLI to discover the addons and plugins. And from then on, it's really out of the hands of Ember. But it sort of leads into a little bit, Luke mentioned this concept of immutable web apps. And I've been thinking a lot about this lately because a deployment strategy that ember-cli-deploy use as an example a lot and it's kind of become [inaudible] ember-cli-deploy in ways, the lightning approach which is this whole idea of splitting or putting your assets in CDN and your index HTML separately maybe in Redis and serving that. I've been trying to work out how I can talk about this to the wider JavaScript community in a non-Ember way and knowing full well that the concept of lightning deployment means nothing to anyone outside of Ember. Just by chance, I was just talking to some people and this terminology of immutable deployments kind of rose. I started searching around and I come across a website called ImmutableWebApps.org which was just scarily the same as what we've been talking about for the last three or four years with ember-cli-deploy. And a way to boil down at a framework-agnostic level, what are the key points that you need to consider when building a JavaScript web app to make it immutable. And it was just really amazing seeing it. This website was put up 3 weeks before I did my Google search coincidentally. And it's basically word for word what we have been talking about the last three or four years, So, someone else in the other side of the world's been coming up with the same ideas in their company like you were talking about earlier and we've reached out to him. I guess that, to me, is sort of the way forward that I want to sort of pursue to try and get these ideas out in a framework-agnostic way to the rest of community and say, "Hey, we thought about deployment in this way. Have you thought about building your app in this way to give you these sorts of capabilities?" CHARLES: I think the wider community could definitely benefit from that because most of the blog posts and talks I've seen that concern themselves with deployment of single page applications, it's still much more of the tutorial phase. Like, "This is how I achieve getting this deployment strategy." Not, "This is how I repeatedly encode it as a program," and leverage it that way. And so, definitely getting that message out to a wider audience, I think it's a -- what's the word? It's an underserved market. LUKE: Yeah. I really like this idea also. I think about this ImmutableWebApps.org, if you look at it. It's sort of a manifesto with conceptual description of what are the qualities that your app has to have to qualify as an immutable web app which I think is kind of a funny idea but one that people can start to get their heads around and compare that description to their own apps and say how do I hit this or fall short. And it reminds me a lot of kind of the idea of Twelve-Factor App which is an idea that I think came out of Heroku originally. And it's an idea of a backend app that is portable to be able to easily move across different hosts and easily be scalable to different instances of [inaudible] if your app obeys all of these things then it's going to do well under those circumstances, that will satisfy those needs. So, I think it's a great way of thinking and probably maybe even a better entree into the conversation with the wider community than a library, this is certainly a library called ember-cli-deploy. CHARLES: This is a fantastic discussion. It's definitely reminded me of some of the best practices that I haven't thought about in a long time and definitely opened my eyes to some new ones and some new developments. So often, we can be focused on how our apps work internally, like how the JavaScript code works that we can just kind of -- what's the saying -- lose sight of the forest through the trees or I can't remember. It's like too busy looking down the end of your nose to see past your face. I've probably mangled both of those adages, but maybe 60% of two mangled adages is at least equal to one. This is something that we need to be thinking about more, that everybody needs to be thinking about more. This is actually a very exciting, very useful problem space and I'm just really grateful that you guys came on to talk to us about it. So, thank you, Mattia. Thank you, Luke. Thank you, Aaron. MATTIA: Thank you so much. It was a great time. AARON: It was a pleasure. Thanks for having us. LUKE: Thanks so much. CHARLES: Thank you for listening. If you or someone you know has something to say about building user interfaces that simply must be heard, please get in touch with us. We can be found on Twitter at @TheFrontside or over just plain old email at contact@frontside.io. Thanks and see you next time.
Edward Faulkner joins Sam and Ryan to chat about his work on Embroider, a new three-stage architecture that will power the next generation of the Ember CLI ecosystem. They also talk about myriad other topics, including Yarn Plug'n'Play, the benefits of debugging other people's code, how Ember is embracing the larger JavaScript ecosystem, and more. Topics include: 0:00 – What's hard about programming, why schools are bad at teaching math, and more 10:47 – Why computers should empower ordinary people, and how we can close the gap that exists between the technologically skilled and unskilled 22:12 – How the experience level of the median JavaScript developer affects tech choices made by the community 27:54 - The npm dependency graph and Yarn plug-n-play 36:24 – How to avoid making too big of a leap when improving software 41:58 – What Embroider is, and what problems it's focused on solving 46:10 – The three stages of Embroider and the V2 Addon format 1:00:15 – What Embroider enables, like tree-shaking unused Addon modules and route-level code splitting 1:21:08 – How to try Embroider out in your projects today 1:34:39 – How Ember is embracing the larger JavaScript ecosystem 1:39:35 - Why debugging other people's code is a great way to level up as a developer 1:48:28 - What Embroider's next steps are Links: Ed on Twitter Embroider Yarn Plug'n'Play
Panel: Dave Kimura Charles Max Wood Nate Hopkins Special Guest: Josh Justice In this episode of Ruby Rogues, the panelists talk with Josh Justice who is a developer, writer, and speaker. Josh streams JavaScript and web development on Friday’s at 2:00 PM (ET) here! The panelists and the guest talk about Josh’s background and frontend testing in Ruby. Check it out! Show Topics: 0:00 – Advertisement: Sentry.io 1:04 – Chuck: Hi! Dave, Nate, and myself are on the panel and our special guest is Josh Justice! I am developing a show about developer freedom and it’s called The DevRev. It will be streamed through YouTube, and I will record Friday afternoons. Check out Facebook, too! 2:11 – Josh: Thanks! I am happy to be here! 2:18 – Chuck: Introduce yourself, please! 2:24 – Josh: I have been a developer for about 14 years. I have used PHP and then got into Ruby and then frontend development. 2:46 – Chuck: You work for Big Nerd Ranch in Atlanta? 2:56 – Josh: Yep for the last 3-4 years! 3:15 – Chuck: Can you introduce the topic? 3:25 – The guest talks about Big Nerd Ranch and frontend development. Learn TDD is mentioned, too! Check it out here! 5:06 – Panel: How much bouncing do you do between React and Vue? 5:11 – Guest. 5:47 – Chuck: We need to get you on our podcast shows for React and Vue! It’s an approach that I am familiar with in Ruby – and Selenium what a pain! 6:16 – Guest: I’ve had a good experience with Cypress, actually! 7:47 – Guest: Panelist, can you share your experiences? 7:57 – Panel: Not bad experiences with testing, but now I am trying to minimize my use with JavaScript. 8:30 – Guest: I think there is a big push towards considering more server site rendering. 9:35 – Panel: What’s your recommendation to setup Cypress? 9:40 – Guest: Their docs are really great! They had some conference talks on how to set it up! 10:15 – Guest: Check out my talks about this topic. (Connect Tech 2018). 10:29 – Panel: I think Cypress is a pretty cool solution but one thing that left me confused is that you have to have an environment that is already stood-up and running. Is that accurate or has that changed? 11:00 – Guest: Can you clarify what you mean by a “running environment”? 11:04 – Panelist clarifies. 11:44 – Guest: Luckily for me I have something to say b/c I tried a week ago! 12:01 – Guest mentions Vue CLI 3. 14:38 – Panel: How can you test your code coverage? I want to know how much of my code coverage am I hitting? The applications are up and running, it’s not going through the files (per se), and is there anything that would indicate how good your coverage is with the Cypress test? 15:10 – Guest: Let me as a follow-up question: How do you approach it on the frontend? 15:24 – Panelist answers the guest’s question. 16:06 – The guest mentions Vue CLI 2 & 3. 18:31 – Chuck: Are you using the tool Istanbul? 18:36 – Guest: Yep Istanbul is the one! 18:54 – Chuck: I’ve heard some similar rumors, but can’t say. 19:02 – Panelist talks. 20:13 – Chuck: I have been working on a project and what doesn’t get test-coverage gets a candidate to get pulled-out. 20:40 – Guest: Talking about test-driven development... Guest: Have you read the original book? 21:02 – Guest: The book: “Effective Testing with RSpec 3” is updated information – check it out! The guest mentions his live stream on Friday’s. Check out the links found below! 23:57 – Panel: How is the stability with tests like Cypress with end-to-end tests? If you are testing with a login then the user has to be already created. Or what about a Twitter app – the user has to be created and not followed? How do you handle that? 24:22 – Guest: I think we are spoiled in the Rails world b/c of those... 24:53 – The guest answers the panelist’s question! 26:59 – Fresh Books! 28:07 – Guest: Does that help? 28:10 – Panel. 28:21 – Guest: I have been thinking about this, though, recently. Thinking about the contracts through the business. I have dabbled with native development and I see the cost that runs a native app. 30:21 – Panel: It’s refreshing to hear the new market’s demands. I truly haven’t seen an application that requires that. I have built some extensive applications and also very simple ones, too; the need for productivity. 31:17 – Guest mentions a talk at a conference. See here for that information! 31:43 – Guest: I have a friend who was a new developer and he really knows his stuff. He said that he didn’t know if he could be a full stack developer in the next 5-10 years. Wait a minute?! Guest: The freedom to create something that stands alone. Guest: Tom Dale is mentioned by the Guest. 33:35 – Panel: To choose Rails as a new developer (today) it’s not as easy as it was back in the day. Today you have Active Job, Action Cable and so many other components. It’s more complicated today then it was in the past. It could be overwhelming to a new developer. 35:00 – Chuck: I think a lot of that is the community’s fault and not Rails’ fault. 35:57 – Panel. 36:04 – Panel: The counter-argument could say that’s where server-less come in. 36:27 – Chuck: To some degree you can get away with it. You don’t have to worry about the infrastructure or anything else. 36:44 – Panel: Have you tried messing around with server-less functions with AWS? I have and...it’s not easy. There is not a good flow or good work flow in a server-less environment. 38:01 – Chuck: You can go to this website. It makes the setup easier b/c you are adding your Azure or AWS features. 38:30 – Panel: This topic, though, does tie back to the testing topic we were talking about earlier! 39:14 – Panel: Yeah that is why I haven’t gotten into server-less things. The Rails holistic approach is so appealing. 40:14 – Panel continues: I want to take smaller steps when it comes to technology! I want to move into things that we are laying down the tracks to make it easier travelable. That way we can consider the things we’ve learned in the past and help those in the future. 41:07 – Chuck: What are lacking then? What is the friction that is left? Seems like Cypress helped removed that but maybe not? 42:02 – Panelist mentions Cypress, Jest, Mocha, and others! 43:10 – Panel (continues): I am all about experimenting but I want to know all the reasons. What has changed and what hasn’t’ changed? 43:29 – Panel: There is an article written that talks about this topic. 43:59 – Guest mentions the video “Is TDD Dead?” (See links below.) 44:29 – Guest: I like brining thoughts together and taking his or her input and come up with my own thoughts. 46:32 – Guest (continues): The testing trophy is heavier on the top (picture of a trophy). Guest: I think the thing that draws me to unit testing is that... 47:37 – Guest: I am obsessed with testing. The guest gives a summary here! 48:15 – Chuck: We talked with Quincy Larson last week and it’s a really good take on what we are doing and what we are trying to accomplish with our tests. Check it out – it’s coming out soon! 49:05 – Panel: When you are younger into your career – the way you think about structuring your code – when you are comfortable you really don’t need that guidance. 50:00 – Guest: I would encourage folks who were new to coding to do the following... 51:36 – Guest: Think about WHY you are doing (what you are doing) and being able to articulate well what you are doing and why. 52:03 – Panel: There is no question – every time I test I am surprised how much it shapes my thinking about the code and how many bugs that I catch even in code that I thought was operating well. When you go too far though there is a fallacy there. 52:54 – Panel: Yes, testing is very important. I am a test-after-the-fact programmer. That is my self-key term. Don’t write 500-line methods b/c you won’t be able to test that. Don’t make it too abstract so have a common pattern that you will use. Have a lot of private methods that aren’t exposed to the API. 54:03 – Guest: Yes thinking about how to structure your code can be challenging at first but it gets easier. 55:58 – Chuck: I have had talks with Corey Haines about topics like this! 56:47 – Guest: Yes it can be helpful in consultancy now. 59:23 – Guest: Think about this: choosing what level to test at. 1:00:14 – Panel: It’s hard b/c it changes all the time per function or something else. There are tradeoffs with everything we do. 1:00:41 – Chuck: You are the consultant it depends doesn’t it? 1:00:51 – Picks! 1:00:55 – Advertisement: Get A Coder Job! End – Cache Fly! Links: Get a Coder Job Course Ruby Ruby on Rails Angular Cypress Vue React VUE CLI 3 Jest.io Mocha.js GitHub: Istanbul The RSpec Book RR 068 Episode Ember CLI GitHub: Factory_Bot GitHub: VCR Big Nerd Ranch Big Nerd Ranch: Josh Justice / Team Manager The Bike Shed Keynote: Tom Dale @ EmberFest 2018 JSJ 291 Episode Serverless Article: Test-Induced Design Damage Video: Is TDD Dead? Music: Sub Conscious – Electronic / 2004 Music: Interloper / 2015 Disney Heroes: Battle Mode Google Play: Disney Heroes / Battle Mode Book Authoring Playlist Tom Dale’s Twitter Corey Haines’ Twitter Coding It Wrong Josh’s Twitter Josh’s GitHub Josh’s LinkedIn Josh’s Vimeo Video Sponsors: Sentry CacheFly Fresh Books Picks: Nate Phutureprimitive - Sub Conscious Carbon Based Lifeforms - Interloper Dave Dust collections system in Wood Shop Doctor Who - Theme Music Charles Authoring music Disney Hero Battles Josh Effecting Testing with RSpec 3 Growing Object-Oriented Software, Guided by Test XUnit Test Patterns Spectacle App Alfred App
Panel: Dave Kimura Charles Max Wood Nate Hopkins Special Guest: Josh Justice In this episode of Ruby Rogues, the panelists talk with Josh Justice who is a developer, writer, and speaker. Josh streams JavaScript and web development on Friday’s at 2:00 PM (ET) here! The panelists and the guest talk about Josh’s background and frontend testing in Ruby. Check it out! Show Topics: 0:00 – Advertisement: Sentry.io 1:04 – Chuck: Hi! Dave, Nate, and myself are on the panel and our special guest is Josh Justice! I am developing a show about developer freedom and it’s called The DevRev. It will be streamed through YouTube, and I will record Friday afternoons. Check out Facebook, too! 2:11 – Josh: Thanks! I am happy to be here! 2:18 – Chuck: Introduce yourself, please! 2:24 – Josh: I have been a developer for about 14 years. I have used PHP and then got into Ruby and then frontend development. 2:46 – Chuck: You work for Big Nerd Ranch in Atlanta? 2:56 – Josh: Yep for the last 3-4 years! 3:15 – Chuck: Can you introduce the topic? 3:25 – The guest talks about Big Nerd Ranch and frontend development. Learn TDD is mentioned, too! Check it out here! 5:06 – Panel: How much bouncing do you do between React and Vue? 5:11 – Guest. 5:47 – Chuck: We need to get you on our podcast shows for React and Vue! It’s an approach that I am familiar with in Ruby – and Selenium what a pain! 6:16 – Guest: I’ve had a good experience with Cypress, actually! 7:47 – Guest: Panelist, can you share your experiences? 7:57 – Panel: Not bad experiences with testing, but now I am trying to minimize my use with JavaScript. 8:30 – Guest: I think there is a big push towards considering more server site rendering. 9:35 – Panel: What’s your recommendation to setup Cypress? 9:40 – Guest: Their docs are really great! They had some conference talks on how to set it up! 10:15 – Guest: Check out my talks about this topic. (Connect Tech 2018). 10:29 – Panel: I think Cypress is a pretty cool solution but one thing that left me confused is that you have to have an environment that is already stood-up and running. Is that accurate or has that changed? 11:00 – Guest: Can you clarify what you mean by a “running environment”? 11:04 – Panelist clarifies. 11:44 – Guest: Luckily for me I have something to say b/c I tried a week ago! 12:01 – Guest mentions Vue CLI 3. 14:38 – Panel: How can you test your code coverage? I want to know how much of my code coverage am I hitting? The applications are up and running, it’s not going through the files (per se), and is there anything that would indicate how good your coverage is with the Cypress test? 15:10 – Guest: Let me as a follow-up question: How do you approach it on the frontend? 15:24 – Panelist answers the guest’s question. 16:06 – The guest mentions Vue CLI 2 & 3. 18:31 – Chuck: Are you using the tool Istanbul? 18:36 – Guest: Yep Istanbul is the one! 18:54 – Chuck: I’ve heard some similar rumors, but can’t say. 19:02 – Panelist talks. 20:13 – Chuck: I have been working on a project and what doesn’t get test-coverage gets a candidate to get pulled-out. 20:40 – Guest: Talking about test-driven development... Guest: Have you read the original book? 21:02 – Guest: The book: “Effective Testing with RSpec 3” is updated information – check it out! The guest mentions his live stream on Friday’s. Check out the links found below! 23:57 – Panel: How is the stability with tests like Cypress with end-to-end tests? If you are testing with a login then the user has to be already created. Or what about a Twitter app – the user has to be created and not followed? How do you handle that? 24:22 – Guest: I think we are spoiled in the Rails world b/c of those... 24:53 – The guest answers the panelist’s question! 26:59 – Fresh Books! 28:07 – Guest: Does that help? 28:10 – Panel. 28:21 – Guest: I have been thinking about this, though, recently. Thinking about the contracts through the business. I have dabbled with native development and I see the cost that runs a native app. 30:21 – Panel: It’s refreshing to hear the new market’s demands. I truly haven’t seen an application that requires that. I have built some extensive applications and also very simple ones, too; the need for productivity. 31:17 – Guest mentions a talk at a conference. See here for that information! 31:43 – Guest: I have a friend who was a new developer and he really knows his stuff. He said that he didn’t know if he could be a full stack developer in the next 5-10 years. Wait a minute?! Guest: The freedom to create something that stands alone. Guest: Tom Dale is mentioned by the Guest. 33:35 – Panel: To choose Rails as a new developer (today) it’s not as easy as it was back in the day. Today you have Active Job, Action Cable and so many other components. It’s more complicated today then it was in the past. It could be overwhelming to a new developer. 35:00 – Chuck: I think a lot of that is the community’s fault and not Rails’ fault. 35:57 – Panel. 36:04 – Panel: The counter-argument could say that’s where server-less come in. 36:27 – Chuck: To some degree you can get away with it. You don’t have to worry about the infrastructure or anything else. 36:44 – Panel: Have you tried messing around with server-less functions with AWS? I have and...it’s not easy. There is not a good flow or good work flow in a server-less environment. 38:01 – Chuck: You can go to this website. It makes the setup easier b/c you are adding your Azure or AWS features. 38:30 – Panel: This topic, though, does tie back to the testing topic we were talking about earlier! 39:14 – Panel: Yeah that is why I haven’t gotten into server-less things. The Rails holistic approach is so appealing. 40:14 – Panel continues: I want to take smaller steps when it comes to technology! I want to move into things that we are laying down the tracks to make it easier travelable. That way we can consider the things we’ve learned in the past and help those in the future. 41:07 – Chuck: What are lacking then? What is the friction that is left? Seems like Cypress helped removed that but maybe not? 42:02 – Panelist mentions Cypress, Jest, Mocha, and others! 43:10 – Panel (continues): I am all about experimenting but I want to know all the reasons. What has changed and what hasn’t’ changed? 43:29 – Panel: There is an article written that talks about this topic. 43:59 – Guest mentions the video “Is TDD Dead?” (See links below.) 44:29 – Guest: I like brining thoughts together and taking his or her input and come up with my own thoughts. 46:32 – Guest (continues): The testing trophy is heavier on the top (picture of a trophy). Guest: I think the thing that draws me to unit testing is that... 47:37 – Guest: I am obsessed with testing. The guest gives a summary here! 48:15 – Chuck: We talked with Quincy Larson last week and it’s a really good take on what we are doing and what we are trying to accomplish with our tests. Check it out – it’s coming out soon! 49:05 – Panel: When you are younger into your career – the way you think about structuring your code – when you are comfortable you really don’t need that guidance. 50:00 – Guest: I would encourage folks who were new to coding to do the following... 51:36 – Guest: Think about WHY you are doing (what you are doing) and being able to articulate well what you are doing and why. 52:03 – Panel: There is no question – every time I test I am surprised how much it shapes my thinking about the code and how many bugs that I catch even in code that I thought was operating well. When you go too far though there is a fallacy there. 52:54 – Panel: Yes, testing is very important. I am a test-after-the-fact programmer. That is my self-key term. Don’t write 500-line methods b/c you won’t be able to test that. Don’t make it too abstract so have a common pattern that you will use. Have a lot of private methods that aren’t exposed to the API. 54:03 – Guest: Yes thinking about how to structure your code can be challenging at first but it gets easier. 55:58 – Chuck: I have had talks with Corey Haines about topics like this! 56:47 – Guest: Yes it can be helpful in consultancy now. 59:23 – Guest: Think about this: choosing what level to test at. 1:00:14 – Panel: It’s hard b/c it changes all the time per function or something else. There are tradeoffs with everything we do. 1:00:41 – Chuck: You are the consultant it depends doesn’t it? 1:00:51 – Picks! 1:00:55 – Advertisement: Get A Coder Job! End – Cache Fly! Links: Get a Coder Job Course Ruby Ruby on Rails Angular Cypress Vue React VUE CLI 3 Jest.io Mocha.js GitHub: Istanbul The RSpec Book RR 068 Episode Ember CLI GitHub: Factory_Bot GitHub: VCR Big Nerd Ranch Big Nerd Ranch: Josh Justice / Team Manager The Bike Shed Keynote: Tom Dale @ EmberFest 2018 JSJ 291 Episode Serverless Article: Test-Induced Design Damage Video: Is TDD Dead? Music: Sub Conscious – Electronic / 2004 Music: Interloper / 2015 Disney Heroes: Battle Mode Google Play: Disney Heroes / Battle Mode Book Authoring Playlist Tom Dale’s Twitter Corey Haines’ Twitter Coding It Wrong Josh’s Twitter Josh’s GitHub Josh’s LinkedIn Josh’s Vimeo Video Sponsors: Sentry CacheFly Fresh Books Picks: Nate Phutureprimitive - Sub Conscious Carbon Based Lifeforms - Interloper Dave Dust collections system in Wood Shop Doctor Who - Theme Music Charles Authoring music Disney Hero Battles Josh Effecting Testing with RSpec 3 Growing Object-Oriented Software, Guided by Test XUnit Test Patterns Spectacle App Alfred App
Panel: Dave Kimura Charles Max Wood Nate Hopkins Special Guest: Josh Justice In this episode of Ruby Rogues, the panelists talk with Josh Justice who is a developer, writer, and speaker. Josh streams JavaScript and web development on Friday’s at 2:00 PM (ET) here! The panelists and the guest talk about Josh’s background and frontend testing in Ruby. Check it out! Show Topics: 0:00 – Advertisement: Sentry.io 1:04 – Chuck: Hi! Dave, Nate, and myself are on the panel and our special guest is Josh Justice! I am developing a show about developer freedom and it’s called The DevRev. It will be streamed through YouTube, and I will record Friday afternoons. Check out Facebook, too! 2:11 – Josh: Thanks! I am happy to be here! 2:18 – Chuck: Introduce yourself, please! 2:24 – Josh: I have been a developer for about 14 years. I have used PHP and then got into Ruby and then frontend development. 2:46 – Chuck: You work for Big Nerd Ranch in Atlanta? 2:56 – Josh: Yep for the last 3-4 years! 3:15 – Chuck: Can you introduce the topic? 3:25 – The guest talks about Big Nerd Ranch and frontend development. Learn TDD is mentioned, too! Check it out here! 5:06 – Panel: How much bouncing do you do between React and Vue? 5:11 – Guest. 5:47 – Chuck: We need to get you on our podcast shows for React and Vue! It’s an approach that I am familiar with in Ruby – and Selenium what a pain! 6:16 – Guest: I’ve had a good experience with Cypress, actually! 7:47 – Guest: Panelist, can you share your experiences? 7:57 – Panel: Not bad experiences with testing, but now I am trying to minimize my use with JavaScript. 8:30 – Guest: I think there is a big push towards considering more server site rendering. 9:35 – Panel: What’s your recommendation to setup Cypress? 9:40 – Guest: Their docs are really great! They had some conference talks on how to set it up! 10:15 – Guest: Check out my talks about this topic. (Connect Tech 2018). 10:29 – Panel: I think Cypress is a pretty cool solution but one thing that left me confused is that you have to have an environment that is already stood-up and running. Is that accurate or has that changed? 11:00 – Guest: Can you clarify what you mean by a “running environment”? 11:04 – Panelist clarifies. 11:44 – Guest: Luckily for me I have something to say b/c I tried a week ago! 12:01 – Guest mentions Vue CLI 3. 14:38 – Panel: How can you test your code coverage? I want to know how much of my code coverage am I hitting? The applications are up and running, it’s not going through the files (per se), and is there anything that would indicate how good your coverage is with the Cypress test? 15:10 – Guest: Let me as a follow-up question: How do you approach it on the frontend? 15:24 – Panelist answers the guest’s question. 16:06 – The guest mentions Vue CLI 2 & 3. 18:31 – Chuck: Are you using the tool Istanbul? 18:36 – Guest: Yep Istanbul is the one! 18:54 – Chuck: I’ve heard some similar rumors, but can’t say. 19:02 – Panelist talks. 20:13 – Chuck: I have been working on a project and what doesn’t get test-coverage gets a candidate to get pulled-out. 20:40 – Guest: Talking about test-driven development... Guest: Have you read the original book? 21:02 – Guest: The book: “Effective Testing with RSpec 3” is updated information – check it out! The guest mentions his live stream on Friday’s. Check out the links found below! 23:57 – Panel: How is the stability with tests like Cypress with end-to-end tests? If you are testing with a login then the user has to be already created. Or what about a Twitter app – the user has to be created and not followed? How do you handle that? 24:22 – Guest: I think we are spoiled in the Rails world b/c of those... 24:53 – The guest answers the panelist’s question! 26:59 – Fresh Books! 28:07 – Guest: Does that help? 28:10 – Panel. 28:21 – Guest: I have been thinking about this, though, recently. Thinking about the contracts through the business. I have dabbled with native development and I see the cost that runs a native app. 30:21 – Panel: It’s refreshing to hear the new market’s demands. I truly haven’t seen an application that requires that. I have built some extensive applications and also very simple ones, too; the need for productivity. 31:17 – Guest mentions a talk at a conference. See here for that information! 31:43 – Guest: I have a friend who was a new developer and he really knows his stuff. He said that he didn’t know if he could be a full stack developer in the next 5-10 years. Wait a minute?! Guest: The freedom to create something that stands alone. Guest: Tom Dale is mentioned by the Guest. 33:35 – Panel: To choose Rails as a new developer (today) it’s not as easy as it was back in the day. Today you have Active Job, Action Cable and so many other components. It’s more complicated today then it was in the past. It could be overwhelming to a new developer. 35:00 – Chuck: I think a lot of that is the community’s fault and not Rails’ fault. 35:57 – Panel. 36:04 – Panel: The counter-argument could say that’s where server-less come in. 36:27 – Chuck: To some degree you can get away with it. You don’t have to worry about the infrastructure or anything else. 36:44 – Panel: Have you tried messing around with server-less functions with AWS? I have and...it’s not easy. There is not a good flow or good work flow in a server-less environment. 38:01 – Chuck: You can go to this website. It makes the setup easier b/c you are adding your Azure or AWS features. 38:30 – Panel: This topic, though, does tie back to the testing topic we were talking about earlier! 39:14 – Panel: Yeah that is why I haven’t gotten into server-less things. The Rails holistic approach is so appealing. 40:14 – Panel continues: I want to take smaller steps when it comes to technology! I want to move into things that we are laying down the tracks to make it easier travelable. That way we can consider the things we’ve learned in the past and help those in the future. 41:07 – Chuck: What are lacking then? What is the friction that is left? Seems like Cypress helped removed that but maybe not? 42:02 – Panelist mentions Cypress, Jest, Mocha, and others! 43:10 – Panel (continues): I am all about experimenting but I want to know all the reasons. What has changed and what hasn’t’ changed? 43:29 – Panel: There is an article written that talks about this topic. 43:59 – Guest mentions the video “Is TDD Dead?” (See links below.) 44:29 – Guest: I like brining thoughts together and taking his or her input and come up with my own thoughts. 46:32 – Guest (continues): The testing trophy is heavier on the top (picture of a trophy). Guest: I think the thing that draws me to unit testing is that... 47:37 – Guest: I am obsessed with testing. The guest gives a summary here! 48:15 – Chuck: We talked with Quincy Larson last week and it’s a really good take on what we are doing and what we are trying to accomplish with our tests. Check it out – it’s coming out soon! 49:05 – Panel: When you are younger into your career – the way you think about structuring your code – when you are comfortable you really don’t need that guidance. 50:00 – Guest: I would encourage folks who were new to coding to do the following... 51:36 – Guest: Think about WHY you are doing (what you are doing) and being able to articulate well what you are doing and why. 52:03 – Panel: There is no question – every time I test I am surprised how much it shapes my thinking about the code and how many bugs that I catch even in code that I thought was operating well. When you go too far though there is a fallacy there. 52:54 – Panel: Yes, testing is very important. I am a test-after-the-fact programmer. That is my self-key term. Don’t write 500-line methods b/c you won’t be able to test that. Don’t make it too abstract so have a common pattern that you will use. Have a lot of private methods that aren’t exposed to the API. 54:03 – Guest: Yes thinking about how to structure your code can be challenging at first but it gets easier. 55:58 – Chuck: I have had talks with Corey Haines about topics like this! 56:47 – Guest: Yes it can be helpful in consultancy now. 59:23 – Guest: Think about this: choosing what level to test at. 1:00:14 – Panel: It’s hard b/c it changes all the time per function or something else. There are tradeoffs with everything we do. 1:00:41 – Chuck: You are the consultant it depends doesn’t it? 1:00:51 – Picks! 1:00:55 – Advertisement: Get A Coder Job! End – Cache Fly! Links: Get a Coder Job Course Ruby Ruby on Rails Angular Cypress Vue React VUE CLI 3 Jest.io Mocha.js GitHub: Istanbul The RSpec Book RR 068 Episode Ember CLI GitHub: Factory_Bot GitHub: VCR Big Nerd Ranch Big Nerd Ranch: Josh Justice / Team Manager The Bike Shed Keynote: Tom Dale @ EmberFest 2018 JSJ 291 Episode Serverless Article: Test-Induced Design Damage Video: Is TDD Dead? Music: Sub Conscious – Electronic / 2004 Music: Interloper / 2015 Disney Heroes: Battle Mode Google Play: Disney Heroes / Battle Mode Book Authoring Playlist Tom Dale’s Twitter Corey Haines’ Twitter Coding It Wrong Josh’s Twitter Josh’s GitHub Josh’s LinkedIn Josh’s Vimeo Video Sponsors: Sentry CacheFly Fresh Books Picks: Nate Phutureprimitive - Sub Conscious Carbon Based Lifeforms - Interloper Dave Dust collections system in Wood Shop Doctor Who - Theme Music Charles Authoring music Disney Hero Battles Josh Effecting Testing with RSpec 3 Growing Object-Oriented Software, Guided by Test XUnit Test Patterns Spectacle App Alfred App
In this internal episode, Charles and Wil talk about testing issues and BigTest solutions. Pieces of the testing story are discussed, such as the start and launch application, component setup and teardown, interacting with the application and component, convergent assertions, and network. Then they talk about testing issues: the fact that cross browser and device-simulated browsers are not good enough, maintainability and when and when not to DRY (RYE), slowness and why (acceptance) testing is slow, portability and why tests are coupled to the framework, and reliability. Finally, they talk about BigTest solutions: @bigtest/cli to start / launch (Karma recommended for now) @bigtest/react, @bigtest/vue, etc for setup & teardown @bigtest/interactor for interactions @bigtest/convergence for assertions @bigtest/network in the future (Mirage recommended for now) Resources: Justin Searls – Please don't mock me This show was produced by Mandy Moore, aka @therubyrep of DevReps, LLC. Transcript: CHARLES: Hello, everybody and welcome to The Frontside Podcast, Episode 115. My name is Charles Lowell, this episode's host and a developer here at the Frontside. With me today to talk some shop is Mr Wil Wilsman. WIL: Hello. CHARLES: Hello, Wil. WIL: How's it going? CHARLES: It's going good. I'm actually pretty excited to get to jump into this topic because we're going to be talking about some of the big things that are happening at Frontside and some of the things that we've been developing in almost for the last year. WIL: Yeah. It's been about a year now. CHARLES: It's been about a year and we've talked about it in various podcast but we're going to be talking about it again because there's just been so much progress that we've made, I think in a lot of clarity in kind of what we're going for here when we talk about BigTest and testing big and how we want to roll out the BigTest framework. We just have a lot more experience using it on a number of different projects, so we get to talk about that today. Before we get started, I just wanted to talk a little bit about what BigTest is, both in terms of the framework and also the philosophy. Wil, you're the one who works the most on BigTest. When you think about philosophically, what does BigTest mean to you? WIL: It's the size of your test, not a physical size like size and storage but how much your task actually does. The test itself can be very small as our test are but it tests the whole application from the user interacting with it down to the network requests. That's the definition of the philosophy of a BigTest to me. It's to tests your application from the biggest point of view. CHARLES: Actually, achieving that can be surprisingly difficult, especially in a frontend JavaScript application and there are a lot of solutions out there for testing and we've talked about them. One of the questions that arises is when we talk about BigTest, what exactly are we talking about? Are we talking about a product that you can download and install? Are we talking about the philosophy that you just outlined? Or are we talking about the individual pieces of software that make that philosophy real? I think the answer is we're kind of talking about all three but we want to take this episode to talk about where we're going with the product. What we've identified is the subcomponent pieces of that product. In other words, in order to get started testing big, what are the things that you need to think about? What are the things that you need to do? And then what are the component pieces? Because one of the things that I think is very important to us is that you be able to arrive at wherever you are in your project, whatever framework you are using, whatever current testing solution and be able to begin using BigTest. That means, you might be using some of it or you might be using a lot of it but we want to meet you exactly where you are, so that you can then, get onboarded and start testing big. WIL: Yeah. Definitely an important distinction that we get confusion about is what is BigTests and people just assume like this whole test suite is BigTest but we used the parts of it ourselves like we use Mocha, which is not part of BigTest. We use Chai, which is not part of BigTest. We use Mirage which is kind of part of BigTest but definitely it originate in BigTest and Karma and things like that. BigTest isn't your testing suite. It's not one thing to go-to to grab, to start writing tests. It is a small pieces that you can use in conjunction with other small pieces, just to make it really easy and flexible to test your application. CHARLES: Exactly. Because it turns out that there's a lot going on in the application. Maybe we should talk about what some of those pieces are that you might want to start using BigTest with or that you might need to test big, I guess I should say. What's a good place to start? Let's start with talking about some of the issues that you want to do when your testing big. Then we can talk about what pieces of the testing story that fit in to solve those issues. One of them is you need to test that your application works, like actually works. That means you need to be able to test on a multiplicity of browsers, for example. We're limiting to the domain of web applications. There are actually a shockingly large number of browsers. It's not just Chrome. It's not just Safari. There's Mobile Chrome, Mobile Safari, which are subtly different. There's Edge and I'm sure the Mobile Edge is slightly different too, so you want to be able to test cross browser, right? WIL: Yeah, absolutely and things like Nightmare and JS DOM and things that simulated browsers, we don't necessarily think those are the best tools for writing BigTest because we want to ensure that those browser quirks are caught and tested as well. CHARLES: This is not theoretical like sometimes you'll have a syntax, like the parser is slightly different and you have something that throws a syntax error in Safari or in the Internet Explorer and your whole app is completely busted. If you just take in the time, just even trying to load the app in that browser, you would have caught that. That's what I've been on many times. WIL: Yeah and what I just saw came up yesterday, which comes up frequently is not closing your CSS Selector and Chrome doesn't really care like web to browsers don't care too much but that will fail in Edge and depending on what you're missing, the failing is part of that too but mostly, Firefox and Chrome don't care about that kind of thing. CHARLES: Right. It seems like the majority of testing solutions are kind of focused around Headless Chrome or some variation of Electron. That entire class of really dumb errors has already been caught. Like I said, to actually catch it, it takes less than a millisecond of CPU time just to load it onto the browser and see that thing doesn't work. Unfortunately, they can be catastrophic errors but the problem is how do you actually do. We want to test like cross browser. This is something that we want to do. For me, I just can't imagine shipping an application without having some form of cross browser testing, some capability of being able to say, "I want to test it," like, "We want to work on these eight browsers and so we're going to test it on these eight browsers," but how do you actually go about doing that? WIL: Right now, we are working on the BigTest CLI which will help us launch browsers but that's not complete yet. It has some bugs on. For the meantime we've been using Karma, which is great. Basically, you just have this service that's able to find the browser binary on the system and just launch them pointing to local hosts with your app loaded up and your normal development server take care of loading the test up and running the test. Karma and the BigTest CLI is just there to capture output and launch those separate browsers. CHARLES: Yeah. I remember when I was first using working with Karma and I think Testim is another tool that's in this space. There's Testim, Karma and BigTest actually is we're developing a launcher because launching is something that you're going to need but it's such a weird problem. I feel like with the browser launchers, there's three levels of inversion of control because you're starting a server that then starts another process, which then calls back to your server, which then loads the app resources, which then loads the tests and then runs the test. There's a lot of sleight of hand that has to happen and – WIL: Including injecting the adapter that you use, like the Mocha adapter, the Jasmine adapter that ends up reporting back to the CLI. That's something that Karma and Testim and BigTest will handle for you. CHARLES: Right, so you're fanning out the test suite to a suite of browsers then collecting the results but basically, you need some sort of agent living inside the browser that's going to act on behalf of the test suite, to collect the results. I remember when I first came into contact with Karma and Testim, I was like, "This is so unnecessarily complex," but then, having used it for a while and I think there are some complexity that can be removed but if you want to do cross browser testing, that kind of level of ping-ponging is there's a certain amount of it that just necessary. It's something that's actually quite complex that you need to have in your stack, in your toolbox, if you want to truly test big. WIL: Yeah and all the solutions is mechanisms for detecting when the browser has launched and restarting the browser based on its health check, etcetera and things like that that you wouldn't think of actually loading up a browser but you need to think of when you're doing automated testing. CHARLES: What is it that sets apart, for example the launcher solution? We kind of call this class of solutions launchers, so Testim, Karma, the BigTest CLI. What is it that sets BigTest CLI apart from say, Karma and Testim? WIL: We're trying to be as minimal config as possible and just really easy to get started and going. Karma has a lot of plugins that you need to make sure you have installed and loaded in the options set for those plugins. Testim has some stuff bundled but it still requires this big config bulk at the beginning that you need to passing or that's all what you were doing. We're trying to avoid that with BigTest CLI and one of the ways that we're able to avoid that is by just letting your Bundler handle bunding the test. In Karma, you need Karma webpack or something. Testim has some stuff that it needs and really, we just want like in-testing mode. When you're in the testing environment, just change your index to point your tests, instead of your application and your Bundler will do all the work and we just serve that file and collect the results. CHARLES: Right, so it doesn't matter if you're using Parcel or you're using webpack or you're using Ember CI. WIL: Yeah, Rollup even. CHARLES: Or even just like low level Broccoli or Gulp or whatever. There's a preponderance of bundling solutions and that was always something that was just a huge pain in the butt with Karma. I know it's like just getting to the point where my tests are loaded and you look with Testim, most of my experience come with Testim comes through how it's used in Ember CLI like the histrionics that undertaken just to bundle all your tests assets and your application assets and your vendor assets and just kind of bootstrap that thing. It's a lot of work. WIL: Another thing with BigTest CLI that doesn't include in Karma and Testim does is a concept of a watcher because all these Bundlers, you have HMR -- hot module reloading, Rollup and things like that. It come with plenty of plugins. Parcel is always set out of the box, so if you're using your Bundler, your existing Bundler to bundle your test, you get that watch feature for free, so it's another complexity that the BigTest CLI kind of eliminates. CHARLES: What it means is we've hidden most of that complexity. Just let the Bundler handle it, right? The Bundler is the part of your project that bundles. WIL: Yeah. CHARLES: You should have your launcher actually doing that for you but we still do need to have some way to do that set up and tear down. When we have that testing endpoint, we have some way to say, "We're starting a test, not the application. We're ending the test, tear it down," so how do you abstract that away? WIL: That's kind of something that we can't really avoid. It is just like some sort of dependency on the framework itself, your application framework. It's like you need to mount a React app. You need to mount an Ember app, etcetera and there's different ways to mount those things. This is one of the things that can't really be decoupled as much as everything else can but BigTest has BigTest React and BigTest Vue and we want to eventually gets like BigTest Ember but really, the main export of all these packages is just a simple mount helper that will mount and clean up your application for you and your testing hooks, whether you're using before each from Mocha or before from something else like Jasmine. You know, no matter what you're doing, you just have a hook that mounts your application and then, cleans it up on the next mount. CHARLES: It's worth pointing out here that this is kind of a core concern of testing and testing big is being able to mount your application and tear it down with regularity and having hooks into that process. Whether you're using BigTest or whether you're not, can you still use BigTest React and BigTest Vue, even if you weren't using anything else? WIL: Yeah, absolutely. Like I said, they just export simple mount helpers. I don't even think they have any other inner BigTest dependencies. They just have pure dependencies on their frameworks. CHARLES: Right and so, you could use it, even if you wanted to roll everything else by hand or you wanted to get started somehow and you needed to do set up and tear down, again this is something that's key to being able to test big, so you should be able to use it independently, whether you use the CLI or not, whether you're using any of the other tools or not. All of the tools can be used independently. WIL: Then another feature of the BigTest React and BigTest Vue is the tear down that happens before set up, rather than happening after your test runs, having a separate tear down. This allows it. Whether your test passes or fails, you can look at it and play with it and inspect it and debug it much easier than if you had tear down. You have to disable at tear down or throw a pause in there to keep other or something. CHARLES: Yeah, I love that. When something goes wrong, you can just let the test case run and the last test that it runs, it just leaves at set up. It does the tear down right before the set up. WIL: Exactly, yeah. At the very end of the whole test run, there's an app there waiting for you to play with. CHARLES: If you focus in on a single test, we most commonly use Mocha, so you say a '.only' to run that single focus test, then you have the state of the application at that test case set up and ready to go. You can just play with it, you can inspect it, you can actually just use it as a starting off point and interact with the app normally as you would. WIL: I want to say, Cypress does this too. They do their tear down before they're set up as well. That's how you're able to play with Cypress test. CHARLES: Yeah, I like that trick. Now, we talked about launching, setup and tear down but we haven't actually talked about much of what actually happens in the test cases themselves. We talked about how to start and launch your test suite, how to do that across a bunch of different browsers, how inside of that, you have a separate concern as applications set up and tear down and how you want to lean on how you're actual app is actually bundled because that fits in with the philosophy of testing big. You don't want to use an external Bundler for your test suite. You want to use your real Bundler, how the asset is actually going to look. But when it comes down to actually writing the tests, you need to be able to interact with at the highest level as you possibly can. When I say highest level, we want to verify that the users, when they take certain actions, we'll see certain outcomes and so, we want those outcomes and we already talked about this to be reflected in a real DOM, in a real browser. But at the same time, the real interactions, we want those to be as high fidelity as possible, so you want to be sending events to the browser. You want real mount events, real key events, real interactions. WIL: Yeah, interacting with application. That's another core philosophy that we kind of talked about earlier that defines a BigTest. It's the user interacting with your application. We're not calling methods and expecting other callbacks or arguments to be passed or clicking on a button and expecting a message to pop up that says, "Form submitted successfully." These are user-facing things were starting on and acting on. CHARLES: Yeah and then, it can be really tricky because these things don't happen synchronously. They're happening inside of your browser's event loop. I click that button and then it goes off and there's some loading state and then, I might get an error message that pops up this thing that animates out and then, goes away. The state of the browser is in constant flux. It's constantly changing and so, it can be very difficult to put your finger and say, I want to be in this state if you are limiting yourself to only reading from the DOM. Some frameworks, Ember for example, you have kind of a white box where you can actually inspect the state of the Ember run loop and use that to do some synchronization but it can be very, very hard to coordinate these interactions. WIL: Yeah. You know, to talk about getting to the solution as a BigTest interactor, which is basically modern page components or page objects. If you ever heard of page objects, it's just a way to encapsulate interacting with big pieces of your pages. It's not a new concept. It's been around for a while but BigTest interactor has kind of a new twist on it where they're immutable, composable interactions that are also convergent, which we'll get into later, which basically means if your buttons not there, it won't click the button until it is there. They're really powerful and they're making really easy and fun to write these tests. CHARLES: Yeah, they're super powerful. I remember we talked about convergences last time when we talked about BigTest but interactors, I think are definitely a new development. I think we should spend a little bit of time there talking about, not just the power but also the ergonomics of interactors because they are like page components or page objects, except they're scope to the component. Not only do they have all this wonderful stuff where it'll make sure that the component exists before it starts to interact with it and things like that but their composable. If I have a button, then there are certain operations that are valid for that button. I can click it. I can hover over it. I can do all these things. They're the operations that make it unique to the button. Now, those might actually map to real events. WIL: Similarly, their assertions about that button as well, like as primary is secondary. If this button is repeated throughout your application, you might want to make sure that your form has a primary and secondary button. CHARLES: Exactly. It really encapsulates all the knowledge of how you can interact with both in terms of taking action and reading state from that button. It almost feels like an accessibility API. It would be easy to write a screen reader if you had these interactors for every single component on the page. WIL: That's kind of what it is. It's just like you're defining an API around how your user would interact with your application and what your user would expect in the application. That's the point of page objects and interactors as you're defining this user API, essentially. CHARLES: Yeah and so, really the step that interactor take is that they take the classic page object and it make them composable, so I can have, you kind of touched on this before, a modal dialogue interactor, which is composed out of two button interactors. One for the primary action, one for the secondary action and maybe, it's aware of its own title text, so you can assert on the title text but I didn't actually have to write the individual button interactors for that modal dialog interactor. Then I might have a second modal dialog interactor or a form that's on a modal dialog just composed of the modal dialog interactors and the individual form components, which appear on that particular modal dialog. WIL: It's essentially how we've been building applications lately with components but this is for page objects in your test if you want to mirror that. You don't have to have one-to-one mappings of an interactor to a component but if you do, it's really powerful. CHARLES: Yeah. I found that when we have one-to-one interactors, that's when it just feels the best. WIL: Yeah and on top of this, if you have a component library and your component library exports the interactor that it uses for the component test, like we said, this BigTest technology, they're sprinkled also. We don't have to use interactors in big acceptance tests. We can use them for smaller component tests too, so if we ship these component interactors with the component library, your application that's consuming this component library now can test those components for free, without having to write their own interactors. It can just compose the interactors exported by the library. CHARLES: Man, I almost want you to repeat that word for word again, just so it can sink in. It's so awesome. Because when you actually go to write your tests, you're not starting from ground zero like, "How do I do this?" They're like, "I'm writing some tests for this thing and I'm using these components and so, I've already got the prepackaged interactions for those components." It's like you start writing your tests. If your tests are a 10-story building, it's like you're starting on Floor 7 and you only have to walk up to Floor 10, instead of slogging up all 10 stories. WIL: One really helpful interactor that we work within the open source stuff we've been working on is a date-picker interactor because date-pickers can be really complex. Just having that common interactor and have a date-picker on multiple forms where we can just use that one interactor, we don't have to tell every single test how to interact with that date-picker. We just say pick date and pass the date. CHARLES: Yeah, it's so awesome. That is actually a great example. It doesn't feel scary to write a test for a page that has a date-picker on it or two. If you're doing like a date range or something like that, you're like, "Oh, my God. I don't write the selectors to test this." You just import your date-picker interactor, you set the date, it actually worries about all the low level events and there you go. It feels like you're operating at a much higher level. WIL: Yeah. The interactor API essentially, you're telling me the test what the user would be doing and what the user would be seeing. CHARLES: Yeah. It's worth pointing out again. We've identified starting and launching. We've identified set up and tear down but interaction is a core concern of BigTesting, no matter what tool you're using. One of the things that we found as interactors are something that you can sprinkle on literally any test suite if you're testing an interface and it makes it better. We've used it inside big acceptance tests. We use it inside Jest, doing just little component tests. There are people in the BigTest community who have used it to basically, write component tests against a JS DOM and while theoretically, philosophically, you want to make those tests as big as you possibly can, you can use that piece in your test suite. If you are using a simulated DOM and if you're running a node in a browser, these interactors will still work and you're going to get high fidelity test cases that are resilient to this asynchrony and are composable and if they do have a full-fledged test suite, you can reuse these interactors. They are a really awesome power up that you can bring into your test suite. WIL: And they are not tied to the framework at all. We use them in React for our stuff but we've also written some in Ember. Robert's written some in the Vue and ported some test and one of the beautiful things we've seen from this is that one interactor goes everywhere. You just write the interactor once and you can use it in Ember, in React, in Vue, in those test suites. If the rest of your test suite is framework agnostic, you have this test suite that you can jump frameworks in your test suites until it works and can test your application with high fidelity. CHARLES: Yeah, it's fantastic. I remember when we first tried using interactors inside an Ember test suite because Ember comes with like a big kitchen sink in testing set up but interactors just slotted right in and there's absolutely no issue. WIL: Yeah and there is actually a speed boost even because in most of the Ember test offers a hook into the Ember run loop and interactors are not. There is actually a good speed boos just using interactors. CHARLES: Yeah. This is a good point. It's a good segue because typically, we think of acceptance tests as being really slow and one of the reasons, even the people [inaudible] acceptance tests or testing big as they think like it's going to take a long time. We found that actually we've been able to maintain a happy medium of testing big but also, having those test be really, really fast. When you say you said a speed boost from using interactors with Ember, where is that speed boost actually come from? WIL: I mentioned the Ember test offers a hook into the Ember run loop and interactors aren't and the reason of this is because interactors are converging and they wait for things in the DOM to exist before interacting with them. Instead of waiting for the framework to settle, it just waits for the thing to appear and then interacts with it immediately. If you're starting something about a button toward the top of the page, you don't really care that another button at the bottom of the page has rendered yet, unless of course you have assertion about that but if they're converging, you don't need to hook into the wrong loop to wait for the entire page to load, to interact with just one piece of it. CHARLES: Right. You're just waiting and you say, "I'm expecting something to happen and the moment I detect it, no matter what else is going on, the page could be taking 30 seconds to load but if that button appears and I can interact with it, I can take my action then or I can make my assertion then." It's about kind of removing gates -- artificial gates. WIL: Yeah. Another common thing that's helped with is animations as most test that are hooked into the run loop, you kind of have to wait for some of these animations to finish before you can even interact with the element and that means if a model has a half second animation where it flies in and you have 30 tests around this modal, those tests are extremely slow now because you have to wait for that modal to come in, whereas -- CHARLES: -- Straight up flaky. WIL: Yeah, straight up flaky. Whereas in the actual DOM, that modal is inserted pretty immediately and can be interacted with pretty immediately. With interactors, they don't need to wait for the animation to finish. They can just immediately interact with that modal but of course, if you need to wait for the animation to finish, there are options for that as well. CHARLES: Yeah. If there's some fade in that needs to happen, you can kind of assert on any state and as long as it's achieved at some point, the interactor will recognize it and recognize it at the soonest possible time that it possibly could. I remember getting bitten on one project where the modal animations in particular were so brutal. Not only were they flaky, they just were slow because there was all these manual time outs. It wasn't even a paper cut. It was kind of like a knife cut, like there's someone sitting there and kind of slashing you with a pocket knife. It just was a constant source of pain in your side. WIL: Yeah and that's how you end up with things like waits and sleeps in your test suite. When you need to wait for the animation to happen or something, you just see a sleep for four seconds with a comment because we have to wait for the components to load in. That's kind of a code now. CHARLES: Yeah, that's just asking for trouble both in terms of slowness and in terms of it's going to get flaky again. That has been kind of one the most freeing things about working with interactors and working with convergent assertions on which they're based is you just don't ever have to worry about asynchrony. Really, really truly, most of the time, you're writing your tests, like it's all synchronous and that kind of makes sense because from the user's perspective, their consciousness is synchronous and they don't care about the internal run loop. It's just they were making observations in serial and at some point, they're going to observe something, so the interactor sits at that point and really observes the application the way that your user would. WIL: Yeah. We've mentioned a few times now the convergent assertions, which interactors are based on. A little caveat there if you're using interactors and you're making non-convergent assertions, they might fail or be flaky. That's because interactors wait for the thing to be there to interact with, so as soon as the buttons there, it clicks it but it doesn't wait for after that event has fired and your application has reacted to that event, that's your application is concerned. We need something there like our convergent assertions that can converge on that state and wait for that state to be true before it considers itself passing or in times out. CHARLES: Maybe we should dig a little bit into convergent assertions. I think the last time we had a public conversation on the podcast about this, this is kind of where we were, like we hadn't built the interactors, we hadn't built these other component pieces of the testing story. We were really focused on the convergent assertion. We've talked a little bit about this but I think it's worth rehashing a little bit because it's a unique way of approaching the system but it's also kind of horrifying when you see how it works under the covers. I think when we tell people about the fact that it's basically polling underneath the covers. The timeout is configurable but it's basically polling every 10 milliseconds to observe a state. I remember the first time being confronted with this idea and I was horrified and like my programmer hackles on the back of my neck, like raised up and I was like, "Wait a minute. This is going to be slow. It's going to be computationally intensive." WIL: Yeah. That was my exact thought too because this is going to be slow. If acceptance tests are slow and we're doing an acceptance test every 10 milliseconds, it's going to be really slow and that's actually not the case completely. It's actually the opposite. They're extremely fast. CHARLES: It is shockingly fast. You've got to try it to believe how fast it is, how fast you can run acceptance tests. WIL: Yeah, talking like 100 tests in just tens of seconds. CHARLES: Right. You basically gated by how fast your framework can render. Your tests are not part of the slowness. Your test -- WIL: And also, memory leaks can be costly too. We experience that recently where we had memory leaks that were slowing down our test but we fixed those up in test and put our backup. CHARLES: Yeah, because basically, running the assertion or running the convergence is very fast. It's just a very light ping. I kind of think of it is as it is light as the brush of a photon or something that was bouncing off of a surface, so that you can observe it. It's extremely light and most of the time, it's just waiting so the test and the convergence really just gets out of the way. Just because they can run a thousand times or a hundred times in a second, it's doesn't gun it up. But the thing is it means that your tests run as fast as your application will run. You get back to the point... Was it in React where the kind of the key insight is that JavaScript is not the bottleneck? Well, your tests are not the bottleneck. WIL: Yeah. CHARLES: I guess this is what it is. I don't know if there's anything else that you want to say about convergences. WIL: No. We pretty much summed it up there and that's what interactors are based on. That's how they're able to wait for things in a DOM. It basically polls the DOM until it exists and then it moves on and actually does the interaction. CHARLES: Once again, this is actually a very low level thing on which BigTest is based but this is once again, something that you can use independently. You can write your own convergent assertions. You can write your own convergences that honestly have nothing to do with testing your assertions. It's a free standing library that you can use in your test suite or elsewhere should you choose. WIL: That doesn't need to be a DOM for BigTest convergence there. I use BigTest convergence in BigTest CLI to converge on the browser being launched. Instead of waiting for the browser to report that, I can just kind of poll and see how that process is doing and the convergence waits for that process to start before moving on. CHARLES: Right. I guess the best way I've thought about it it's a way to synchronize on observations and not on callbacks. It's a synchronization mechanism and 99% of the synchronization mechanisms that we're used to, they've involved some sort of callback, a promise, an event-listener, things like that or even a generator where control is handed back explicitly to a piece of code when something happens. Whereas, this is a fundamentally different synchronization primitive, where you are writing synchronous code that's based on observations, so what I observe this, do this. When I observe this, do this. It's extremely robust. WIL: Yeah, very. CHARLES: It is a core piece. A fundamental thing that on which interactors are based on, which the CLI is based, I don't know if it's core to writing tests but -- WIL: It definitely helps. CHARLES: It doesn't helps. We couldn't have BigTest interactor without that. WIL: No, definitely not. CHARLES: Because that's what makes it fast, that's what makes it not flaky at all and having those things, I think it makes it easy to maintain because you can work at the interactor level or the level of user interaction and you don't have to worry about synchronization, so the flow of your tests are very natural. WIL: Yeah. We don't have to explicitly wait for request to be done for making an assertion about your app. That'll just come with convergences, just waiting for test date in application to true. CHARLES: Let's talk about one more piece of the testing issue because when you're testing big, when you're testing in the browser, there's always the issue of what are you going to do about your API. You got to have your API running. It's just always an issue and this is kind of interesting because this sits at the crossroads of testing big and also, getting the most utility out of your test because in an ideal world, if you're testing really big, you're going to be using a real API. You're not going to poke holes in reality. WIL: Yeah. One of the things that we avoid in BigTest is poking holes. We're not shallow mounting the components and testing the methods and the results. We're fully mounting these things and fully interacting with them through the full DOM API. CHARLES: Yeah, exactly, using real browsers. It just occurred to me the irony of us talking about reality being things that are still running inside of a computer processor. I think we've inherited this term from that talk that Justin Searls at AssertJS in 2017. It's a really, really excellent talk. I think he gave it at RubyConf. It's the 'Don't mock me.' WIL: Yeah, it's one of my favorite talks. CHARLES: Yeah, it's a great talk. In it, he talks about the value of a test is a balance of how many holes you poke in reality and sometimes, you encounter a test where all it is like holes in reality. Whether you're mocking this, you're mocking that, you're mocking the DOM, you're mocking the browser, you're mocking your network layer, you're mocking this external API and the more holes you poke, the less useful it's going to be. Network is one of those where it can be very difficult to not poke holes in that reality because it's a huge part of your application. Your frontend application is how it's going to interact with the server but at the same time, servers are gigantic pieces of software themselves, each with their own dependencies, each with their own set up and tear down -- WIL: Have their own concerns. CHARLES: Yeah, exactly. They might be in a different language. They've got runtime, things like they might need external C libraries and crazy stuff like that. They're their own beast. To get a true big end-to-end test, you going to have to stand up your server but the problem that presents is you want your tests to be also isolatable. If you're a developer, I can go to a repo, I can do an install of my dependencies and I can run the tests without having to do any external dependencies other than the repository and the language in which I'm working. This is one where we kind of have tried to walk the line of not wanting to poke holes in reality but also, have the test be containable to the actual application. In order to do that, you need something that presents a high fidelity version of the network. You can kind of try and have your cake and eat it too. You want to have something that acts like a server and really acts like a server but it's actually not a server. WIL: And still poke as few holes as possible and the application and how that's all set up, we don't want to be intercepting methods and responding with fake data. That's not a good way to mock that network. CHARLES: Right. We want to be calling actual fetches, calling actual XMLHttpRequest. Ideally, if you've got service workers, making actual service worker requests. WIL: Basically, as far as the application is concerned, it's talking to a real server on us. CHARLES: Yeah and that's kind of the litmus test for is it a hole in reality or is it just a really great illusion? WIL: Yeah and that's a good name for Mirage, right? It's a really great illusion. CHARLES: Yeah. It is a simulation of reality, so we use Mirage, which is something from the Ember testing world but something that we have extracted and made available as BigTest Mirage. WIL: Yeah. The main difference just being is that we've taken away the Ember dependencies and the run loop stuff. It's just plain JavaScript Mirage. It works exactly the same as you use it in Ember minus the auto imports and the file... Oh, man. I can't think of that word. Aside from automatically importing your files for your server config, you have to do that manually because Ember is what provides that but other than that, it's a form of Mirage. You define models and serializers and factories and all the good stuff. CHARLES: Right and then you can use those factories and you can use those models to really give a high fidelity server. If you are building something in whatever framework, you can use BigTest Mirage to simulate that network layer. Again, we've used it in a number of different scenarios but having that in place means that you're going to be able to have those high fidelity tests where your application is actually making XMLHttpRequest but it's all isolatable, so that it can be run in repo. This isn't really related to testing but it has a fantastic capability where you can prepopulate, you can use the factories to prepopulate your server with data, so that you can use the application without the actual server being implemented. WIL: Yeah. That's extremely powerful. That's we were talking about earlier and getting at is the scenarios which are setting up specific, essentially fixtures but you're generating these fixtures. Factories are essentially high level fixtures, network of fixtures. CHARLES: Yeah, higher order of fixtures. WIL: Yeah, so the scenarios are just setting up these fixtures for a scenario of your applications, like the backend is down or the list only responds with two items as opposed to 5000 items, something like that. You want to be able to, not only test these things but be able to develop against it and Mirage makes that really easy because you can just start your app with Mirage-enabled point to that scenario and you're there. You have that exhausted scenario to develop in. CHARLES: If you've never used Mirage, it is really hard to understand just how incredibly powerful it can be. We've used it now on at least four projects, where we did develop the entire first version of the product without any backend whatsoever. It's an incredible product development tool, even apart from testing, that then informs the shape of what the API was going to be. I know we've talked about this on the podcast before but it's really an incredible technology and it is available to you no matter what framework you're using. I think it's one of the best kept secrets in JavaScript development. WIL: Yeah. That's definitely great. That said, though it does have some fallacies. It's great but it can be a little slow sometimes, so we are eventually working on a BigTest network like another piece of the BigTest pie that you'll be able to sprinkle into your application but in the meantime, praise Mirage. CHARLES: Yeah. We are going to be offering an alternative or maybe collaborating for another version of Mirage but hopefully, we can make Mirage faster, we will be able to make this thing faster, so that it can use service workers and be used in a bunch of different scenarios. Just to recap, we've talked about a lot of different components but over the past year, a couple of years, these are the things that we've identified as being really key components as big part of your acceptance testing and really your testing stack. How you're going to start and launch these things? How are you going to set them up and tear them down? How are you going to interact with the application from a user, both in terms of making assertions and how are you going to take action on behalf of the user and still have it be maintainable, have it be resistant to flakiness, have it be performant? BigTest is the answer to that for those particular areas of the testing story and so, some were using we're using existing components like we use Karma, we use Mirage to date. Those, we did not develop but where we see kind of key pieces of that puzzle missing is where we started writing the BigTest solutions so things like the interactor. Eventually, we are going to make BigTest into a product that's you're going to be able to use kind of out of the box, just like you might install Cypress, where it's a very quick set up and we make all of the decisions about the components for you. But in the meantime, we're really trying to take our time, identify those pieces of the puzzle and build the software component that fits that piece of the puzzle at the absolute best so when they're polished, use them in a more comprehensive product. Things like convergence, things like interactor, things like BigTest React, BigTest Vue and very soon, BigTest Ember. These are things that you can use today, to make your tests just that much bigger and that much better, especially interactor. It's been an incredible journey this past year as we kind of develop these individual pieces and there's just going to be more goodness to come. WIL: Absolutely. Right now, I'm working on some validation type API for interactor that I'm hoping to land soon. That'll open up the possibilities of maybe hiding away those convergent assertions a bit more in your tests and just handling this automatically. It'll be pretty good. CHARLES: It's really exciting. Writing test has got more and more easy and more and more fun over the last year for us. I think we're already starting in a pretty good place. If you have any questions about BigTest, how would folks get in touch with us? WIL: We have a BigTest Gitter channel. You can find a link to that on the BigTest website: BigTestJS.io. Just ask us questions on Gitter and we'll try to answer them. CHARLES: And as always, you can ask us directly. You can send email to Contact@Frontside.io or reach out to us on Twitter at @TheFrontside or you can actually reach out to the BigTestJS Twitter account directly and just call us on Twitter at @BigTestJS. Thank you very much, Wil. WIL: Thank you, Charles.
Sam and Ryan chat about what to do when a node module breaks in FastBoot, how to best wrap 3rd-party libraries in an Ember Addon, and how to test the filesystem. They also answer some listener questions. Topics: 0:00 – Node modules in FastBoot 13:55 – Ember Addons that wrap 3rd-party libraries 19:07 – Testing the filesystem with Broccoli Test Helpers Q&A: 32:11 – How can I speed up my Ember CLI build times? 38:31 – What do you think about the Angle Bracket Polyfill? Would you use it? 42:08 – I'm building an app and I need to build it with skeleton screens. Do I use a model hook with loading states, do I use Ember Concurrency tasks? What approach should I take? 46:44 – I'm building a table, and each row has a bunch of CRUD actions – edit, delete, view. What are the best UI patterns for this? A few I'm considering: a cog that you click that exposes a dropdown menu; icons in the row; buttons in the row.
Toran talks to Sam and Ryan about his project Ember CLI Hot Loader, which is an implementation of component-based hot module reloading for Ember apps. Topics: 0:00 – Losing hot reloading when moving from handwritten CSS to functional css 2:16 – Why Toran wrote the Hot Reloader 4:45 – How the hot reloader leverages Ember CLI to reload components 8:31 – The need for hot reloading 14:56 – Are there situations where you don’t want to use the hot reloader? 19:05 – What’s the easiest way to try using the hot reloader today? 21:05 – Design vs. build mindset 22:30 – Engines aren’t currently supported 23:53 – How local state affects hot reloading 27:50 – Fast feedback is the primary motivation 34:05 – What are the next steps for Ember CLI Hot Reloader? 37:51 – What happens to a component’s transient state if it’s hot reloaded? 39:44 – How to help if you’re interested in hot reloading in Ember Links: Ember CLI Hot Loader Toran’s side-by-side hot reloading demo Bret Victor, Inventing on Principle
Robert and Tom join Sam and Ryan to chat about how LinkedIn uses Ember, when teams should use Engines, build optimizations that are coming to Ember CLI and more. Topics: 0:00 – Engineering challenges of scale at LinkedIn 6:00 – Engines at LinkedIn 8:40 – When should teams use Engines? 15:25 – What are some of the downsides of Engines? 17:38 – Build-time versus AOT library transpilation 21:47 – How just-in-time compilation relates to code-splitting and importing node modules 29:50 – Ember’s philosophy on bringing new JS features to years-old apps 32:55 – How can the community be most helpful when contributing to Ember? 41:32 – Analytics and performance tracking at LinkedIn 46:07 – What are your thoughts on Vue.js? (Question from jamiewhite) 52:18 – How can we help improve the developer experience of using Handlebars templates (autocomplete, error correction, template linting, etc.)? 1:02:40 – Moving questions from Slack to the Discussion forum
How do we ensure a high level of quality and maximize the refactorability of our code? Frontsiders, Wil and Charles, talk about their battle tested techniques for testing web applications, not only in React JS, but in any JavaScript framework. Links Acceptance Testing Integration Testing jest Cypress.io Assertion Ember CLI Mirage mirage-server react-trigger-change Transcript CHARLES: Hello everybody and welcome to The Frontside Podcast, Episode 90. My name is Charles Lowell, a developer here at The Frontside and your podcast host-in-training. And with me today is Mr. Wil Wilsman. Wil, who just got back from Nodevember just walked straight into the office and is ready to podcast with us on a very, very, very interesting subject, I think, today. We're going to be talking about acceptance testing in JavaScript applications, especially some of the techniques that we've developed here around testing React applications based on the lessons that we learned from the Ember community. But really, more than just React applications. Really, testing any JavaScript application from the inside out, making acceptance tests for that. So, I think we're going to talk about some of the challenges that you encounter and some of the really novel solutions that are out there that we had nothing to do with. And I guess we really didn't have, just more of cobbling together of various techniques for a powerful witch's brew for acceptance testing. Anyway, so Wil, just to round out the problem space or explore the problem space, what are some of the challenges that you encounter with an acceptance test? Actually, let me back it up even further. What is an acceptance test in a JavaScript application compared to what people normally encounter? WIL: Acceptance testing or end-to-end testing is just a problem that every JavaScript app should face. Not everyone does, but they definitely should. And basically, it's how the user interacts with your app through the browser. And every part of that we want to test, from the browser triggering browser events, interacting with the app, not calling functions or clicking buttons, and we're pretending we're a user. CHARLES: Yeah. You know, I know that when we showed up in the React space, that was not really the way that most people tested their applications. WIL: No, not at all. they're all about unit testing. Make sure every small piece of your code works, and to some degree integration testing, making sure your components work with other components. But, nothing is out there really for those big acceptance tests that you want the user to click a button and expect them be brought to a page or these fields to be filled out, et cetera. CHARLES: Mmhmm. Yeah. And there certainly was a very high level of maturity around unit testing, like you said. There are tools like Enzyme and… WIL: Jest. CHARLES: Yeah, Jest. But I was actually shocked to find out that Jest didn't even run in the browser. WIL: Yeah, it's all virtual. CHARLES: It's all virtual. It's completely and totally simulated and stubbed. And that presents some problems. WIL: Yeah. The main problem is cross-browser testing. Some people might consider that to be separate from their acceptance testing but you should be able to just run your acceptance tests in multiple browsers and be able to also test cross-browser support. CHARLES: Mmhmm. Yeah. And so, if you're using something like Jest, you're never actually running the code inside Safari. You're never actually running it inside Internet Explorer. You're actually running it in NodeJS. WIL: And you know, your user is not going to run it in Node. [Laughter] WIL: They're going to use a browser. CHARLES: I don't know about your users. WIL: [Chuckles] CHARLES: [Laughs] You know, we like to stick to the pretty advanced. It's like, go to getNodeJSBrowser.com. WIL: [Laughs] CHARLES: Enough of this Firefox BS. But not seriously, it was certainly a problem. We were looking around, because we never like to build anything ourselves if we can avoid it. But it really just seemed like there was not an off-the-shelf solution for writing these big style acceptance tests in JavaScript. There are some services out there. There's a couple now. What was the… WIL: I think the main one here is Cypress. CHARLES: Cypress, yeah. So, there's Cypress now. I've watched the instructional videos but never actually tried to integrate it into my application. WIL: Yeah. I think at its core it takes the same approach that we've been doing with how we're interacting with our tests. CHARLES: Mmhmm. Okay. The main difference is, is it that it's a service? Like you have to edit your tests through… WIL: Yeah. CHARLES: Their web browser, their web interface, and use their assertion library? WIL: Yeah. I'm not sure about the editing part. But yeah, it's their assertion library. I'm pretty sure it's their test runner and it's their testing environment. Really, the only control through that is through their UI, or through settings, basically. And you're stuck with those. You can't use other… I don't think you can use Mocha with Cypress. CHARLES: Right. WIL: Although it's very much like Mocha… CHARLES: Right. WIL: It's not. CHARLES: Right, right. And I also noticed, we'll touch on this later, the assertions, most of the side effects that were happening were happening right there inline inside your assertions. And that might be an opaque statement, but we will actually get into that later. WIL: Yeah. And I think one of the things about their side effects so to speak is everything leading up to a side effect is a promise with Cypress. CHARLES: Mmhmm. WIL: So, when you select a button and click it, Cypress is going to wait for that button to actually exist before it clicks it. CHARLES: Right, right, which is actually pretty cool. So, that's actually a perfect into into one of the primary challenges with doing acceptance testing in general in a JavaScript application. This is a problem when you're doing it in Ember. It's a problem in React. It's really a problem anywhere. And that is, how do you know when the effects of a user's interaction have been realized? Right? WIL: Yeah. And in Ember you take advantage of the run loop. Once that action happens, you wait for the run loop to complete and then your tests run. CHARLES: Right. So, the idea is that I've clicked some button or I've typed some key or I've moved the mouse. And then I listen for the run loop and when it's “settled” then I can now run my assertions because I know that the side effects that I was looking for have now been realized. WIL: Yeah, hopefully, if you're... CHARLES: Hopefully. WIL: Writing your app right. [Chuckles] CHARLES: Right, right. But that actually presents some problems in itself because it requires visibility into the internals of the framework. WIL: Yeah, so Ember is built with testing in mind. CHARLES: Mmhmm. WIL: And other libraries like React just being a view library might not be built with testing in mind. So, we don't have those hooks to wait for this loop to complete, wait for all of these things to be rendered before you continue. CHARLES: Exactly. And so, this is, I think it's actually kind of both a blessing and a curse. Because there are such strong conventions in Ember, they were able to build this wonderful acceptance testing regimen from the get go. WIL: Yeah. CHARLES: But like you said, that doesn't exist at all in the React ecosystem. And so, what do you do? There's no run loop. You're cobbling together a bunch of different components. And maybe you're using Redux, maybe you're using MobX, maybe you're using… you're certainly using React. And all of these things have their own asynchronies built-in. And there's not one unifying abstraction that's keeping track of all the asynchrony in the system. And so that presents a challenge. So, the question is then, if you're trying to not actually check and observe the state of a system until the right moment, how do you know when that right moment is? WIL: Yeah. And in early testing of a side React project I had, I would basically wait for a state to be complete before I continued my ‘before each'. And in the testing we're doing now, it's essentially what we're doing except the state is what the browser sees, or what the user would see in the browser. CHARLES: So you were actually querying the... WIL: Yeah. So, I was using Redux. So, in my app I was saying, when the Redux app is done loading... CHARLES: Mmhmm. WIL: The instance is set to true or false, then continue the test. CHARLES: Mmhmm. And so, what that means, what we're doing, is doing the same thing except observing at the DOM... WIL: Yeah, exactly. CHARLES: Level. And what it means is we actually… I would love to set this up and have a big reveal but I guess we'll just have a big reveal, is that essentially what we do is polling. WIL: Yeah. CHARLES: Right? So, when we run an assertion, let's say you click a button and you want the button to become disabled, there's an inherent asynchrony there. But what we will do is we'll actually run the assertion to see if it's disabled not one time. We'll run it a thousand times. WIL: Yeah, as many times as needed until it passes. CHARLES: Right, exactly. As many times as needed until it passes. And I think that is, at least to most programmer instincts, an odious idea. WIL: Yeah. CHARLES: [Laughs] WIL: It's like, “Oh wait, you're just looping over every single assertion how many times?” CHARLES: Yeah, exactly. And it feels, yeah, it feels weird as an idea. But when you actually see the code that it produces, it just sweeps away so much complexity. WIL: Yeah. And… CHARLES: Because you don't worry about asynchrony at all. WIL: Yeah. And it's pretty genius. If I'm a user and I click a button, it's loading when I see that it's loading. So, our tests are going to wait until that button says it's loading. And then the test passes. CHARLES: Right. And so, what we do is we essentially, we use Mocha but you could do it with QUnit or anything else, is that when you run your assertion, you declare, you have an ‘it' block or I guess, what would it be in QUnit? WIL: A test? CHARLES: A test? WIL: I think it's just a test. CHARLES: You have your test block. And so that function that actually runs the assertion and checks the state will actually run, yeah it could run three times. It could run a thousand times. It's just sitting there waiting. And it will time out. And it will only fail if that assertion has failed a thousand times or it has failed through, I think two seconds is our default. WIL: Yeah, yeah. I think we default to the runner's default timeout. CHARLES: To the runner's default timeout, yeah. WIL: Yeah. Or you can set that yourself with how we have it set up. And the other thing that comes from that is if your tests are only failing when they time out, how do you know what's actually failing? And our solution to that was we catch the error every time it fails and right before the timeout actually happens we throw the real error. CHARLES: Yeah. Exactly. But the net effect is that you're able to write your assertions completely and totally oblivious of asynchrony. You don't, we don't have to worry about asynchrony pretty much at all. I mean, we do, and we'll get into that. So, I made a global statement and then immediately contradicted it. WIL: [Chuckles] CHARLES: But hey, you got to be controversial. But for the most part, asynchrony just disappears because asynchrony is baked into the fabric. So, rather than thinking about it as a one-off concern or a onesie-twosie, it's just every single assertion is just assumed to be asynchronous. And so, that actually means you don't have to deal with promises. You don't have to deal with run loops. You don't have to deal with anything. You just write your assertion and when it passes, it passes. And there are some really unique benefits for this. And there are some challenges. So, I think one of the first benefits is that it's actually way faster. WIL: Right. CHARLES: Which is counterintuitive. WIL: It's incredibly fast. CHARLES: It's very fast. WIL: Yeah, for all the loops that's happening you might think every loop is going to slow it down slightly. But it really doesn't. Our tests, each test, even though it asserts five or six times, it takes milliseconds. CHARLES: Mmhmm. WIL: The test itself might only loop twice. CHARLES: Right. Exactly. Whereas if you're waiting for a run loop to settle, you might have some… you click a button, it disables, it also fires off an Ajax request and does all this stuff. But if all my assertion wants to know is “Is this button disabled?” then I only need to assert until that has happened. I don't need to wait until all the side effects have settled... WIL: Mmhmm. CHARLES: And then do the assertion. I just know, “Hey, my assertion, the thing that I was waiting for - that happened. Let's move on.” Yeah. And so, it's so, so fast. And that was actually, I didn't predict that. But I was definitely pleasantly surprised. WIL: Yeah, that was a very nice surprise. And all of our tests ran so much quicker than they would have in a run loop environment with Ember or something. CHARLES: Right. Yeah, yeah. That was, we actually had just come off a project where we were having that thing, that exact problem, which was that yeah, our animations were slow. Or, the animations were fine. They were perfect. [Laughs] But there were slowing down the tests. WIL: Yes. I think in that project, it was like, 30-minute tests... CHARLES: Mmhmm WIL: For the whole suite to run. CHARLES: Yeah. To which I'll add a public service announcement. I think this is a conjecture but I do believe that animations are best applied not to individual components but by the thing that uses a component. So, I shouldn't have an animation that's like, implicit to a dialog. It should be the thing that's showing the dialog that gets to decide the animation to use. Anyway, just throwing that out there. WIL: [Laughs] CHARLES: Because animations are about context. And so, the context should provide the animation, not the individual atom. Anyway, moving on. WIL: Some other podcast. CHARLES: Yeah. [Laughter] CHARLES: That's another podcast right there. But there's also, this does present some challenges or requires code to be structured in a way that facilitates this. So, there are some challenges with this approach, some things you need to be aware of if you're using this kind of system. We've kind of settled on a name for what we call these types of assertions and these types of systems. WIL: Yeah. We call them convergent assertions, because you're converging on something to happen. It's going over and over until it happens. CHARLES: Right. WIL: And yeah, a lot of these challenges that we've come across are things that you might not think of, like there are a few instances of false positives... CHARLES: Mmhmm. WIL: That happen with these convergent assertions. CHARLES: Right. So, what would be an example there? WIL: So, the most common example that I'm seeing so far is when you're asserting that something didn't happen. CHARLES: Mm, right. WIL: That would immediately pass. But if it takes your app... CHARLES: [Laughs] WIL: A few seconds for it to actually happen, then you could still have an actual failure but your test passed immediately. CHARLES: Right, right. So, what's the countermeasure then? WIL: We invert our assertions. So, we make sure they fail for a certain amount of time. CHARLES: Right. So, the normal case where you just want to say, “I want to make sure that my state converges to this particular state.” WIL: Alright. I said fail at first. I meant, pass. We have to make sure it passes for a certain period of time. CHARLES: Right, exactly. WIL: So yeah, the normal way is it fails until it passes, and then it passes. When you invert one of these convergent assertions, you're just making sure it passes repeatedly and if it fails at any point, you throw a failure. CHARLES: Right, okay. And so, that's like, if I want to check that the button is not disabled, I need to check again and again and again and again. WIL: Until you're comfortable with saying, “Alright. It's probably not going to be disabled.” CHARLES: Yeah, exactly. And so there, it's kind of weird because it is dependent on a timeout. WIL: Mmhmm. CHARLES: You could go for two seconds and then at the very end it becomes disabled. So, you just kind of have to take that on faith. But... WIL: Yeah. CHARLES: In practice, I don't think that's been much of a problem. WIL: No. CHARLES: It's more indicative of, if your button disables after... WIL: A few seconds. CHARLES: A few seconds, what's up with your... WIL: Yeah, what's up with your app? CHARLES: Yeah, exactly. WIL: If you're waiting for an Ajax request or something, an example, then you should be using something like Mirage Server. CHARLES: Right. Which is, man, we got to get into that, too. There are a couple of other things that I wanted to talk about too, with these convergent assertions. And that is, typically when you look through the READMEs for most testing frameworks, you see the simple case of the entire test, the setup, the teardown, and the actual assertions, are in the actual test. WIL: Yeah. The ‘it' block in Mocha or the test block in QUnit. You click a button, and then make sure it's disabled, and it moves onto the next test. CHARLES: Mmhmm. WIL: Then you click a different button or the same button and you assert something else in the next test. CHARLES: Mmhmm. Right. WIL: And yeah, you can't do that with convergent assertions because they're looping. So, if you click a button in a loop it's going to keep clicking that button over and over and over again. CHARLES: Yeah. [Laughs] Right, right. So, it means that you need to be very conscientious about separating the parts of your tests that actually do the things that actually act the part of the user from the part of your test that's about observation. WIL: Yeah. So, our solution to that is we move out all of our things that have side effects like clicking a button or filling in a form, all that stuff happens in ‘before each's. And all of our actual assertions happen in these convergent ‘it' blocks that loop over and over again. So, our ‘before each' runs and clicks the button and then we have 10 or so tests that will loop and wait for various states to... CHARLES: Yeah. WIL: Be true. CHARLES: Right. That means that yeah, all these assertions do is they read state. And you just have to, you do have to be conscientious. You're not allowed to have any side effects inside your tests, your actual assertion blocks. WIL: Mmhmm. CHARLES: But that's actually, it's a good use case for the whole Act-Arrange-Assert, which has been around way, way, way before these techniques. But here, we're doing Act and Arrange in our ‘before each'... WIL: Mmhmm. CHARLES: And then we're doing Assert later. And I think it actually leads for more readable... WIL: Yeah, definitely. CHARLES: Things. WIL: And it also opens the door to something that we can't really take advantage of yet but if you have 10 assertions with one ‘before each' side effect, you could run all of those assertions in parallel. CHARLES: That's right. WIL: And your tests would be 10 times more faster. CHARLES: Mmhmm. Yeah, exactly. Or you could run them in parallel or you could just run them one after the other but you wouldn't have to run that ‘before each' 10 times. WIL: Yeah. But something with that, that I found, is if we move all of our side effects to ‘before' blocks instead of ‘before each' blocks, sometimes a test three tests down that's waiting for something to happen... CHARLES: Yeah. WIL: That thing might have already happened earlier... CHARLES: Yeah. WIL: And it already went away. A loading state is the best example of that. CHARLES: Mmhmm. WIL: You show the loading state, the loading state goes away. So, if you move that button click into a ‘before' and that loading state test is three tests in, that loading state is already going to be gone. CHARLES: Yeah, so I think the long story short is we've kind of come to the conclusion that we would have to write our own runner. WIL: Yeah. CHARLES: Essentially to take advantage of this. But that said, we've done some sketching about what we would gain by writing our own runner. And the speed, we're talking about exponential speedups. WIL: Yeah. CHARLES: Maybe taking an entire acceptance test suite and having it run in five or six seconds. WIL: Yeah. We're talking about these tests that are already extremely fast. CHARLES: Mmhmm. WIL: Each test takes a few milliseconds or tens of milliseconds to complete. But then if you can run all of those at the same time, all of your tests for that entire ‘describe' block just ran tens of milliseconds. CHARLES: Right. Yeah. So, it's really exciting and pretty tantalizing. And we would love to invest the time in that. I've always wanted to write our own test runner. But never had, [chuckles] never really had a reason. WIL: Yeah. CHARLES: Certainly not just for the sheer joy of it. Although I'm sure there is joy in writing it. But that, yeah, we'll have to wait on that. But I am actually really excited about the idea of being able to maybe bring this back to the Ember community. WIL: Yeah. CHARLES: Because acceptance tests getting out of control in terms of the speed is I think a problem with Ember applications. And I think this would do a lot to address that. WIL: Yeah. CHARLES: I think, how long, if we were just using a stock Ember acceptance testing setup for this, I think we have about 250 tests in this React app... WIL: Yeah. CHARLES: How long does it take to run? WIL: Right now I think our tests take something like 20 seconds. And that's also somewhat due to they have to print the tests on the screen on Travis so that takes a little time. In an Ember setup, that could maybe take a few minutes. I mean, that's not that big of a deal, a few minutes. CHARLES: Right. WIL: But compared to 20 seconds. CHARLES: Right. you're still talking about an order of magnitude... WIL: Yeah, exactly. CHARLES: Difference. And using this, I think you could get a 30-minute test suite... WIL: Yeah. CHARLES: Down to the order of 3 minutes. WIL: Now when we're talking about those times, we're talking about the tests themselves. Of course, the CI would have to download stuff and set up the [inaudible]. CHARLES: Mmhmm, right, right. WIL: And that of course all adds to the time. CHARLES: Yeah, mmhmm, yeah. Earlier you mentioned, we talked about Ember CLI Mirage. This is actually something that is having now been using it for what, 2 years or something like that, it's just… it's impossible... WIL: To go back, yeah. CHARLES: To go back. It is. It's like [chuckles] you come outside the Ember community and you're like, “How is anybody ever dealing without this?” WIL: Yeah. CHARLES: [Laughs] WIL: A lot of the mocks are usually mocking the function that makes the request and it returns it in that function. That's what's out there currently, minus the Mirage stuff. CHARLES: Mmhmm. WIL: But once you use Mirage, you're mocking the requests themselves. CHARLES: Yeah. And you've got such great support for the whole factories. I love factories. It's something that is very prevalent in the Ruby community, and maybe not so much elsewhere. But the ability to very, very quickly crank out high-fidelity production data... WIL: Yeah. And you don't have to have files upon files of fixtures. CHARLES: Yeah, exactly. And you can change, if something about your schema changes, you can change the factory and now your test data is up and running. So, Ember has this tool called Mirage which is just, like I said, it's so fantastic. Oh yeah, it's also go support for running your application. Not just in your tests, but you can actually run your application with Mirage on and... WIL: Oh right, yeah. CHARLES: And you've got now the most incredible rapid prototyping tool. WIL: Yeah. You don't need to connect to a server to see fake data. CHARLES: Right, right. And we were even talking about this yesterday to a potential client. they're trying to, they've got to present something to investors. And how wonderful is it to just be like, “You know what? We just don't want to invest in all, we don't want to move the inertia, invest the money to generate the force to move the inertia of a backend.” Especially in this particular use case, the backend was going to be really, really heavy. WIL: Yeah. And there were some questions about the backend that we couldn't address quite yet but we wanted to start working on something that we could show, something demo-able. CHARLES: Right, exactly. And so, Mirage is just so wonderful for that. But again, Mirage is, it's an Ember-specific project. WIL: Right. CHARLES: So, the question was, “How are we going to use that?” WIL: And you actually took this on yourself. CHARLES: Mmhmm. WIL: I just saw this pop-up one day and boom, you converted Ember Mirage to vanilla JavaScript. [Chuckles] CHARLES: So, I did extract it. But the lion's share of the credit goes to the developers of Mirage themselves. Sam Selikoff and the Mirage community, they built Mirage not using much of Ember. There were some utilities that they were using, but mainly things like string helpers to convert between camel-case and dash-case, and using a Broccoli build, or using an Ember CLI build. WIL: Yeah. That was one of the challenges that we came across using Mirage outside of Ember, was how do we autoload this Mirage folder with all this Mirage config and Mirage factories and models, et cetera. CHARLES: Right. The internals were all just straight up JavaScript classes, for the most part. And so, extracting it, it was a lot of work. But 90% of the work was already done. It only took three or four days to do it. WIL: Amazing. CHARLES: Yeah. So, it was actually a really pleasant experience. I was able to swap out all of the Ember string helpers for Lodash. So now, it's good to go. It shares a Git history with Ember CLI Mirage, so it's basically a fork. WIL: Mmhmm. CHARLES: Like, a very heavily patched Ember CLI Mirage. But I keep it up-to-date so that it doesn't... WIL: Good. [Inaudible] CHARLES: Yeah, so I think the last time I merged in from master was about a month ago, something like that. Because it's got all the features that we need but it's not a big deal to rebase or just to merge it on over in. Because yeah, it's a really straightforward set of patches. WIL: Was there any talk with the creators of Ember Mirage about getting this upstream? CHARLES: So, I've talked a little bit with Sam about it. And from what I can tell, his feeling on it is like, “Hey, my goal right now is to focus on this being the best testing and data stubbing platform for Ember. Anything that happens out there, outside of that scope, that's great. And I certainly won't get in the way of it. But I'm pretty maxed out in terms of the open source credits that I have to spend.” WIL: [Chuckles] CHARLES: And there hasn't been much motion there. I'm happy where it is right now. I would like to see it merged into upstream. I think it would be great to have basically this Mirage Server and then have Ember CLI bindings for it. WIL: Yeah, yeah. I was going to say, either another Ember CLI specific package for Mirage or maybe to make it a non-breaking change or something. CHARLES: Yeah. WIL: Just like an Ember-specific entry point. CHARLES: Right, exactly. And I think that's definitely doable, if someone wants to take it on. I will say, we have been using this extracted plain vanilla JavaScript Mirage Server now for what, almost six months? WIL: Yeah. CHARLES: And it really hasn't... WIL: Yeah, I don't think I ran into one issue with that. CHARLES: Yeah. It's solid. It's really, really good. So, kudos to the Mirage team for doing that. And if anybody is interested in using Mirage in their projects, it's definitely there and we'll put it in the show notes. WIL: Yeah. We call it Mirage Server. CHARLES: Mirage Server, yeah. So, I don't know. Maybe it's time to reopen that conversation. But it has become a very integral and critical piece of the way that we test our JavaScript applications now. So, what are the foundations of it? We've got, we're using Mirage. We're using these convergent assertions. We're using Mocha, although that's really... WIL: Yeah, we have jQuery and Chai jQuery just to help us out with interacting with the browser as a user would. And I think one of the big challenges with that actually, I just remembered, was triggering changes in React. CHARLES: Yeah. WIL: I think this is pretty specific to React. You might run into problems with the view. I don't know how to mess with view. But in React, at least I think 15 or React 16, one of them, they changed the descriptor of the value property on an element so that they can appropriately interact with it, make changes, watch for changes, et cetera. So, when you set this value property using jQuery or just straight up ‘.value()', that change event isn't triggered in React. Your on-change handlers are never called. CHARLES: Wait, they actually update the JavaScript property descriptor of the DOM element. WIL: Yes. CHARLES: Boo. WIL: Yeah. So, there's a nice little helper out there called React Trigger Change. I dug through it and I've stripped some of it down to just be for more modern browsers, more modern React. But there's a lot of good code in there. And basically, it just caches that descriptor, updates the value, triggers the change, and then adds the descriptor back. And that ends up triggering that React element. CHARLES: Okay. [Laughs] WIL: [Chuckles] Yeah, so that calls your handlers and that's how we get around that. CHARLES: Right. There's a few fun little hacks there. But I think it is good to tie that into a larger point, is that the amount of touch that you have with the framework is actually very low. WIL: Yeah. CHARLES: So, the amount of affordances that we've had to make just for React, there's that, that you just mentioned. And is there… there's not much else. We had to write a test harness to mount the app. But that's like... WIL: Yeah, yeah. Our describe application helper is pretty React-specific. CHARLES: Right. WIL: So, you'd have to render it and set up a Mirage server, et cetera. CHARLES: Right. But that's application-specific setup. WIL: Yeah, that's one file. CHARLES: Right. WIL: So, your goal for acceptance tests is you want to be able to have a refactor and your acceptance tests still pass. CHARLES: Right. WIL: So, what if that refactor involves switching libraries? CHARLES: Right. WIL: If you're writing Ember acceptance tests, you're going to have to rewrite all your acceptance tests. CHARLES: Right. WIL: That's a huge downside. CHARLES: Right. WIL: So, with this method of interacting with the actual library very little, we have that one file that sets up our app and then we have that one trigger change helper, we remove those, we can use whatever framework we want underneath this. And our tests would still work. CHARLES: Yeah, exactly. And I think that we actually could theoretically, and honestly I have enough confidence in this style that we're developing the tests now, we could refactor this application to Ember and not have to rewrite our tests. WIL: Yeah, exactly. CHARLES: In fact, the tests would be an aide to do that. WIL: Yeah, and the tests would be faster than Ember testing with that run loop problem. CHARLES: Yeah, exactly. that's really something to think about or to think on, is like, “Wow. You're really at this point completely, not completely, but very loosely coupled to the actual internal library code.” Which is one of the goals of a nice, big acceptance test, is to be able to make major changes, break big bones, and be able to set them and have your acceptance test suite be the bulwark that holds it all together. WIL: Yeah. CHARLES: So, I actually don't know what a bulwark is. WIL: [Laughs] CHARLES: I just know that it's a really strong thing. [Laughter] CHARLES: Maybe we could put that in the show notes. [Laughter] WIL: A link to what that is. CHARLES: [Laughs] So, alright. Well, I'm trying to think if there is anything else that we wanted to mention. Any challenges? Any next things? WIL: So, one of our next steps is something we mentioned that Cypress does, is they wait for elements to exist before they interact with them. And we're actually not doing that in our app currently. And we don't have helpers out there for it yet. CHARLES: Right. WIL: But that's very much the next step. When we go to click an element in our ‘before each', we have these describes that are nested. Say, you have nested describes and you get down three levels into a ‘before each' when you're clicking a button. That button might not exist yet. CHARLES: Right. WIL: And especially since we're using jQuery, if you trigger a change on an empty jQuery element, it's not going to throw an error. It's just not going to tell you that it triggered anything. CHARLES: Right. WIL: So, we get those skips where that button's not getting clicked and we should really be waiting for that button to exist. CHARLES: Right. So, what we've done right now is we're converging on our assertions at the backend of a test. But at the frontend of a test we need to also be converging at some state before we can actually interact with the application. WIL: Right, yeah. CHARLES: So yeah, so that part is missing. And that actually brings up, we are very slowly but nevertheless doing, we're collecting these convergent assertions and convergent helpers in a repository on our GitHub account. We're going to be adding these things so that you can either use them out of the box or use them to make your own testing library. WIL: Yeah. And one of the other next steps that goes along with waiting for the element to exist is when you need to chain convergences. Like, wait for this element to exist and then click it and then wait for this thing to happen before actually running a test. And that presents the problem of our convergences are waiting for that timeout and those timeouts will accumulate. So if you have three chained convergences, that's now a six thousand millisecond timeout as opposed to a two thousand millisecond timeout. CHARLES: Right. WIL: So, one of the next steps is getting that tracking under control so if you chain three convergences together, they're smart about it and they still fail under the two thousand millisecond timeout. CHARLES: Right, right. So yeah, so we're going to be collecting all this stuff that we're learning into some publicly available code. We have a repository set up. I don't know if I want to announce it just yet, because it's really early days. WIL: Yeah. CHARLES: But that definitely is the plan. And that way, whether you're using Mocha or whether you're using QUnit or whether you're using Chai or jQuery, you've got these underlying primitives that help you converge on a state, whether that state is to interact with some piece of the DOM or to just assert some observation is made about that state. We'll be continuing on that. But by all means, get in touch if this is something that is of interest to you. Let's make something happen, because it's something that we're pretty excited about. And honestly, it's pretty comfortable living inside the four walls of this test suite. WIL: Yeah. CHARLES: It feels pretty good. WIL: It does, yeah. They're very fast. And some places in the test might need a little reworking, but for the most part all of our tests are very well-written, very well-readable. And you can just open up a test and know exactly what's going on. CHARLES: Yeah. Alright. Well, I think that about does it for Episode 90. Wow, Episode 90. WIL: Man, coming up on that 100. CHARLES: Yeah. We're going to have to have a birthday cake or something. WIL: Do we celebrate Episode 100 or Episode 104? CHARLES: What's 104? WIL: 104 would be 2 years. CHARLES: Oh really? WIL: Well, I mean 2 years' worth of podcasts. CHARLES: Oh, right. 2 years' worth of podcasts. Yeah. WIL: Yeah, like if you go every week. CHARLES: Maybe we should celebrate a hundred hours or something like that. WIL: Oh yeah. CHARLES: We can add up the thing or celebrate… I don't know, be like, “You've literally wasted 2 years of your life.” WIL: [Laughs] CHARLES: “2 weeks of your life listening to the podcast.” Anyway, so that's it for Episode 90. and thank you so much, Wil. WIL: Thanks for having me. CHARLES: It's always a pleasure to talk about these topics with you. And as always, if you need to get in touch with us, please reach out to us on Twitter. We are @TheFrontside. Or you can send an email to contact@frontside.io.
Toran Billups: @toranb | GitHub | Blog Toran Billips joined us for an insightful conversation regarding glimmer-redux: Predictable state management for Glimmer apps. Resources: Glimmer Redux Demystified Talk from Tom Dale on glimmer internals (contrast with Preact made in this talk) ember-redux Glimmer progress report that mentions the migration to Glimmer 0.8 (Big Changes) Blog post following EmberConf 2017 that announced GlimmerJS (for the Ember dev) The Frontside Podcast 086: Routing in Ember with Alex Matchneer An ember-rideshare Blog Post A Rollup plugin for glimmer-redux RollupJS Transcript ELRICK: Hello and welcome to another Frontside Podcast, Episode 89. My name is Elrick Ryan, a developer here at the Frontside. I'm joined by Wil Wilsman, another developer here at the Frontside. Wil, how are you doing? WIL: I'm good. How are you? ELRICK: I'm great, man. I'm excited for this podcast that we have coming up here. Today we are fortunate to have with us a podcast elite member now, Mr Toran Billups. Toran, how are you doing? TORAN: Oh, man. I joined the elite platinum club or something? ELRICK: Yes, you are in the platinum club right now. I think this is probably what? Your third or fourth episode by now? TORAN: Oh, yeah. I think the fourth. ELRICK: Oh, yeah. You're in the elite club right now. You are a Midwest programmer and I hear there is a difference between a Silicon Valley programmer and a Midwest programmer. Could you tell us about what the difference is? Because it's the first time I've heard anything about this. TORAN: Admittedly, I stole this from a very popular developer, Justin Searls who spoke at length one time on a podcast, not too different in this one about his experiences in consulting for companies, who are more in the startup phase or a company that you'll find in Silicon Valley that is mostly just trying to test an idea and get to market, versus his experience for finance or insurance companies based out of the Midwest. I like that idea because my experiences have taught me. I'm a little bit happier when I'm working for companies that are interested in quality or attributes of quality and view the software longevity as mission-critical versus a software that is really just a byproduct of an interesting idea and if we validate that idea in a market, we can always rewrite the software later. Midwest, I guess the short version is we care about the work we're doing and we understand that rewrites are difficult, if ever possible. ELRICK: Interesting, so the Midwest seems to be concerned with long term goals. TORAN: Yeah, I think sustainable -- ELRICK: Sustainable software, at least. TORAN: Yep. ELRICK: Today, you are joining us to not only talk about the Midwest and the beautiful Midwest programmers. You're here to talk about Glimmer Redux. TORAN: Glimmer Redux is a little library I wrote, I think last month. I should start off by asking you guys if you're familiar with a Glimmer JS or if you've heard of that. ELRICK: I've heard of Glimmer JS. I haven't had an opportunity to play around or mess around with it yet. I don't know if that's good or bad because I'm just really busy but I really want to get into it. Wil, what about yourself? WIL: I've read through the docs but I haven't played with it at all. It looks really nice. TORAN: I think the joke that was off the air last time I was on, Wil you might remember this. You're on that podcast with Charles. I said something like, "I'm not young enough to actually be working with Glimmer," and I felt that way for a long time because one thing you should know is it's a pre-1.0 and if you guys have ever worked in a pre-1.0 ecosystem, myself the biggest experience I have to draw from is really pre-1.0 Ember and there were some big changes before 1.0. You can imagine back to that throwaway comment about being very young, there was actually a big change in Glimmer itself recently where they decided to... I don't know if the right word is Pascal Case but they've literally gone away from that 'dasharized' components. It used to have 'foo-bar' and in your template, you would actually see lower case of 'foo-bar' and now that would just be all uppercase. Well, not all uppercase but 'FooBar' and no dash, which is a big change recently. WIL: So a class case, kind of like React or JSX. TORAN: Yeah, exactly. They have a great blog post. Actually, we can reference that in the show notes, about some of these big changes in that release. It was Glimmer 0.8 so it's still, it's making its way to the 1.0 but I got interested in this really for two reasons in the last couple of months. The first was, if you actually go build something with Glimmer -- and this is my experience -- is for the novice programmer just taking a look at it, it's really just a way to use web components to build an application. There's no routing. There's no opinions, really. There's no services like you have in Ember or contexts like you have in React. The first challenge you run up against is when you get beyond a single component or two components and suddenly, you need to share some state across this application. How do you do that? If you guys have some experience, I know the Frontside, with React, if you're not using MobX or Redux or something like that, a lot of times you'll see this pattern where you're actually passing a piece of state through the entire tree or the shared state through a big part of the component tree. Of course, that becomes painful as the application gets to a certain size. One of the things I thought about is if I was to build a real application, the one in mind that was certainly not built yet because I'm not using Glimmer at work but I always think about the ember-rideshare. I know you guys had Alex Matchneer, recently talking about routing and Alex mentions in that episode this challenge for the Ember router today, to be reactive to server-sent events. In the case, imagine you have an Uber or a Lyft app and after the ride is over, the server wants to send an event, maybe and then the app needs to react to that event -- sending you maybe to a new route or sending you back to the map to pick a new ride. The gist of the ride share app is, and Alex, of course I would reference anyone to that podcast, he does a lot better job describing the routing challenges and those are a little bit out of scope for this discussion, but imagine you're going to build an app that ambitious and you're going to build a Lyft in Glimmer. What I found was missing is really what we take for granted in Ember, which is the Ember Service and that is like a singleton or an object that allows you to have a piece of state and then share that state around by injecting that service in only the components that need to reach up and grab that shared state. Redux, which I know your audience is pretty familiar with but a quick recap, Redux is just kind of a global JavaScript object that has state and there's often a library that lets you connect to that state so you can use it in your various components. Glimmer Redux is no different than that, actually. It just allows you, instead of having to create maybe one global JavaScript object and kind of pass it down the hierarchy, you can instead just connect the components that need to be aware of Redux. The ones that don't, of course they just don't connect. ELRICK: I know that you had a hand or build ember-redux and now you build Glimmer Redux. Were there any challenges between building those two different add-ons into two different ecosystems? TORAN: I should take one minor step back because that question is a great segue. I didn't want to touch on the second motivation for Glimmer Redux, which is actually really closely related here and that is, of course I did write ember-redux so with every open source project, there's a little selfish motivation here. I imagine last year when Glimmer was announced at EmberConf that there would be a story from Glimmer to Ember. The idea being you're a small startup, you just want to get your web application going, you don't necessarily like all the big conventions or you just don't think you need all of Ember when you get started but six months down the road, you're suddenly looking at tree shaking and lazy loading with engines and you're thinking, "I wish we had that." Realistically speaking, like today what would a transition for a Glimmer shop to Ember be. Honestly, I think it's tough without a library like Glimmer Redux. Of course, I wrote this with pretty much a mere of the connect API. If people were to check out the ReadMe of Glimmer Redux and ember-redux and you looked at a connected or redux-aware component in both of those cases, the best case scenario is the only difference would be in the import. Instead of import connect from a Glimmer Redux, you would be import connect from ember-redux. Everything else underneath, all the ecosystem of Redux that you can use and both are completely compatible. In fact, if you were to move, imagine you Ember new and you're thinking, "I got to move my Glimmer ride-share to ember-rideshare. Since Redux does a good job in encapsulating all of the state transformations in vanilla JavaScript, you don't have to really worry about the differences between a number object and not having Ember object. After you did Ember new, essentially you would copy over your components. For the most part, they're still template-driven. A lot of handlebars and a lot of TypeScript to JavaScript is the biggest mismatch you would have between Glimmer and coming over to Ember, of course but there is Ember CLI TypeScript or Ember TypeScript, I think. Long story short, you essentially copy the directories of your reducers or middleware from your Glimmer app over to Ember and there should be no changes necessary at all. ELRICK: I know that is the dream that you touched on, I think they phrase it as 'NPM installing your way up to Ember.' In your perspective, do you think that is going to be a thing? Is it going to get there? What are your feelings on that? TORAN: I would definitely be in trouble if I didn't say upfront that I'm not on the Ember core team. Sometimes, people get that confused for some reason but I don't speak for the core team and I'm not really privy to anything. But I do think that the core team has this in mind that there will be a set of NPM installable modules that eventually land you the full set of tools and abstractions that we see in Ember today. A big one that I'd hit on earlier is services. What will services or the Glimmer 0.5 version of services look like when it lands and what about routing and those sort of things? This was really my personal take on how could I make that migration right now without asking permission from the core team. In a Glimmer Redux, I think honestly it offers a good 80% of that. You still have the routing issue, which is a little challenging and you have the TypeScript issue, which you just have to be aware of some of the limitations of using TypeScript in Ember. ELRICK: That's an excellent point that you made because when people outside of the core team take it upon themselves to then try to implement different things around the ecosystem, that can then be motivation or an example for people outside of the core team to see like, "This is a possible solution to a goal we're trying to reach." Kudos to you. TORAN: Back to your original question about 15 minutes ago, what was different about the ecosystems writing ember-redux the add-on and Glimmer Redux, which is... I don't really even want to call it an add-on. I kind of label it as a Glimmer library but to your point just a second ago, when I got interested and saying, "I wrote Glimmer Redux, now I want to share it so other Glimmer authors don't need to copy/paste this file," and the first resistance I hit up on is there really is no Glimmer library or Glimmer add-on. You could write an Ember add-on because if you guys get into Glimmer, you'll find this as well. There are certain hooks that are used in the Glimmer build process where Ember add-ons like Ember CLI SASS can be used from Glimmer. But the challenge I had using an Ember add-on, of course is that this wasn't an Ember component or anything Ember related. It needed to really be test driven from a Glimmer apps. Really, if you went to NPM installers, what you're pulling in is effectively my Glimmer app that also exports publicly this connect function, which is not necessarily you're leading, maybe anything to core team that could happen. A big reason for that as well and one of the challenges building this, is that Glimmer right now, after to try to emulate my 'quasi-success' in doing this, is really bring your own build system, to actually share a Glimmer components or internals like this connect API that Glimmer components can use. What I mean by that is on the website, one of the challenges I faced was -- this isn't a knock against the core team, this is just my honest experiences -- when I read the Glimmer JS docs and it says right in the installing guide, "Glimmer uses Ember CLI, this battle-tested command line interface from the Ember project." Now, pause right there because again, not to beat up on the Ember core team or anything but assuming in that one sentence that they're using Ember app, what I noticed when I opened the Ember CLI build file is the project was actually a Glimmer app. Now, I did a little bit of digging here and I think this is validated, at least back when I worked on Glimmer Redux last month, that Glimmer app is not like inheriting or pulling in a bunch of shared code from Ember app. It's actually a completely separate build tool. As part of this process, I actually for the first time had to go through and learn Rollup and understand how the Broccoli process is kicked off, how both Rollup and Babel are used to build this and then how to apply some convention. If you guys are familiar with Ember, you have this add-on directory and an app directory. The guidance from the Ember team is around how to structure add-ons. Of course, you write all of your kind of private-ish or add-on code in the add-on directory and then whatever you think will be public, you export from the app directory and that sort of merges it into the tree when the application is built. People are allowed to use your code but then also, they can override that code. One of the challenges here is if I wanted that exact same API and I want people to make this migration from Glimmer to Ember using Redux, I had to actually invent that convention so I wrote a Rollup plugin and it's all listed in the docs here. One of the strange things people who are checking out Glimmer Redux hit me with first is, "I see a Yarn installed Glimmer Redux but then second step is installing this Rollup plugin. What's the deal?" I think it is because most people assume the Ember CLI you're using is identical and somehow, I should have written an Ember CLI add-on for this. I think that was the biggest learning curve and people should just be aware of that. If you're interested in sharing code right now, there is really not a baked story and that's okay. It allows people to innovate. Of course, the innovator's dilemma being that, I don't really know without [inaudible] some migrating RFC or getting involved with the core team, how to make that thing. I ultimately just hope the core team improves this and I'm sure they will but for right now, I don't really want to wait around for it. ELRICK: Got you. What is Rollup, for people that are not familiar with what Rollup is? I'm sure everyone is probably familiar with Babel by now because it's used everywhere but what is Rollup? TORAN: Embarrassingly, I don't know the technical... But I would say the role that you can see, if you actually step through the node process as your Glimmer app is being built, is it helps really condense the overall build size. What I see is it's essentially traversing like Browserify in some ways. This is, again just my primitive look but it traverses all the imports you have and it tries to pull in the bare minimum to keep the bundle size as small as possible. ELRICK: Toran, you have had a lot of experience with Redux and Redux is now being used in several different software platforms, I guess or software areas like Vue and they probably even have in Angular now. They have it in Ember and React. Redux is kind of spreading its wings and it seeds across every ecosystem. Do you feel that Redux has reached a state where people are just satisfied with the current state of Redux or do you think that people are going to be then, looking to build another abstraction on top of Redux? Do you have any thoughts on that? TORAN: The fact that Redux is so simple has allowed it to become so ubiquitous. I heard someone say this term the other today, which is like, 'ubiquity over consistency,' and that I think describes the both the growth of Redux and why it is kind of de facto for data management across all ecosystems. I think there's two camps that I hear about and I'm curious if you guys see this in your consulting work but there is certainly, the developer see this ubiquity but no consistency and see chaos in their experiences. I can totally relate to this. There are development shops I've seen where one team goes this direction because there's no strict guidance goes another and then when those teams meet up for a project in 12 months, they look at each other and the apps are, of course nothing alike, which is a big problem that Ember tries to solve. My biggest question here really is kind of curving us slightly back to the Glimmer story. If I can reframe your question, Ember is traditionally very big on convention and I think a lot of the community that is still in Ember today in large part is because of this convention, these guide rails about the community has set up but Glimmer being this NPM install your way to Ember, I think along the way, there's going to be either a new set of users that are coming just for the winds of the Glimmer VM and they happen to find themselves, not necessarily in love with some restrictions or opinions that would come with a migration directly to Ember and I'm curious if the Glimmer community that will show up for that is mostly Ember backed, meaning that they want to slowly build with RFC as a process that the entire community uses and there's one solution like we end up with often an Ember. If a community evolves more experimentally like you saw in React, where there was, of course Redux but then there was MobX and then there was various little wares for Redux that different teams would try out and eventually, there was no one proven way but there was always at the heart of it, Redux with some extensions or other add-ons around it that got teams to where they are today. I'm curious to see where this Redux, especially with the Glimmer influence, will end up. WIL: You touched on a little, I think one of the, maybe not a problem necessarily but one of the biggest barriers in Redux and React and maybe Glimmer -- I'm not sure -- is that it's almost too loose without any opinions at all so it kind of gives developers the freedom to mess things up big time. What's your opinion on that with Glimmer, like Glimmer is headed toward this NPM install? Is it too loose? TORAN: I guess that's the question, I wish we both had the answer to. It's funny. It's a double-edged sword. If it's loose, it seems like somebody is going to go create a mess but at the same time, if it's loose on the surface, it often seems like it has less surface area and as a result, a lower learning curve. React is a good example where most people, I think have gone to React or at least in my experience, I like React because it was so simple and there wasn't a huge amount of things to learn. There wasn't this full ecosystem, at least out of the gate but of course, what you find the moment you want to join a team or go build something ambitious is that you've got to make a bunch of decisions and that is certainly the calling card of Ember. What makes Ember special is they've settled on a handful of those decisions. I think ideally, I'd like to see the community in Glimmer check out Redux, get an idea of what problem it actually solves for them and if it is useful, then find a set of middleware or extensions from the wider ecosystem that actually solve the problems they face. Back to this Glimmer rideshare example, I think one thing that stands in the way as I play around with that is just a very basic routing story. Even if that is as simple as I have a component that I'll just call it route, what hooks in this Glimmer component are correct to fetch data. In the Ember ecosystem, we have a very special route object, essentially who has a set of hooks that are known for handling the asynchronous stuff in our Ember apps but there isn't anything like that yet, in Glimmer which is the next stumbling block for me to actually go build something big. I'm kind of messing around with the idea of this reactive router built out of Glimmer components but until that's actually kind of surface, mostly just spit balling here. ELRICK: With flexibility comes a lot of power but then there's also the case where our flexibility could lead to chaos. But being that something as flexible, it allows you to adapt it to whatever your particular needs are -- you know, the 'special snowflake' as everyone ends up being. Because Ember has been around for a while now and has proven itself and its battle-tested in a lot of areas, now as NPM install in our way from Glimmer up to Ember, do you think that they'll be able to then, extract some of those hardened pieces of Ember out of Ember and then give us a solution inside of the Glimmer ecosystem based off of the Ember ecosystem? Then not have so many varying different opinions or different packages or add-ons or libraries that you may need to pull from that you may just have like a set of Glimmer-approved libraries or add-ons to use to then, get your way up to this full Ember app. Do you think that that's a road they're taking? Or a possible road? TORAN: Yeah, I think for sure. A lot of the talk right now if you're in the Glimmer channel on Slack in the Ember community, I think the next big step here is having the ability to take a Glimmer component as it exists today and use that, extrapolate from there and the plan is to prove out things in a more experimental ecosystem as pre-1.0 Glimmer ecosystem. As they become more solid, we essentially just adopt them and then use them as a first class. In Ember actually, this isn't true but I envision a world where in the months ahead, we're essentially using Glimmer components in Ember so I'm already challenging myself with how would a library or add-on author help people make this progression from Glimmer to Ember if they don't do something like I've done here with Glimmer Redux because eventually, there will be this shared component world, at least in the middle ground, where Ember has both Ember components and Glimmer components. I think it's a road yet to be traveled and that's what I'm excited to be on the podcast and get people talking about building libraries for Glimmer, just because there is not a cow path or a paved road for you right now. I think if you learn just a little bit of Rollup or you dive in and take a look at the DI system built in a Glimmer right now, there is a lot you can actually do with it. I know there are certainly big named add-on authors already checking it out in preparation for such a migration. WIL: Besides the whole Rollup process, was there any other friction points in integrating Redux with Glimmer? TORAN: One that I want to call out but it is, I believe still Rollup related. It's mostly a PSA, to warn people. If you are building one of these little libraries like I talked about with Glimmer and you're going to do a Yarn link, which means that you're going to just work locally and not really publish to NPM until you're done, be aware that if you're Yarn linking and then going over to another project to test this Glimmer library, then you'll actually get temporarily two copies of Glimmer. In fact, that is how this Rollup plugin I wrote -- sort of 'bring your own build' for Glimmer -- became essential as I was like, "I'm getting two copies of the Glimmer component," so what was happening is example, I was playing with this connect API, it was always calling into the wrong Glimmer code so the code that I was expecting in my add-on was never firing. We come to find out when you're not doing Yarn link or you're not working locally, this isn't a problem. Actually, Tom Dale reached out and helped me a little bit later because my first version of the Rollup plugin had this little hack in there that said essentially, "I'm going to mask away this duplicate Glimmer problem," and it turns out it's not a problem. If you are working locally, be aware that you will have this problem as my guess. ELRICK: What gets you most excited using Glimmer? Are there any specific features or things within Glimmer to get you most excited? I guess the second question would be, what do you think Glimmer is going to unlock for the future of app development in Ember? TORAN: I think the first thing I get excited about was visible in this talk that Tom Dale gave a couple weeks ago. I'll try and dig that up for the show notes where he show the advantages of Glimmer over the competition today. The big thing that just blew me away was some of the advantages over, even Preact, which I was kind of surprised that a lot of times there's this rivalry for performance especially between React and Angular and Ember but no one ever really talks about Preact, which is known in a lot of ways as the thinner, lighter-weight React, if I'm not completely wrong. I'm sure somebody is going to be table flip on that definition. But my view was that if you were really performance-hungry, you could check out Preact, which was for performance reasons there was a smaller bundle size so you're just actually shipping less JavaScript, which means they're parsing less JavaScript and Tom went directly after this library in his talk and just showed a very interesting point at the end. I don't want to spoil it for people but let's just say, it appears to show Glimmer as just an order of magnitude better as a primitive for building web components. I think that is the big draw and how will that make Ember better. I think, mostly in the same way that I just described, where we'll essentially get a component for free in Ember that is just a better performing primitive for the web. ELRICK: I'm not too familiar with the guts of Glimmer but from what I understand, Glimmer compiles down and it has some opcodes that then compile down to binary. Is that correct? TORAN: Yeah, I think there is a binary format that they're shipping or they will soon be shipping. If you're really interested in the technical details of that, I'll definitely be sure you check out this talk from Tom because now the real magic behind this is they essentially boil it down to the ability to compile these templates down to 'byte code,' as they call it and Tom has a really funny part in his talk where he says, "You know, it's not a marketing term, this byte code word," and it becomes true because later in the talk, you hear that, essentially the Glimmer VM or the big value add of Glimmers VM is that you're just feeding it with byte code until the next 16 millisecond buffer comes up to paint, in which case you just pause and that allows, I think as he describes, less jank or allows less freezing up that main thread because you're releasing control back to the UI every 16 milliseconds, essentially. ELRICK: Yesterday, there was a meet up with a lot of the Ember core team. Ed Faulkner had made a point that since Glimmer compiled down to byte code that then is not too far of a stretch to then use that with something like Web Assembly, that with then give Glimmer an extreme performance boost. He sets up Glimmer to be used in what can be potentially the future of the web, which is Web Assembly, which I thought was really interesting and it kind of blew my mind to think, "Oh, yeah. That is true since it compiled down to byte code and Web Assembly compiles down to that." We can get that performance boost in that Glimmer is forward thinking in a sense. TORAN: Yeah, man. I totally agree. One of the things I honestly value about the Ember core team is they're very both tactical and visionary at the same time, where in the short term, they're doing things to accomplish real pain points we have but without anyone really realizing it, they're also setting up the stage to solve huge problems that we're all going to face in six, 12, 18 months. I definitely appreciate and love the work these guys are doing. They should hear about it. Obviously, this is all open source and most of this time is gifted, just given away so I really appreciate the core team. WIL: Speaking of performance, we know that the Ember has a run loop and basically, most of these libraries have some sort of loop that determines when they should batch things together or render things to the screen. Does the Glimmer have this concept? What do they take advantage of to make it as performant as you say? TORAN: Yeah, that's actually a really good question and I'm probably minimally equipped to answer it but the short version of it is there is no equivalent run loop for batching work that I've seen inside of Glimmer. Instead, you're more directly interacting with request animation frame, which we miss directly from Mozilla here but requests animation frame tells the browser you [inaudible] browser call specific function to update an animation before the next repaint. Where does this come in for Glimmer? Essentially when you call set or you decide to change a property that Glimmer is listening to and if anyone was not familiar with Glimmer, you designate this by using the tracked attribute. The tracked attribute, when you change a value, it fires this 'set property did change' and behind the scenes, 'set property did change,' if you are familiar with Ember, in my mind is close to 'notify property change,' which is what happens when you do Ember.set. If you've ever actually change something in Ember behind the scenes, there is a notify property change event fired and then we queue that work and it's a similar-ish process except that there is no run loop. What we do is we just call schedule rerender, I think in Glimmer and that just fires off request animation frame to try and rerender within that 16 millisecond window before the next repaint. WIL: From my understanding, the request animation frame is Glimmer's run loop essentially. TORAN: I think I saw actually a discussion between someone at Ember core kind of saying in the public channel that, if you're using Embers run loop, the equivalent-ish today would be request animation frame but the point came up that there's really no way to have a different set of cues because Ember itself has many different cues in the run loop and request animation frame, as far as I know really is just one function with a single callback, where you try and fit in as much work before that repaint as you can. I don't think there's prioritization that you would get in the Ember run loop. But at the same time, I'm not sure if that's actually a requirement. I don't think request animation frame was as mature as it is today back when backburner, which is behind the scenes of what Ember run loop is using, was built years ago. ELRICK: Since Glimmer is using requests animation frame and not the Ember run loop, is it going to continue to use requests animation frame in the future or they're going to develop like a run loop equivalency for Glimmer? TORAN: That's definitely out of my depth. I know from looking inside the code, the rerender work essentially calls like a 'begin,' to say begin doing your work, which I believe is like the reconciliation type work if you have a React background, I believe. I don't know what decides to end that. If the request animation frame is truly saying, "We're at the 16 millisecond budget and we're going to quit feeding the Glimmer VM byte code instructions now because we need to go back and paint." I would guess that that is the high level narrative but I actually don't know the implementation details. ELRICK: Since Glimmer is pre-1.0, it's a place for you to experiment, try out new things, really exciting area to play around in. What kind applications do you see people building today using Glimmer and what's the good application that's a good fit for Glimmer right now for you to experiment with? TORAN: The big application that I've seen that exists is being built with Glimmer in its current form is the Glimmer Playground. The Glimmer Playground is an area to go mess around with Glimmer, if you've never used it or you just want to go [inaudible] with the basics. As far as what is an ideal application, honestly I think we're at a point where we need to push the bounds of what a purely component based library can do. I think if you could come up with some kind of basic routing story and have a mechanism to share state and bubble events, whether that's Redux or some kind of home grown service layer at some point. That would allow you, in my opinion to build just about anything. The only caveat that you're going to be missing is a ton of opinions and you're going to be paving new grounds so just be aware that happy path for any pre-1.0 is be aware that they could change anything, anytime. But that shouldn't really restrict you from making a hobby project out of it. Back to your original question, I would say building any app that you're okay to go back and rework, not necessarily reinventing Facebook or something like that with it at this moment but at the same time, it would be great if someone did in a hobby way because we need to see some of the constraints and challenges. I got playing around with it myself and noticing if I'm going to build anything with Glimmer, I've got to have a way to share state and bubble events up to the single atom at the top that allows me to share all state. I think without some experimentation, we just won't know what apps are possible. ELRICK: You've been talking a lot about Glimmer today and using Glimmer. Since Glimmer is pre-1.0, are there any limitations that people should be aware of when they're going to be going into building a new Glimmer app? TORAN: For Glimmer Redux specifically, one of the challenges that people would see and they should know about if they're going to use this little Glimmer library, is that it doesn't yet allow you to write reducers in TypeScript, which would be a little counterintuitive because if you get into Glimmer, you'll notice the big differences -- everything is in TypeScript and not JavaScript. Luckily though, I think this is really just a build tool decision. Truthfully, the spike version of this that I have where you can use TypeScript, it doesn't require any change to the Glimmer Redux library at all. In fact it's completely unchanged. The difference here is that the Rollup plugin I use needs to see a change. It's kind of weird in that way, back to my point earlier where you kind of bring your own build chain and one of the things I don't like right now, which is the reason I haven't published this TypeScript version of it is that I'm actually doing a TypeScript compile of all the reducers or middleware in the Rollup plugin. With the mass confusion right now between Broccoli, Rollup and Babel, I just don't feel really great about it. Mostly because I have not truly been in the guts of the Glimmer app build tool or the application pipeline yet and I want to be a bit more educated there before ship something, back to being a Midwest developer here. I just don't feel good about shipping something and say, "Oops, we got it wrong." I take a lot of time and I also take a lot of pride in what I am shipping so I want to have a really good story about TypeScript. It does make for a little bit of a weird experience: bouncing between Glimmer components written TypeScript and flipping back to reducer file written in JavaScript. just be aware of it and at the same time, I didn't want to completely halt shipping it because again, I think we need to actually build apps with this and a concession here being that, of course you have to write reducers in JavaScript was still enough for me personally to get some value out of building Glimmer apps and honestly, it got me building them sooner. WIL: Is there a way to use Glimmer Redux without the Rollup? Can we import something into our Glimmer app to use it or this Rollup is required? TORAN: Yeah, that's a great point. You can omit the Rollup plugin entirely. What that results in is you'll have to do some hand wiring yourself. One of the upsides or one of the benefits of this Rollup plugin that I wrote is this conventionally provides a store and redux-thunk, kind of like a happy path for people who are just not familiar with wiring up their own Redux store. If you forego this plugin, you just have to do that yourself. You may actually have to do some kind of Rollup hacking in your Glimmer app, which is the thing I want to avoid. The one in particular that I know you'd have to do is there is a Node ENV that is looking for a production setting in Redux so the first thing you have to do is use a Rollup replace plugin to replace Node ENV with Ember ENV. If you can't do that, you actually get an error in just trying to stand up your Glimmer app with Redux. ELRICK: Toran, are you giving any talks or have any books or anything that you want to get out there and talk about? TORAN: I'm not actually on speaking circuit right now. I am certainly, probably like you guys are, thrown a talk or two together for the EmberConf proposals that are now out. I think they're open until November 21st. If anyone is thinking about submitting a talk to EmberConf, this should be in next March. Now is the time to get those in and I certainly have one out there but I've got one, off the top of my head that I would certainly like to find some time and submit that's related to Glimmer. ELRICK: Cool. We had a wonderful podcast today. We touched on Glimmer Redux and Glimmer and I want to thank Toran for coming on. Thank you, Toran. TORAN: Thanks for having me, guys. The fifth time I have to be on, I don't know if that will be in 2017, though. ELRICK: Yeah, we're going to bring you back for a fifth time and I would also like to thank Wil for coming on the podcast as well. Wil, thank you. WIL: Thanks for having us, Elrick. ELRICK: Anytime. Toran, if people want to reach you, is there a particular place on Twitter or anything that people can reach out to you or email or anything? TORAN: Yeah, at GitHub, I got my email out there but also on Twitter, of course. You can reply me there. If you have a question specifically about Glimmer Redux, of course you can got to GitHub and throw an issue up there or hit me in the Redux channel on the Ember Community Slack. ELRICK: Thank you all once again for listening. This is the Frontside signing off and if you want to reach out, you can always hit us up at the Frontside.io and we always want to hear about your new project that you're working on. Thank you for listening and that's peace from the Frontside. WIL: Everybody have a good Thanksgiving!
Sam and Ryan talk about uploading images to S3, a new Storefront API for dealing with server errors in Ember Data, how to be a good community citizen when it comes to publishing consumable libraries given that our package managers now use lockfiles, and some ongoing work on the Ember CLI Addon Docs addon.
Alex Matchneer: @machty | FutureProof Retail Show Notes: Charles and Alex Matchneer have a great discussion that centers around routing in Ember.js: what they want to see in a router, what problems it solves, what's wrong with the routing solutions we currently have, and what the ideal future looks like in respect to routing. Resources: Episode 067: ember-concurrency with Alex Matchneer Cordova ember-rideshare react-router Transcript: CHARLES: Hello everybody and welcome to The Frontside Podcast, Episode #86. My name is Charles Lowell, your developer here at the Frontside and podcast host-in-training. I'm flying solo today. It's been a while but that's okay because I've got a really fantastic guest on. Actually, we debated this at the beginning of the show, whether this was the third or the fourth time he's actually been on but no times are too many so hello, Alex Matchneer. Welcome back to the podcast. ALEX: Thank you. It's great to be back. CHARLES: You're still at the same place that you were the last time. ALEX: Yeah. Still working at FutureProof Retail. I'm still working on bunch of mobile ember-cordova apps and that's definitely occupying on my time. CHARLES: Nice. Because FutureProof Retail has a large hardware component and we were doing a series on IoT, we were originally going to have you on the show to actually talk about that experience of what it's like to be a part of a startup and develop software that's going to be running on a bunch of devices and the unique set of problems that poses. But in the pre-show, we decided to scrap that because there's actually a topic that we're both very interested in and you've been heavily involved in lately and might be a really interesting preview as to what's coming in the Ember community and at large. Today we're actually going to go back to talking about the same subject that we talked about in our first podcast, which is routing: what we want to see in a router, what problems does it solve, what's wrong with the routing solutions that we have today. Talk about what that beautiful, ideal future that we want to live in looks like with respect to routing. You've been thinking about this a lot lately. What have you been thinking? ALEX: I'm an Ember core team emeritus and back when I was on it and I'm a lot more active, I did a lot of work on the router, particularly with how it handles asynchronously loading data when you click on links and go to different sections of your app. I spend a lot of time over the last three or four years figuring out the nice patterns for what you actually want to use if you're building out lots of Ember apps. Then kind of around that time, right after landing some cool stuff and some not cool such us query params, which has been a challenging aspect, I start working at this company FutureProof Retail that is like 90% of the Ember work that I do there is in mobile apps. We use Cordova so we're basically running these apps inside a web view, inside either iOS or Android so that we can stay with the technologies we are most familiar with, such as JavaScript and CSS and HTML and build apps using that. We can use Ember to do that. What I found was that I couldn't really apply a lot of the same patterns, all these nice conventions that Ember router gives you. I couldn't really find a way to map that onto what I need to build in mobile apps and there's a few different reasons. I got really busy with the startup, just trying to build these things and kind of went off the happy path where I really just couldn't find a way to make it look like an Ember app. One of the nice things about the whole points of convention over configuration as this sort of Ember and Rails philosophy is that, one of the benefits is that if you know Ember and know Rails, you can drop into someone else's apps as long they're following these basic conventions and immediately know how to be productive and know how it's structured, know how to make a change to it and have it maintain a convention and not just have everybody who's using some framework build these totally different apps from each other that have no shared conventions and whatnot. Everyone is supposed to be able to learn from each other, grow with each other as long as they stay with these conventions. I couldn't really find out how to stay within Ember conventions and build this mobile apps. For a long time, I just didn't really contribute too much to the Ember router at all. I kind of fell out of touch with how most people are using it because most people are building these desktop-centric apps and here I am working on these mobile apps after three years. CHARLES: What are some of the specific use cases that were just impossible to, or not impossible but presented a challenge? ALEX: The first one is which is I think is actually one of the easier problems to solve but still some challenging is that you want something that's called stack routing or stack navigation in a mobile app, which is if you're actually building a native iOS app or an Android app, they both have different names for how they provide you this. But you're thinking of things in terms of stacks. In Android, you might open another activity, which is a full frame of a page in your app and you can push it and then when you press the back button, which is built in in Android phones, it'll pop that off the stack and take you back to where you were. In iOS, they give you a UI navigation controller and let you push and pop view controllers and that is how they want you to think about these applications. That is contrasting to what Ember makes you think about, which is go and define your static hierarchy of all the different places that you can be in an app. But with stack-based navigation, you don't necessarily know upfront all the different orderings of which frames are going to be pushed onto what and you might have situations where you want to be able to dynamically push, say an 'Add a Credit Card' page to where you are and maybe it depends on some data that's been loaded at some lower level in the stack and you can't model that as nested routes in the way that you might think about it in classic Ember apps. It's a different structure -- CHARLES: Now, when you say lower in the stack, I'm curious, if you're entered in aren't you... Oh, you mean... I see, previously in the stack. Okay, so lower in the stack so you're thinking like your current position is at the top of the stack. ALEX: Right, yeah. CHARLES: I see. Now, let me just clarify this in my own head. Your Ember routing structure is ultimately realizes a static tree but at any moment, you are entered into one path through that tree so you do have something resembling a stack. It's just is it the pathways that the ways that you can actually get nodes onto the top of the stack is you're limited because that can't be dynamic. ALEX: Yeah, but even then, it's hard to describe what the difference is but the kind of stack that you're thinking of in terms of the classic Ember router map is more like you're in these different substates than you are different frames that you've pushed onto your -- CHARLES: There's a finite and fully enumerated set of next states. ALEX: Right. To be very concrete, if you have a post route and then a post show route and then a comments route under that and these are all nested in a row, then if you're in the comments route, you are in a kind of hierarchical stack that might have loaded the post that you're looking at and maybe the post call-to-action above that and the comments for that but you're still in one thing. You've just expressed that one thing in terms of these substates so that every other state that's in the parent state can share the same data loading. That's different from saying, "I'm on this page and now, I want to push another page on it and maybe tap some of the data that has been loaded on previous pages." That's more of a navigation stack in a hierarchical substates stack. CHARLES: Is the difference then, the data dependency? Because if you think of the Ember classic where you got the static tree, at least theoretically all of the data in the leaf nodes depends on the data that's above. It's not just being able to dynamically push stuff onto the new stack but it's also saying, you want to be able to push stuff that might have no dependency on the stuff further up and it doesn't need to be re-rendered if stuff further up the stack changes. ALEX: Correct. CHARLES: But sometimes it might. ALEX: Right so there are a lot of corner cases that come out if you try to model this new way that a lot of corner cases have been thought out of if everything matched nicely to this hierarchical substate classic Ember stack but not for navigation. If you want to do something that's stacked routing-based, I've had a few different approaches. At our company, we maintain a suite of different apps that are sort of retailer or grocery-centric and the first one we did, which is more popular flagship one is Mobile Checkout, which is an app that lets you going to stores, scan items with your phone and checkout and skip the cashier line, which is great if there's huge lines and you just want to buy a little handful of things or maybe in your shopping cart. But that is like any other mobile app is really conducive to this step navigation approach. Then we had to make a few apps after that such as like another app that is [inaudible] do a manual check then ordering app and other of handful things that you can imagine is might be used on a grocery store. I took the opportunity to like, "I don't really like how the routing turn out the main mobile checkout shopper apps so let's try different things." If you approaches, at least have their pros and cons without really feeling you're solving the problem and one is to maintain your own in-memory stack of where you were, every link to you, you might recall where you were and then use that logic in addition to what's in a URL to decide what transitions to make, which to use Liquid Fire for that. But already, there's these weird growing questions like, "Why are you even using the URL? Is it helping you at all?" That was the main issue with the main app that we did. The other approach was to try and not even use any of the 'router.map' stuff at all. I use the router.map to basically just create one wildcard route. You can use normal Ember to use it like '*half' and that basically collects the rest of the URL as a param that you can use to do whatever you want with. I was using that to basically pass to another, which is internally used by Ember to do the stack-based parsing like grab a little bit of the URL and then parse the param for that then grab another. Every time you could see your stack in the URL. That has its benefits but the worst part about it is that it's getting further away from Ember so any add on that you might want to use at Internet of Things in terms of which route you're in and has conventions like that you just can't use. I can't think of a good example at the top my head but it's like the further you get away from those norms, the less the Ember system can help you and on your own building your own framework. This is all to say that I think I have enough experience at this point to bring home some of the things to Ember and I'm excited to get back into contributing to Ember with this one particular thing that I'm focusing on now, which is... I don't even know what to call it. It's like -- CHARLES: What does it do? The route stuff? ALEX: It's route stuff. Actually, let me get into the other... That's what is tricky about stack routing and tricky to sort of, if you already have to go through a mental hurdle with thinking of the Ember router and as a stack of states or substates and you train your brain to think that way, it's really hard to take yourself out of it and realize that what you're trying to build with like a classic mobile navigation is almost looks like the same thing but it's really different. The other challenging problem, which is specific to our particular app is that you wouldn't think of it as a very heavily server-driven app but if you're writing an application that at any point can get a message from the server like, "Hey, your status has changed," and that state is heavily coupled to navigation of where you're allowed to be in your apps for the state of some certain model, then you're going to have a really hard time, I'd say in modeling an Ember. I have a really hard time convincing people of this until they've actually tried to do it themselves, which is why I'm going off and just building things showing people. CHARLES: You don't have to convince me because I think one of the biggest problems is the router is like the one non-reactive piece of Ember, which is unfortunate because it's essentially, what is the equivalent of the Redux store in a Redux application, where it's the state that drives literally the entire application and yet, any type of non-hash change driven updates, you have to manually manage. Every time that we've done it, it's been a problem and depends on what data, at that point you have to be very thoughtful because, at least from the highest level, if there's damage to a piece of the tree higher up, you need to realize those effects of that damage or that change all the way down the tree. ALEX: Exactly. That is a great way of putting it. This is maybe a good time to mention this thing called ember-rideshare. I've had a really hard time describing these problems to people so I figured what I would do is write this blog a few months back, a little article called ember-rideshare. It's just a given name to the kind of app that still really hard to write in Ember. It's a mobile app. It involves stack routing but the other part is really difficult about it is this problem of the router being in a silo. It is reactive but it's only reactive to that URL. Other things changes, they need to, like you said come in and patch up something else about the router in case you add some URL that is no longer able to present some model of whose status changed. That's an article on a blog that I can probably link to in show notes or something. When I talk about ember-rideshare, imagine using Ember to build Uber or Lyft and it's got just the slightest bit of the whole thing. The whole point of the app is to coordinate your client-side request of I want to ride with the server going off and doing a bunch of things and finding a nearby driver, displaying you bunch of driver locations and it'll show up. Then finally, find you a driver. It's a constant communication. Throughout that point, you can sort of imagine modeling all the different screens as routes but the routes that are actually allowed to see at any given time are heavily dependent on what is the current state of the user's current ride. But you shouldn't be able to go to a route that says like 'cancel ride request,' if you haven't requested a ride in a million of these other things. If you're an Ember developer and you think that's an easy problem to solve, you're probably thinking, "I would use before model hook when I'm entering that route to check the state of the model," and if it doesn't make sense for the route of entering, I want to transition elsewhere. That's fine. That's good if you're doing an app if the user is the one deciding where to navigate to. But then when you're on a route like that and then the server tells you that your ride is done, you can't still be on that route so you've got to have some kind of validations that is like, "This is no longer a valid route to be in. Is the user still in this route?" CHARLES: "Where am I going?" ALEX: Yeah. Before model doesn't really help you. It's this one-shot discrete event and you just can't capture all the different things. The ember-rideshare describes some of these problems a little bit more detail but that's the main issue with it. Like you said, what is actually missing about the router? Maybe it's reactive but it's only reactive to the URL, what about all these other things that are happening into your app? I think there's a handful of APIs in Ember that they're great but they're kind of siloed off in a way. If you want to make two different kinds of worlds meet, you've got to write a bunch of your own code yourself or you just have to do mentally going back and forth and being like, "I did this, so I can't use this kind of API." I did a lot of work on the Named Blocks RFC, which previously there is silos between if you're passing blocks to a component versus data, you've got to think about them differently and all the ways that you might forward that data to a different internal component, if you want to build these composable, reasonable internals, you got to be kind of split-brain about it. I feel the same way about how the Ember router works. It's only good at dealing with stuff that has to do with the URL and you're on your own, if you needed to react to data changing. That's what I'm trying to fix. Does that correlate with your experience of working on Ember stuff as well? CHARLES: Absolutely. I think that's a great way to put it. I think we've come to a consensus of the problem statement. I am curious to see a big separate query params. I'm going to throw that wildcard out there or maybe we should save it for later. ALEX: Yeah, I definitely going to come back to it. If I say all this cool stuff and I still don't have a solution to that, then what am I talking about? CHARLES: Right. ALEX: Which to be honest, I haven't thought of every single possible thing. I'm doing the thing where I talk about it on a podcast that everyone can guilt me into really finishing it. I actually really think that I'm going to finish it. I'm very confident in stuff I'm working on. I'm very excited to bring it to people but it is not all 100% fleshed out and I definitely appreciate anyone's help to those interested, understands the nature of the problem and wants to help me work on some of this stuff and like that, in Ember community Slack or wherever. CHARLES: Yeah, I'm really excited to hear it and see in what ways we might be able to contribute. ALEX: Basically, the goal is to find some underlying primitives that can model the current behavior without mistake because obviously, we can introduce something that's going to break into Ember apps. Basically, to recognize that the URL is something that goes through multiple passes of transformation, to eventually become the thing that displays stuff on your screen, from the very foundation of it, and this is the actual mini-course of what Ember router does internally because it involves a few different libraries and maybe this is a re-hash from the podcast that I did with you guys but -- CHARLES: Can I just say that there are some things that the Ember router really does right, that are fantastic? One of those things is it baked in to every single piece of data. It doesn't do the stack but in that tree that it models, every single node in that tree abstracts away the asynchrony of that node. I think that's absolutely huge so you get both the dependency enumerated like these are the things that I need to marshal the data to render myself and it's implicit that it might take some time. I might need to draw on a couple of different things to actually assemble this data so the asynchronous nature is modeled up front and it's implicit and it's there every single time, which turns out to be the right thing. The sampling that I've missed has been an excruciating void in all the other routing solutions that I've tried outside of the Ember community is that they just punt over asynchrony to you. You deal with it, not our problem and it's like, "Actually, that is the problem." Anyway... ALEX: That's a great point because if the router doesn't help you with any of this stuff at all, then it basically means that every one of your pages that you might want to render after the fact, probably has to have some loading logic like if data is loading, show us spinner. Otherwise, here's all the data -- CHARLES: Yeah, if something happen wrong. ALEX: Right and sometimes that is actually what you want to do. Sometimes you want to do these skeletal in UIs that looked like the page that's about to display but the date isn't there yet so everything is, regardless going to be wrapped in these 'if' statements, 'else' statements. I worked in ember-concurrency and some people are using that to basically move more of that loading into controllers, that's fine. If that's what you're actually trying to do and that's what you're opting into, that's a perfectly reasonable solution but most of times, chances are you're entering a route and you don't want to have to teach the entire template tree underneath it that has to handle all these different states. There's these nice ideas that work in some cases and I'd like to make them work in more cases than Ember helps with and a whole loading all the promises and the model hooks and absolutely going into the loading state are really cool primitives that Ember is going to do for you. The other frameworks, they don't try to be opinionated. They won't do any of that for you. Sounds like you ran into that with some of your React stuff? CHARLES: Yeah. I definitely did. There's just not much help when you actually want to model asynchrony. You can do it. It's pretty easy. You just implement the right hooks or model a series of actions, either with a Saga or Epic, if you're using redux-observable. But again, you have to assemble it by hand and you have to generate those abstractions by hand and you just want to have them at hand already and not have to worry about that. But the advantage, though is that generally those ones that you do have at hand or that you generate are fully reactive. If new information comes that's germane to that particular leaf in the tree or that particular note in the tree, there's no difference between the initial state and the update state. Whereas, in Ember, you got your first shot and then that data is now at rest. ALEX: Right. I definitely have been looking at React router, in particularly v4. I think it's all contentious for people to see it at first but being able to put things like in your render function, you can say, "If this data is present, something that's going to be past and be a prop or something," then show a loading spinner or otherwise, start matching these subroutes. That's really cool. That's expense that you can't look at essential map of all the states of your router can be in but that's also a real problem and if you can demonstrates that the state world is not in a separate silo than the routing world. CHARLES: With great power comes a lot of bugs. You do run into a lot of things where you have rogue matching. You have random things that are inside your view tree that are matching against the route and they just render and you have to be very careful because it's almost the difference between blacklisting and whitelisting. I see what you're saying. It could be confusing. ALEX: Yeah. I think it's definitely a tradeoff. I think if I had something like a match, I might have been able to maybe arrive at a stack routing solution a little earlier. I'm not sure about that. It's definitely something that could be handled by React router. I think one of things that React and React routers better at in general is that everything is, more or less a component that is more easily swappable or something else here. You're not going to have as many of those silos and I really do think, it went through a lot of churn and maybe, some people had trouble, maybe a lot of people, I don't know had trouble kind of following all the major versions. But I think React router Version 4 is pretty damn cool. I think there's a fullest realization of that kind of modular mindset. CHARLES: I think the biggest problem I have with it, though is it requires the view tree to model your routing structure. That bothers me. I feel like you could do the exact same thing. You could have a way to express your routes, not necessarily with a separate routing file. I supposed you could do it with JSX or something but actually have it be kind of orthogonal to your view tree. The way you can model this dynamically updating thing that can match against anything and maybe, even express it all in one place. Although once you get a big tree, it could be hard to control that. The part that I've come into most conflict and maybe who knows, maybe I just haven't used it enough, we've only got one application that we're using the router V4 on. But the fact that it's actually in the view tree, it bothers me. It's in the state objects. It's hard to adapt to Redux because that state is opaque. It's the routers controlling it and I would it to be not have to pass through React components but just be like, give me the firehose of the router state. ALEX: Right. I love what you're saying. If I'm going to bring this stuff to Ember, I can't suddenly make it work like matching within the view tree. That's not what I'm working at or proposing here. All the stuff is basically to empower that firehose to respond to more things that can drives views and respond to them in a live way, not like a one-shot async validation, only when you enter. CHARLES: Maybe this is what the problem that you're trying to solve and one of the things it's really nice to be able to match against anything inside the view tree is that Ember's rendering process of a route is very opaque. The process, by which an outlet gets connected, that's not something that you really have much visibility into. Is that a good statement of the problem? ALEX: That's definitely part of it. You definitely have to go to the documents. I think it's telling that -- CHARLES: I've never done it. I don't really know how that works and I've written a lot of Ember code. ALEX: How what works? CHARLES: How the route gets rendered, like the mechanics around, which I understand how the route object actually, you makes the decision to render its template and do all that stuff. I know it as a user but I don't know the mechanics and I wouldn't know how to extend it. ALEX: I'm not sure if the stuff I'd work on but it immediately make some of that stuff more clear. One of the goal or constraints is to really try and break down the silos. Whatever I'm about to propose bringing to Ember, I want it also be something that would be useful, possibly at the component or template or controller level, rather than just being this thing that lives only in the router's weird black box of logic that occasionally calls hooks that everyone knows about. CHARLES: Right. In a sense, I'd say that they both suffer from that same problem. I'm curious to hear about the firehose. ALEX: To actually get into what I think you're building here, we can dance around it all day and then we -- CHARLES: Just save it for the last 30 seconds of the podcast. That way there could be no -- ALEX: We're swapping JS for React router V4. Bye! It's basically this. What's happening today is that you have a URL, it's going to be parsed in a way that you've tied it to via the router map file, which every Ember app has the place to go to see all the different places that you can navigate to an Ember app, which is great. You basically taught Ember how to break your long URL string into these usable bits and that's going to give you an array of these things that internally who cares what they're called but they're called handler infos and they basically say, "The first element of this array is named application. Every Ember app has one. It doesn't have any params." The next one, it starts getting into what your URL actually is. Maybe it corresponds to the '/post' portion of the URL so that's going to be named 'post,' and that doesn't have any extra params either. Then there's this thing that is post show or something like that. That has a dynamic param because that's the part of the URL as like the '/123' and that corresponds to the post ID. It's basically, if you like thinking of things in terms of transformations or observables or mapping and functional transformations, that's taking a URL and turning it into an array of these useful POJOs of information. The goal is to keep transforming that into something eventually has enough data to display and templates and whatnot. In this giant black box of the Ember router, it's going through those transformations and then it's going to go through this long series of using these params and this useful array of POJO information, start hitting hooks on people's routes to load data. Hit before model after model, redirect all these things to give tasteful names to all the tons of validations and checks that you might want to do. You do cool things in your before model hooks, check if the current user is actually an admin to prevent them from going into any '/admin' subroute. That's a really cool place to go and it's also a great convention. If you're new in Ember app, you realize you can't go on this route. It should sort of click in your head and that sounds like they've got one of these redirect hooks to ensure that you're not going anywhere you're not supposed to go. All these things are really still to this day, extremely strong, well-designed, it went through many passes of review before it landed. I think they cater to a certain kinds of user-driven clicking around apps but they are extremely strong to this day. I think the only thing that's missing is the smell. That example I gave like checking if the user is an admin, it's a bit of a smell that is not reactive. It's a hook. If it passes, great. You're in the route. It's not going to keep on checking that. What I want to do is basically, either in addition to or as an alternative to specifying these one-off model hooks or these hooks that you, not only really just fire one time, have essentially what is an async computed property or an async validation that is upfront about things it depends on. Ember is going to be smart enough to constantly reevaluate these things as stuff changes. It can depend on not just URLs or URL parameters but it can also depend on data. If you're thinking about ember-rideshare, which again is the imaginary Ember app that it's essentially Lyft or Uber, if you have a current ride model loaded somewhere, maybe by a parent route or maybe it's some sort of service, you should be able to specify it like an async property or validation that says, "I depend on ride.state," and for all these subroutes, you would want to say that, either upon entry or any point in the future, if the state ever changes to something that I don't know how to handle that go to some default route. That would be already, particularly in my app, which is a subset of a different kind of ember-rideshare app, that would be a huge help because the only other alternative is to build a sibling-central coordinator to the router that isn't the router but has to sort of agree with it and then, every one of these frames that you might push onto the navigation stack, they have to do some little chunk of code and then invoke this logic and be like, "Did the state change? Go where you're supposed to go," and they have to do that logic. It would be, I think a great win for conventions as it has if it's a benefit to make people shout out their states in advance to empower them to shout out also their data constraints in advance so that you get things like automatic redirects and things change, I think that would be huge. I know that would immediately benefit off of it and I think it would fall in the same kind of problem solving that they worked on like Ember-related stuff which people don't realize how big a problem is until they see there's a better way of doing stuff. I think with that being there -- CHARLES: As an example, let's say that you're an admin and then all of a sudden, you got fired and there's an event that comes from a server that's this person is no longer an admin and it wipes out the Ember data store and then redirect you outside of the admin route or something like that. ALEX: Yeah, that's a perfect example. To be pedantic, I think a lot of people do hard refreshes between login/sign-off stuff but if you have it all in your Ember app, that would just happen automatically. You'd still want the ability to have more graceful transitions because one of the tricky things about having stuff driven by data is that you have this giant matrix of like, "If I'm in this state and this event happens, how do I handle it? How do I make it look well-designed to the user?" But you're not going to be able to hit every one of those constraints so to just have some basic logic that's just like, "Oops, something happened," you're not an admin so we move you to the sign-in page. For in those cases, we haven't fully filled in all those leaks. I think it would be a huge win and you can just progressively decorate things according to the common flows that people take through your app. CHARLES: You know, I'm just imagining this. Model promise, for example would be some computed property, then how would you enumerate your dependencies? Just do the mechanism that we have now? Or are you imagining something entirely new? ALEX: I don't have a strong opinion on it because the moment I start saying what that specific syntax is, more people will agree on what's missing and what we need to have, regardless and be like, "I don't like it." I'm leaning toward something inspired by a lot of my learnings from observables, which is actually we talked about last time. The whole thing about observables is that there's almost limitless flexibility as to if you're in observable, it can take that event. It has been another observable based on that thing. If a URL changes and you're listening to that via observable description, inside that, you could kick off another observable of Ajax request based on that URL and it doesn't make you enumerate all these things upfront. I think there is going to be a compromise between that. I think when you get into these kinds of problems, you run into stuff like Relay, which is familiar with -- CHARLES: I haven't used Relay. ALEX: Just the idea of dynamically collecting all of your dependencies upfront before hitting the server and asking for specific chunks of data that you need, it's a very promising idea. There's cases of just dynamicism where the data comes back from the server, then you realized that you need this other piece of data and there's no way you could have collected upfront, unless you statically wrote it upfront. I expect to find that with this approach that there's going to be some stuff where you just have to be more upfront about it. But I had a cool little strike the other day on auto-computed properties and I'll also link to that. It's a different way of running computer properties where you don't have to specify your depending keys upfront but your getter function gets passed a getter function itself. CHARLES: It's past the dependencies? ALEX: Not even that. Imagine writing a computer property and the first [inaudible] is a function that you can call to get a property off of this but also track that you've got that property. If it ever changes, it'll invalidate again. That means if you're implementing a [inaudible] in computer property, you don't have to write first name twice, both in your dependent keys and in the actual getter in your function, which I think is kind of cool. I'm trying to make that pattern work for this data loading thing so that you don't have to have this huge verbose thing. You just lift this stuff in one place. I've sensed that the magic will probably break down in some complicated cases but that's what I'm trying to run with because I think it's pretty cool and succinct and sort of the natural evolution of what people think of as computer properties. The other major constraint and this is also what we're talking about because it's one of the best kept secrets about the router or it's one of these things that everyone's benefiting from without realizing it, is that if a transition occurs in the router, everything in the router is going to be a possibly long asynchronous chain of operations that it collects all the data that it needs for the new routes to display. In that time, if something happens, if some hook comes along and has an exception, it can load data from the servers. If something happens then it just says 'transition.abort,' that's going to stop whatever transition is in place and you're going to stay exactly where you were and if you're not stuck in a partial transition state, that's pretty awesome. That's basically database atomic transaction semantics that people have been benefiting from if they've been using Ember for years at this point. But again, it suffers a problem being locked away in the router. That is a cool concept. You should be able to specify like I intend this change of the state this way and if I gave you something that is logically inconsistent or can't be fulfilled, don't leave me in a weird half-assed state that I need to somehow fix and know how to fix all the different places, where I might be kicking off this transaction. I'm trying desperately to preserve those semantics when data comes into it. One of the hardest things to do is and honestly, can be one of the hardest sells for people who are used to thinking about Ember is there's an issue of if you imagine whatever API we're talking about, it's probably going to live on the route. Some kind of hook that might be called resolve or something else, like what is the value of this context object that every function has? Is it a route? It's tempting to want to do that and maybe, that will end up winning but winning out is the best API to get people to use. The thing to realize is that there is no consistent value of this. This implies that there's a state of the world and you're looking at it and currently, these things have these values. But in the transaction phase, there is no stable 'this object' and you can wind up with some weird surprises. I know because, not actually these days but particularly, when a lot of the stuff landed and people started trying to do weird things and these transaction hooks, there's just like, "Why can't I grab the controller? The property isn't what I expected?" Honestly, all the stuff that is gross about query params because of this fundamental violation. You have something that pretends to be a property that is there today but is still driving this asynchronous thing that could fail. CHARLES: I kind of viewed this as playing an off-note in the jazz thing like you only want to reserve using this, unless you're the Miles Davis of JavaScript, don't use this. ALEX: And by Miles Davis, you just mean like the god of concurrency that's incorrect race-condition-y code. CHARLES: Right, so it's just like you've got the right reason and you can spot the one-in-a-million case, where it's appropriate. You can spot it in an instant. ALEX: Exactly. I'm not that person and I don't know too many people who are and that's not the API you want to land. I'm trying to, maybe wean people off on dependency on this because the way we've gotten around it in the past is to use again, is more discrete, get the value functions called 'get model' and 'get params.' These are all very in-depth stuff if you're pretty experience Ember developer but it's a way of getting a value from one of these parent routes when you're inside a transition and the rest the world can't see it but you can because you call this hook at the right time. It's super gross because it's just a method on a route that anyone can call in any given time, whether you're inside this transaction or not. The branching logic of, "Should I look up the data from the transaction object?" because once valid, I should have get the current value of a loaded route. It's really gross to me and it causes real problems that confuse people and causes them to write issues because they've given an API that makes them feel good about treating these things as stable objects. CHARLES: I'm trying to imagine now, just like a spike in my head. I know you don't want to get too into syntax but essentially, modeling the route tree as a set of observables, where essentially, instead of returning a promise from your model, you're just mapping an observable off of some combination of the URL state or what are the other streams of state you want to merge to realize that route. But what I'm not seeing, which I'm sure you also have the answer is the original problem, which was stack routing. What we've been talking about is making the router fully reactive like this fully reactive tree that's always on. But that problem seems almost orthogonal to the stock routing problem. ALEX: It is. It's been very tempting to combine them. Why it is such a hard problem? Because you've got navigation stack, which almost to this route hierarchy stack that [inaudible] about but they're separate so you can't really apply the same lessons. Then you've got stack routing, which is you want the ability for routes to while they're loading, reference data that is dynamically available to them. I don't have a solid answer but I would say, the one thing that I think is going to help is that you have a few options for what you want to stash how you want to represent a URL or where you want to stash your hierarchy. Actually just track it in-memory and if you refresh the page, it'd be like, "I depend on some data that I expected to be there but it's not. It transition elsewhere," which is not a great developer experience. You could want to be able to make changes and refresh the page and continue where you left off. Otherwise, URLs aren't actually used by mobile app users. But the other place that you could possibly put the navigation where event stack is in a query param because that can be fully dynamic and you can just sort of manage every single page. The most current page you've pop is just some top-level route but you're tracking the state on the side. I think if you solve the problem of being able to depend on things that aren't the URL or go through a more complex transition than what the router gives you by default, I think it would be possible to treat that query param or that thing you're stashing in in-memory as another source of data. The other thing that I want to try and make sure that this new API has is really treated dependency injection where you specify all the things that you need and you don't really care from a route's perspective where they come from. I think if you had that, that would solve a lot of problems with stack routing and where it gets data from. To be very specific, today if you were in that post '1, 2, 3' comments route and you needed to access the post model from within the comments route, you would probably do this model for post. Basically you're naming not just the model that you need. You're naming the route that you know provides it upfront, which I think is that. Actually, the real reason it's kind of the smell is that, if you ever need to change the nesting, maybe you need to introduce another level or you want to nest all that under an admin route. Then suddenly, you're asking for the wrong route name. You're not really sure all the different things you need to update if you ever change the nesting of your router. There's solutions like relative URLs that a lot of people thrown around but I think -- CHARLES: To go back in the observable world and specifically, the redux-observable world, it's like a simple map. You're just mapping down off of a global prop, you've got some tree of state and you're just mapping off... What was that like? A model hook and you're just mapping down off of that? Wherever that state lives, you're mapping to it and now you kind of slicing off your little garden hose off of the firehose. But still one huge -- ALEX: I've tried to apply observables to this problem. I don't think I've never seen the observable analogue of is this idea of dependency and injection. To model something as a stream that transforms over time, that's proven to be very useful but to sort of say, "I am an observable that expects these objects given to me," I'm not really sure what that API would look. CHARLES: I would say, just as a straw man perhaps, you have this dependency that it's a well-known location. It's a well-known name. With dependency [inaudible] in classic, it's like, "I depend on the off service. This thing called 'service:off' or whatever. Imagine that you have some pool of state and there's some key called ‘service.off' there and as long as I'm just basically basing my stream, the first thing I do is map off of this and maybe map off of another key and then combined those into a single stream, then I can be sure that I have those things at all times. If they change, my mapping function or my transformation function is going to get evaluated again. Does that make sense? ALEX: Yes, I think we should [inaudible] C without code or something. CHARLES: And maybe I'm thinking about it wrongheadedly but that would be a simple mechanism. ALEX: Could you run by me one more time --? CHARLES: Yeah. Let's say that we've got some authentication service that you want to depend on like you want to inject on it. You want to inject that dependency so why can't you base your stream off of that key? You have observable map, for example. The list of transformations that you would have to do to peel off multiple keys, I'm sure you could write helpers for it. But basically, probably if you're going to be wanting to inject multiple dependencies will -- ALEX: The problem is this. Basically, if you want to write your resolved observable, if this thing based on observables, remember that there is no this in a route because of the transactional reasons of what we've talked about earlier, what are you getting that from? You need to have something passed into you, to be like 'context.get observable blah.' CHARLES: I would just assume that it's implicit. I was thinking a bit basically, the simplest case would just be an observable that was basically taken off of the entire global state or whatever of the router or what have you. The way the redux-observable works is every single epic is what they call them is just a transformation on the global stream. Usually, the first thing that happens is they map down to the local context so the -- ALEX: Like a path? CHARLES: They have a helper like action of type, blah. You only see a subset of the actions that get maps to the Redux store. I think it's redux independent but at least in theory, every single epic is basically going off of the entire global state but the first in reality, what the first thing that happens is you're like, "I am only interested in this subset of the state," so you do a map off of the global state down to your local scope and then you work from there. In fact if you had the convention around that, you could even make that part implicit. It's like I return an observable that it's only seeing the stream of local states. ALEX: That makes sense if there's sort of canonical state of the world but what you're doing when you're transitioning into a route is trying to feel out another state in an asynchronous manner. Redux is the action causes state to change, now the state is this. But the action for type thing, I think that makes sense if you are subscribing to the world global action on this one store when you're constructing this new tentative, may not actually become the store, you're depending on values. What we need in our API is something that depends on values that are from a tentative store. CHARLES: It's similar so in redux-observable, you're mapping actions to actions and you're not necessarily mapping actions here. You want to get state into the equation. ALEX: Yeah and it's so almost observables. It's just this twist of transaction dependency injection. It sounds really over-engineered but the thing is it exists in Ember today and if it exists in a less siloed way, I would certainly benefit on it. I think everyone else would too. CHARLES: Okay. With that hand wave... ALEX: Oh, I didn't mean for that to come as a hand wave. CHARLES: No, no, no. I'm kidding because I think we actually have a lot more to talk about here and we're running out of time. One of the thing that I want to ask is, talking about redux-observable, talking about redux and stuff, have you given any thought as to what this might look as a library that everybody could use? ALEX: I basically have something that's using Ember CLI only because it's so easy to just use it as a sketch pad and get test passing but everything I'm building so far is just ES6 class syntax that can be transpiled in it to whatever. I'm actually realizing, there's a lot of overlap between some of the primitives that are involved and Glimmer so it may or may not have a pass that uses references for tracking when things change until no one to invalidate and refire these async hooks. But either way, I'm going to make sure it lives in the JS usable world and not just Ember's special object model end. CHARLES: Right. Those interfaces are pretty narrow. The things that implement those interfaces are huge and complex but the way, at least I understand it, isn't the reference interfaces themselves -- ALEX: They're really simple, yeah. CHARLES: -- Really simple. It could almost be copied and pasted and not have much maintenance overhead in there. Here's a question and this is probably getting too far into the weeds. Can you not model a transaction as an observable? Essentially, with a flatMap, you would merge in some observable into the chain that was basically a transaction of all the other observables from which it is composed. ALEX: You know, a transaction as it builds up all the new state over time could be part of the main tree and if there is an active transition, then that's future potential state that the world might become and it could be modeled as a leg of the Redux state. I think you could theoretically do that. Definitely worth a try. I don't think I would benefit too much from doing it now and I think this could be a premature optimization but I think there would be just quite a bit of intermediate object collection to express that. I think theoretically it works but how it's going to physically map to Ember in the near future, it would be harder [inaudible] in a way. There's actually a lot of stuff that is very redux-y that again, a lot of Ember people don't maybe know about because it's internal but the way that Ember [inaudible], I think since Edward brought some of his learnings of Liquid Fire back to core Ember, there's this concept of outlet state, which describes -- I'm not an expert on it -- what's rendered where and then each outlet gets a chunk. Like you said, a little piece of the firehose or garden hose, pulled off the main thing so it can just focus on the one piece of state. Those are simple objects that produce this part of this transformation process. That's kind of redux-y in the way that everything just gets a new POJO and stuff changes but it's not strictly redux, obviously and probably won't become that just because it's already good enough on its own. CHARLES: Yeah. I think it's actually good at this point to be hand wavy because the most important thing is to be non-committal about the syntax, like you said because that's when the bikeshedding begins and now it's not the phase. The phase is to come to some agreement about what is that we would love to see. ALEX: Basically, the thing is this. I think people need to realize that Ember won the bet that the URL is an important thing to build apps around and if you have a state that's representable in URL, that state should go in the URL so you can send links around and not break the web and have an app that works that's built on half-assed routing. The only thing I'm proposing is going to make that go away. It's just that there is already this giant world of stuff that's not expressible in Ember today because it is driven by state. If you make that as easy to express and as upfront to express, I think you can have shared conventions versus what everyone is building these apps that I have to do, which is to make a sort of separate router of state-aware stuff and not have to make those two things agree with each other because it's really hard. CHARLES: Right. At that point, you're writing your own framework. Maybe this is the next big thing because I feel like Ember usually has the best stuff way, way, way, way before. Now, we're finally getting to a point where everybody seems to realize that having a CLI is absolutely critical to the developer's experience and most frameworks aren't taken seriously until they've achieved that. It was the same thing with a router back in the day. I'm wondering what that next thing is. ALEX: I don't know. I don't think this is going to be it. I just think it's a good progression. I think a way forward that progress is still a pretty legit central structure to build apps around and just would be welcomed. CHARLES: When are you going to be done? ALEX: About two or three days. I don't know. I think I'm basically going to be continuing to get feedback like the way that a lot of that original router stuff came back or it's just like constantly hit people with real examples, Ember twiddles, things are just like, "Oh, yeah. That thing. That's a cool pattern. That sucks in my app. I didn't realize that until I saw this example." These things that really teach people why this is necessary because that's going to get people's urge to be like, "Well, you could just do..." Oh, you can't because the thing that's hard to explain. It's going to be a lot of that regardless and I hope that will kick off in the next few weeks. CHARLES: And the focus of that is going to be the ember-rideshare application. ALEX: I think that's a good one. This is one that everyone's familiar with. CHARLES: Have you already kind of implemented in it, like this kind of Frankenstein-ish, like this is the kind of histrionics that you have to go through in order to implement the style of routing or the style of application using today's Ember? Or have you started to begin experimentation with these new concepts and try to build out better ways of doing it? ALEX: I'm not strictly extracting it from one app. It's sort of combined. Like I said, the few different apps that we had were an opportunity to be like, "This sporadic stuff is hard." The main route recognizer approach was an example to try different stack routing pattern. But the thing that sort of working on is drawing from three different apps and slightly different takes on it. Basically, I have something that is close to being testable in one of my main apps that will be a great chance to validate if all the stuff is as nice as I think it is going to be. CHARLES: Okay. If the people want to get in touch with you, to help to contribute to the conversation or just publicly guilt you into moving faster towards it, how would they get in touch with you? ALEX: I'm at @Machty on Twitter and GitHub and also, the Ember community Slack. I think I'm going to try to get people to talk about this on channel called Dev Dx Router where it's focused on development stuff all around the router. This is kind of funny because I'm talking about this thing that I've only had maybe, 12 people take a look at and comment on and begins these conversations. I think maybe some people are going to hear this and be like, "What are you talking about?" but if it gets people -- CHARLES: No, no, no. You know, the best conversations seemed to be organized around you, man. I'm just trying to think of some of the best development conversations that I've had in 2017 and you were definitely, I would say the one who fomented them. It starts with 12 people but then, if enough people take interest and be like, "Wow, yeah. Oh, man. I didn't even know that was a problem. This would be a cool way of doing it." They have a tendency to balloon and some fizzle out and some end up with real results. Anyway, I'm looking forward to it. ALEX: I appreciate it and likewise, you're definitely one of the best people to talk about this stuff with. CHARLES: Well, I hope other people will love listening to our conversation. With that, we'll head on out. Thank you everybody if you've made it this far. As always, you can get in touch with us at @TheFrontside on Twitter or just send an email to Contact@Frontside.io. We will talk to you next week.
Mike North: @michaellnorth | mike.works Show Notes: 00:51 - Transitioning from CTO to Independent Trainer 03:37 - Customizing Content and Developing Curriculum 06:37 - Bringing a Developer Into the JavaScript Ecosystem 12:47 - Training Developers with Non-Traditional Backgrounds 16:56 - Keeping Up with “Fifth Gear” 19:27 - Developing Frontend Masters Courses 22:40 - “Progressive Web Apps” 34:37 - Web Security Resources: LinkedIn's REACH Program IndexedDB Transcript: CHARLES: Hello, everybody and welcome to The Frontside Podcast, Episode 79. My name is Charles Lowell, a developer at the Frontside and your podcast host-in-training. With me today is Elrick, also at the Frontside. Hello, Elrick. ELRICK: Hey, what's going on? CHARLES: Today, we are going to be talking with Mike North, who is doing all kinds of interesting stuff as per the usual so we'll jump right in. Hey, Mike. MIKE: How is it going? I'm glad to be here. CHARLES: Last time that I saw you, I think it was about a year ago at the Wicked Good Ember Conf and we were standing on the beach, drinking scotch and talking about Fastboot but you were doing something completely and totally different then than you are now so I was wondering, we were talking the conversation before we started rolling, that your role nowadays is independent consultant and personal dev trainer. I was wondering if you talk a little bit about that move from the CTO role that you're playing at your old company to kind of moving into that independent trainer, like why and how. MIKE: Yeah, I do remember talking about Fastboot at Wicked Good Ember. It feels like things have moved quite a bit since then. I have always loved teaching developers. When I've been a team lead, it's the favorite part of my job just because I get profound satisfaction out of helping people get over these hurdles that most of the time took me a much longer time with blog posts and podcasts and incomplete examples and libraries that were out of date and Stack Overflow with half answers. I've decided to dedicate myself to trying to make it easier for people in an increasingly complex web development world to wrap their head around everything. While I was a tech lead or a CTO, I always had to split my focus between helping developers grow and something else. Oftentimes, that something else was where the deadlines were and the time pressure was. It felt a little bit like I was driving a car that only had first and fifth gear where you're like on the bleeding edge of open source and what was the latest commit to master and [inaudible]. Then like, "Oh, let's be extremely patient with this person. They've never seen promises before because they came from another programming language. Let's help them digest this at their own pace." It's this slow and patient process of building up from the fundamentals and then the bleeding edge is like, "Let's use Babel Stage 0." It was very hard for those two aspects to exist at the same time in myself so I decided I'm just going for the training side. That's really all I do these days. CHARLES: It was so, but now would you qualify that as the first gear or the fifth gear? MIKE: That's the first gear. It gets you off the ground. It takes you from stop and gets you moving and then you have to develop your own expertise beyond that. But I like to think I'm developing a really, really excellent first gear. Today for example, I'm converting a bunch of Python developers at LinkedIn who are basically the ops team. I'm teaching them Ember and JavaScript at the same time through a series of about 20 exercises over three days. That process is many weeks long without assistance so this is like, "Let's get rolling much more efficiently and quickly," than via DIY approach. CHARLES: Now, do you find you have to custom-tailor for the environment or the developers moving from like someone coming from, say C# would have a different experience than someone coming from Python? MIKE: Absolutely. When I have my material, I have sections that I can drop. If you are a C# developer, I do not have to explain conceptually what 'async' and 'await' mean. You've been working with that for a while. I probably throw up a little example in C# and then the equivalent in JavaScript to sort of create a bridge from your existing expertise into the JavaScript world. Another one -- this is very true -- is teaching Ruby developers how to use Elixir. You don't have to say, "This is a router. We have controllers. There are actions and controllers." There are so many parallels that really it's more useful to help, rather than teach things from scratch to create connections back to the expertise they already have so they're not starting from zero and they can say like, "In the Ruby world, I would think of doing XYZ." Now, I have a map in between that and this new thing. CHARLES: Obviously, there's a lot, a lot, a lot of languages and environments that you could transition to, probably more than matches your own personal experience, in doing that frontline development. What kind of research do you have to do to develop a curriculum for, say someone coming from Clojure or someone coming from Scala or something like that? Maybe that never happens. MIKE: I have a pretty, pretty broad background. My entry into programming was a subset of C and then I graduated to C++ and Java and Ruby and I used to do ASP stuff. I've written iOS apps. I feel like I have enough of a foothold into various areas like I know one JVM language. That is usually enough. If you're running a lot of Clojure, I can at least speak Java to you because odds are, you're working with that and you're seeing that and you know it. Oftentimes, I have what I need. There are situations where I can borrow something in a very cursory level. Not to rip on Scala but I have not found it valuable to make connections to that particular language for clarity and [inaudible] but I have used Haskell before and I'm not a Haskell developer but it is a pure functional language. When trying to help people understand how is this different, then the JavaScript got them running where the Ruby ends up running. It's useful to use something like that. It's a very small language, very simple and you can wrap your head around the basics. ELRICK: What are some of the particular challenges that you face when bringing in a developer outside of the JavaScript ecosystem into JavaScript since JavaScript is kind of the Wild West that you can do everything in JavaScript? What are some of the challenges you face in bringing in a new developer from Python or C or whatever that may be? MIKE: You put it very well. It is definitely the Wild West. You can do anything if you have enough [inaudible] yourself and enough power to get serious stuff done. Really, it's like the explosion in number of choices and tools, the explosion of complexity. I learned JavaScript when it was something that you sprinkle on top of your Rails app for a little interactivity, a little animation on a screen or something like that. I was lucky to learn it at that point in time when that was the norm because I've been able to gradually accumulate for more than ten years now. The tooling like using Grunt, using Golf, using Brunch and then stepping up to other more sophisticated build tools. I learned those one by one in the context of real projects. Now, it's like the mountain is so high, people don't know where to start so that's a big challenge for developers. To throw them into a meaningful project like if you asked a mean JavaScript developer, not angry but the average JavaScript developer, they're like maybe -- CHARLES: I should dare to say that the average JavaScript developer is mean. MIKE: A little bit and probably maybe [inaudible] with me as well, depending on [inaudible]. But they're going to spin up some project with webpack and Babel and all of these tools. If that's your first exposure to the language and to working with the language, you're operating in an environment that you don't understand. Research shows that is the less effective option there to slowly building things up over time. I spend a lot of time going back to the basics and making sure we're not working with promises until we've explicitly focused on them, chained a couple together, managed errors and then now, we can work with Fetch. We're not going to jump into that and throw ourselves into this deep end of the pool. We want to incrementally build up skills. It takes a little bit longer but when you have that understanding as you're learning, you get a lot more out of it because anything that you can't get a grip on to as you learn it, it sort of just evaporates into thin air and don't retain that, even if you kind of fill in those holes later. CHARLES: Yeah, it could be so hard too. Actually, this has been an experience that I've been having, I would say almost for the past two years, as the tools advance, not only you are starting from a place of not understanding but the tools themselves do not teach you. I've had two moments where I got really mad. One actually was on an Ember project and one was a project using webpack but it was the same fundamental problem where in one I was actually working with someone who was very new to JavaScript and an error happens and the stack trace was some just big bundled garbage that gave no insight at all. MIKE: In vendor.js. CHARLES: Yes, in vendor.js or in bundle JS. It was like, "How is anyone supposed to learn?" The most fundamental thing about working with Ruby or working with Node or working with anything is you get a stack trace. MIKE: Debugging is really hard. I think it just takes a little time reaching out to people who are experiencing the Stockholm Syndrome like most of the time, JavaScript developer. We all are working with Ember CLI and webpack. I'm not ripping on these tools but we're used to that complexity in our lives. When we see that stack trace, we're like, "Oh, well. I probably need a source map. I'll make sure that that's there. It's natural that I'm debugging a file that the browser is not really seeing like it mapped back to my source code debugging." This is natural to us. But if you put that in front of a developer who hasn't been living under those circumstances, the number of times they raised their hand is like, "What the hell is this?" It is just amazing and it really helps. I've reset my expectations to what a normal programming experience should be and JavaScript does not provide that today. That is really challenging to keep someone in the midst of all that. CHARLES: I feel like it's hard and do you think we'll ever achieve that? Or is it just going to be a constant hamster wheel of progress versus the tooling to educate what progress has been made or to communicate what progress has been made? MIKE: I think the tooling is fine but it's just that we have a gap in terms of learning experience. We just need really -- I'm not voluntary here because I've got a ridiculous backlog -- a couple long tail horses working with vanilla JavaScript, rendering some stuff on the screen, maybe a course of React but no JSX yet, just create component. A couple of things to fill in a gap between where maybe code school leaves off and where you are expected to be by the time you start interviewing for a spot as frontend developer on a team but there's a huge chasm right now. There's the intro guides and then there's professional life and trying to bridge the gap between those is ridiculously a challenge right now due to the huge ramp up of complexity from like, "Let's do some stuff in the console," to, "Running transpile JSX code with async [inaudible]. We've got regenerator in there to polyfill generator functions." There's so much in your average JavaScript at these days. CHARLES: Your work that you're doing at LinkedIn, part of it is trying to bring and train developers who come from more nontraditional backgrounds, including a lot of things like boot camps. What is your experience of their experience coming in? Are boot camps doing the right thing? Are they teaching the right things? Are they trying to kind of parachute them on top of that mountain? Or do you find that they're just at the base camp, so to speak? Because it sounds like your approach is like you've got to really start from fundamentals so that you can understand the layers of complexity if you're going to, someday stand on them. MIKE: I think a lot of the boot camps are doing an excellent job. These days, the employees we have at LinkedIn who come from boot camps, I would bet on them against your average MIT grad every time, just because their education is so practical. It's amazing that in the world of computer science, the stuff that you're taught in school is a little bit farther removed than one would expect, compared to the stuff that we do every day in our jobs -- building real apps. I do not need to know in my day-to-day work at LinkedIn how an operating system works or how to build a device driver. This is a little bit too fundamental. It's the wrong abstraction for practical everyday work for most people. Where in these boot camps, they focus completely on the practical. In fact, I've been fortunate enough to get involved with the REACH program here at LinkedIn, where we hire explicitly people from nontraditional backgrounds like boot camps. They're not all from boot camps but many of them are. We just hired 30 of them in March. The pilot program, I think we've hired two or three in our New York office and it just went really well. It started like, "Let's double down and double down again and double that again." This time, we're doing 30 and I expect there will be a new round next year where we poll even more. The idea is we take these REACH candidates and pair them with a mentor engineer for six months. At the end of that six months, we had to make a decision as to like this person at the level we expect of an entry level software engineering hire. From what I've seen, we're doing really well at preparing these folks and they're unbelievably valuable to the teams that they've been placed in. ELRICK: That's amazing. That's very interesting. Is there a standardized curriculum thing that each mentor will follow to get this person after they entered his REACH program and then ramp them up or is it like each person just goes and looks at what the person knows and then ramps them up accordingly. MIKE: I'd say, it's a mix of both. We have a set of technical trainings for them or we'll have a testing expert from within the company and teach a little testing seminar to them. There's that standardized curriculum there. But the nature of being taught by boot camp or teaching yourself is that you're going to have holes in your knowledge and it's not often predictable where those holes will be. That's why we make sure we do this mentorship very explicitly and over a long period of time so that if it turns out that you never learned about how to work with tree-data structures. That was not part of the go-no/go decision that brought you on but we should probably, at least get you there. At least to the point where if you're traversing a down tree and you're like parent and child, what is this, what do you mean by leaf-level node. This is stuff that is actually meaningful for web developer in some cases. CHARLES: In the context of the work that you're doing with the REACH program but also touching on something that we talked about at the beginning about the first gear and the fifth gear, part of generating a curriculum is still being in contact with what's up in the fifth gear right because ultimately, what you're trying to do is you're working with people who are in first gear or looking to get a smooth transition in the first gear but at the same time, you want to set them up and you want to be in contact for what's in fifth gear now is going to be first gear in five years. How do you feed that in? MIKE: I'm fortunate to have a great team that I work with here. This group that I roll up to in LinkedIn, they're experts and you probably know of like Chris Epstein and Tom Dale and Steph Petter. A 15-minute coffee break with one of these people is enough to keep [inaudible]. Sometimes, it's a little bit like drinking from a fire hose because it's like I spend an hour with a student trying to help them understand like, "This is why a Promise is useful. Here is the callback equivalent," and then now, "Let's dive in to Glimmer. Why this track annotation is the right way to go for automatic updating." It sends me for little bit of a loop sometimes but it is definitely keeping me up to date. The other factor, of course is when you've been doing this for a while. History sort of repeats itself so a lot of the patterns that we're seeing today, I've seen somewhere else. I was working with code splitting when I was writing Dojo JavaScript code years and years ago. I was defining my module layers in a very explicit way. I had to do that. I didn't have done a webpack that would figure out, put these splits are. But I have that experience to look back to and for that reason, it is not often that an entirely new concept comes along. Oftentimes, they're like amazing refinements on things that how to smell like stuff that we've used before in the software engineering world. CHARLES: Yeah or here's something that has never been used, is very prevalent in these other context which we're going to apply here. MIKE: Exactly. CHARLES: And like, "Oh, my goodness. It's a perfect solution." In addition to the work that you're doing with LinkedIn and developing those training curricula and stuff, you're also doing some work for Frontend Masters in an area that's very exciting, I think to me. I'm sure it's exciting to you because you decided to throw a whole lot of time into developing a course for it. That's in the development of progressive web apps, which for me has been like this thing that I'm so curious about but I'm like a kitten playing with a little yarn ball. I want to dive in but I'm just going to tap it with my paws right now. MIKE: Yeah, it's a really interesting area and I think that even if you're not using progressive web technologies today, it's one of these things that sort of reinvigorates your energy for JavaScript's future and what may be possible soon. Steve and I have put together this amazing progressive web app course, which has I think like 18 short examples of iteratively building up a grocery shopping app. If you've used InstaCard or something like that, we start out with app already built and it's like a single-page app as doing everything that you would expect. After a few of the exercises, it works offline. After a few more, you can add stuff to the card and background sync, push it to the API when you come back online. We get deep, deep, deep into service workers. That's one of the areas that my work at LinkedIn and my teaching with Frontend Masters overlaps really well because I've been heavily involved in creating our service worker for LinkedIn.com. I may be able to take some of what we've learned here and disseminate it a little bit so that, hopefully fewer people have to learn the hard way. It's best to keep things simple at first and add on functionality. I'm about to cross like the [inaudible]. This is my favorite just because the example turned out to fit so well and in particular, on Frontend Masters, I think Steve and I have had contrasting teaching styles but they complement each other so well because I'm like the 'melt people's brains' instructor. I love to throw people exercises that are like 120% of what they can do and it's going to hurt, just like when you're lifting weights at the gym, like you're going to beg for mercy but we're going to make you strong. Then Steve, just listening to him, even with I am in the classroom and he is teaching me Electron. He's so energizing and he's really funny too but not in an overtly cracking jokes kind of way. He's just so fun when he teaches. I think it is a really good combination just because things lined up just by luck and through hard work and just the right way out of a couple of important areas. CHARLES: Now, just for people who might not be familiar with the term progressive web apps, what does it encompass? Do people actually call them PWAs? MIKE: No. I'm going to start, though. I like that. That carries very well over a video chat or something. Nobody knows how to spell that: P-U-A? P-W-U-A? It is a rejection of the old idea that in order to take advantage of some web technology, it has to be supported in all of the browsers that we need to support. The idea here is to hold as a core tenet of our design practices, the idea of progressive enhancement, meaning we serve up a basic experience and where we can take on these superhero features, like the ability to work offline, the ability to receive push notifications, we go ahead and do so. If your browser doesn't support this, that's unfortunate. No big deal. You still get a good experience. But if you're using a very recent version of Chrome or Safari or you have a new Android device, these browsers can take advantage of sophisticated metadata or sped up a background process that can serve up data to your app and your app doesn't even know that there's something between it and the API. That is the idea of progressive web apps -- apps that become superheroes where possible and they still work and provide a great basic experience for antiquated browsers like IE8 and Safari. CHARLES: The idea theoretically, you could work without any JavaScript or whatsoever. What's the ground floor there? MIKE: That is ideal. I think server-side rendering, which is what you're talking about there, even if JavaScript is not working, just HTML and CSS will provide a basic experience. That's great but that's not a modern browser technology thing. If you have JavaScript turned off in today's Chrome, like Chrome 60, versus IE9, both of them working with them without JavaScript. What we're really talking about here is app-like characteristics, where we are pushing web technology to the point where you will swear that this came from an App Store. It's on your home screen. It's running in the full screen. You're getting push notifications. It works offline and you can store a large amount of structured data locally on the device. All of the stuff sounds like the list of reasons to reach for native mobile technology because the mobile web is not good enough. But in fact, it has a feature set of this family of progressive web technologies. It's really like a web app that is so good and so modern that it feels and looks just like a native mobile app. CHARLES: That sounds so hard to do right. MIKE: Well, it is now, just because what we have to work with can be thought of it like a basket of ingredients, rather than a solution that we drop in. But over time, as more people start working with these ingredients, I think we're going to see a lot of consensus around the best patterns to use and boilerplate code will fall away as we can identify that the set is in fact commonly needed and not a beautiful and unique snowflake. CHARLES: Because it seems like the thing that I always struggle with is not wanting to put the critical eggs in the basket of a superhero feature or have you being able to provide an alternative if the superhero feature doesn't exist. Some features, if you just don't have it, that's fine. You can turn it on if the capabilities available but certain features are very critical to the functioning of your application. I'm casting about for an example and I'm not finding one immediately but -- MIKE: Offline is a great one. That fits pretty neatly. If you're using an older browser or if you're using Safari, which by the way, I should stop ripping on Safari. For the listeners out there, we saw a commit lend in webkit, where service for APIs are beginning to be stubbed out. No longer do we have to look at length. Service worker, enthusiasm and Safari has got it in the five-year plan. There was motion last week. We haven't seen motion in ages so thank you Safari Team. Thank you. Keep up the good work. CHARLES: Is there a discipline of Safari-ologists who monitor the movement of Safari to bring this news? MIKE: Of course, we monitor it because right now, Chrome and Firefox, they are pretty much hopeful in terms of supporting this modern stuff. Opera supports this modern stuff. Samsung's fork of Chromes support this modern stuff. Especially when we think about the mobile web, you got to worry about Android and you got to worry about iOS Safari and right now, like we've talked about these progressive web apps, you don't get that superhero experience on an iPhone or an iPad. Once we crossed that threshold, this is going to have a breakaway level of adoption because there are no more excuses. Essentially, for a mobile web experience, you can send push notifications to the user. That is huge. That is probably at the top of the list for why some people use native apps, instead of mobile web. The more we can do that, the more we can make it so that a great LinkedIn experience can be delivered to your phone without having to install a binary. I just have to update Facebook the other day and it was over 100 megabytes. Why do we need to do that? You should be able to make it work with less. I'm sure that there's some great stuff in there. Apparently, Snapchat filters are popular but I don't need this. Can we code split that away or something because I don't want to have to download that? I can't even download it on the cell network because it's over 100 megabytes. It's really exciting to see the web start to compete with this heavy mobile experience because now I think is ready. CHARLES: Now, when you talk about push notifications, you're talking about being able to send things to my lock screen. MIKE: To your lock screen while the browser is not on the foreground, while the app is not open. Essentially, you're installing a lightweight process that runs in the background. It receives events that originate from your server and the user can tap on them and then your little lightweight worker process in the background decides what to do when that tap happens, like open up the app, take them to this URL or something like that. That is a game changer. That's huge. Or background sync like the user added some items to their cart and then they lock their phone and now, their plane has landed. That's why they were offline and they get back on the internet and without them having to touch their phone, now we can push that data to the server and everything's in sync, rather than like, "Please revisit your app. We need to run some JavaScript code to flush IndexedDB or API." It still feels like a hack at that point. This is a fluid experience. ELRICK: Wow. This is exciting for me as I don't have any more space on my cellphone, thanks to all the apps that I have to install to do various things on the web. MIKE: You're not alone. CHARLES: Yeah, it's crazy and just the amount of code sharing that you can have, I guess that doesn't happen much these days on the web where you've got these popular libraries out on CDNs so that the chances are that you've got jQuery 1.2.1 on your cache, you've got 16 versions of jQuery so most of your web applications don't have to do that. I guess we kind of do the equivalent of statically linking everything. MIKE: There is a benefit near that where we have imperative code managing our cache, instead of just relying on the HTTP cache or app cache, if you have a vendor.js file that is not changing over six months, there is no reason you should be re-downloading that every time you deploy your app or letting the browser evict that, just because memory pressure is high from Google image search results or something like that. We really don't have much control over it. But with a service worker, we can say, "Hold on to this," or maybe like prefetch the next version of the app so that we're going to show you the old version now but the next time you refresh, here's the new version available instantly. It's downloaded in the background and it's like click to update your version, like it's already here waiting for you. That's huge. That's amazing. CHARLES: That is amazing. Although the complexity skeptic in me is thinking, "Oh, my goodness. Now, we've got all this state that we're storing on the server. We have to have data migrations." We need some sort of migration mechanism for our clients-side state and perhaps some transaction and rollback in case you're not able to successfully migrate your data. It sounds like a lot of fun but I'm just imagining we really are getting started here. Has there been any work on that aspect? MIKE: If you've ever worked with IndexedDB, it does have a concept of migrations. Basically, the data you store on a device has a version and when you read in what's called a file but it's a database, when you read that in, the first thing you do is you basically bring it up to date incrementally. You'll bring it in, you're looking for version nine like your code wants version nine. What you see is version two because your user hasn't been at your site for six months and you're going to take it from two to three to four to five to six. Each of those, essentially constitutes a migration. We just have to apply the same principles of forward-compatible changes. The escape hatch here is remember it's progressive enhancement so if we had to destroy everything, fall back to a basic experience and start from scratch, like discard all of our data, it's really being held there as an optimization. Some people use this immutable caching strategy or basically, like rolling out a new service worker version constitutes for the most part. Any data that wasn't created by a user you're going to discard that and you're going to fetch it new. You don't have to worry about like, "Crap. This six month-old thing is still plaguing half our users and we can't get rid of it," like you can have [inaudible]. But you should really check out this course. It is simpler than you think and what we demonstrate is not a trivial like hello service worker. It is taking in a classic single page app, making it completely offline, having it exist on the home screen and I think the service worker ends up being no more than 100 lines of code. It's not too bad. ELRICK: I'm definitely going to check that out because my progressive web app journey is still on just service workers. MIKE: That's very [inaudible], though. ELRICK: Yeah. I'm definitely checking it out. Sounds like a really fantastic course. MIKE: I've been focusing a lot on this area and another one is security. The reason I picked these two is because developers are not really going to learn about these on the critical path to [inaudible] plus they learn about them the wrong way. As the JavaScript world is becoming radically more complex with each passing year, I've tried to target some of my efforts towards areas where they are not getting as much attention as I'd like to see, just because we have to focus somewhere. Obviously, getting the app out and figuring out how to make the build tools work for us. Without that, we can't do anything at all. One of the courses that's coming in September for Frontend Masters is a one-day web security workshop or we'll do with like cross-site scripting, how to work with certificates because if you start playing with HTTP/2 -- the next generation of HTTP -- you will need to generate some certificates for development at least today you need to. I've seen some amazingly smart developers get this dangerously wrong to the point where they compromise their own machine and anything that's on that machine, just by trying to set up dev environment. Typically, I'm an optimist but when it comes to this PWA stuff and security, I am paranoid. I feel like, we as a community need to get together and have the discipline to brush up in these areas so that as we introduce all of this new stuff, we don't end up opening a bunch of holes. Nowhere near the same rigor as put into frontend compared to backend and now, the line is blurred. Right now, we're server-side rendering so our code is running on the backend somewhere so injecting something can really mess things up in a bigger way. ELRICK: Yeah, I think that's a fundamental characteristic of someone does going to be involved in security paranoia. You have to be paranoid about everything. MIKE: Yep. I don't trust anything. CHARLES: It's important to make those things easy because I'm definitely fall more into the hippie camp like, "Everything is going to be fine. Let's trust everybody," which is I know is totally unrealistic. But then you get into these secure technologies and you learned enough of it just to get the task that you're going to do and then you forget. SSL is a great example. Over the course of my career, I've learned how SSL certs have worked probably, at least 10 times. ELRICK: Right, [inaudible] you had to set it up in production. CHARLES: Yes, exactly and then I promptly forget about it, never worry about it again and then the next time I'm like, "How did that work? What's this trust chain? What?" ELRICK: Exactly. I read a study from Carnegie Mellon a couple of years ago that showed developers observe security best practices dramatically less than the general public and the general public is not good. Do you know what I'm talking about when I say a certificate warning and a browser, there's big scary red screen saying like something is wrong here? Before the Chrome team put some effort into improving that, 70% of people would click through those and proceed anyway. After their improvements, over a third of people still clicked through and that number when you just look at Canary versions of browsers, that number is actually considerably higher close to 50% of our developers. We're trained by every broken certificate system that exists on the internet like the legitimate ones or maybe some things just expired. They're training people to just click straight through these things and as a result, it is terrifyingly easy to mess with people. We have to remember as developers, our machines, those have the private deploy keys and those have the SSH keys to commit code to GitHub, we have to treat that like it's a private data. It's really, really important that we make it easy and that we make sure that that easy path is also very safe. CHARLES: Absolutely. All right. Well, thank you so much Mike for coming by and talking with us. We touched on a lot of subjects but I feel like I certainly learned a lot. MIKE: Yeah, thanks. It's been so much fun talking with you this morning. CHARLES: Anybody who wants to go and check out those courses, they're on Frontend Masters. Now correct me if I'm wrong, you've obviously got the one on progressive web apps or PWAs. If it doesn't work offline, it's faux-PWA. MIKE: Yes, I like that. That's going to become a t-shirt sometime soon. CHARLES: The fundamentals of progressive web app development, which is now released if I understand correctly. MIKE: Members have access to everything, you can watch the raw video now. The edited course will be available later this year. CHARLES: Okay, and that's with Steve Kenny. I am very much looking forward to looking at that and learning more about it. Then you've also got ones coming up in September on TypeScript web security in Visual Studio Code. MIKE: Yep and members can watch that as a live-streamed event. Frontend Masters even ask people to watch the comment stream so you'll have a proxy question asker or hand raiser in the room. It's really a great experience to be part of a live thing. CHARLES: Oh, man. That sounds awesome. Then if you are obviously doing your independent consulting and if people want to get in contact, how would they do that? MIKE: You can find me on Twitter, @MichaelLNorth or you can visit my website, Mike.Works and I have all of the courses I teach and outlines and I can just open up a little chat bubble on the lower right, ask me any questions that you have. I am really passionate about teaching people. If you like that's useful for your team, please reach out and I'd love to talk. CHARLES: Fantastic. Thanks, Mike and thanks everybody for listening to us. If you want to get in touch with us, you can always do that. We're on Twitter at @TheFrontside and email, Contact@Frontside.io. Thanks, Mike. Thanks, Elrick and I will see you all later. MIKE: Thank you so much. ELRICK: Bye.
Robert Jackson: @rwjblue | rwjblue.com Show Notes: 01:00 - Build Tooling in JavaScript 02:19 - Ember and Babel 07:14 - Deciding on Features 11:46 - Class 13:29 - Workflow 14:39 - Payload Size 15:24 - Config Targets 17:18 - Source Maps 25:05 - Ember Decorators, Objects and ES6 Classes 36:07 - What's next and when can we get it?! Resources: Babel.js esperanto Ember CLI Targets
Balint Erdi: @baaz | balinterdi.com | Rock and Roll with Ember.js Show Notes: 01:58 - What is JSON API? Advantages 03:22 - Tooling and Libraries 05:49 - Relationship Loading 07:51 - Designing a Data Loading Strategy 11:23 - Pitfalls of Not Designing a Data Loading Strategy 13:53 - Ember Data 16:37 - Pagination & Sorting 23:06 - Writing a Book 25:48 - Implementing Searches with Filters 31:08 - What's next for Balint? Resources: Balint Erdi: Data Loading Patterns with JSON API @ EmberConf 2017 (Talk) Balint Erdi: Data Loading Patterns @ EmberConf 2017 (Slides) jsonapi-resources GraphQL JSON API By Example by Adolfo Builes ember-cli 101 by Adolfo Builes 33 Page Minibook + Coupon Code! Transcript: CHARLES: Hello, everybody and welcome to The Frontside Podcast, Episode 65. My name is Charles Lowell. I'm a developer here at The Frontside. With me, also from The Frontside is Elrick Ryan. Thank you for being with us, Elrick. I know this is your first podcast. ELRICK: This is my first podcast. It's great to be here. CHARLES: All right. Fantastic. Yes, we hired Elrick a little bit ago and it's been fantastic. I'm glad to get you on. With us today is a really awesome guest. His name is Balint Erdi. I actually like to tell a little bit of a story when I have an anecdote and I do have one about you that I think you might like, although you might not even remember it. But it was shortly after EmberConf. Last year you and I got on a pairing session remotely and I don't even remember what we were working on but I was struggling with this way to decorate objects without changing them, without touching them or mutating them in any way and you showed me this technique of actually decorating it by creating a new object with the old object as the prototype. Do you remember that? BALINT: Yes. I totally knew. How could I forget? CHARLES: Yeah. That one hot tip changed my life. It is one of the best techniques that I have discovered in the last five years of working with JavaScript. It really was great and I use it all the time. BALINT: Wow. Amazing. CHARLES: Thank you. I don't know if I ever said, "Thank you," but thank you, thank you, thank you. BALINT: Yeah, no problem. I also learned a lot from this pairing session actually. I didn't know that my small contribution made such an impact. I'm glad to hear that. CHARLES: Yeah, that was fantastic. We need to actually make that happen again. I don't know why we only did that once. BALINT: Yeah, we should. CHARLES: Anyway, we're here to talk about data loading, it's something that is absolutely critical to building good frontend and building UI and yet, it's something that the users never really see. Sometimes, it feels like it's 90% of the problem. BALINT: Exactly, yeah. ELRICK: Yeah, that's so true. CHARLES: We're going to talk about techniques that we use and you use and, in particular JSON API, what it is and what's so great about it. So, what is JSON API for folks who've never heard of it? BALINT: JSON API is a standard way to build APIs. I think the specification has reached 1.0, I would say two years ago or three years ago. I remember it was in June, I'm not sure which year. It basically lays down everything that's usually consider when you build an API: how do fetch relationships, how to paginate data, how to sort, all of these things that I think developers tend to invent again and again. I think probably the biggest advantage of JSON API is that it just declare a standard way to do that. It basically reduces the byte sharing going on at the start of the project. Well, not just at the start, later on too. In my talk at EmberConf, I coined a JSON API the conventional over configuration for APIs. CHARLES: I see. Pagination is something that everybody does. Why need to byte share over the syntax, like the actual data from it? BALINT: All of these things are things that everybody does. It's just that everybody does it differently. There's a lot of discussion going on which the best ways, for example when there's a team, at least every team that I was involved with had several discussions going on about what data formats to send data in and how to paginate and all these, I think details where it's more important to get to an agreement just to agree on something and move on than to get it perfectly, if at all there is a perfect way to do it. CHARLES: I guess my question is if you have the standard way of doing of everything, what kind of tooling can you build, that can you kind of inherit for free? At what level, both from the low level and then up to the top level? When I say top level, I mean what the user is seeing. BALINT: By low level, I guess you mean the actual libraries that implement JSON API in different frameworks, right? CHARLES: Exactly. Are there now a lot of libraries out there so whatever I'm using, if I'm using JSON API, is it available in a lot of different ecosystems now? BALINT: Yes. It definitely is. There is a full page on the JSONAPI.org, on the official JSON API page that just list all of the different libraries that are now implementing all these languages. I have experience with Rails, probably at Ruby too and there are three libraries and I think all of them are pretty good just for implementing JSON API. The one I use is called JSON API resources and it's very telling. Well, it's a rather simple application but I basically didn't have to write a single line of code. I've only had to write very little code in the server to implement a JSON API specific feature. Most of the relationships could be implemented with just declaring JSON API resources and then the name of the resource in the Rails application. For all the other things, I really didn't have to do that much so in every time, it was just adding one or two lines or changing a configuration value, then it was just there. CHARLES: Now, how do you choose then what relationship you want to load and which order? Is that controlled by JSON API? BALINT: It's controlled by the frontend. It is a frontend application that's going to send these requests to the backend so that's where you should consciously think about what relationships you are fetching and how. CHARLES: Right so part of the specification is a way of specifying which relationships you want to load. In my understanding, part of JSON API is an interface along with say, the user, "I want to load all of the posts that this user has made." BALINT: Yes. JSON API indeed has a keyword called 'included', which you can implement on your backend which does this. If you specify 'include' and then the name of the relationship or relationships for several ones, the backend must comply with that request and also send back those related resources. That is called compound document in JSON API parlance. ELRICK: Is that the reverse of what they doing in GraphQL because at GraphQL, I think you have to request the relationships you want on the frontend and then it kicks it off to the backend and it gives you the information back. Is it like JSON API that includes that same thing but in reverse? BALINT: I'm not sure because I'm very familiar with GraphQL but all the things it does is that you are normally fetching a resource and then if you specify 'include' then you are telling the backend, "Please also include these related resources with a primary source." CHARLES: I think it occupies a very similar concept that you want to have control on the frontend about which resources or what data gets fetched in addition. ELRICK: Yeah, it sounds very similar. CHARLES: Well, I'd love actually to do a comparison because I know there's a lot of overlap between GraphQL and this. Maybe we can get into that a little bit later. One of the things that you said back there is having this, gives you kind of fine-grain control over when and how you load your data because that always seems a pretty difficult problem to attack on your frontend because as you're rendering your application, you have to incrementally fetch little pieces of data here and there and make sure that it's already, at the time that you actually need to render something like a component and then it's got the right data at the right time. It seems like it's this constant dance of whack-a-mole and like, "I'm loading too much here. It's taking too long," versus, "I've got too many loads happening. I've got 20 requests to run the single page." How can I back those up into a single thing? How do you go about thinking and designing that data loading strategy, as you're ready to render pages? BALINT: That's a really good question. I think the short answer is how you load data has to be part of the design process. You really have to spend time thinking about how you're doing that based on the needs of the UI. I think the way you need to render the UI will suggest the way to do data loading. Especially in Ember, I think do I really need ways to, for example block the page from rendering too early so anything that you want to render first, you can fetch in this non-blocking way into model hook of Ember. Then anything else, if you're okay with rendering later, you can fetch in other ways like to set up controller hook or from the templates or from controllers or whatever way but not in the model hook. CHARLES: But if you are doing something outside of the model hook -- because this is something I feel like a pattern that comes up a lot -- and regardless of where you're operating, if you're using Ember, if you're using another framework, you have kind of this top level data loading. But then you have your nested components might need more data, how do you go about loading that data. I guess you have to think about that also. Upfront it's like, "I've got this component that might want to request more data," how do I actually design that and think about that of I've got this data that's going to come, who knows, maybe minutes after the initial route is rendered? BALINT: That would be different but I think that you can apply the same principle. You can fetch some data in the model hook in this blocking way and pass it all it down to your component if you don't want to render the component before the page renderers or you can just even fetch it from the component while the component is rendered. CHARLES: You're thinking maybe, in terms of streamlining, the rendering process so that you can begin rendering while your data is loading. Is that the use case? BALINT: Yes. If you, for example fetch the data from your component, then it's just going to fetch the data as needed. You have the whole page load as render and then when the component is render and it fetches the data, then you're going to see other requests go out to the backend. The data comes back and then the component is going to be rerendered with the new data. I think in most cases, that's totally fine but you might have a use case when you don't want to render the page before the component is all over the data that it needs. In that case, what you can do is once again, if the fetched data is needed in the model hook, it will just pass it all down to the component. ELRICK: What are some of the pitfalls that you would run into by not thinking about your data loading strategy beforehand that you can pull out and explain? BALINT: I think the classic one is what was known name in Rails and other framework is 'N + 1 problem' and it's when you fetch many related resources, then you might end up with doing end requests for a number of resources. In the case of Ember, you have for example a blog post as your model and then in your templates you write model.comments, then what's going to happen -- depending on actual library that you use on the backend but I ran into this myself -- is by default, if you are going to make those end requests. Ember solution is really, they just works. I mean, the default solution just works and you might not even run into this because you might not have the scenario. You might just have a few records. But if you have a great number of them, then it's going to be a bad experience. ELRICK: So someone that just dealing with Ember and then they go and make a request and then see all these requests come back, that would be something that they would then have to turn around and asked or fix within the backend to say like, "Only give me a certain set of this." BALINT: Yes, exactly. ELRICK: Or is there something on the Ember side with Ember data that you can say, "Only fetch X amount." BALINT: Right. I think both. I can speak about using Ember data and JSON API resources so what you can do to mitigate this case is to use links or cause relationship links instead of fetching the comments one by one, the backend can actually drive Ember data to fetch all the comments in one request from the link that it sends the frontend. You first ask for the blog post itself and then a JSON API compliant backend will send back the blog post resource but it's going to have a relationship link inside. An Ember data automatically records this so when it needs the comments for the blog post then it's going to fetch down from that provided URL. Actually, I haven't really talk about it in a lot of detail at EmberConf. CHARLES: Yeah, I see. I'm going to go off on a little bit of a tangent because I feel like this is a pattern that's coming up more and more. To give a little bit of context, I feel like the way that our data loading strategies have evolved is we're used to the page loads, then we kind of analyze the URL, we decide what data needs to be loaded to render our components and then we pull that data from the server based on a decision and then we do our render. But it seems increasingly more prevalent than we are having a combination of both pulling the data from the server and having the server push data onto us. One is what are the strategies for dealing with that? Given kind of certainly, at least in the Ember world, routes aren't reactive. Then does JSON API actually help with that at all? BALINT: Yeah, a good question. I don't think that JSON API specifies how [inaudible]. You are thinking about something like web sockets like pushing data from the server sockets. I don't think JSON API covers this summary. CHARLES: Yeah. It definitely seems like beyond the scope but I'm wondering if there are any thoughts about general strategies, about how to handle this model state that sitting at the top of your render tree. In Ember for example, in your route and how do you handle the fact that the route requests data and how do you handle data coming in after the initial render? BALINT: If you use Ember data, then you can push data coming in from a web socket, for example to the store. You probably do some massaging on the data that comes in and then you push it to the store and then depending on how you fetch the data, you might have a live collection. For example, if you do a store, find all notifications and then notification is coming in that is going to get displayed right away on your page because then your template is bound to a live collection. But not all of things in Ember data are live collections. CHARLES: Okay, it's mostly library dependent but if you're using Ember data, then you just push those directly into the store, those live collections. It kind of like a real time query. BALINT: Yeah, exactly. But what I'm saying is that not all Ember data query that you do are live collections. For example, relationships are probably not, depending on what method you use to fetch that data. You might have to do some additional footwork. CHARLES: Okay. Now, getting back into the area in which JSON API really does shine at things that can really shave off a lot of time and consequently money from your work, let's talk about those a little bit. For example, you mentioned pagination. How is JSON API going to help me if I want to have paginated data? What are the scenarios on the client where I would need paginated data? Then maybe we can walk back from here's this user interaction that I need paginated data for and how is JSON API going to help me with that? BALINT: Sure. I guess the typical scenario on the frontend is there is a long list of items and you don't want to overwhelm the user by showing them what it wants. You need to just show them page by page so JSON API recommends to use so it's agnostic about the exact paging strategy that you use. You can use the classic page-based approach or cursor-based one or start of pagination technique. It doesn't really force you to choose the way you want to do that. It also mentions that, I think the way it frames it, you might want to use the page for your parameter. I think that the libraries, at least at JSON API resources for sure, you use that page parameter to send back paginated data. You have a page and a square brackets number and then page size. The request variables are page number and page size. Then the server knows that I just have to send back the second page if the page size is 25 and they just set that [inaudible]. CHARLES: Then if you're using a library on the server side, then you don't have to do any extra work. BALINT: Yeah, exactly, depending on the library I guess. JSON API resources made this one really simple. CHARLES: I see. Then in terms of library support on the client, I assume that there are libraries, like Ember data that automatically will support this so when you're creating these live queries, you can include information about the page. BALINT: Yes. I'm very in to Ember so I'm not sure about the frameworks but I suppose that there are some ways that make this very easy for the developer in many of these frameworks like Angular and React. CHARLES: Right. Something that has just bit me on the butt so many times is when I have paginated sorted data. Imagine you've got some infinite scrolling table or not infinite scrolling but you've got some a bunch of table rows that are maybe 300 of them or 3000 of them so you don't want to load them all at the same time. But at the same time, you've got complex sorting that's happening on each column. You might have seven layers of sort. You want to sort by name, followed by ID, followed by date. One of the biggest problems I've encountered is trying to reconcile and sort on the client versus trying to sort on the server. Are there any facilities to help you deal with that? BALINT: Yes. I think the approach I usually take is if you do it on the server, then do it on the server. Do not mix the two things. In this case for example, if you are sorting and then you change just sort field, I would just send a request to the server to have the items returned according to the new sort criteria. I think that's the simplest approach because as you said, I've probably experienced things can get really messy, if you want to do that on the client. CHARLES: Then you've got the third page but when you do the sort, the contents of the third page could be anything. BALINT: Yeah, that's the other thing. I think if you change the sorting criteria, you'd probably want to go to the first page. I haven't thought through all of the scenarios but I think it's really rare that you want to stay on the fourth page while you change the sorting criteria to be created at descending. You probably want to see the first item the way it was created. CHARLES: Someone should seriously write a book about sorting and pagination and loading these data sets because seriously, I feel there's this tribal knowledge of things that people have learned from screwing it up. There's not a written down way of this is how you build the data loading layer for an infinite dataset so that you can sort, you can paginate and here are the problems that you'll encounter. BALINT: There's actually a book written by Adolfo Builes. CHARLES: He wrote a book on Ember CLI, too, right? BALINT: Exactly, Ember CLI 101. He's the same guy and he wrote JSON API By Example. I have it on my mental to-do-list to buy that book. I'm not sure if it covers these exact scenarios but he must cover several in that book. CHARLES: Well, I'll be sure to reach out from because certainly there are a couple of scenarios that have bit me too. The other one is where you have some collection that's paginated and sorted, then someone adds on the client side a thing to that collection. Say, you want to create a new row in that table, well then what do you do with that new row? chances are it's not going to be anywhere on the screen because who knows what the sort order is and the terms of the total sort, which is only the server knows and who knows what page it's going to be on? You get all these problems that compound and it would be great to have one place where people could reference them or have a little cookbook. BALINT: Sure, absolutely. I think in that scenario, the simplest thing, which I think probably works best like 99% of the cases is again, just to reset the sorting and the pagination. If I create a new record, I really want to see that new record. CHARLES: Yeah, maybe you put the new record up in a box up, at the top in a special new record place. BALINT: Sure you can go fancy and do that. That would be a good solution too. But probably you can just reset the page number and show the first page with the new record. CHARLES: Ah, yeah. I see. BALINT: It's tricky. It's going to get more complicated than this. CHARLES: You might have a problem where you don't want to lose that context to the records that you were looking at. BALINT: That's right. Somebody should write the book in this. I know somebody who wrote a book [inaudible]. CHARLES: It could be you. You haven't written a book in over a year, right? [Laughter] BALINT: It's been two years already. CHARLES: It's been two years. BALINT: Exactly. CHARLES: I'm never going to write a book again. I don't know. Do you think you might? BALINT: I think I might. I actually have this urge. CHARLES: If I recall correctly, you're one of the few people I've talked to who was like, "Yeah, you know, writing a book, it wasn't that bad. It was kind of an amazing experience." And literally, everyone else I talked to have been like, "Urgh!" ELRICK: That's really interesting too because his book keeps up with the releases of Ember so that makes it even harder. That's surprising to hear that like, "Oh, it wasn't that bad." BALINT: Exactly. Well, I kind of put off writing the second book for a while because if I just wrote a book, then I could just be done with it, I would be happy to start writing the second book. But if I have to maintain it for years, I don't have to do that but it's just so much extra work that I'd have to take this into consideration. CHARLES: Yeah. Essentially, what you've done is you've rewritten the book. In terms of absolute content, given how much everything has changed, you probably flipped over the content of the book in the same way that people flip over the atoms in their body. I think there was something like you don't have a single atom in your body three years from now that you have today. It takes about three years and you have all the matters completely and totally exchanged. It's kind of like that. BALINT: Yes, it's kind of like that. Well, I think maybe half of the book is still relatively as it was when I released it because since Ember 2 came out, Ember didn't change that much so in the 1.X series it did change a lot and I think my book originally came out when Ember was 1.10, I would say. There's a lot less work that require now to maintain that it was back then. But it had changed a lot for sure. ELRICK: Yeah, I think I bought the book on its first release. It was 1.10. I guess you automatically get assigned to the GitHub repo so you just see a constant barrage of updates, updates, updates and I'm like, "Wow, Balint is really killing it in updating this book." BALINT: Yeah. CHARLES: It is a good book and everybody should go buy it. The other thing that I want to cover to, as long as we're talking about scenarios that come up again and again, we talked about pagination, we talked about sorting, what about things like search? Is there a uniform mechanism to help you out there? BALINT: You can implement searches by using filters. It's a JSON API concept of using filters. You can pass a parameter called filter to your query and then a square bracket. You have the name of the field that you want to search and then just pass the value, the search term basically and then backend should return the items that matched according to some criteria. That's the simple case. CHARLES: It's a simple case but clearly, it's up to the backend to implement that API. BALINT: Yes. CHARLES: So I'm wondering what libraries are available if I'm doing something in Elixir or I'm doing something in Sinatra or I'm doing something using Express, how seamless is it because I feel like a lot of times you can run into problems where these leaky abstractions about the fact that one thing is a Mongo backend, then one is based on Postgres. Maybe that's a better example than a different server technology but more of sticking with a single server technology -- let's use Ruby -- but one is I'm using a Postgres backend and when I'm using, say MongoDB or some other key value store. In your experience, if you've seen this, how much does the backing store leak into the frontend? Is JSON API a good protection and the ecosystem around it from those leaks? BALINT: Yeah, that's a good question. I was about the say that the backend needs to be the abstraction that's use you from having to know what kind of persistence layer you use. The frontend shouldn't care about -- or any client of that backend -- whether you use MongoDB or Postgres. That's a responsibility of the API. You can still send, in this case for example, a filter query. However, the backend translates this to database queries. That's his job. I think the answer to your question is that JSON API does protect you from having to know the intricate details of the database. CHARLES: You might have some work to do but it's possible. BALINT: Sure. You might have a lot of work to do on the backend but it's possible. But it's not just JSON API that protects you. Any kind of API should protect you from this kind of knowledge. CHARLES: Right, unless you're using GraphQL. BALINT: Could be. I don't know exactly how GraphQL works. CHARLES: Yeah. I think there would be actually nice to read something from somebody who's got a lot of good experience with all of these, like different technologies to make a comparison. I feel kind of in the dark. Unfortunately, the problem with any technology, I feel like most of the comparisons out there, if you're going to compare, most people have a huge implicit bias for one tool and a little bit of experience with the other, maybe dangerous of like, "I don't definitely want to render opinions on my GraphQL and certainly not versus the API that I'm used to because I feel like I can't make a good comparison." BALINT: Yeah, absolutely. That's a good one. CHARLES: But it is something that I'm so intrigued because I feel like there's a lot of overlap there but who knows. BALINT: Yeah. ELRICK: They need that to do API like how they had to do MVC, they need to do API comparison. CHARLES: Yeah. One thing we could do, we could implement JSON API over GraphQL and kind of just move your backend on to the frontend. BALINT: I think you could but you just said that with GraphQL, you have to know the client on the frontend, like feels the database. CHARLES: Right. You could technically have a JSON API on top of your GraphQL backend because I think the thing that kind of freaks me out -- this is a crazy idea that no one should ever do it but I hope someone does -- about GraphQL is being as old as I am, I saw so many projects ruined by the visual basic kind of mantra of just like, "Just query your database right inside your components," and that was literally the rope that hung ten thousand projects and just made people despise visual basic development because there was no shield and then literally every button was coupled to your database. But you could theoretically have the best of both worlds where you're sitting on an abstraction that's also on your client but just moving your query language from your server over to your client or something like that. BALINT: Yes something like that could work, in theory. CHARLES: In theory. Like I said, no one should ever do that unless they really want to. BALINT: Yes. CHARLES: Fantastic. The other thing I want to ask you is kind of what do you have cookin'. You got your book, you wrote but you keep updated, you recently have been evangelizing data loading patterns most recently at Ember Conf. What's next? What's now? Or you're just kind of taking a break? BALINT: I already have published book a mini-book about these data loading scenarios. Actually, I just cover the things I told them out at EmberConf then add some more but I might make this into a full-fledged book, providing I don't have to update it. [Laughter] CHARLES: I'm going to write this book -- BALINT: But just once. CHARLES: -- But just once. BALINT: Yeah, I still have to find a way of doing that. CHARLES: All right. We will look for all of those things. One thing that just occurred to me is just how much of actually building UI and building frontend really is about thinking about the structure and flow of how you load your data and how much the user doesn't see that but how important that is to provide a good experience to that user. That's one of the things that sometimes we, as UI engineers don't like to think about but I think it is absolutely true and crucial and foundational. Thank you so much, Balint for coming by and talking with us about these important topics. We will see everybody next week with that. I will bid everybody to do. Good bye, Elrick. Good bye, Balint. BALINT: Yeah, thank you very much for having me. Goodbye.
Toran Billups @toranb | GitHub | Blog Show Notes: 02:23 - Ember 2.0; Data Down, Actions Up 08:28 - redux and State 16:39 - Dispatching Actions/Patterns 24:00 - Components and Routing 31:00 - ember-redux and Cloning the react-redux API 35:22 - Hot Reloading 41:22 - Audience 47:02 - Motivation 50:25 - Building Component Trees Resources: Toran Billups: Test-Driven Development By Example @ EmberConf 2015 Dan Abramov: Live React: Hot Reloading with Time Travel @ react-europe 2015 react-redux Charles Lowell: Immutability is for UI, You and I @ EmberConf 2016 redux-thunk Ryan Toronto: Safety of the herd EmberMap: Component side effects Functional Programming Browserify More Toran Billups Talks Transcript: CHARLES: Hello everybody. Welcome to The Frontside Podcast. This is Episode 55. We're broadcasting and everybody's here in Austin, although we're still remote. I am here with a really special panel today. There's me, which makes it special by default. My name is Charles Lowell. I'm a developer here at The Frontside. I'm also here with Robert De Luca, who also develops JavaScript codes at The Frontside and we have today [drum roll sound] -- I'm really, really going to work that drumroll -- Toran Billups. What's up, man? TORAN: Hey, man. Thanks for having me. I'm really excited to be here. CHARLES: Toran is with us today and he's going to be talking about a lot of things. He's going to be talking about today mostly about Redux and his efforts to meld Redux and make it useful within the Ember community. But first, if you have not heard of Toran, I think the first time we'd interacted over email, Slack briefly but then when I really, really saw you for the first time was at EmberConf, I think in 2015 and he just gave the most amazing talk on Test Driven Development and really kind of the focus on you can set up your acceptance tests from the outside into really define that behavior and set out that firm shell and then actually build your application from the outside in. You've really kind of been talking about that message. We like to have people on here who all about walking the walk. That's certainly the first thing that I've noticed that you were doing in the community but then more recently, you've been playing with Redux. Not playing with Redux, actually making a concerted effort to bring this kind of pattern into Ember. I just wanted to start out, how did you jump onto that track? TORAN: Some months after EmberConf in 2015, as you mentioned that talk was not only, probably the most well-rehearsed talk I've ever given but definitely the most well-received. I got a lot of people excited and really gave me a lot of opportunities that weren't there before that was also believe in that keynote in 2015 as when Ember 2.0 was announced. The interesting part of Ember 2.0, of course was we were using it, and it was called Ember 1.13, which actually made it really great. At the time, I was very much excited about the stability that offered. Other folks were not as much as interested in that idea or those values, in the JavaScript community so it's really exciting. Yet at the same time, there was this new mantra that was being talked about more that I knew nothing about. It was this 'data down, actions up' idea. I still remember as much as the stability was awesome, I also started to doubt not Ember core in particular but the ideas that were being espoused by other folks around the Ember core team because I didn't really understand the value. For instance, if I had the tree of components back then in early Ember 1.13 or 2.0 days and I had an Ember model or some kind of Ember object at the bottom of this tree, why would I not just do Ember.set. I remember, actually you may recall conversations you had with people at EmberConf around that time but there was actually varying definitions of what 'data down, actions up' meant to different people and actually never met the same thing to anyone. It was funny enough. Because of that, it sort of drove this fear in me that I didn't know what I was talking about. I was consulting at the time so I wanted to sound like I knew what I was talking about as you probably should. You guys are in that business so you know what I mean. Because of that doubt, eventually I sort of become apathetic to really trying to understand better what 'data down, actions up' meant or how components should be constructed and really what the wider impacts of Ember 2.0 meant. Because of that, I just found myself, not really loving learning. I felt like everything else in learning was a hyped up thing that would never happen or a hyped up thing that I didn't really understand or didn't make sense in the context of Ember at that time so I just kind of floated by. Everybody has their ebb and flows in the journey of excitement or not. For me, this was just the down moment. One of the things, like an analogy to this is when you lose your hunger in real life, you'd be very much like losing your hunger for learning. There's this interesting hormone that your body produces when you're actually physically hungry that kind of gives you the physical symptoms like your stomach cramps that tells your brain probably should eat somewhere. When those things aren't happening or that hormones not being produced, it's often because you've quit eating yourself. If you've ever gone on a fast or something weird like that on day three, your body quits secreting this hormone so you just sort of or not hungry at all, which is kind of weird. The same sort of thing was happening to me. If you ask a doctor or a physician, "What's the first thing I should do? I'm not hungry anymore." They'll tell you, "You just start eating." But I'm not hungry now so the same thing applied in my life and I think the first step really is just eat anyway. In this case, it was just learn something anyway even if you're not in love with learning right now. Eventually, your body will start producing this hormone, in the hunger example and for me, I just sort of got back in the flow and what came from this was a routine, which is really the second part of how you get your hunger back, not just eating once a day. I was eating three meals a day or more, especially if you haven't been eating. For me, I just set aside an hour a day, in addition to consulting work and things that would get me interested in loving learning again. The third component to this was trying something different. At the time, of course I was just doing Ember, I pretty much had done Ember since 2012 like some of you guys and I feel like there wasn't a lot of new. There was patterns and ideas but there was anything really challenging me. That's when I sort of looked around at the React community and I had done some React in the early days when I was super hyped up but I still feel vaguely different. Not that it's jQuery or any way but I didn't feel like this fully encompass single page out framework. The reasons I got into Ember very early on were that I wanted to build rich single page apps. If you guys remember from the early React days, that also wasn't really the messaging with React and maybe today with View. In fact, that's kind of one of the benefits or they speak to in those communities about why you use React because you don't have to use it for your whole app. You could kind of piecemeal it in, which totally cool. You got to see it out with Ember too. But in my mind, I just wanted to build a rich JavaScript lines that could compete with the iPhone or the iPhone apps that were popular in that day. Through this process, I started looking at React and really just kind of get back into it again, get going again. I wasn't really in love with it but I needed to try something outside of the realm I was used to. As part of that, I noticed there was this talk by Dan Abramov, I think he works for Facebook now, big in the React community, of course and he gave this talk at a conference in Europe that introduced Redux. What's funny, if you find out or dive deeper into that story is he actually pitched the talk, not really having built any of this and just thought, "This sounds like a great idea," and then of course the talk was accepted. Like most, he delivered on that promise and made a great talk. There are definitely courage folks to check out and I should link it to you here. We can show noted that, I'm sure. That talk make me excited mostly because there was a lot of whiz-bang. If you guys remember any great talk you've ever seen, the talk even that I gave at EmberConf that you mentioned, Charles the thing that blew people away was this very end moment that, of course I had produced to be a great moment. In the same way, Dan during this talk introduced some new ideas or new to the JavaScript community. One of those was the tooling that can change when the state doesn't change in your application. That got me sort of piqued my interest, in part because I was actually big test driven guy and I thought, "I won't use any of this stuff. It just seems cool. It's a gimmick. Tester development is how you really build app." If anything I thought to disprove it by getting involved and learning a little bit more but what I instantly found was the simplicity of data changes rerender. That sounds very high level, of course but it was almost just that simple, instead of being like how does this change to an object in my array, bubble out through notifications on the Ember side and notify the Ember change detection to rerender. Well, I'm not entirely sure so when I was start debugging that, I noticed a lot of framework code between me and the rerender. It's that's how Ember is, right? When I boiled that down in jQuery with vanilla Redux, not even using React at all, I was like, "Wow, there's just a call back. I wonder why I haven't been doing this." CHARLES: As a single callback for a global state? TORAN: Correct. CHARLES: So there's no call back for every single path in your tree. You just used that one call back? TORAN: I'll fill in for Rob here. I know he's jumping at it. You should probably define a Redux is. He's really good at asking that question. Redux in this case, for me is just a global JavaScript object to use to hydrate your templates. They'll give you some big spiel about state container, if you go check out the website. But for me and in this context of being on an Ember-centric sort of podcast, we already use this idea in Ember today. If you're just feeding your templates from some high level service, it's a very similar idea in that Redux is just a single service. In the Ember case, especially you can talk about the add-on, I maintain later, but really it's just a service with a single object that will help you populate all of your components. ROBERT: Yeah, I love Redux. I actually sort of coming into the Redux world, probably to about six to eight months ago and it was around the same thing like exploring React stuff. I share similar opinions to you as nobody really can define 'data down, actions up'. I also think that 'data down, actions up' cannot just live in the component. In a lot of the Ember apps I worked on, there's times where I'll be looking up to get a new state and it comes in from the side and something's mutating, something that I have no idea why and where it was mutated and Redux does a really good job at helping you manage what changes and why it changed. CHARLES: I have a question too. When you're actually using Redux, you said you got a single tree that you used to hydrate your templates. In the context of Ember, where do you maintain that single object? I assume you have one store, one instance of your Redux state per application? TORAN: Correct. There's just a service like you imagine in the Ember data service and that holds on to really just an identity map or a single graph object that will let you pass or pull that in by injecting the service into your components if you want to do that or your route then just asking for that state. CHARLES: Because I think that for a lot of people in the Ember community certainly, when I was kind of grappling with these ideas, the idea of having a single global object as your state seems so counterintuitive, so going to go against everything that we learned, that you have to decompose a problem into its component parts. Obviously, Redux has an answer for that so how does that work? How do you decompose that state into saying, "I'm just interested in this kind of local state." How does local state work in Redux? TORAN: I should define local state is state specific to the component. It doesn't need to bleed up and has no value at the global level. CHARLES: Usually, I got two components. Let's say, I want to store both of their states in the Redux store. Obviously, component one is not interested in seeing any state that's not related to it so it's only interested in its own state and it's not interested in any of the surrounding context. How does that work? How do you connect a single component or connect a route to the store? TORAN: There's really just a simple method on Redux -- the Redux store itself, which it says, "Give me the state." What may not sound great at first is that it say, "I will give you all the state and that is your job to pull from that or map three attributes from that whole tree into my component." Then by side effect if you're using our add-on or if you don't React-Redux, you actually subscribe then to call backs on any of those changes so if something were to be bumped, then your component is given the opportunity to rerender during that call back. CHARLES: Now, in terms of Ember-Redux, that kind plumbing is hidden from you. You don't actually have to explicitly map that state. You can say, "I want to connect this component into the Redux store," and you're just off to the races. ROBERT: Is there a mapStateToProps or... I don't know what that would be called in Ember-land. TORAN: That brings about interesting point. I literally copied this API that you guys are probably looked at from the readme from this very popular project in React called React-Redux. The word that you're using, Charles is this word connect. Actually, I like that word because that's how I think about it. I want to connect the components to the single source of truth and then respond by rerendering when something changes. The API is actually very similar on what you said, Rob. In fact, the set of mapStateToProps is just map states to computed, which is very much the same idea so instead of really defining the component like you might normally, this is where it gets a little weird for your classic Ember developer, you actually just write two functions and really only one is require. The first one is what you're hinting at Charles, which is I want to pull from the state a set of properties and as you mentioned, the plumbing is sort of hidden, magically those are actually created as CPs or Computed Properties on your component so you can go to your HPS file, your handlebars template and say, "Oh, I took number from the global state and I'm just going to map it in this function and now I can go to my handlebars template and number," and there it is. Every time you bump number up or down, you'll get a rerun in your callback and the HPS will update. The other function, as sort of glossed over is really just for your closure actions. If you would like to ask the store to do something and saying, "I would actually like to increment the number," then you can fire an action and the second block just does also additional magic, which just maps a closure action by letting you get this dispatched keyword. Dispatch in a Redux context is just, "I'm going to send an action," and you can think of it almost in vanilla JavaScript terms as, "I have an event. Someone will handle this event and I'm just going to throw it up." ROBERT: It makes its way to reducer then from there, right? TORAN: Correct. We haven't talked too much about that process. The reducer really says, "I'm going to be given a state or the initial state, if you haven't done this yet," which would be maybe in the number scenario. I'm going to start with zero as a sensible default and then I'm going to have an action, whether that's add or subtract in this simple example and in add, I'm just going to take the state coming in, even if it starts out at zero and then do something, transform it to a new state. Actually the important word here is that -- I know you guys are big in the functional world, functional programming and that's the word actually got me interested and really excited about programming again as well, in the most perfect sense -- a pure function, which just means that there are no side effects. There's no mutation or changing of the state that comes in when you do it correctly. In this case, actually instead of mutating something I'm actually returning to number two or to number one and you're like, "Now, we have both zero and one in kind of a timeline." If you think about this almost as the realistic stories, we're just kind of kicking a pointer to a new block of state. Every single time you come to reducer, we still have the old state and we can still walk backwards, which is how the time travel debugging works as we just flip the pointer back in time. As you guys have talked about and I think, Charles you mentioned last year in EmberConf, the immutability story has of course a whole slew of great properties that come with it and those we haven't even obviously talked about. But hopefully I gave people a broad overview of what the reducer does. In its most simplest form, state comes and action returns a new state. ROBERT: Yeah, in Charles's talk and his research, I got to sit next to him and watched him do that actually kind of shaped a lot of my thinking and hunger, if we want to keep that going towards doing like something that's immutable and state management in Ember. I would like to thank you, Toran for building that add-on and spearheading Redux because Redux is pretty awesome for state management. CHARLES: By the way, you did in that call out the analogy for hunger. I really, really, really like that. It's an important tidbit not to miss is that when you are feeling those kind of doldrums of development. I know I was actually ironically feeling that about the same time in 2015, feeling of in a funk because I feel like there was a lot of stuff coming down the pipe like with 'data down, actions up' but no good examples of where we've actually seen this in practice. I think Redux is an actual implementation of 'data down, actions up' so I think it's fantastic that you were able to go and seek inspiration there like, "We've got this message of the way things that ought to be doing with the applications ought to be built." But we don't actually have any concrete examples that we can look to. I think the Redux actually is almost the most pure version of that 'data down, actions up'. I guess my next question is given that you've got this global store, you've got a way to connect components. I assume there are other ways to dispatch actions from within your Ember application like what are the patterns that you're seeing emerge around this? We've talked about how you would use them in components. Suppose my tree of components gets pretty complex, how do I manage that to kind of the passing of data down? Do parent components play any role in the data that their subcomponents see? Is each component connecting directly to the store? I'm just kind of curious where that balance lies and how things are kind of playing out? TORAN: There's really two points in your bigger question. One that I was going to try out of you but then you kept going. That was really around side effects. How do you actually dispatch or make changes, requests changes and see the flow and we could talk about that really starts out briefly with a Promise based approach. With Redux, most people don't know but it's basically like asynchronous flow. Dispatch would normally be like asynchronous action where you're sort of blocking and then doing, transform and getting it back. In the simplest ways, you see there is this tool or this add-on, Redux-thunk, which you can use Promises now and async will still work as if it were synchronous essentially by firing dispatch up and letting your reducer do the work. I think that is a great introductory because especially as Ember developers, we've got a lot of experience with Promises so this is just the same thing. In most of the demos I've done and if you check out the read me, there's like a full Yelp Clone example. It's using this approach because it's a little bit more familiar to most folks. CHARLES: Just to clarify what would happen there is you're essentially getting a new state transition when every Promise resolves or rejects. If it's rejects, that's a state transition. If it resolves, that's a state transition. The next Promise that resolves is another state transition. Is that fair to say? TORAN: Assuming you want to alter and use that top level state, of course you could reject or resolve and just not even bother with the top level store. We kind of skipped over some of the benefits and we could just roll back to that briefly. Why would you use top level stores at all? You mentioned earlier and it kind of seems counterintuitive. This is basic global variable. That's what we're talking about. In the Ember example, I think it's actually sort of not weird because if you guys, your Ember data in its earlier form or even today, it really very much is that. We have this one cache of objects related or otherwise and we pass those around. They are a global object or almost like a global variable. The downside of that in my experience has been that is truly mutable and actually everything is driven by mutating those and then having callbacks or denotify property change drive your template updates. That is not the process with Redux, of course. It feels more explicit, where I can actually go look up kind of a tree or look up table of actions and see exactly what's going to happen. Then also to your second half of the question, which is like how was the components wired up? How do they map? I actually uses an interesting pattern which isn't specific to Ember-Redux or Redux, which is to create a seam in my components now where I have truly HTML CSS components. Separating those from the components and know about the data and the closure action story. Forgetting Redux for a moment and all of this actually made my regular Ember much better because I started to produce this component that would connect to a Ember data store, provide closure actions to send up in the most pure 'data down, actions up' sense and then I would connect it using the yield block, which credits to you and other folks at EmberConf that you, Charles kind of talked me into this because I was a espousing this idea but I didn't really understand that I would actually nest within this parent, the HTML component that would just be handed the properties to render. When we do this, again it still is I think a better pattern even if you're not using Redux but when we did it and I when I started with Redux, the only thing that really gets me in hot water is when people see this and they're like, "Oh, so this is the first thing that comes down from the routed controllers template. Then there's always this brief moment of like, "I'm not sure what to say. I don't want to predict the future and I'm not trying to be Mr Routable Components here." But for me, most of my controller templates are just a landing page for the component tree to begin. Again, that's not me trying to hacking the route or anything to say, "I want to use this controller as a routed to component. I think eventually when that RFC lands, this will look different, anyway so I'm not trying to have people do things really outside of the Ember ecosystem or outside of the norm." But from there, I feel like still just landing into a component, allows you this composition which is supposed is the real value of the components structure. They are too primitive to build pages and then eventually full apps. ROBERT: So if we want to drop parallel, it's container versus presentation components, right? TORAN: Yes and that of course, again stolen from, not me probably stolen from someone else in the 70s. But you know, Dan Abramov is accredited to bringing that idea about in React. Actually I like the idea because let's pretend I had done this pattern in 2013. Now, it's using Ember data or simple store or Erik Bryn's Ember model, something like that. Then eventually, the community start shifting to something else. It could be MobX, it could be Redux and whatever the case, I could just very easily swap out those connected components that have no HTML CSS. The data source changes and all the presentation components do not know. They do not change. There is actually an iterable story to refactor through, an update like that normally is kind of a [inaudible]. If you have ever done PHP in the early days or at least my PHP experience in 1999 -- no offense to PHP today -- was that everything was so stuck together or so couple that I could never refactor anything out of it. Of course, you probably do this in a consulting space as I have, where he first thing on a messy project is actually making those scenes in the application anyway to allow you to upgrade incrementally. This process is just more of an upfront thought and I don't think it's really taken hold than it needs to in the Ember community. It's just something I was experimenting with and I'm finding a lot of value because I think the connection of the data source is a different activity than HTML. ROBERT: I think it also holds a lot of value. CHARLES: I think it holds a lot of value. I think there's a dawning awareness of this. In your comment, I actually thought of two blog posts for EmberMap, which I was just reading this morning. One was talking about kind of the safety of the herd and don't worry so much about controllers versus radical components like use your controllers, use your components. Don't worry about it too much. It'll get sorted out. I definitely agree with that. Although, you definitely want to experiment when you're experiencing particular pain around something. But then, the next thing which I think came out yesterday was talking about basically components for managing side effects, which I think is an unfortunate name because I think side effects is a tainted word. But basically, the idea is having presentation components and container components and the container components are responsible for managing the state. I think that idea is valuable in of itself and I hope that it takes root. I think that's something that you're doing, something that we're doing and as people kind of realize it, it does take root, just kind of by virtue of its own value. Let me summarize if I understand it correctly. As part of these job, you've got these container components and their job is, I like the term that you used, creating a seam. Their job in the Redux world is to take a slice of that global state. You have these components whose responsibility is taking a slice of that global state and presenting that global state to HTML CSS aka presentation components that lie underneath them. Is that a fair assessment? Then if that's so, I've got a second part to that. I just want to make sure I'm understanding it correctly. For components that are further downstream on that tree, do you ever switch back to data containers like you switch between data components and presentation components and then back to data components and then to presentation components and kind of back and forth and back and forth on down the tree? Or do you mostly see it as one-kind of container component on top and then presentation components all the way down? TORAN: It's a great question. I think that still needs a fair bit of experience in the Ember community because the patterns I pulled from the source code I read a lot is mostly from the React ecosystem. Because of that, there's a very split view or a different view in that community on routing. We may share some of those views in Ember but I think for the most part, we assume routing actually and that's one of the tricky part to answer your question. This is a broad statement so I'm likely wrong in every context but I don't love to be creating these data components that don't get routed to if I can help it. I'm sure there are situations that have been really complex, places where you just have to make, no route here because I don't want change the URL for instance and I'm just going to make this thing like a routed to component with no URL to get me here. But for the most part, I treat the entry point to this route and when I land on this route at this time, it's appropriate to ask for the data likely coming from the model hook in the route. In fact, all that's still the same. That's also where it's a little weird. If you've ever seen a full component tree in a React app, they may not have a router at all. In that situation I think, Redux was in particular even better because you don't have to pass from the top app component, the same props or the same data all the way down that tree. In fact, if you read documentation about why Redux in the React ecosystem they'll say, "It gives you this place where we can create a little shim and then ask for the data down here in the [inaudible] mode. You don't have to pass it from the app to that, to that." I see those benefits but in Ember we don't really get as much from that. In fact, they still tell people who challenged the global state idea that not everything maybe should be a global state but you give up some things by doing that. The first one I would say, which I think is the most valuable for anyone doing vanilla Ember with Ember data or someone experimenting with React or Redux. Or the case I'm most interested in, the audience I'm after which is Redux in Ember, which is do you actually need to have that state in one place. The prime example of this that is the greatest use case is master detail. What I mean by that is you have a list of things and when someone drills into one of those, you can also see that at the same time. There's really two choices you can make here. One is I'm going to have two separate data sources to feed two separate components so the list will go get its data and then the detail won't even use that data at all. Just go get its own data. In that case, you may up against a problem where you need to synchronize at some point and here's the tradeoff. Either synchronize the two separate states or you have a single source of truth. That's a real benefit I think of Redux for the most part. It's like the broad, "Do I want deterministic rendering?" We've all heard the joke about the Facebook nav bar that's like, "You have one message," and you're like, "No, I just answered it down here." Well, that's a different component so the joke is like, "Oh, Redux must be working. We have one up here but I've already read the message." You know? Someone obviously is in charge of synchronizing in those sort of examples. Maybe not just doing it well or they run up against an issue synchronizing that. My experience doing back end development, colors this for me. What I rather have three databases and they kind of synchronize the state across them or I rather have the one postgres or SQL server database that is the source of truth so that when I render something to a customer, I can guarantee that it's not in a transition to be synchronized. It is the source of truth. CHARLES: Right, I really like that and I think the point that I take from that is that, and again this speaks to people who might be internally reacting to this idea of a global state is that you actually do have a global state always in your UI, whether you acknowledge it or not. It's composed of all the other distributed states that are sprinkled around your application so if you take an approach like Redux, you're kind of acknowledging that upfront that at any given time, I do in fact have a global state. I might as well deal with that explicitly. That's kind of a key innovation. I also like what you said too about kind of treating the router in Ember really leaning on the router as a good way to partition your data or drill down into a sub-piece of that global state. Inside Ember-Redux, are there explicit hooks for dealing with the Redux store inside your routes? TORAN: Yeah, that's that one that gets me the most trouble. When I see a blog post and memes that are all about the herd lately, can't help but feel like they're pointed directly at me because of some of these new ideas. CHARLES: Toran, I'm just telling you. This is a safe space. We believe in innovation here. You're okay. TORAN: Yeah. CHARLES: Let me add-on that. I didn't mean that as a knock to you. I do think they call this out of the end of the blog post. I think acting in concert with the community for the most part, actually fosters innovations and an innovative journeys like the one on which you're currently embarked because you don't have to worry about CLI tools and you don't have to worry about this. You can focus on the problem of like how does an Ember application work with a global atom as its state. TORAN: That is the idea. I mean the route is interesting. I have a little helper to your point, Charles if you've seen some of the docs or any of the examples. There is a little helper for routes and all it really does is provide dispatch as an argument. For instance, a lot of times I just want a model to be a regular function and dispatch to be an argument so I can return a Promise or do some Generator stuff as a side effect. In that way, I sort of create a shorthand which is just really simple. It allows me to say [inaudible] model and then have dispatch as an argument and run my code then just providing that to this special little helper. It's a functional type helper called route and what it does behind the scenes is it injects the Redux service for me, which is again something you can do by hand. If you really just don't like that or you want to be more in the herd, you can just have a regular route, inject the service and then get dispatched from that service and use it. ROBERT: It looks like you just dropped the version 2.0, like three hours ago. I would like to ask, we heard about your journey like you were feeling like you weren't hungry for learning. I want to know more about where you actually sat down and wanted to write this add-on on and why you chose to clone the React-Redux API and what took you on that path? TORAN: Yeah, that's a good question. Back to benefits or the reasons I got excited about, of course I mentioned during the talk that Dan Abramov did. There was some interesting dev tools. First of which was this thing Time Travel Debugging which it allows you to sort of move backwards in time and pretend as if actions and mutations or what looked like mutations that never occurred. That was very interesting. I wasn't really sure of the value, especially at the time. I told you guys around 2015, I was consulting which lucky me, I was doing Greenfield. Thankfully, I was working with a really great team and some great people, built an amazing product. I don't really understand the pain of this. For the most part Ember-set was doing its job and I didn't really have a lot of interest in learning this. But as I got more into it, also started a full time job last year, I pretty much just fix bugs for a year. Anyone who's been on one side of the fence or the other knows that the bug fixing side will sort of expose, maybe the weaknesses of the application or patterns or choices made. For me, that was really mutation or shared mutable stake aka the root of all evil. If you've ever looked at your Elm ClojureScript, Elm next is the same vein where immutability is very much there. Charles, of course gave his talk on immutability and trying to get people interested in that or more interested in the Ember community. That was really all I wanted to do to your point, Rob was provide really an outlet for people to use this and I wanted to keep the messaging away from the things I didn't like, which I think was actually something I screwed up to be fair early on. I think I was very vocal in the microcosm that I would talk to people about like, "These are the things I don't like about Ember," or I would use the word 'Ember the good parts' plus 'Ember the bad parts' and I was told not to say that anymore on the Slack channel. Once I started getting too much needed feedback -- I don't want to be negative about it -- I changed my messaging and as part of that, you mentioned Rob I basically cargo-culted or copied this API from React-Redux called connect and excluding the brief route helper that I mentioned, Charles a minute ago, the real idea here is you just call disconnect function with two other functions: mapping state and closure actions. Everything else becomes then vanilla JavaScript in this reducer function we talked about briefly where I have state coming in and I need to transform it into a new state. One interesting benefit of that -- I wasn't overly critical about until I really saw the difference is that -- I'm no longer using the Ember object. I'm not doing Ember.get and set, which immediately start to open the door some time last year for TypeScripts interest. I'm actually not a super type friendly person. I sort of left Objective C and C# and Java in my background and have like this Vietnam experience when people ask me about types. But I do understand one very critical fact that I can't dispute about types is that there are more information for the next programmer than you have without them. Again, my experience this last 12 months has been, as a maintenance programmer, I need more information. Tests are great when they're there but they also don't provide the interface or all the information about those and certainly the compiler may help as well. I don't know yet. I'm not doing any TypeScript. What I started notice is also more functional programming and maybe just not in our core yet but also things I wanted to steal from other ecosystems because I also found is very interesting. I started to study functional programming. I know like nothing about it, of course. I don't think anyone does because I can't describe a monad without getting in trouble or being wrong. For me, the real value is the separation of the data structure and the function. I'm preaching to the choir here but that was so much like an interesting idea to me and actually spurred on some of the further patterns or adoption of those in my work in Ember-Redux because this presentation and container component idea was really that I was separating the data structure from the function of the view. I think you mentioned this in your talk at EmberConf where the actual HTMLbars template is really just a function that has data in, HTML out. I started to internalize that and think about that and what were the properties I got from that, as well as I enjoyed functional programming. Some other great benefits that we've already touched on briefly are just how much more of this I felt explicit, not that Ember-set is inherently implicit but when you do a Ember-set for mutation to chase down every single place in a complex system to determine why they something render this way? It does feel a little more implicit than something like React-Redux with this connect function where I was like, "Wow," when I was doing React. Especially, I was like, "I bet I could just put a breakpoint at every connection so when that callback happens, I can know exactly what action spurred on this new callback to rerender," and that was something that was very new and interesting. Then of course, falling out of all this was another hyped tooling thing that I thought was really cool, not explicit to Redux, again but it got me interested because that's hot reloading. All hot reloading of CSS and Ember CLI, which I've never done design work which I'm not good at. But I do write some CSS or hack-on it when friends show me what to write. Then writing HTML was a separate experience. Once you wrote the CSS, you would hot reload in that course, what do you do every time you change CSS, you also change HTML, which would incur a full-page reload with a live reload tool, if you're familiar with that in Ember CLI. This tooling allowed the Redux store itself because it's stored the state, allow me to really throw the component away in the page without refreshing it and then providing a new one and just go rerender because the state was instantly mapped in and then rerendered. I actually did a demo sometime last year and like, "I'm going to build a star rating component and here it is with live reload. Here it is with hot reload. I'm not going to make a decision about which one is better. You decide," and overwhelmingly people were like, "This is a much nicer feedback loop to make HTML and CSS changes in real time." ROBERT: Agreed. Let's pedal back the hot module reloading because that is pure awesomeness. But that has a little bit of setup they have to do and changing your application. I remember we were talking about this. When you did that demo, I remember this. But there's a little bit they have to do to make your components stateless. They have to come down from the Redux store. TORAN: Correct and this actually still applies if you are, I think using Ember data as well, as you just can't pull the state to reload it anything local, which may go against what you're trying to do with your component. ROBERT: Right. That's cool but I do want to highlight a little bit something that was cool about the Redux dev tools as with all the state that you have since it's in a centrally managed place, you can take your state and then play it back over the top of something like if it did live reload and it'll just pop you right back down to where you were when you were debugging. When that page refresh happens, if you're not doing hot module reloading, you still won't lose all your state which is really cool. You just play it right back down on top and you're exactly where you were before. It's almost like you would throw a specific test that puts you into that state that you're trying to debug. TORAN: Yes, it's like git rebase. It lets me pull off my state, replay the new component function and then drop my changes on top of it and see it all viewed together. ROBERT: Yeah, I think that's massively powerful. CHARLES: Yeah, it is fantastic and that's where you get into that power. I can get on my immutability soapbox. But it turns out that as programmers, we deal in information and not throwing information away, not just flushing it down the toilet is hugely powerful. I think the thing that's so fantastic is that Redux takes this concept and then all of the tools to leverage it are there for you. I think that it is something that is missing from the Ember development story and people don't realize that it's missing, that we have all these wonderful tools, we have this conventional way of building our applications, of deploying our applications, of rendering our applications, of marshalling the data in our applications in the form of routes. But what we're lacking is this unified atomically based state management solution. I think that, Toran it's been fantastic that you have pioneered this and trying to bring what I see as a glaring gap in the developer experience to the community. I'm curious then to ask you what do you see as the future. You know, 2.0 just dropped and there's this need. I feel very strongly that Ember 3.0, 4.0 or Ember 'dot future' at some point should have a unified state management solution. How do you see the road that you're on intersecting with that future if it does in fact exist? ROBERT: Also how can I help or how can we help? TORAN: Just real brief before I dive into some of those questions. I just want to mention that 2.0, as awesome as that sounds, of course I dropped that this morning just so we could say that on podcast, really. We've had a beta in the works for Ember. The only change really, if you're like, "I just got into an Ember-Redux last week. Is it all garbage?" No, this isn't Ryan Florence 2.0 -- it was a joke for any [inaudible] router folks in here. Actually, just us removing Browserify because if you are familiar with Browserify in the Ember ecosystem, talk to Robert Jackson or Stef Penner, folks familiar with that in Broccoli, they'll tell you that one of the harder things to optimize and although, it created a great entry point to how do I use Redux? Boom! Ember Browserify, install Redux, I'm done. If you've ever seen an [inaudible] in Ember that has 'npm:', you're using Ember Browserify to pull in, either a common JS module or some kind of node module and use that in the Ember ecosystem without an additional shim. Now, what we found or learned was that bigger teams that are using this, paid a little bit of a cost and not just cold rebuilds. I'm talking hot rebuilds because Browserify just isn't friendly to get those to be optimized, I guess is the word, so we removed it completely or just use some smaller simpler shims. You actually get the performance improvements hopefully -- ROBERT: That is awesome. TORAN: -- Which is big win. Back to your question, Charles. The audience that's intended, of course is a little different than most people like me to talk about. In fact, the API itself, I think was a bit rejected. You're sort of asking like, "What does this mean in the future?" I don't really feel that the traditional Ember audience has picked up around with it because of something that's missing. You said the 'C word' earlier so convention is certainly still missing from this and even in the React ecosystem, they're just barely thinking about, "Look at all this great stuff we can do with one-way data flow and immutability and functional programming," but guess what we're giving up. No one's really come around with this perfect pattern and conventionalized it as Ember did in its early days so there's a lot of churn, I wouldn't say overly so much that you're not going to getting work done but more than the average Ember developer is aware of. My audience is actually not the average Ember developer, which may be bad for what you're asking about, Charles. Instead, it's actually the person who maybe has done React and maybe Redux or Backbone in the last two years. They love some of those patterns. They're not in love with the Ember-object because of getting set. Maybe they love TypeScript and they say, "I want to use this in Ember." They joined a new company that's a little larger than the startup they'd been on the last two years and they are using Ember. They love a lot of Ember but they would also like to use some of the predictable state patterns that you get with Redux. As well as maybe the dev tooling, things like that so they have adopted this. I feel like that really is the new audience that I aim to please or I'm falling in line with, which is a little bit outside. I feel like there's room for some fragmentation and a good beat up on me for that because when the realities of this herd conversation that we're kind of talking around a little bit is that the herd is great until something innovative needs to happen. Innovation, obviously takes some risk and I feel like that's sort of what I did last year and said, "Here's some interesting ideas. I have not shipped Facebook with it yet so let's just check this out." Of course, Ember add-ons are a great way to enable someone to try a new idea. But I think most people got into it, saw this funky connect thing and they're like, "What the heck is this?" It's a function and returns a component. All right, that's not doing that so most people bailed out. But I do hope people still and I know great folks at LinkedIn, Chris [inaudible], of course. We chat occasionally. Mostly he just tells me what I'm doing wrong. Shout out for Chris. But he knows a lot more about some of the stuff than I do and I think he is fully aware of the values that are in Redux that are great and then working hard, of course during his full time gig to apply these to Ember data and hopefully these do make their way in naturally. I just wanted to be a bit more radical. I don't want to wait around and I wasn't really involved in the Ember data project. My own fault there but I think if nothing else, the ideas will come out of it because the developers want this. Whether you're the audience I'm talking about, which is a React developer from two years ago, you're in Ember, you're eventually going to really understand and want this and then those 'data down, action up' ideas that were pretty unclear to me in 2015, will be very clear. In fact, if anyone seen or heard of this Project MobX, which is like an alternative in a way, popularity-wise to React ecosystem. It kind of looks like Ember in a way where you get sort of some more magic and what I found quickly in playing around MobX is that you can very much fall into the shared mutable state problems. The interesting part about MobX is you can opt into a strict 'data down, actions up' approach. But if you don't have the Ember battle scars like we do, you're just going to come in and say, "What's less work?" Just like in Ember when I can do a set in the [inaudible] node, why would I do 'data down, actions up' and that's the transition I want to see folks make. Hopefully they learn something from that. CHARLES: Right, I agree with you. Although, I think the time has definitely come, I think the term 'herd-mentality' is an unfortunate one. I prefer to think of it as like a pack. If you travel as a pack, you can bring down moose that are bigger than you are individually. But every once in a while, like a gigantic moose with laser horns shows up and then what are you going to do? If you're hunting as a pack, you have to introduce new things because I like that analogy a little bit better than a herd because the job of the herd is just to not get eaten, where is the pack has this idea of these entities that have to stick together. They're hunting and they're tackling different problems as they come but sharing in the benefits. But I think that there has to be room for innovation inside that herd/pack-mentality, whatever you choose. I do think this idea needs to be introduced so what I would say is that if you're listening to this podcast, you should actually go and you should try and use Toran's add-on and you should try and build something with it so that if you have opinions about how it should fit into Ember, then we can hear them. It sounds like you're taking a minimalist approach, you're emulating patterns that are proven to work in the React community so kind of enabling that seed cross-pollination right there. I would say go build something with it, experience what it's like to have your state as a single atom, experience what it's like to have incredible development tools that come along with that. I think that if you're in the Ember community today, you need to go build something with React, you need to go build something with Redux and you actually have made it one step easier to do. You don't even have to leave Ember to do that. You can build something of node with production quality code using Redux and you can experience what it's like. That's my challenge, I think to the Ember community. Go try it, go experience it because you'll come back, I think like I did. You'll come back with superpowers just from having tried that. ROBERT: Managing state becomes so easy. TORAN: Yes. I want to jump in briefly and just cover one point that we haven't talked about that's very controversial so why not drop it at the end here. I think, Rob you might have asked about it earlier and I just didn't feel brave enough to talk about it at that time. But you guys keep going back to this idea and I have to talk about a little bit too. One of the motivations is I live in Iowa. I work in Texas. Thankfully, this great company, Q2 employs me and I don't know why I'm being paid. I'm lucky to be writing JavaScript for money, probably we all are. But in the Ember local community that I'm in, a very little folks writing Ember and that was even years ago. I was like the only voice in the middle of the Midwest screaming and then folks in Minnesota would tell me that wasn't true so I went up there and did a conference as well. But for the most part, I looked around the job market too and thought, "It be really great if I understand some of the more JavaScript-centric parts of building web apps today," and when I looked at Redux functional programming, the way the reducer worked and structured, the way to React-Redux project was structured and thought, "I bet I could emulate that an Ember," such that I could actually and I believe this is to be true, that if you were in a React-Redux project or even an Angular like ‘ngRedux', which is a very similar connect binding, you could copy a whole directory of your reducer code, which is all vanilla JavaScript. If you're doing generators, which we didn't talk about but if you're doing you know any additional side effects, you copy all that vanilla JavaScript, drop it into your Ember app and it all works because it doesn't matter if it's in React or Ember or even Angular, even View if View has some connect API like this. We all share this common API that is just give me the functions that enumerate over the data and return new states of the data and call back to rerender. There's something really powerful about that but the tradeoff being there are not a lot of strong conventions, Charles that I have adopted. That's kind of what I'm cautioning here a little bit is that I'm still also just watching the other communities to see what eventually turns out not. This is going to be am Ember add-on and I don't care what everyone else is doing. This is my vision because really my vision was to make a drop in for anyone already doing Redux on any platform. CHARLES: You know, to the point, there's a pack that extends beyond the Ember community and it sounds like you're also leveraging and being a part of that. TORAN: There's an interesting idea about the hunger thing, which just tied us in and there's where the fourth thing that a doctor will tell you to get your hunger back is go experience eating with other people. There's actually a statistic that when you sit down to eat with someone else or many people, you're likely going to eat 44% more food than you did on your own. That's just, I guess a statistic that's true. I just made it up for this podcast. No, I think it's true. If that is the case, then I think that very much translates to programming as well where when I'm developing code with other folks and I'm on like the React channel and we're just talking about vanilla JavaScript, it doesn't have to be me being an Ember developer anymore, which has been a large part of what's blocked me from being, I think an asset in my local community in the broader JavaScript community. At large is every time I get a conversation it's like, "I have to do it the Ember way," and that's changing actually. The Ember has credit a lot of deprecation if you guys have seen or follow the RCs and other just Ember upgrade deprecation. We're kind of getting away from being Ember and writing just more JavaScript and even maybe sometime this year beginning ES6 classes, instead of Ember object extend. I think Ember is heading in that direction. I just went there, rather rapidly because I also was again experiencing vanilla JavaScript with other communities, View and React. ROBERT: I think we're walking on this very similar path. I'm following your footsteps right now, it sounds like. TORAN: My last point which was that third bullet about building component trees, it didn't sound like either of you guys really contest that and I'm friends with, obviously Chris Freeman, formerly The Frontside and Chris tells me, "You're trying to build full component trees once you're injected at the route level and you're not doing like a ton of HTML in your controller HPS files." Is that true? CHARLES: We treat our controller basically as a component. Sometimes, we'll be like, "This is the controller and if we ever use it in more than one place, we'll take out its component." We're not super dogmatic but we definitely see the clear separation of the route is for maintaining the data and everything else is just one tree of components just below that. ROBERT: The more I think about it though, I'm so conflicted because I really like routes in Ember and they do a lot for you. I like having the data be maintained in one spot but I don't know a single store with Redux maintaining that and using like Redux-thunk or Redux-saga. I got some exploring to do. CHARLES: I don't think those are mutually exclusive propositions. That's what you were saying at the beginning, right Toran? You still do all of your data munching in the route. There's two kind of subjects that I wanted to broach briefly, although I don't think brief is possible with them is actions, like how we talked about data down, we talked about where you draw the seams in your application, where you're loading your data, where you're mapping it to your components and having that separation into your presentation components. We didn't get to talk about reducers so much and how you map. You touched on it like the mechanics but suppose I have a to-do list and I want to delete an item and I've got some button to delete an item, that's down my component tree. How do I map that action back up to the store? I don't know if we actually have time to cover that because it is meaty-meaty subject. ROBERT: Redux part two? TORAN: Yeah, we have to follow up because really that is a little bit more of an advanced segment not that folks shouldn't hear about it. But one thing that's a radical shift, Charles that we would have to go into and talk about, which is controversial as well as most folks want to operate in one structure, one dictionary not in the array. Then immediately, everything flips to being a Lodash operation. I didn't really use Lodash at all until I got into this. You guys probably actually are smart folks to do. But for me, this store is not in array now. When I'm doing array operations like remove or filter, I'm actually operating with Lodash on an object to produce those new states and most of it is just learning the Lodash operators because I didn't actually know them so the Yelp Clone that I have out there is a very simplistic look at using Lodash with Ember. But it accomplishes some of that. Then also, the secondary piece that would also consume a ton of time that we should go into but maybe not today is switching from Thunk to Generators with Saga and then maybe even observables with RxJS, which seems like possibly the future. Those all sounds cool but I think they're going to blow the heck out of scope on this thing. CHARLES: All right. Well, thank you so much for coming by Toran. As always, our conversations are too big to fit into a single podcast. I really want to have you on again. There are so many things that we haven't even touched on. We haven't touched on the subtleties of how action dispatching works. We haven't touched on using Ember-data -- I'm just [inaudible] out there and say it. With Redux, we haven't open that can of worms and who doesn't want to just sift through a can of worms on a podcast? We are going to have you on again. I am positive of that. ROBERT: We're going to paint that bike shed. CHARLES: Yeah, we're going to paint that bike shed. It's a bike shed that needs to be painted. It's something that the community, I think needs to face head on. Thank you so much for coming by and talking with us about Ember-Redux. Everybody, go and check it out. Toran, you've got some talks coming up, if you want to mention those real quick. TORAN: Yeah, I just wanted to plug. There's possibly going to be a talk, we're still lining up the official date with the Washington DC Ember Meetup sometime in April. I planning out to fly out there actually and give this talk on Ember-Redux. I want to thank just publicly the RSA team for kind of helping sponsor me to fly out and check it out. As well as give a more in-depth talk on Ember-Redux in the Meetup setting. CHARLES: Fantastic. If you're in the area, be sure to go check that out. If not, watch it on video and then unrelated Ember-Redux, if you haven't watched Toran's EmberConf talk on Outside-In development. TORAN: That's out actually global Ember Meetup, I think. CHARLES: Okay, that one. Actually, just go watch all Toran's talks. The thing that I didn't mention at the beginning of the podcast is that you do a lot of live coding, which is just makes my bowels freeze when I think about doing it. You just pull it off so effortlessly so it's definitely, definitely worth a watch. With that we, will take it out. We'll see you guys later. That's it from The Frontside. Remember to get in touch with us at Frontside.io. If you're interested in UI, that's engineered to make UX dreams come true.
Godfrey Chan @chancancode | GitHub | Tilde Inc. Show Notes: 02:27 - What is Glimmer 2? 11:24 - Key Changes for Glimmer 2 12:54 - How do these libraries (i.e. handlebars.js; htmlbars) work together? 18:02 - Maintaining Compatibility 24:38 - Components 27:55 - Looking Forward to Non-Performance-Related Features 34:43 - Animations and Visualizations 39:09 - Glimmer 2 For an End User 41:33 - Stand-alone Glimmer? 46:12 - What are the performance gains on mobile? How does it better position Ember for mobile devs? 49:23 - Bubble Tea 50:37 - Contributing to Glimmer 2 Resources: Godfrey Chan: Hijacking Hacker News with Ember.js @ EmberConf 2015 Announcing The Glimmer 2 Alpha Isemberfastyet The Quest Issue (#13127) D3.js EmberConf Yehuda Katz & Tom Dale: Opening Keynote @ EmberCamp London 2016 TypeScript Ember Community Slack Transcript: CHARLES: Hello, everybody and welcome to The Frontside Podcast Episode 53, brought to you by The Frontside where we engineer user experience that is just so. If that's something that you're interested in, please feel free to reach out to us on either Twitter or at contact at the Frontside.io. Today we have a really fun episode. Again, we're second week in a row, we've got a nice fat panel. Jeffrey Cherewaty and Chris Freeman, who are developers here at The Frontside and we're also here with Godfrey Chan. Just a little bit of background on Godfrey, from my perspective, I remember very distinctly back in EmberConf 2014, I went out to dinner and I sat across from this guy who was the organizer of the Vancouver Ember Meetup. Was it Vancouver? GODFREY: Yeah, that is correct, Vancouver, BC. CHARLES: Yeah, Vancouver, BC. You know, I was struck at the time and I was like, "Wow, this guy is really smart and insightful and actually making me laugh a lot." GODFREY: You're very kind. CHARLES: I don't know if you remember that but that was borne out at the next EmberConf in 2015 where he gave this fantastic talk on the power of Ember Data's adapter and serializer layer, where he repeated the same trick except at scale in front of the audience. I think we were all rolling in our chairs with laughter but also learning a lot about this really, really powerful pattern and you had written serializer and adapter layer to basically build without a back end at all, a completely new UI for Hacker News. It was really a fantastic talk. Since then, you've just been going on to do a bunch of other great things: you joined the Rails core team, the Ember core team, and most recently, it sounds like the major thrust of what the last year or so has been giving birth to Glimmer 2, which is the next generation of the rendering engine in the Ember.js framework. It's a really fascinating topic. Thanks, Godfrey for coming on and talking with us about this. GODFREY: Thank you for having me. CHARLES: Yeah, it's a huge deep topic so we're just going to scratch the surface. Obviously, can't cover a year of life in just under an hour but we're going to do our best. Why don't we talk just a little bit about what Glimmer 2 is? For our audience members who are deeply involved with Ember community, it probably is not going to come as a surprise but we actually do have other listeners. What is it and why is it important? GODFREY: Like all good software, Glimmer 2 was basically born out of an accident. Glimmer 2 on a very high level is the new rendering engine for Ember. That's pretty vague but I guess, we'll go back a little bit in terms of the timeline and maybe that would become more clear. The time frame was pretty much when I first joined Tilde, we shipped 1.14 for a while and we just about to ship 2.0. That's when the original Glimmer planned it. That year at EmberConf, I believe it summer of 2015, like Tom and Yehuda talk about this new Glimmer thing on stage that has promised to basically renew the Ember programming model to better match the data down, actions up paradigm as opposed to very reliant on to a bindings and stuff like that. On one hand, it gives you better programming model and on the other hand it's promised to be much faster at rerendering. It's more or less inspired by React so you can just treat your component as if it's refreshing a page on a server-rendered HTML or something like that. You can just update your data and then rerender a component and that's going to be efficient enough that you can just basically rely on that as the main fully-rendered model. That ship in 1.14, for most part it was great so we were planning to start working on the next thing and at that time, the plan was to work on rehydration. If you're not very familiar with it, it's basically the next iteration of FastBoot where today when you have a FastBoot render page, when it goes [inaudible] has to then download JavaScript the data and rerender the page basically for the DOM then re-insert the newly rendered content into the page. There are several problems with that. First of all, it's a lot of wasted work because you already rendered all the HTML on the server side and now you're re-doing the work and you're framing them away. Also your users will probably see a brief flash because you're deleting the old DOM and you're replacing with a new DOM. You probably lose important things like [inaudible] position and probably not the most performant way to do that also. That's what we're going to work on next. Basically, allow the rendering engine to instead of rendering a new DOM, just rehydrate the existing markup that was sent by the server and just wire up the thing so it can be updated further on the client side. CHARLES: What I'm hearing is that the original Glimmer that was introduced in 2015, it had to always assume starting from a zero state. It couldn't take an existing DOM and kind of converge. GODFREY: Right. That's still true today. I wouldn't say that the rendering engine is not capable. It's just that the feature was not written yet, at the time we were about to start writing that feature. It took us maybe a week or two spiking on it. We got something working like as we go for that exercise, I was basically new to the code base at the time so Yehuda was explaining a lot of things to me. We were pairing basically full time at that time. If you know Yehuda, he also travels a lot. He has a lot of other responsibility like [inaudible]. We basically paired for a few days and then he might go on a short trip or I might go on a short trip for a conference or whatever. Then we'll come back and then it was like, "Wait a minute." I basically forgotten most of the things so we have to go through the concepts again. That was a little bit painful. On the other hand, the code was not really that well-rationalized or well-structured. It's a relatively old code base or at least in terms of JavaScript age, the original Glimmer 1 was basically bolted on top of what we were using at the time, which is HTMLbars engine where we can perhaps go into a little bit more details on that later. But basically, the engine was not really designed for a lot of those so it was getting a little bit difficult. Separately on another fret, a lot of things is going on at the same time, we're getting more reports on performance regression on Glimmer 1, which is probably a little bit surprising because the whole point of Glimmer 1 was introduce a new algorithm to make things faster. That's the big promise of the original Glimmer but it turns out that, indeed we rerender performance a lot faster. However, because it was so slow before, basically a no one used that feature ever so the existing apps are not getting any of the benefits because you would have to do a lot of refactor to take advantage of new programming model. However, you have existing code that you're using in production. Those code did not used new programming model, did not get any of the benefit. On top of that, it turns out that even though we have this superior algorithm in Glimmer 1, we inadvertently regressed it the initial render performance for components. That's not a tradeoff that we explicitly made. It's just that we wrote a lot of new code and we were mostly focusing on making the rerender pass as fast as possible. By the time were done, everything seems fine, we shipped but in the wild, people reported, "It turns out the thing I care about just got slower," and because it's not like a design decision that trade off that would made, we don't actually know what's going on like we have a lot of new codes somehow, that made thing slower when you do investigate. Basically, at that time, we had to polish our work on rehydration and focus more on performance. As we dug deeper into this rabbit hole, it turns out one of the main thing that happened was how we handle blocks. In the handlebars template, you have a pound or a hash, like let's say, '#if' and then if something and there's a block in there then you do slash if, that's blocked in handlebars. It turns out we made some significant changes in how that works and blocks got significantly slower for some reason and you can see that by comparing the performance between the block form of the if-helper, like #if, blah-blah-blah, versus the equivalent of the inline form just the curly-curly, if something then show render a string, otherwise render some under string so if you compared to those two versions, they really should be the same thing. They are not functionally any different but if you compare the render and performance between the two versions, it turns out the block version is like in order of magnitude slower, for some reason. That's bad because it turns out we also made some changes to how components work and each component has at least two hidden blocks that you can't see. It were like basically, how the tech name and stuff were rendered so these components, some blocks and blocks got a lot slower so the end result is component initial rendering got slower. That's unfortunate because that's probably one of the most useful feature of Ember or any view [inaudible]. Like on a client side, the way I like to think about it is like if you're writing code and if you've a really long function you probably want to break it down to smaller function for your own sanity. I think components serve a similar role in your templates, like when your template are really big, you probably want to split them into some more modular or hopefully reusable components. If nothing else, just break it down to smaller chunks so you can reason about it. Components are really important and the community is really starting to pick up the idea of components around that time. Unfortunately, we made a change that made components slower so we have to do something about it. That's more or less why Glimmer 2 happened like you're starting out as an investigation into why components got slower, what can we do to make it faster and deeper? We take down on that rabbit hole. We found more things about the HTMLbars engine that is not very aligned with the way we want things to work, which makes it more inefficient than we will like. Basically, it turns out as an effort to realign how the engine actually works with who we actually do with the engine. It start up very incremental and at some point, several things happen that basically cost it to become a complete rewrite. That's basically the backstory of Glimmer 2. CHARLES: Now, here we are, there are these fundamental problems with Glimmer 1 that you can't get to where it is that you want to go, which sounds like these set of optimizations so a rewrite is underway. What were the key things that needed to change in order to make this happen? GODFREY: The overarching theme is basically the original rendering engine. There's not much of a rendering engine to speak off. I think at the time, we don't really fully understand what our requirements are. We don't really know what our needs are so we built something very, very flexible. That's basically HTMLbars and it's kind of self-evident at this because we could take HTMLbars and retrofit the Glimmer 1 [inaudible] from on top. HTMLbars is literally just handlebars plus HTML. It's capable of rendering static HTML and every time it sees a double curly or a mustache, as we would call in handlebars, like every time you see open double curly braces, it provides a set of hooks for you to hook into that process. Every time you see curly-curly, what happens? It says, "This is a block or this is an inline helper," and it just delegate to Ember to, "Please tell me what to do next." That's basically handlebars. CHARLES: If I can kind of interject a question because I think this is kind of a source of confusion, certainly for me. What is exactly the relationship between handlebars.js, like if you go to handlebars.js, the GitHub organization, it is a separate code base, is that just a parser and a syntax? What exactly do the individual libraries contribute? Because we have handlebars.js, HTMLbars, Glimmer 1, Glimmer 2. I think it's a source of confusion that's how are these composed to work in tandem or in tridem when I actually use Ember. Because I know there's people who use handlebars.js that have nothing to do with the Ember community so what's the relationship there? GODFREY: Right. There's handlebars, the language, so to speak and there's handlebars.js, the library. Handlebars is basically just a string templating language. The word 'templating' is probably more confusing than it helps in this context but it's a fancy string interpolation. In JavaScript now, I guess in ES6 you can do it or in Ruby, you have special notations and string to interpolate things. Handlebars is a platform independent language for writing interpolated strings. It has some fancy features like helpers and stuff. But at the very core, it's a way to write really long interpolated strings. Handlebars.js is the JavaScript bindings for that language. As I said, handlebars itself is platform independent but if you have a helper and handlebars like you need to be able to write code for that helper somehow and handlebars.js is the binding that let you write those helper functions in JavaScript. Handlebars.js indeed has a parser in there so you can give it a handlebars template and it would parse into NAST for you. It also has a small runtime library that allow you to register helpers and stuff like that. That's handlebars.js. CHARLES: And HTMLbars is using handlebars.js? GODFREY: In some sense, yes. The original Ember up to 1.10 or something like that, actually uses handlebars.js. It used to be that. We actually do everything as string templates. We just interpolate the string and more or less, just set 'element.' in HTML equals '.string' and that's how Ember used to render things on a screen. Now, HTMLbars does use a part of that pipeline, specifically uses the handlebars parser. How it actually works is there are two possible orders and maybe in the middle of this, I realized I was wrong and it's actually the other order. But I believe how it works, let's say you have an a HTMLbars template or just .hps file in your Ember app, you basically run that through the handlebars parser so you get this some string and then there's some curly mustache here and maybe this is a helper, this is a block, this is whatever. Then I believe we then take all the text notes in the handlebars-jst and then we parse that as HTML tokens. Basically, if you have user.firstname, let's say, and close curly-curly, closed diff, that will basically end up being parsed into a combine jst of this open element of diff and then there's a mustache of user.firstname and then there is a close element of diff. That's the extent that HTMLbars uses handlebars so basically, it uses the handlebars parser to help with some of the work. Now, the part I said I always get wrong is either, you parse it through your handlebars first and then you parse the HTML inside the handlebar-jst or you parse the HTML first and then you use handlebars to parse the curlies inside the HTML-jst. I'm pretty sure we do the handlebars thing first but I'm still not 100% sure. One way or the other, if it turns let's say it parses handlebars first, if it turns out that I'm wrong, I'll probably sent a tweet or something after the show. Does that answer your question? Does that make it more clear? CHARLES: It does because I was always kind of wondering, does Glimmer and Glimmer 2 include its own completely separate implementation of handlebars or not and I think it answer the question of where that boundary lies. GODFREY: Right. Actually, there's a minor detail. I think we're actually on the older version of handlebars. I think there are some new handlebars feature that we need to reconcile. But for the most part, yes, we use the handlebars parser and that's basically the part of the handlebars.js we actually use. JEFFREY: That leads to talking about we used the handlebars parser at the bottom layer. How do you maintain that compatibility? Do you want to have a really great upgrade path from using HTMLbars as the renderer to using Glimmer 1 or 2 as the renderer? Would you talk a little bit about how you maintain that [inaudible] and compatibility? GODFREY: Actually, the handlebars parser part is probably the least interesting part in terms of compatibility. When we did Glimmer 1, I'm kind of speaking as outsider person here because I was not super involved at that time. But from what I hear, after EmberConf 2015, there was a website called IsEmberFastYet.com. It basically count down the number of failing test. Glimmer 1 was kind of a similar situation in that. It was still using the same HTMLbars library and it was part of 1.14 so it still maintained support for a lot of the legacy features like Ember.View and things like that. It's 'easy' in a sense that most of the test are still applicable so more or less, you just rewrite the code and you keep running to test and see what passes or what fails. Then when everything is green, you ship. That's the Glimmer 1 story. However, the devil is in the details. The tricky thing is at the time the test coverage is not very good. As it turns out passing on to test isn't really mean a whole lot so the difficulty in Glimmer 1 is you don't even know who your enemy is really. Not a lot of ways to find out if it actually did the job or not, other than actually just shipping it. As you ship, people start to report a lot of bugs and we're like, "Oh, crap. Actually, this is not tested at all so now we need to fix it." That went on for a long time really. If you actually look at the release history of 1.14, probably have the most number of point releases and that's probably the biggest divergence we ever had from the six weeks release cycle. Unfortunately, what the software is supposed to do is it's unspecified at the time, at least in terms of actual tests so it was a long process and somewhat painful process for the community to figure out what we actually need to support. That was the 1.14 transition. Unfortunately, some apps are still stuck on 1.14 today because of that, because some add-ons or some part of the code bases using some of the features that were previously undocumented or unspecified and it doesn't work on Glimmer 1 anymore. That's Glimmer 1. After that transition, we have a much better test coverage story to work with when we did Glimmer 2. However on the other hand, we actually rewrote the entire engine and also in leading up to that, we actually drop a lot of the legacy Ember features. The test coverage we previously have is useful to have but they're also pretty outdated. Concrete example of that is most of the tests previously written was written in terms of [inaudible] that's no longer a thing in [inaudible] Ember but all of the tests use views internally to test things. The first thing we actually need to do when we try to integrate Glimmer 2 is to port all of those tests, update all these tests and make sure they're still meaningful and modernized them. That was actually a huge task. Thankfully, it's also a task that's very paralyzable. The first thing we did, Yehuda and I spend some time porting those tests and Yehuda being Yehuda we actually spend some time making a really nice abstraction, a really nice test harness for doing that so we started porting some of those tests. But as we start doing that, we realized this is a lot of test to port. Fortunately, it's very paralyzable so what I did was I spent some time writing this really long issue and now are known as The Quest Issue for Glimmer 2, which outline, I for one, this is what we are trying to accomplish. This is going to be a lot of work but fortunately, the work is pretty mechanical or at least the transformation is pretty easy to describe in words. I did that. I described the work that needs to be done and we invited the community to help along. Let's see, that Issue# 13127 on the Ember report. That's known as The Quest Issue and basically, it have a checklist of all the test that still needs to be ported. Surprisingly, a lot of people were really into that, like a lot of people turns out were interested in contributing to Ember but didn't know where to start. This Quest Issue end up being a very good place for someone new to Ember to start contributing. We got a lot of response from that and within a relatively short amount of time, certainly much less than what we would have spent time doing it ourselves. In the relatively short amount of time, all tests were ported. I think that was one of the most successful call-for-help in the history of Ember or even in the history of open source software that I am personally involved with. As part of that too, by doing the harness, we actually introduced much more rigorous approach to testing things. In that process, the test coverage is probably increased several faults as well. With that, we were able to have a relatively high confidence that once all the tests are passing, that we are certainly in a very, very good shape. There might still be some unspecified behavior like there will always be some of them. But I think given the Glimmer 1 transition and also given the new style of testing, that is a lot more rigorous than before, we certainly did that much, much better compared to a Glimmer 1. After doing the original Glimmer 1 and even further back, we start with handlebars and then we wrote HTMLbars, then we wrote Glimmer 1, by now we're actually have a pretty good picture of what we actually trying to accomplish here. The requirements is becoming more clear and at the same time, we have a much better or much clearer model to work with on the Ember side because we got rid of a lot of the legacy features in the transition into Ember 2.0. HTMLbars started off as a very generic library that allow you to add behavior on top of HTML and handlebars. Glimmer 1 was basically loaded on thing using those very generic infrastructure to implement the algorithm we actually want. It turns out that we actually know what we're doing now. We don't need a super generic infrastructure for this so let's make it more tailor-fit thing for the requirements we actually have. An example of that is in HTMLbars, there is no concept of components. There's only thing called block helpers or either inline helpers or block helpers and what happens is every time you see curly-curly something and then you call into Ember, "I found a curly-curly, please do whatever you wish with this," and then we checked and, "It turned out this thing has a dash in there so probably a component. Let me try to resolve that. It turns out it actually is a component so now please synthesize some things and callback into HTMLbars library. This is the thing I actually want to render. Please do it." In Glimmer 2, actually component is pretty fundamental feature so let's build it into the rendering engine. Hopefully that would give you a better idea of what I actually mean by relying the engine with what we actually want. We know we have a pretty good specification of the problem now so we will build the thing that solves that specific problem. When I say, let's build components into Glimmer, it's not even a very concrete thing, like I don't mean the current syntax that happens to be Ember or the hypothetical angle bracket component syntax that's coming to Ember. It is just a very generic concept like there's a thing called component. It's like function calls but in templates. Let's make sure we have a good support off that. Basically, the more the engine knows, the better we are able to optimize that. Previously it's like, it turns out there's a helper-ish thing here so I guess the only thing we need to do is to hand it back into Ember and let it do whatever it wants. Now, the engine actually knows that this is a component so let's try to figure out how we can optimize this component invocation based on what else we know about the arguments and things like that. That's basically the motivation or the design behind Glimmer 2. CHARLES: Right. It's amazing that you find this pattern, kind of cropping up again and again in software where less really is more. The more assumptions that you can make, you can often make the underlying system more powerful. It's kind of counterintuitive because we want to think we want to make everything super flexible and can handle every single case. But it turns out that if you can eliminate a bunch of cases just out of hand, then you're going to have more power. One of the things that I'm curious about is it sounds like a lot of the motivation has been around performance, making sure that initial render is performant and not just a rerender. I'm kind of curious, what nonperformance related features is this going to unlock? This has been a while coming, Glimmer 2 land in what? 2.10? GODFREY: That sounds about right. CHARLES: Looking forward, what are some of the things that we can expect or what are the kind of cool features that this is going to unlock? What's the potential that we're going to see and realized kind of over the next few years based on this work that's been done? GODFREY: In a very technical sense, there are not necessarily a lot of features that are absolutely blocked in a very narrow sense of the works. However, as I mentioned before, everyone kind of felt the same way about the previous code base. Basically, the complexity is getting a little bit out of control like it's so super generic that the things are so spread out across different libraries that's really hard to work with. It's really hard to add new features. All the rendering related features are kind of put on hold as we work on Glimmer 2 because everyone knew that this better code base that's going to come along pretty soon. If we were to do anything significant, we should probably wait for that to finish. The good news is that has finished now and I think most people would agree that code base is in a much, much better shape now. In that sense, it unblocks a lot of work, both in terms of this lock that has been released but it's also in the sense that as we design Glimmer 2, we have all those things in the back of mind and we basically make sure the engine has good support for building out those features. Some of the things that are in the pipeline is I guess rehydration. We basically paused like Glimmer 2 spun off that but we never got back to finishing that work. I would say that's coming. There is angle bracket components. This is actually interesting in that. I think the plan for it to land has changed a little bit. I don't know how much I'm supposed to- Well, there are actually not a lot of secrets but just that someone's in the middle of writing out those RFCs. I don't know if I should [inaudible] shout too much of that. But as I mentioned before, Glimmer 2, the engine has pretty good support for components out of the box, like it's a pretty generic concept of component that's not necessarily tied to a particular syntax and even particular feature set. It's not tied to a particular component API, like this is not forcing you to have a specific base class and stuff. A lot of the features in Ember, like the mount keyword for engines or outlets in Ember or the render helper in Ember, all of those are actually implemented as 'components' under the hood, inside the engine even though they're pretty different things from the curly bracket component that you're used to in Ember today. I think there's a rough consensus on this, like I said, the RC is still in progress so a lot of these things can change but I believe the plan is we'll try to stabilize the core component primitive in the Glimmer 2 engine, that basically let you implement your own component API however you want as a very low level feature. If you remember how we implement the engine, it's kind of similar. We stabilized the core primitives for making engines work under an Ember and then we have an official Ember engines add-on that uses those primitive to provide the actual user-facing API when you want to support. I believe angle bracket component would be similar in that. We would try to stabilize the core primitive of implementing components in the Glimmer engine, then we'll iterate on the new Ember component API, probably as an add-on or something like that. We can get more people to try it and improve the API before actually land that as a core feature in Ember. CHARLES: What I'm hearing is there's actually the potential here to treat the kind of the core component API as an extension point like if I want to define my own different set of semantics and lifecycle hooks and what have you for my special components within my add-on or my Ember application, I could do that and yet have it exist alongside kind of standard components. GODFREY: Exactly. It's a pretty low-level API and I don't think most users would want to go for that. But I think it unlocks a lot of potential for add-on and things like that. Because as I previously mentioned, the [inaudible] in Ember is implemented using that API to render helpers, implement using that API so hopefully you can imagine there are probably something that people really wanted to do and add-on step could be made possible with that low-level API. It might not even look like a component. It could be things like you do in Liquid Fire. I think, [inaudible] has a suite of add-ons that provide some pretty events rendering features that could fall under that umbrella. Basically, it's just opens up a pretty powerful low-level primitive that add-on authors can use to implement the features they want but at the same time, also allow us to iterate on that. I don't imagine a future where literally everyone is building their own component API. I think we would still, as a community have basically this system main kind of component you use in Ember but for whatever special case you have, you can drop down to the low-level and do whatever you want. CHARLES: Right, and at least that area for experimentation and innovation is at least there. GODFREY: Right. CHARLES: That actually kind of brings to mind a very specific case that I was thinking about so I kind of throw this at you as a very friendly curveball that like this is something that you could conceive of being possible. I recently was working on an Ember application with my dad and there were some visualizations. Originally, I was doing these visualizations in D3 and it was cumbersome as D3 code can actually get. The part where you actually compute the D3 scales and the SVG attributes in D3 is very concise but the actual D3 rendering code can be very verbose and can kind of degenerate into this jQuery type like soup. What I did as kind of a first pass is I separated the computations and the slicing and the dicing of the data in D3 and presented those to a simple HTMLbars template as computed properties of a component so I had done all the computation around the visualisation in my Ember component. But then for the template, I used just a simple SVG template and it was beautiful. It was this pretty complex SVG visualization fit into, I want to say, less than 20 lines so you could perceive the entire visualization in one standard editor window, which if you've done a lot of D3 code is actually hard to achieve. When I saw that and I promise I'm going to make a point here, I was like, "Wow, this is like a powerful concept." I feel like this is the way that we ought to be doing SVG visualizations. But the thing that I lost was the thing that kind of this special sauce of D3, which is I wasn't using D3 to actually do the rendering. I was just doing it for the computation so I didn't get those really sweet transitions. One of the sweetest concepts the D3 has is this join model where when you make a change and you push a new set of elements onto the visualization, it computes for you the SVG, the actual DOM elements that are leaving, the ones that are entering and the ones that are updating. I was thinking, "Gosh, it would be really great if there was some way to hook into that inside of Ember," and I'm just kind of curious would such a thing be possible to actually get hooks on the low-level elements? Because essentially, that's what a dom-diff is, which elements are leaving, which ones are coming in, and which ones are changing. Would it be possible to have those hooks with Glimmer 2? GODFREY: I think it's definitely possible. I don't know how much of that you can actually do right away in the current code base but I think conceptually, that makes a lot of sense and that's definitely something that we should have support for, if we can already do that today. What can be adapt was I haven't spent a lot of time doing animations myself, but I would say that makes a lot of sense. I hope most of that is already achievable today. But if not, we should definitely make it happen. I think a lot of people didn't realize but we actually spend a significant amount of time on our end, making sure that we have good support for SVG. We do have a spec compliant HTML parser and stuff so it's actually rendering SVG with Glimmer or with Ember, which is actually really nice. We have some of those animations or visualization stuff in Skylight and we actually take a similar approach where we actually have SVG templates and we just use Ember to fill in the dynamic data and we have some, I believe, JavaScript code to do the animation but we should definitely talk more about that topic and making sure it's solid. CHARLES: You know, I can't reiterate how sweet it feels to do as SVG. Really, when I kind of stumbled upon it, I was like, "Wow, man. Someone needs to do this more." GODFREY: I believe in the latest iteration of D3, they actually broke up the library into pieces that makes some of those things much more easier. I think that's definitely at direction that everyone wants to have to work. CHRIS: I know that you talked about that there are people writing RFCs and EmberConf is coming up so I'm assuming that there are possibly some things that are going to be talked about there. But one of the things that has really kind of floated around Glimmer 2 ever since last year's EmberConf is that in terms of the next leap forward for Ember, Glimmer 2 was often pointed to as the blocking thing. You know, angle bracket components, a lot of other features that people would like to see in Ember, a lot of it seemed to be bound up and Glimmer 2 was going to unlock a lot of these things for us. I'm curious for an end user of Ember, what is Glimmer 2 really mean for them in terms of the next six months to a year? Are there a lot of things that are planning to be unlocked by Glimmer 2? Or is it going to be much more of an incremental progress? Or do we actually know everything that's going to be unlocked at this point? GODFREY: I think it's a combination of all of those. Like I said earlier, there are probably features that along the lines of the angle bracket component or the low-level component primitives rehydration. There is also this concept of chunk rendering in that, basically, do as much rendering as possible without making a significant pause on the UI [inaudible] and then yields expected browser for user interaction and then go back to rendering more stuff and repeat that until you're done. The net effect is you basically, don't block scrolling and things like that for a significant amount of time. Even though, your initial render might actually take more than the 60 FPS or whatever time frame you have allocated. Also, performance in general, I think we're very much not done here. We're just getting started. We have a much better engine to work with and there are a lot of further optimizations that we want to do so now, that we've shipped with completed compatibility, we climb in, more or less I think everyone is excited to get back on to those things that they were previously working on. CHRIS: Another one I have seen kind of reference a couple times, especially by Tom is Glimmer components and Ember CLI as kind of like a lightweight Ember without all of Ember. Even if you poke around the Glimmer repos, a lot of benchmarks that you can see a version of [e] components that don't yet exist, you see TypeScript, you see ES6 extends Glimmer component. A lot of things that I know people would be absolutely thrilled to see in Ember, a standalone Glimmer like planned to be a thing at all and like [inaudible] syntax, like ES6 class components is that as they make Glimmer 2 unlocks it all or are there other things that are blocking that? GODFREY: Yes, all of those are definitely in the pipeline. Standalone Glimmer is interesting. As you mentioned, Tom and several other people have started experimenting with that today. I think Tom talked about it in his EmberCamp London keynote this year or last year -- 2016. If you haven't seen that, you can definitely go check that out. It's not something I would recommend doing today in production just because there are a lot of [inaudible] in the code base still so we need to stabilize that. Literally, when I went on vacation for the last three weeks, you could basically rewrote the entire VM. It's some work that we have been talking about for a long time and he basically end up having some free time to check on that. Everyday changed after I came back from vacation so if you do that today, that's probably what you would have to deal with in the foreseeable future in the next few months. But I think we are definitely working towards making that more stable so we can enable the kind of things that Tom is doing. Part of it is definitely we need to make it easier. Currently, Tom has to do a lot of work to make that happen and Ember CLI has to be a core part of the story and etcetera, etcetera. But I think a lot of people were definitely working towards that goal. In terms of TypeScript ES6, TypeScript is actually pretty interesting. It's kind of another happy accident that came out of the Glimmer 2 rewrite. As I mentioned at the beginning, when I was new to HTMLbars code base, there are so many concepts and Yehuda and I both travelling a lot at the time so every time we reconvene, it was like, "Wait a minute. I forgot to read things so let's actually take the whiteboard and write down all these things here permanently so I won't forget them." As we start to do that, it was like, "Actually this is very complicated to write on the whiteboard so let's just write out the types somewhere," not in a very rigid sense but just, "Oh, there's this thing called render node and this is basically the responsibility. These are the methods on that thing and these are the fields on that thing." As you write that you would probably want to remember, "Oh, this is actually a string or this is an object with these sub-properties," and as we actually tried to do that, it was like, "Wow, we should not actually invent." We either have to invent a notation for that or we could just use a notation that people have made for this purpose already so let's just go to the TypeScript playground and type it out there. Then that turned out to be great but it's not that amazing to write. Many interfaces in the browser so let's just go back to the editor window and type in there and it turns out TypeScript is written in a way that all [inaudible] JavaScript is fellow TypeScript. Basically, a superset of JavaScript. Eventually what we ended up doing is we just went through an entire code base and renamed all of the JavaScript file to .ts, then we made a commit of that. Incrementally, we end up switching the entire code base to TypeScript and that's actually how it happened. In terms of using TypeScript and ES6 classes and Ember is probably block by few RFCs. There are probably some design work needed there but I would say that's happening. I don't know how close it is but just because there are a lot of things in the pipeline right in it. But I think it's a relatively high [inaudible]. CHARLES: Before we wrap up, we had some great listener questions that came in over Twitter. I want to put those to you. The first one comes from Elrich R and the question is, "What are the performance gains on mobile for Glimmer 2? How does this better position Ember for mobile development? GODFREY: I think the short answer is it's faster. As far as how much faster, unfortunately, a really hard question to answer just because it vary so much from app to app. We have some numbers that we have been looking as we develop it but at the end of the day, each app is very, very different and the kind of things that slows your app down might not be very obvious. There's a pretty interesting thing that happened when we were [inaudible] Glimmer 2. One day I was checking the Ember communities Slack and someone reported, "I have this list of 1500 items that I'm rendering. I know that's not ideal but it is what it is for now. But I just tried Glimmer 2 and it's really slow. It's taking three seconds to render that list of 1500 rows. Is there something wrong?" I was like, "That sucks." We tried to make this thing faster but I agree, three seconds is still really slow. I was like, "Can you share your app? Can you check what is the delta? What was the number pre-Glimmer 2?" He's like, "Let me go and check. Actually, it turns out it was 14 seconds pre-Glimmer 2 and it was now three seconds." I was like, "Yeah, okay. I agree that's not great but with 1500 items and we went from 14 seconds down to three seconds, I think I would take that as a win." Part of it is difference like that, really is how complicated your page is. Also there are a lot of factors that are actually unrelated to rendering, perhaps surprisingly, all of which we're working on but for example, how many routes do you have in your app, actually for some reason, plays a pretty significant role on the initial render timing and also how big your app is and things like that. I think across the board, it's pretty much faster. As you can see sometimes, it's 14 seconds, three seconds for small apps. It might be from 500 milliseconds to 400 milliseconds. In Skylight I think, we're seeing anywhere from 7% to 40% overall and we're talking about micro numbers just like everything from download in JavaScript to everything up until the page is interactive. There's a lot more than rendering going on there but I don't have a good one-size fits-all number for you here. But I think overall it's faster and we'll make it faster still and we'll continue to make it smaller. Hopefully all of that would be meaningful improvement for mobile or even just performance in general, if that's something you care about in your apps. CHARLES: Yeah, because I understand that the payload size is a lot smaller and that ought to make a huge difference there. The final question is and this one comes from Lauren T, "What is your favorite flavor of Bubble Tea?" GODFREY: Interesting. I love Bubble Tea but for whatever reason, I'm just not really into milk teas. I know that's what most people go for when they get Bubble Tea and my personal favorite is probably Honey-Lemon Green Tea. That's probably my go to. CHARLES: That's delicious. I think, I subsisted wholly on those AriZona Iced Tea in 20-ounce cans from about the age of 17 to 18. There might have been a few months where that represented all of my caloric intake. GODFREY: I think I once bought a one-gallon pack of those from Wal-Mart and unfortunately, the bottle broke in my trunk on my way home so I basically stopped buying those after that. CHARLES: You get the nice smell of rancid tea. All right-y. We'll thank you so much for coming by Godfrey. GODFREY: Thank you again for having me. CHARLES: Yeah, it had been very enlightening. A deep dive into the what the Glimmer 2 is all about, the challenges that you faced of getting there and where we can expect to go now that it's here. Oh, let me ask one final question before we send it out. Glimmer 2 has been a long process. There's been a lot of hills to climb and I know a lot of people that I've talked to, as part of the community, one of the biggest questions I have is how can I get involved? How can I help? Where can I throw my weight to see this technology blossom and become really, really useful and widely applicable to everybody inside the Ember community? Just in general, where are more of those quests that you just described? Where can people go to find out more to contribute more? GODFREY: There are several places. First of all, there is the Ember communities Slack and there's [inaudible] Ember channel and there's also a [inaudible] Glimmer channel. I think we might merge them back into a single channel at some point. But currently, those are where people hang out. In terms of quest issue, actually really counting to it in terms of the time investment versus the payoff. If there's one thing that I wish I did earlier and wish I did more is probably I would have started these quest issues earlier and do more of them. I guess we have to write more of them. But basically, hang on those channels. A lot of times, people asked questions then we try to help them out. A lot of times those end up turning into opportunities for contributions. It's kind of like documentation. I don't actually hate writing documentation but it's not the first thing that comes to mind, in terms prioritization. I think writing Quest Issue is kind of like that one. You actually do it, you realized, "Wow, this is actually really helpful and I should do it more," but it's just so counterintuitive that it's often not the first thing in trying to do when I try to prioritize my day. It's just something I have to keep reminding myself and I appreciate the reminder here that I need to write more on these issues and get more people, empower more people to be able to help. CHARLES: Alright-y. Well, you heard it folks. Thank you very much and we will see you all next week.
В этом году мы записываем серию подкастов со спикерами конференции RailsClub 2016. 22 октября, Москва, подробности и регистрация на сайте конференции. Первое интервью было с Лешей Тактаровым Ссылки These Guys Code Hipsters - Ироничные новости фронтенд-разработки глазами бьюти-кодеров Rollup - Next-generation ES6 module bundler Webpack – A bundler for javascript and friends Foreman – Manage Procfile-based applications Hivemind – The mind to rule processes of your development environment Статья Равиля Brunch – A Front end build system CODE. The Hidden Language of Computer Hardware and Software - Код. Тайный язык информатики The Nature of code Being A Developer After 40 – Каково это — быть разработчиком, когда тебе сорок перевод Расшифровка эпизода, опубликованная на Habrahabr Как ты пришел к Ruby ? Моя история знакомства с этими технологиями довольно нетипичная. Я начинал свою карьеру как человек, который делает системные тулзы. Я и с фронтендом тогда не встречался, просто занимался нативными интерфейсами для Windows. Какое-то время потратил на то, чтобы делать программы, которые работают с большим количеством потоков, которые работают с concurrency и так далее. А затем как-то плавно перешел во фронтенд, тогда как раз появился хайп. С Ruby и рельсами я начал работать уже после этого, и для меня это было небольшим откровением, потому что не все вещи, которые там работают, работают так как я привык. Лучший пример: в некоторых средах, где ты всегда должен следить за ресурсами, если ты что-то взял в одном потоке и работаешь, то должен быть уверен, что в другом потоке не будет проблем с этим - в ruby все эти проблемы обходили стороной. Я столкнулся с совершенно другими концепциями. И это было клево! Если говорить конкретно - я пришел на проект как фронтендер, делал только фронтенд задачи. А потом у нас не стало бэкендера :) Он ушел, некому было решать его задачи, и я решил попробовать. Было необычно: обсудить было не с кем, человек который мне помогал был этаким мудрецом. Я приходил к нему раз в неделю, он говорил какие-то магические слова о том, что мне делать. Потом я уходил, вздыхал, думал: “О боже, что происходит”. Через какое-то время мне вроде удалось постичь эту мудрость, хотя наверное не всю. Ту часть, которая заложена во фреймворке и языке, я почувствовал этот вкус. Где и чем ты сейчас занимаешься? Из личного - готовлюсь к свадьбе. Работаю над своим проектом, который еще слишком сырой, чтобы про него рассказывать. А еще работаю с партнером в команде, которая называется These Guys. Мы специализируемся на быстрой разработке MVP. Стараюсь по-максимум применить тот опыт, который я получил работая со Злыми марсианами, и с другими командами. Но сейчас я больше ориентируюсь сейчас не на решение технических задач, а на решение бизнес задач, продумываю как оптимально все построить для клиента. То есть ты сейчас открыл свою компанию? Да. Хотя сказать об этом вслух мне сейчас очень страшно, почему-то :) Что тебе не нравится в текущей реализации рельсов с точки зрения фронтенда? Мне кажется, что произошла такая ситуация: два или три года назад фронтенд резко скакнул и понесся вперед со скоростью локомотива, сметая все на своем пути. Ребята из других сообществ на это смотрели, кто-то скептически относился, кто-то воодушевленно. Но надо признать, что ускакал он очень далеко. В этом плане мир рельс остался без изменений. Есть мнение, что рельса должна перестать быть инструментом, у которой есть и фронт, и бэк, сосредоточиться только на бэке. Потому что фронтенд часть в самой рельсе сейчас явно не успевает. Приходится рельсы использовать как серверную часть, а фронтовая стоит отдельно, там отдельные инструменты, отдельная команда, отдельная история. Какой позиции ты придерживаешься насчет этого? Я всегда пытаюсь смотреть шире. Когда я вижу хайп вокруг фронтенда, я всегда пытаюсь найти и хорошие, и плохие стороны. Хорошо, что все развивается и движется, много идей, много что можно сделать такого, что поможет следующему поколению разработчиков. Но на это нужно смотреть с опаской, смотреть на то, действительно ли все так, как кажется? Это касается и компаний: какой они выбирают стек, как они общаются со своими разработчиками. Например, разработчики брали какой-то популярный сейчас стек, а потом все разваливалось. Компания переставала работать, потому что технология была сырая. У вас было такое? Я стараюсь придерживаться золотой середины. Недавно прочитал статью Равиля Байрамгалина из марсиан про новый рендерер. В ней интересна даже не сама реализация, а то, что идет в начале статьи: у DHH нет большого количества времени, чтобы уделять его разработке, но он записывает и рассказывает много идей, которые могут подхватить другие разработчики, чтобы успешно развивать фреймворк. Мне кажется, это здорово. Круто, когда есть видение, когда DHH понимает куда идти. Возможно будут разногласия, где-то это будет не совсем правильный путь. Но мне нравится, когда есть понимание общей миссии. В рельсах такое видение есть, нужно пережить хайп и двигаться дальше. Мне кажется у нас все получится, моя позиция вполне позитивная :) Если говорить про хайп во фронте. Что сейчас является хайпом, а чем реально можно пользоваться? На что, по твоему мнению, стоит обратить внимание? И что будет интересно дальше? Какое-то время назад мы с друзьями организовали в Ростове небольшую тусовочку, которая называется Code Hipsters. Это, в основном, лента новостей во вконтакте и в Телеграмме, мы пишем про всякие модные штуки во фронтенде (это и пытаемся обыграть в названии). Сейчас я немного отошел от дел, всем занимается мой друг Витя. У него прекрасный стиль, мне очень нравится как он пишет. Иногда мы собираемся и понимаем, что мы не читали за прошедшую неделю ничего нового :) Видимо, немного устали. Последнее, о чем я слышал - это Rollup. На мой взгляд, там нет ничего революционного, но посмотреть интересно. Движение в сторону умных бандлеров, правильной сборки зависимостей я считаю очень важным, это хорошее направление. Хотя нельзя сказать, что это rocket science. Во-вторых, компонентный подход. Он пришел давно, все его приняли, и это здорово. В-третьих, FRP. В этом вопросе есть большая пропасть между теорией и практикой. Наверняка что-то появится, чтобы ее преодолеть. Возвращаясь к вопросу о рельсе как фреймворке и к фронту. Что бы ты добавил а рельсу или убрал из нее, с точки зрения фронтенд разработки? Может вообще убрал бы фронт из рельсы? Я бы не убирал фронт. Мне кажется, решение которые есть сейчас, позволит нам выжить в 80% проектов, по крайне мере таких, которые есть на рынке. Ингода очень удобно иметь такой функционал. Даже когда мы говорим о сборке файлов, которая на самом деле не сборка, а просто конкатенация в правильном порядке. Я считаю, что это плохо. Я слышал, что не любят турболинкс, хотя я к ним отношусь вполне нормально, использую их в некоторых проектах. Да, иногда приходится потратить много времени на то, чтобы сообразить, как все правильно делать. Но это приучает к порядку. Мне было проще: я не писал скрипты, я сразу начал писать single page applications. Приходилось думать о том, как выделять ресурсы, как их правильно тушить, о сервисах, о жизненном цикле приложения, о том, что оно может работать продолжительно время. Когда ты делаешь простой мультистраничный сайт с вкраплением скриптов, ты об этом не задумываешься. Но иногда проект требует того, чтобы все это учитывалось, заставляет держать в голове паттерны, которым нас научил правильный фронтенд. Не знаю, что я бы добавил прямо в рельсы. Есть тенденция выкидывать все ненужное, облегчать, оставлять рельсы только для API. Правильно? Там есть отдельная ветка, связанные именно с Rails API разработкой, отключением ненужных вещей. Да, это касается и сборки. Если ты запускаешь рельсовый проект, наверное было бы здорово уметь как-то управлять процессами, которые запускаются. Сейчас это не просто rails сервер, или какой-нибудь Sidekiq. Было бы клево уметь мониторить процессы, которые запускаются для сборки, которые Node.js-процессы запускаются. Было бы круто что-то такое придумать. Хотя и здесь можно в принципе предложить решения вроде Foreman или Hivemind. Раз мы начали говорить про инструменты: за какими ты сейчас следишь? Какие проекты тебе нравятся, на какие стоит обратить внимание? В некоторых случаях я пользуюсь Webpack, меня он вполне устраивает. Я понимаю весь юмор, который стоит за тем, что у него сложная конфигурация. Мне кажется главной концепция, что модули это клево. Я долго пользовался сборщиком Brunch. Его всегда обходили стороной, он оставался в тени. Но для меня это идеальный инструмент, когда нужно что-то очень быстро накидать, когда нужны просто модули в стиле common js, когда нужна очень быстрая сборка. Потому что он действительно работает очень быстро. Меня поразило, что многие ребята, которые делают фреймворки, начинают лепить boilerplate и command line tools, например Ember CLI, или штука для React, которая появилась недавно. В случае с Ember меня поразило то, что ты очень жестко привязан к сборщику, ты не можешь выбрать другой сборщик кроме Broccoli (который я тогда вообще не смог настроить, и он собирал все ну очень долго). По крайней мере, на моей машине это работало вечность. У меня был опыт работы с Ember, мы проект свой до конца собирали на Brunch. Даже учитывая то, что пришлось очень много портировать под себя, потому что все комьюнити перешло на Ember CLI и , мы все равно пользовались Бранчем, терпели. В нашем случае, мы пожертвовали удобством в пользу скорости и быстрой сборки, потому что у нас было много файлов и мы не могли себе позволить ждать вечность. Ты не пытался влиться в open source историю и начать помогать каким-то проектам? Если да, то куда ты коммитил? Да, у меня есть коммиты. Я бы не назвал себя активным контрибьютором. Коммитил во фронтендовые проекты на уровне мелких пулреквестов. У меня есть несколько своих open source проектов (если можно так сказать). Возможно, они не очень интересны, не получили много звездочек на гитхабе, но все же. Я писал враппер для работы с принтерами под Node.js, для одного из моих хобби-проектов. Я делал что-то вроде распределенной печати фотографий из Инстаграма, нашел прикольный маленький принтер для фотографий и подключил его к Raspberry. Благо на Raspberry работал Node.js, пришлось его собирать. Написал что-то вроде агентной системы (не знаю, правильный это термин или нет). Идея была в том, чтобы подключать такие принтеры-устройства и потом печатать фотографии на произвольной станции. Все это легло в основу моего дипломного проекта, который я полностью выложил на гитхаб, я этим в какой-то степени горжусь. Иметь гитхаб это здорово, и использовать его для образования тоже. Вообще дипломный проект получился довольно прикольный. Где ты берешь информацию о фронте: ресурсы, твиттер-аккаунты, за которыми ты следишь, новостные сайты? Про Ruby мы все знаем куда смотреть, на что подписаться, а с фронтовой частью лично у меня с ходу ничего не приходит на ум На первом месте для меня стоит Code Hipsters. Даже если если я не читаю статьи, не ищу их, я все равно пользуюсь телеграмом и читаю канал Code Hipsters c огромным удовольствием. Конечно, я немного по-другому его воспринимаю, потому что это мои друзья. Еще? Твиттер, особенно англоязычный помогает. Не назову какие-то конкретные аккаунты, это накопившийся за долгие годы слой информации. Иногда ты можешь листать ленту, и если произошло что-то действительно трендовое во фронтенде - ты это сразу увидишь, все лента будет заполнена этим. Еще мне нравятся подкасты. Я слушаю Вебстандарты. Кстати, в недавнем выпуске они спрашивали, кто какие подкасты слушает - оказалось, что никто ничего не слушает :). FrontFlip, наверное? Нет, не пошло, вообще не получается слушать русскоязычные подкасты. Я слушаю The Changelog, еще мне нравится подкаст от Thougtbot. Еще Giant Robots, мне очень нравится стиль, атмосфера. Обычно это два спикера, и создается впечатление, что они просто встречаются на выходных, обсуждают, что у них произошло, забывают что есть тема для подкаста. Но это все равно интересно слушать. Это даже два подкаста, один скорее про бизнес (это подкаст от одного из создателей foreign key и еще какой-то платформы. А про разработку это подкаст парня который тоже будет на RailsClub, который поддерживает Phoenix для Elixir. А про фронтенд это The Changelog. О чем ты будешь рассказывать на RailsClub нам, бэкенд разработчикам? О том, что фронтенд ускакал далеко и фреймворк за этим не поспевает. Я буду рассказывать о том, как собирать фронтенд в окружении рельс, какие есть решения, какие есть проблемы. И почему это на самом деле нужно. Буду стараться опираться на свой личный опыт. Как я понимаю, ты не был раньше на RailsClub. Что ты ждешь от конференции? Много интересных знакомств. Я бы хотел увидеть много ребят с горящими глазами. Да и вообще ребят, которые готовы пообщаться, не только на тему конференции. Конференции интересны людьми. У меня была интересная ситуация: в прошлом году мы поехали на Frontend Union Conf, она была в прошлом августе в Москве, в этом где-то в Прибалтике. Мы приехали всей тусовкой, но так устали с дороги, что очень сложно было поймать волну докладов, мы слушали одним ухом. Драйв начался на афтепати. Мы познакомились с парнем из SoundCloud Jan Monschke. Я не помню, какой у него был доклад, но общение после конференции запомнилось. Он клевый чувак, рассказал нам про свои проекты. Речь зашла о Brunch, сборщике о котором я уже говорил. И выяснилось, что он был одним из чуваков, которые начали этот проект. Да ладно!? Это именно то, для чего нужно ехать на конференции: общение. Ну и доклады тоже :) Помимо разработки, чем ты увлекаешься? Читаешь, поешь, играешь на чем-то, ходишь в горы? Сode Hopsters, хотя это скорее связано с работой. Я могу сказать, что меня вдохновляют (и в работе, и в жизни) многие вещи, которые я узнал когда был ребенком. В детстве мне нравились всякие штуки, механизмы. У меня была небольшая мастерская, в которой я делал из дерева всякие луки, арбалеты. К сожалению, у меня не было наставника, который показал бы как можно подключить все это к электричеству, как делать более продвинутые штуки. Когда-то я наткнулся на книгу, которая называется Код, ее написал Charles Petzold. Книга была интересна тем, что рассказывала о детстве: представьте себе, что у вас есть друг, вы живете в домах напротив. И вы захотели общаться, подавая друг другу тайные знаки. Вы достаете фонарик, начинаете рисовать на стене его дома буквы. Потом он плавно переходит к кодам и азбуке Морза, азбуке Брайля, рассказывает про телеграф. Если ты хочешь делать телеграфную связь, то тебе нужен повторитель, а повторитель можно сделать на основе реле… И тут начинается самое интересное. По книге можно сделать всякие logiс gate и тд. Спойлер: книга заканчивается тем, что он показывает как на ассемблере писать прототип операционной системы. Эта книга - идеальное описание того, что меня вдохновляет, вот такие мысленные эксперименты. Еще мне нравится, когда код как-то переплетается с дизайном. Могу посоветовать книгу “ The Nature of Code”, она написана обычным языком, но показывает как писать processing, как моделировать натуральные системы, типа стаи птиц и так далее. Такие вещи меня сильно вдохновляют. Я думаю, это в какой-то степени определяет то, какой я разработчик, то, как я работаю и живу. Сколько у тебя проектов и какой ты сейчас используешь фронтенд стек? Говорить про текущее время сложно: у меня этап, когда я пытаюсь все закрыть. Могу рассказать про то, чем я пользуюсь в реальной жизни. Все зависит от задач, я пытаюсь быть максимально гибким, на благо команды, с которой работаю, и на благо клиента. Если я понимаю, что проект с большим количеством состояний, не требует сильной интерфейсной логики, то почему бы не сделать его multipage, почему бы не сделать его на рельсах, в них все для этого есть. Если вдаваться в подробности, то я пользуюсь Slim, пишу на SCSS. Я заметил, что когда долго пишешь single page приложения, фронтенд меняет тебя. У нас был сложный проект: отдельный бэкенд и много single page приложений. Все они были написаны на ember.js. Вообще у ember интересный путь, от момента как созрела идея, до момента когда вокруг него начало появляться комьюнити и он начал тягаться с react по производительности. Я очень доволен этим фреймворком, в нем все есть для быстрого старта. Какие-то вещи смущают, особенно это касается Convention Over Configuration. Ребята, которые делали Ember (Ехуда Кац из Rails Core Team), вдохновлялись рельсами и постарались перенести много принципов. Мне кажется, что не все получилось здорово. Convention Over Configuration во фронтенд проектах, на мой взгляд, - это очень сомнительно. Мне проще написать больше фронтового кода, чем полагаться на какие-то вещи, которые встроены во фреймворк. С другой стороны, очень много удобных help'еров, можно быстро стартовать проект и так далее. Возвращаясь к теме multipage. Я заметил за собой, что на рельсовых проектах, которые не используют внешний сборщик, а полностью полагаются на assets pipeline, я начинаю организовывать свои фронтендные файлы в какую-то структуру, писать сервисы, организовывать все в некое подобие view. Хотя это просто чистые ES6 классы, которые получают в конструкторе рутовую ноду, от которой можно работать. Такой облегченный backbone view, но только без всего, просто для изоляции. Я думаю, что это хорошая тенденция. Это позволяет и кодовую базу держать в хорошем состоянии, и избегать эффектов, которые часто вылезают при ее разрастании. Сейчас идет какое-то противоборство Angular и React. Ты на чьей стороне, на темной или на светлой? И что есть темная, а что есть светлая? С Angular я практически не работал. Понимаю, к чему ты клонишь, но об этом сложно рассуждать. Я считаю, что эти споры лишены смысла. Не нужно искать кто главный, кто прав, кто нет. Нужно понимать, кто в какой ситуации хорош, где что лучше использовать. Если будет приложение, в котором я буду видеть четкую структуру, переходы, роуты, авторизацию, загрузки и так далее - я, наверное, положился бы на Angular. Хотя в глаза его никогда не видел, но я предполагаю, что там очень много поддержки для таких вещей. Если бы нужно было писать какой-то виджет, встраиваемую часть, какое-то простое приложение, с небольшим количеством состояний, в этом случае, наверное, выберу React. Я не стал бы ориентироваться на измерения производительности и какие-то фичи типа серверсайд рендеринга. Я считаю, что эти вопросы слишком много обсуждают, серверсайд рендеринг того не стоит. В реальности это нужно в 10% случаев, по крайней мере, мне так кажется. Поэтому я бы смотрел на те вещи, которые фреймворк предлагает: на то, что будет полезно для команды, для всего проекта, для компании. То есть ты занимаешь в этой войне нейтралитет? Да! Если бы меня попросили посоветовать что-то следующему поколению, я бы посоветовал прочитать интересную статью про то, каково быть 40-летним разработчиком. Автор очень интересно рассказывает про всю свою жизнь, чему его научила работа больше чем в 10 компаниях. Он говорит очень важную мысль: не полагайтесь на хайп, это ложное чувство, старайтесь смотреть на все трезвым взглядом. Оценивайте, не полагаясь на кратковременные чувства. Я считаю, это очень мудро. Я бы тоже хотел придерживаться такой позиции. Мы выражаем огромную благодарность Лене Могильниковой за помощь с организацией этого выпуска.
02:22 - Michael North Introduction Twitter GitHub Levanto Financial 04:10 - Ember vs React or Angular JavaScript Jabber Episode #203: Aurelia with Rob Eisenberg 07:13 - Convention Over Configuration 09:39 - Changes in Ember SproutCore iCloud Ember CLI Performance glimmer 16:04 - Ember FastBoot Building a performant real-time web app with Ember Fastboot and Phoenix 18:53 - EmberConf Opening Keynote by Yehuda Katz & Tom Dale 22:47 - Mobile/Native Experience & Optimization Service Worker Hybrid Apps 29:52 - Electron 30:46 - Open Source Empowerment; The Ember Learning Team 33:54 - Michael North's Frontend Masters Ember 2 Series 37:11 - The Ember Community Picks React Rally (Jamison) Embedded (Jamison) Remy Sharp: A debugging thought process (Jamison) NashDev Podcast (Aimee) JS developers who don’t know what closure is are fine. (Aimee) Sublime Text (Chuck) DesktopServer (Chuck) MemberPress (Chuck) Frontend Masters (Mike) Wicked Good Ember Conf (Mike) Debugging Node.js with Visual Studio Code (Mike)
02:22 - Michael North Introduction Twitter GitHub Levanto Financial 04:10 - Ember vs React or Angular JavaScript Jabber Episode #203: Aurelia with Rob Eisenberg 07:13 - Convention Over Configuration 09:39 - Changes in Ember SproutCore iCloud Ember CLI Performance glimmer 16:04 - Ember FastBoot Building a performant real-time web app with Ember Fastboot and Phoenix 18:53 - EmberConf Opening Keynote by Yehuda Katz & Tom Dale 22:47 - Mobile/Native Experience & Optimization Service Worker Hybrid Apps 29:52 - Electron 30:46 - Open Source Empowerment; The Ember Learning Team 33:54 - Michael North's Frontend Masters Ember 2 Series 37:11 - The Ember Community Picks React Rally (Jamison) Embedded (Jamison) Remy Sharp: A debugging thought process (Jamison) NashDev Podcast (Aimee) JS developers who don’t know what closure is are fine. (Aimee) Sublime Text (Chuck) DesktopServer (Chuck) MemberPress (Chuck) Frontend Masters (Mike) Wicked Good Ember Conf (Mike) Debugging Node.js with Visual Studio Code (Mike)
02:22 - Michael North Introduction Twitter GitHub Levanto Financial 04:10 - Ember vs React or Angular JavaScript Jabber Episode #203: Aurelia with Rob Eisenberg 07:13 - Convention Over Configuration 09:39 - Changes in Ember SproutCore iCloud Ember CLI Performance glimmer 16:04 - Ember FastBoot Building a performant real-time web app with Ember Fastboot and Phoenix 18:53 - EmberConf Opening Keynote by Yehuda Katz & Tom Dale 22:47 - Mobile/Native Experience & Optimization Service Worker Hybrid Apps 29:52 - Electron 30:46 - Open Source Empowerment; The Ember Learning Team 33:54 - Michael North's Frontend Masters Ember 2 Series 37:11 - The Ember Community Picks React Rally (Jamison) Embedded (Jamison) Remy Sharp: A debugging thought process (Jamison) NashDev Podcast (Aimee) JS developers who don’t know what closure is are fine. (Aimee) Sublime Text (Chuck) DesktopServer (Chuck) MemberPress (Chuck) Frontend Masters (Mike) Wicked Good Ember Conf (Mike) Debugging Node.js with Visual Studio Code (Mike)
We’ve all heard unit testing is good, but how do you get started writing unit tests? In this episode of Front End Happy Hour we share our experiences and advice writing unit tests. We discuss why it’s important and beneficial to have unit tests in your JavaScript. We share how we’ve approached unit tests and what a good unit test looks like. We also talk about the various tools and frameworks available to get your code properly tested. Items mentioned in the episode: Selenium, Black-box testing, White-box testing, Ember guides, Mocha, Jasmine, QUnit, Tape, Jest, Webpack, 5 Questions Every Unit Test Must Answer, Ember CLI, React CLI, Karma, What is the difference between a test runner, testing framwork, assertion library, and a testing plugin?, Ember Guides introduction to Unit Testing Panelists: Ryan Burgess - @burgessdryan Augustus Yuan - @augburto Jem Young - @JemYoung Derrick Showers - @derrickshowers Picks: Ryan Burgess - Caffeine for Mac Ryan Burgess - Odesza Augustus Yuan - Google Doodles Augustus Yuan - OSSU Computer Science curriculum Augustus Yuan - Mura Masa - What If I Go? Augustus Yuan - teamLab: Living Digital Space and Future Parks Jem Young - Flume - the mixtape Jem Young - Programming Sucks Jem Young - Hype Machine Derrick Showers - Google Calendar goals Derrick Showers - $13 bluetooth headset
This week, we talk with Sam Selikoff, the mastermind behind Ember CLI Mirage. He shares how he got started with programming, some tips for avoiding burnout, why he created CLI Mirage, some tips for using it, why it's important to write great documentation, and more. Show Links: Sam Selikoff Follow Sam on Twitter Ember CLI Mirage Pact (ruby) Contract-driven Design by Martin Fowler EmberMap Practical Object Oriented Design in Ruby by Sandy Metz
S1E06 - Chase and Jonathan from Ember Weekend interview Luke Melia from Yapp Labs. Luke shares the beginning of Ember and the adoption of Ember at Yapp Labs when it was just him and Kris Selden coding it up. He shares the behind how Ember NYC started, and how ember-cli-deploy became the default deployment story for Ember. Luke also discusses the success of the ember-cli-deploy plugin ecosystem, the natural evolution of the ember-cli-deploy team, collaboration for open source projects in the ember ecosystem, and his thoughts on how javascript and frameworks will evolve in the next year. Find more podcasts, videos, trainings and online conferences at http://modern-web.org or follow us on Twitter @modernweb_.
Show notes: http://betweenscreens.fm/episodes/98
Chase and Jon discuss Ember's new versioned guides, testing in Ember CLI, and an Ember dependency guide for Rubyists.
Yehuda Katz and Tom Dale join us to talk about the road to Ember 2.0 and "Fast Boot". They share insight about why they stick to a 6 week release cycle, and why they think JS frameworks might be the future of all web apps (especially content sites). We also chat about what "indie open source" means, and exactly how much design goes into the Ember project and community. Yehuda Katz (Twitter) Tom Dale (Twitter) Tom Dale's Klout score is 66 Tilde.io Erik Bryn Yehuda at Hack Summit: "Indie OSS" HTMLBars FastBoot: Ember's Server-Side Rendering solution Tom on Shop Talk Show on Server-Side Rendering Rendr JS Yehuda's RailsConf keynote: "10 Years!" Skylight.io: Make your Rails apps faster with actionable insights Transcript: FILE NAME: The Frontside 16 - Yehuda Katz & Tom Dale Talk About Javascript DURATION: 55:59 minutes CHARLES: Everybody, welcome to Frontside the Podcast, Episode 16. We've got Brandon and Stanley here with me on the podcast and some very special guests who need no introduction, so I'll let them introduce themselves. TOM: Maybe we just start with Yehuda because he's the most famous. Are we starting by number of Twitter followers? STANLEY: Actually, Cloud score. TOM: Yeah, it's Cloud score based. YEHUDA: I think Tom has a higher Cloud score than me. BRANDON: All right, Tom. Go for it. TOM: Hey, what's up? I'm Tom. I had the idea for Ember JS in the shower. [Laughter] YEHUDA: Hey. I'm Yehuda. I work on standard stuff and Ember a lot these days, and now Rust also. TOM: Yehuda just joined the Rust core team. I don't know if you guys saw that. BRANDON: I did see that. Rust is a programming language. YEHUDA: Programming language. STANLEY: Are we going to get to talk about that later? BRANDON: Sure. TOM: We can talk about whatever you want. I'm not going to have any insights on that. YEHUDA: We'll have some insights. TOM: Yeah. I don't know if you guys ever saw the Pokemon Movie, but basically Yehuda is reenacting that with core teams. You've got to catch them all. [Laughter] BRANDON: That's great. STANLEY: That's not just the movie, Tom. That's literally everything around Pokemon. TOM: Oh, okay. STANLEY: That is the tagline. TOM: I will definitely defer. You seem like an expert here, Stanley. STANLEY: You know; I know the most important facts of all time. BRANDON: Stanley is on the Pokemon core team actually. STANLEY: I actually just made a new Pokemon that's like a guitar, a chair, and a microwave put together. BRANDON: What's it called? STANLEY: Rock-On. TOM: That is the worst Pokemon name I have ever heard. [Laughter] TOM: Oh, my gosh. BRANDON: All right, well, off to an auspicious start here. So the two of you and Leah formed the original core team for Ember. Is that fair to say or were there other people involved at that time when you kind of were switching SproutCore 2.0 to Ember? YEHUDA: I don't think I would call the original group that switched SproutCore over to Ember necessarily the core team. I would say that there was a bunch of people that were working on what was called SproutCore 2 at the time at Strobe, and it doesn't -- what we were doing there doesn't really meet my requirements for a good core team or a good Indie Open Source project. But one of the things that we did after switching over to being Ember and announcing the separate project was to make the core team more like what I would want. TOM: Well, I would say that there was never one moment where we were like, hey, let's create a core team. I think one thing that I learned from Yehuda about managing an open source project is that it is extremely important to start delegating way before you feel ready or comfortable. So there was a point early on where we were just totally overwhelmed as people started using it and people came along and were interested. And so we just gave them commit bit without really thinking about the bureaucracy of it or the structure of it. And then it definitely got to a point where it was like, "Why is there no core team yet?" because there's a ton of people with commit. So we should probably think about this a little bit more. YEHUDA: Of the people who are on the core team now, Erik, Chris, and Steph were all involved extremely early. I think Erik Bryn was the second contributor. Well, the first contributor after people working at Strobe, and Chris and Steph got involved really early because they were building an app on Ember that was very, very mobile focused. Well, it's a mobile app, and so they needed heavy performance, and we were not necessarily focusing on that, so they got involved pretty early also. BRANDON: And you gave a really awesome talk about this recently at Hack Summit. We'll throw the link to that in the show notes. I thought it was terrific, and I thought there was a lot of amazing ideas that were clearly born of painful experience. And I want to talk about that in a moment and kind of basically running and maintaining an open source project that keeps the open source ethos, I think, was kind of the thrust of the talk and keeping the Web and Open Source Indie. But before we jump into that, I wanted to get kind of a -- without going into, like, a full state of the union, there's a really lot going on in the world of Ember right now. It can be actually kind of hard for individual developers to just keep up with the news of it. There are just so many cool things happening at once. And there are a few things in particular that I wanted to get an update about. You guys are doing some really interesting stuff right now, but some things that are shipping soon: HTMLBars is actually happening. YEHUDA: It's in the beta. BRANDON: Yeah, it's in the beta, so people -- we tested it in our app already, and with one exception with, I guess, Ember list view isn't quite ready for it yet, but. YEHUDA: I think that's ready now too. BRANDON: Oh, really? TOM: Yeah, that just got updated. BRANDON: So, yeah, it was phenomenal. I mean it just works. Like, it was pretty amazing. So the benefit to users for that has been kind of already gradually been implemented where the metamorph tags in the DOM were gone. TOM: Right. BRANDON: What else can people expect to see once HTMLBars is in place? YEHUDA: So let me just reiterate a thing that you just said that maybe people weren't clear about before I let Tom a little bit about HTMLBars, which is, one of our major goals now and probably forever is to continue to update things incrementally and without breaking apps. And that's something that takes a lot of effort, so I want to reiterate it because it's probably the driving force of everything that we do, so like you said, there's a lot of news. We've been talking about a lot of stuff. We can talk for hours on it, probably. But the key thing is that a lot of times you hear there's a lot of news in a project, and it feels overwhelming. It feels like, oh, my God, if there's that much news, it probably means I'm going to have to spend the next five years catching up with all the things that are happening. And with Ember, our major goal is to make sure that all that, all those new features don't affect your app. I mean there will be a 2.0, and at 2.0 there may be some breaking changes, but even with the 2.0, all the breaking changes will land before 2.0. They'll land on the 1x brands together with deprecation warnings so you'll learn about them as you upgrade. TOM: Yeah. YEHUDA: And so I think this is the driving force of everything we're doing now. TOM: Yeah, I think, with 2.0, it's not like oh, my gosh, there's all this new stuff I have to learn. Instead, what it's going to be is us removing stuff that you probably never even learned about anyway. YEHUDA: Or that we told you in 1.10 or 1.11 to switch away from and you had plenty of releases to remove. TOM: Yeah, you'll have ample warning, and you'll definitely -- it's not going to blindside anyone. But I think this is exactly the point is we're on a six-week release cycle, and it is impossible to do big bang stuff in six weeks. Right? Think about any big software project anyone listening to this has worked on. It's hard to build a huge thing in six weeks, which maybe seems like a limitation, but actually I think we both see that as a huge strength, which is that it really forces you, as an engineer, to think about, okay, I want to move mountains. But I need to do it six weeks at a time, so how do I basically touch back down to reality as often as possible? With HTMLBars, if you think about it, it's a pretty dramatic thing, right? We're basically entirely replacing the rendering engine of this pretty large JavaScript framework, which in some sense is like trying to change the engine on a 747 mid flight. And the only way that we can get away with doing that is to do it very incrementally. And the only way we can do it without breaking people's apps, I should say, is to do it incrementally. Step one was metal-views, which removed metamorphs. But, fundamentally, all view rendering was still string concatenation. And then the next step after that was to get actual HTMLBars in with creating DOM instead of creating strings. YEHUDA: There was actually another step in between, which was to change all the -- so the internal, whenever you use a curlies and handlebars, those curlies, in the old version of the templating engine, would go and they would have ad hoc code to observe something, observe paths, and there was all this complicated code at each point where a curlies was used anywhere in the templating engine, and the new system -- and this is again behind the scenes, so it's easy for even Tom to have forgotten about it. We refactored everything internally so that it used a stream-based system so that all the parts of the templating engine don't have to know exactly how that's all structured internally. And that makes it a lot easier to do performance optimizations, but also makes it a lot easier to avoid mistakes and bugs that cropped up from time-to-time. So that was another step in the direction that was necessary to get all the way to the end. TOM: So now that's in, and I think the next step is to actually -- the next step will be now that we've got HTMLBars integrated in a backwards compatible way, the next step is introducing nice, new syntax. So just one example of this is this gives us the ability to remove the bind-attr helper. Most people that I've noticed when I'm teaching them Ember intuitively think that they should be able to do attrf equals curly, curly URL, and that doesn't work together. You have to do bind-attr. But because HTMLBars is a much smarter parser, we're able to have that context, and we can actually just dramatically simplify the whole model. BRANDON: Okay. And you also answered another question I had, which was, there are a lot of people basically talking about how they should be building apps for 2.0 friendliness, but it sounds like if they stay with the point releases, there'll be very little work involved in moving to 2.0. So you don't have to kind of like today sit and architect your app in a certain way as long as you're staying up to date with the point releases. Would you say that's relatively accurate? TOM: Yeah, I think so. 2.0 is not going to have any new features, and one feature that Teddy Zeenny is working on for the Ember Inspector, you know the Chrome and Firefox plugin for the developer tools, is adding a deprecations pane. So what we expect to happen is that people should just keep upgrading their apps on the 1x point releases and then, every upgrade, you may see one or more deprecation warnings pop up, either in the console or in this pane in the developer tools. And you just fix those at your leisure. Then when 2.0 comes out, all that will happen is that the payload size of Ember will shrink. YEHUDA: Yeah. I think another way to put all that is, when we looked at React, so we looked at React a lot as part of the run-up to 2.0 for the past, like, six months. And when we looked at React, initially we saw a programming model that actually wasn't that different from how we thought people should build Ember apps, so things like you should have data flowing down from a single point and, in Ember, that single point is the model hook in your route, and then we always thought about data flowing down. And you should have events bubbling up, and you should use actions mostly for communication. I remember Erik Bryn very, very early on said, "I think people are overusing data bindings. People should use events more." And that's when we started adding the evented system to a bunch of the parts of the framework. TOM: Actions. Actions weren't there originally … two-way bindings. YEHUDA: Well, we added actions, but we also added, like, Ember.evented. TOM: Yeah. YEHUDA: And I think we kind of knew all this, right? And so idiomatically the way that Ember 2.0 works is actually not that different from how we thought Ember 1.x should work, but I think one of the things that ended up happening is that because data bindings are so -- two-way data bindings can be very nice and clever, a lot of times people would reach for two-way data mining because it was the first thing that was sitting there. And then they would end up building somewhat complicated systems that rely on communication through two-way data mining. TOM: The syntactic sugar pushed you in that direction. YEHUDA: And so a lot of what Ember 2.0 is is about making syntactic sugar more honest about what is the right default, and that does mean that there may be applications that were heavily relying on communication, especially communication channels through two-way data bindings. And that will work much less nicely in Ember 2.0, and it might feel painful to upgrade if you're trying to be both idiomatic and upgrade to 2.0 at the same time. But I think, for most people who are using actions and were using data down through the model hook, I think a lot of it will feel very familiar, will feel very much like how you've been doing things all along. CHARLES: Cool. I actually had a question about HTMLBars landing, and that's when we upgrade our apps, everything should just work seamless. Like Brandon said, we actually did a spike of that, and it mostly seems to be the case. You said that there are no new features, but are there more, like, newer development stories around? Like, given that the templating engine or the view layer understands the DOM, what power or APIs will users have to interact with it, like to do animations or bring things in and out and stuff like that? YEHUDA: Oh, yeah. CHARLES: Is there any of that stuff planned? YEHUDA: I don't think we meant to suggest that there are no new features in number 2.0. Just that they will land in the 1x series, I think, is the point. CHARLES: Ah, right, right. I see. TOM: I think probably the biggest feature is just speed. And I think, also, what HTMLBars' architecture unlocks is the ability to better integrate with other libraries by adopting kind of a diffing approach similar to what React does with the virtual DOM. Basically, in my mind, HTMLBars is all about a bunch of infrastructure work that allows us to make the programming model feel more natural for people who are…. YEHUDA: One way to think about it is that it's the first templating engine that was ever built specifically for Ember. Handlebars templating engine before was built as a general-purpose templating engine, and we pushed it as far as it could go to be real useful for Ember. But things like bind-attr and the metamorph tags kind of crept in as necessary because the templating engine wasn't really built for this purpose, the exact purpose that Ember was designed for. And the HTMLBars engine, part of it is that it's DOM based, and part of it is that it supports diffing, and part of it is that it's faster. But I think, ultimately, it allowed us to look at a lot of areas that are annoying about using templates in Ember and make them nicer. And, yeah, so I think that it's -- TOM: I'd say it also unlocks things like we're working on server side rendering right now, and a lot of that is due to the power of HTMLBars because we can run it in so many different environments, and we can model all of these things as streams internally. It gives us a lot of flexibility about what we can do with your applications. You know, we can do things like server side render your applications even though, of course, you never designed your app for that case in mind. But because of how expressive the templating and, in fact, the entire application architecture is, and because we all agree as a community that this is how we architect our apps, it unlocks a lot more stuff. And I think there'll be more things like server side rendering in the future that we all benefit from by sharing this very declarative application structure and very declarative templating language. YEHUDA: Yeah, I mean honestly, under the hood, the fact a lot of the innovations of the templating engine are not things that any user will ever see directly because they're just implementation. And if we wanted to go around pimping things like streams or the way that the diffing algorithm works internally and the way we clone fragments and all this stuff, we could probably spend a lot of time pimping it, and maybe that would even make a lot of people, some people happy. But I think you'll see, over the next year or so, these things will all lead towards better features or to more features that will be nice, and that's how I think we'd like to roll -- TOM: I think Web components integration is a big one. YEHUDA: Ah, yeah, that's a good point. TOM: I think HTMLBars makes it very easy. And so, in terms of actual improvements coming on top of HTMLBars, the component syntax, instead of being curly, curly to indicate that you want a component, you'll be able to use just regular angle brackets, so that'll be nice. And another thing that we're really keen to get rid of is: You know how today when you're building an Ember component if you want to customize the element associated with that component, you have to say, like, tag name, class name, bindings. You guys know what I'm talking about? BRANDON: Mm-hmm. TOM: So that's kind of annoying because all of those special properties on the component class that you used to customize the element are all duplicating features that already exist in the templating language. So it's just kind of this weird bifurcation of the programming model where, if you want to customize the element for this top level, do it in JavaScript. Everything else, do it in the template. So HTMLBars will allow us to allow you to customize your component element purely in the template, and you won't have to -- basically there are far more cases now where you'll be able to get away with a component that's just a template file, and you'll reduce the number of JavaScript classes in your app. YEHUDA: Yeah, I think, from a high level, the biggest -- the high level of the internal technical improvements are largely that it allows for contextual work. So the old templating engine wouldn't necessarily know that you're inside of an attrf when you have curlies, so we would have to spit out a bunch of extra stuff and maybe make you use extra helpers. It wouldn't necessarily know that you're in image FRC or a video tag or a component. It wouldn't be able to tell if you were using a polymer component that implements the bind protocol, right? But the new templating engine basically lets us see exactly what's happening at every curly, and that just has a large number of positive effects. BRANDON: So you said something else that I felt like was a good segue into the next part of the discussion that this basically allows you to do server side rendering, which you guys are really, like, in the thick of it right now. But for me, a lot of the talk I've seen a about server side rendering comes across as a little inside baseball. There's this sort of discussion between people who are really into React because they're suddenly doing a lot of stuff with server side rendering, and they're seeing some benefits out of it. And you see this stuff kind of pop up in the JavaScript community, but I'm curious to know if you guys can explain a little bit about the benefit of server side rendering that this is a major new feature coming to Ember now. YEHUDA: I'll let Tom maybe give the full pitch, but I think one thing that I feel somewhat strongly about is that, for most people, if you don't have a system that actually gives you something that works pretty well out of the box, in other words it doesn't ask you to do a lot of the work yourself, the idea of isomorphic server side rendering where you run your same app on the client and the server, I don't think that that ends up being worth it. And if you look at a lot of apps that use Ember today, a lot of them have spent relatively little time building non-isomorphic solutions for specifically SEO that have been very, very cheap in terms of time and very, very effective. But I think there's the: I want to not have to write that, even that little bit, and I think that that you get a lot of benefits out of if you just have your framework do it. In other words, if it's not just like your framework does 20% and you do 80%. If it's your framework does 95% and you do maybe a little bit, or you have some constraints, I think that is worth something. And I think the rehydration of fast boot is worth something, although that has even more issues and even a larger percentage that most people have to do on their own. Basically, I think the TLDR for me is that I've always saw server side rendering as indeed somewhat inside baseball because, for most people historically, and I think this is even true largely about React, the solution that you're offered is the framework will do a little bit for you, and you have to go figure out a lot of the details about how to make this work for real. And I think most people just don't have the time to figure all those details out. TOM: So it's been kind of interesting to watch this play out over the last year or two because I think there's been a big split between the JavaScript application community and old school people that create content for the Web who are really keen on this idea of progressive enhancement. And so there's kind been this split. And, for me, for a long time, I personally didn't really care about this case because, in my mind, JavaScript apps were really good for what I'll call workspace apps, which is most of them are behind a login. You log in. You have these very rich interactions. You're editing something. You know, I worked on the iCloud apps. It's a feature, not a bug, that Google can't index your calendar and your email, right? So to me that was the use case for JavaScript apps. But that was until I saw content sites. Like, I remember the first time thinking, "Wow, maybe JavaScript apps are actually the future of all Web applications," was when I saw Bustle, actually. When I saw Bustle, it was just a content site. It was just news articles. And if you would've asked me, I would have said you should probably use Rails or some other server rendered framework for this. But then I saw it, and it felt just like a website. I couldn't actually tell the difference other than how damn fast it was. And I kind of had to step back and question all of my opinions about how people should be building these kinds of applications. And especially for content sites, I think that the server rendering is really important, right, because historically your user has had to download all of this JavaScript and all that JavaScript had to be downloaded and evaluated and run before they saw anything. So having the ability to bootstrap that process on the server and have the first bits that the user starts downloading not be the JavaScript payload, but be HTML and CSS, so that the first thing that they see is useful, I think that's really going to change how people build applications because you get the benefits of server rendering while still retaining the kind of interactions that you can build with something like Ember that you just can't do with Rails. YEHUDA: But again, I think people trying to do this on their own and taking maybe a half solution and then trying to figure out how to make this work reliably ends up producing things that are pretty buggy and feel pretty bad on first boot, or they end up requiring tremendous amounts of engineering resources. And it's possible that, like, huge companies can make this work. But I mostly think about startups, and startups simply do not have the engineering resources to take on the server side rendering task on their own, so this is why I think we care about it for Ember because, as Tom said before, Ember is already pushing you down a pretty conventional path, and we think -- our hope is that by having people do that conventional path and us taking charge of server side rendering will have something that works mostly out of the box for a lot of users. Again, assuming they follow some additional constraints about what you're allowed to do on the server. TOM: And I think we should be clear here because there's, as always happens, there's ambiguity in the terminology. So first is the term isomorphic app, which I don't really love that term, but I guess we better get used to it, Yehuda. YEHUDA: Yeah. TOM: But there's really a spectrum. On the one side of the spectrum you have something like Airbnb has a library for Backbone called Rendr (with no e - well, one e, but not the second e). And that kind of lets you wire up some of the server side rendering. But again, it's very, very manual. And the whole purpose of this is just to make sure that the first thing that you deliver to the browser is HTML and not JavaScript so that the user, even if they don't have JavaScript enabled or they're on a slow connection or whatever, they get something useful. But then on the other side, you have things like Meteor or Asana where the whole idea is -- and to me, I'll be honest with you. It strikes me as extremely silly, but the idea is that you're writing both your server and your client in the same code base, and then you're deploying them both. You describe it, and it sounds like this magic bullet, but it also just seems really silly to me. YEHUDA: Well, I think the fact that even the first releases of Meteor had if Meteor.isClient and if Meteor.isServer, and even the first demos had large blocks of content…. TOM: Yeah. Conditionals. Yeah. YEHUDA: Basically means that people hadn't really figured it out exactly right yet. TOM: Yeah, the point is that even if you have a client side app, your server still has a lot of responsibilities, especially around data access to the database, authorization, authentication, and so on. And putting that in the code base with your UI and your drag and drop code just does not make any sense to me. So I want to be clear to everyone listening that that is not what we're going for. The idea is not that you're writing your json API server in Ember. The point is that you're writing the same old app. In fact, we hope that you don't have to make any changes to your app. And you can deploy it, and it will do a render using the same code. It's basically like your app running in a browser on the server, and then we'll have some way of -- YEHUDA: Except not actually a browser. TOM: -- it's actually a transferring state. YEHUDA: Except, importantly, it's much, much cheaper than being an actual browser. We're not using phantom JS or a zombie or anything. TOM: Right. Conceptually a browser, but we don't want to pay the cost. Phantom JS is a source of great pain for many people, ourselves included, so we want a pure JavaScript environment. But conceptually it's a browser. YEHUDA: I think the reason I hopped in there is I just want to be clear that the goal of conceptually a browser is actually not to be a browser, but to make Ember itself internally abstract enough so that the most expensive parts of being a browser can be replicated in a cheaper way on the server. Obviously the most important part of that is the DOM. And that's the part that React worked out for server side rendering is use the virtual DOM on the server and not a real DOM, right? And that means you don't need real phantom JS and the full scope of DOM. But there's also other stuff like how your routing works and how the model hook runs and how it makes requests, how it makes "XHRs" to get the data in the first place. Right? There are a lot of details if you think about what it takes to boot up an app in the first place. For us, the goal is to go through that whole process of booting up an app all the way through, but not including the did insert element hooks in your DOM and make sure that all that stuff doesn't require -- it has really constrained and clear abstractions, right? So rendering has a render abstraction and routing has a location abstraction, and the DOM has the HTML bars, little dom, lower case dom abstraction, right? So instead of saying we're running it inside of something that pretends to be a browser, we're saying Ember doesn't actually care whether it's in a browser or not, but it has very, very clear abstractions for what it means to be a browser. BRANDON: Okay, so is there--? It sounds like it could be a little like -- is this a little ways off? It sounds like there are a lot of benefits. Like, if you see the hand rolled stuff that Discourse has done, clearly this is something that Bustle cares enough about to sponsor, this is probably a little ways off for Ember developers. Is there anything that you want people doing Ember to know right now about server side rendering in terms of how it's going to affect them or some of the technical stuff that you're learning through this or anything like that? TOM: I think we've been thinking about this particular problem for a very long time. And in fact, we've intentionally designed the architecture of Ember specifically to handle this case, even from the beginning, even like three years ago. We knew that this is something that we wanted or at least we didn't want to paint ourselves into a corner around. So I think there are two aspects of this, and one of them, I think, is pretty well bounded and pretty straightforward. The other one is definitely going to require a little bit more research. The first step is simply getting rendering happening on the server. So because we designed Ember for this case, we were actually able to get Ember as a framework booting up in node in about a day's worth of work. So a couple things have crept in. There were areas where we had been a little bit sloppy and introduced dependencies on things like document.body, jQuery, things like that. So it was about a day to kind of encapsulate those, make sure that they weren't hard requirements for booting the framework, and that was about a day's worth of work. And then, by the end of the week -- we've only been working on this for about a week now -- at the end of the week, we actually had an app booting in node and handling route requests. So in terms of progress, it's been really great. But I guess all that we're saying is that, in a week, we were able to capitalize on the last three years of work we've been doing. That's not as impressive as it sounds. YEHUDA: It was nice that there were relatively few regressions, right? TOM: Yeah. YEHUDA: That the list of things where people were accidentally doing things that assumed the browser was actually relatively small. TOM: Yeah. And the way that we did that is basically introducing an abstraction that provides your environment to you, so a node that's different than in a browser. So that's the first part is to get the app booting, and the second part is to get it rendering. I think what's really cool is that, even though HTMLBars, of course, is a DOM based rendering engine, or despite that, we still use an abstraction around DOM access. What we're going to be able to do when we start, again, in earnest tomorrow, on Monday, is basically replace that DOM helper that we used to create DOM in the browser with something that we'll be able to build up strings so that you can build up your HTML on the server and serve that to the client. That's step one: rendering. I think we'll be able to make quite quick progress on that. I would guess probably about -- I don't know if I should give timelines here. I think we're ballparking around a month before we can at least beta it, the server rendering. BRANDON: That's a little faster timeline than I had assumed. TOM: That's purely rendering. I want to make clear that that is purely for things like SEO, for Web crawlers, for curl, things like that. Then the next phase after that, and this is where it gets into the tricky bit, is being able to -- YEHUDA: Rehydration. TOM: -- is rehydration, what people call it. What we call fast boot. And with fast boot the idea is that whatever state that we use to build up your application on the server, we also transfer that state, not just the HTML, not just the output, but the state that we use to build that output is somehow seamlessly transferred from the server to the client. And the client basically just takes the HTML that we've given it and reconnects all these bindings and goes from there, so it's totally seamless to the user. YEHUDA: And I think there's some complexity there. For example, there may be some part of your page that you can't actually render on the server because it says, like, "Hello, authenticated user," with the user's name. So thinking about ways to make sure that you can mark those as needing to be rendered on the client without causing jank. There's a bunch of stuff like that where, at first glance, it seems not too bad, but I guess the high level if there's a determinism issue, right? So the goal is to make sure that roughly what you did on the server is the same thing that you do on the client because if it's too far off, then you end up having to throw -- no matter how smart our algorithm is, we're going to end up having to throw away everything and replace it again. The idea is how to structure your app, how to structure the way that you set up your app in Ember CLI so that you tend to be putting out output that's deterministic on both sides. And, like Tom said, I think state is maybe overbroad. It's mostly modeled batter, right? Making sure that the model batter that you got on the server is equivalent and transferred together with the HTML payload so that the model hooks that you have in your client will not have to go make another XHR. They'll just have the data that the server already collected, and then hopefully rerender an equivalent DOM on the clients with relatively low…. TOM: There are just a lot of tricky cases, like imagine you have a bound helper that shows relative dates, like 30 seconds ago. So you have a clock on the server, and then you have a clock on the client. How do you reconcile those two? YEHUDA: Yeah, so the good news there -- the good news with all that, without getting too much into the weeds, is that the HTMLBars' engine is already broken up between rendering the parts of your DOM that are static, that are like the hello, the text hello inside of an H1, and updating the static parts with dynamic content. And today that's purely a performance optimization, and so that we could use the same document fragment over and over again after cloning, but that will also allow us to use server rendered content where, instead of expecting to have an empty text node that is to be filling in with dynamic content, we'll have a filled in text node. And we see, in that case, Tom, that the time that is in there already is not the correct time. It's not the equivalent time, and so we'll update it. So that's sort of like the React diffing strategy. I'm less worried about, like, there's a single text node with the wrong content because I know we can deal with that. And I'm a lot -- although if it's too much changes, it will look very bad. It will look very janky. I'm more worried about, like, this entire conditional change. So you're looking at something and then, like, your sidebar swaps out for a different sidebar, which I think would be a pretty unacceptable UI. CHARLES: Obviously there are a lot of different server side environments that people use. What requirements of the server is there going to be if I'm using a Rails app or something in Python or Java or whatnot? How am I going to interface to this? TOM: Well, you definitely need a JavaScript runtime, right, because your Ember app is written in JavaScript. Unless you're planning on pouring it into Ruby or whatever, we're definitely going to require JavaScript runtime. And I think we're starting with just supporting node. But what I would like to see, and maybe you guys can write this, is a Rails gem that you can install that will install dependencies in everything and basically get set up in a production environment. YEHUDA: I think one thing people often forget is you can definitely -- you could you have a node app running. People try to embed JavaScript. They try to use, like, The Ruby Racer, and embedding JavaScript is quite a disaster. BRANDON: [Laughter] I'm sorry. I don't know if you know. Charles wrote The Ruby Racer, and it is a disaster. STANLEY: It's cool. It's a disaster. YEHUDA: So let me be clear. It's a great idea. I use it a lot, but it just fundamentally doesn't now work. Right? It fundamentally cannot -- you cannot embed two VGCs in the same process. BRANDON: Right. YEHUDA: Okay. BRANDON: This is the greatest moment in the history of our podcast. I just want to say that. CHARLES: No, I know. There's no way to collect…. YEHUDA: Yes, exactly. CHARLES: -- for example. YEHUDA: I was about to use cycles as an example. CHARLES: The APIs just don't exist. YEHUDA: Yeah, so basically cycles, so this is why. The reason why I feel strongly about this is that we use Rust for Skylight, which is our product. And we need to embed something, and I would never in a million years embed something with a garbage collector. And I think The Ruby Racer was a pretty good -- I think, for constrained cases, it works fine if you know what you're doing, but people basically tried to use it as, "Oh, I'm just going to write part of my program in JavaScript. And, by the way, both languages have closures, so good luck," basically. The Ruby Racer is cool, but I would not -- I don't think that that's the correct strategy for having long-running JavaScript programs like Ember, like complicated stuff like Ember. I think a better thing for people to do would be to figure out a simple IPC protocol so that they could run their Ember app and then have a simple way of talking over a socket or something with the node app, so booting up your Rails app will also boot up the node app. And, if necessary, and you're serving through your Rails app, you could communicate. TOM: I think, to be clear, the Ember app, even when running on the server, still talks to the database server using json, right? So it's the exact same data marshalling flow. It's just presumably it'll be a lot faster because probably your API server and your application server are in the same data…. YEHUDA: Well, at a minimum, it'll be a lot more consistent, right? TOM: Yes. YEHUDA: I think when people -- when Twitter complained about somebody from some country connecting and getting a really slow connection, the issue there was that they were downloading the app shell and then who knows how long it took to download the json payload, right? But if the json payload is coming from the same data center, then it's, by definition, going to be downed within some range, reasonable range. BRANDON: Okay. Awesome. I'd like to shift gears and spend a couple minutes talking about something that most of the questions that I had originally for this were actually answered in your talk. But I'd like to go over it just a little bit. You alluded earlier to the way that you're running Ember as an ideal, sort of your ideals, discovering your ideals about open source projects and the Indie Web. And I think it's a really important topic, and I want to ask a little bit about that because I don't think a lot of people understand this. I think, especially I see in the JavaScript community, a lot more people establishing open source projects that are corporate run and that being considered a benefit rather than a drawback. And I've seen you push back on that a little bit, and I wanted to ask you, Yehuda, about what your definition of the Indie Web is and why you specifically run the Ember project the way that you guy run it. YEHUDA: Sure. I think there are basically two parts of what it means to be Indie, and the second one sort of derives out of the first one, but I think it's -- you wouldn't necessarily arrive at it yourself, so I'll make it explicit. The first one is that you have a diversified core team. What I mean by that is essentially diverse in all the ways you could possibly think of, and things that I learned from other projects are, like, functionally diverse. So make sure that if there's a person on your team -- if there's a person around somewhere running your events or doing documentation or doing evangelism or running user groups, make sure that if there's a person who is very skilled at doing that that they are the top person on your team in charge of that. The counter, the alternative that I've seen a lot in the open source community is that the person running events essentially reports to the core team, right? There's a person who is maybe a professional event runner, and they are not in charge of events. They're in charge of coming up with ideas for events that they run by the core team, and the core team decides yes or no. The problem is the core team has no skills in doing that, so this person ends up spending huge amounts of time being frustrated trying to explain to the core team something or other, right? That would be the equivalent of somebody on the core team writing some area of code, having to come to the rest to the core team and talking about really tiny, nitty-gritty implementation details. Of course, unlike code where I think people have an intuitive sense that you're deep in the weeds of some performance thing, and I don't really understand that. In a lot of areas that are not code, code people have a very high sense of their own understanding, right? The core teams, I've seen a lot of core teams that people come and they say, well, I happen to know a lot about how people want to read docs in this country and so I'm going to help with the translation effort. All of a sudden the core team is an expert on, like, Indian documentation. And they have all these opinions that are totally unwarranted. Step one is have a functionally diverse group of people, and have people that are not necessarily hardcore coders, but are talented and professionals in their area. Have them do that work at the top level. And I spent a little time on this just now because I feel strongly that this is an area that people miss, and it's just an area that code people are too high on their own supply. They're too impressed with their own skills. They cause a lot of pain for the people who are good at areas that are not hard-core code, so that's one. Two is be diverse in terms of the set of people that own decision-making in your project, so this is what you were talking about with the company run open source, and this is something companies can do. I've seen, for example, I worked with the Rust Project, and the Rust Project originally started at Mozilla. But they've been spending tremendous amounts of effort to try to increase the set of people who are on the core team of Rust that are not working at Mozilla. And this is something that maybe takes a lot of effort once you have an established project at a company. There's all the internal company politics you have to deal with. But the reality is that if you have a project that's at one company, you're kind of at the whims and the mercies of that one company's how they do resourcing, whether they think it's important, what their actual goals are. Maybe the thing that they built the project for doesn't necessarily match what the community is doing, right? So become diverse in the companies that own it. I think projects like Rails, Postgres, Ember, increasingly Rust are good examples of this. And, of course, I mean the regular meaning of the word diverse here, just because if you become more diverse in all areas, you actually find yourself being more function diverse just because of who ends up being in what areas. You end up finding yourself having a lot better insight. You end up sitting in a room, and when there are people of diverse backgrounds, the kinds of questions that people ask. And I can only say this. This is the thing that I've noticed personally. It's not a thing that I can empirically measure. I've just noticed that the kinds of questions that people ask, when you're diverse in all kinds of ways, ends up being -- they end up being stronger, better, and they end up pushing back on the kinds of decisions that you can make as a monoculture with group think, right? The harder it is to have group think, the harder it is for everyone to sit around and say, "You know what we're going to do? We're going to rewrite everything," right? That kind of thing is hard to do when you have a lot of people with a lot of different backgrounds with a lot of different interests. So that's, I think, the higher order bit of what in the open source means is be very diversified in a lot of different ways. But there's a specific thing that I think comes out of it that is very important, which is to do the work that you're doing incrementally. Again, the reason I think that this is a derive is that if you have a lot of people with a lot of different interests with a lot of different projects, I think it becomes very difficult for you to do full on rewrites because everybody has interests, and maybe a few people are excited about doing a rewrite, but everyone else says, "Oh, my God. What about my app?" Then you have the docs guy saying, "Oh, my God. Now we have to maintain two sets of docs?" And you have the evangelism guy hearing all the pushback from the community about the rewrite. So it becomes very difficult for you to have this situation where you're not doing things incrementally. But I think, in my talk, I spend some time on what it means to do things incrementally and what the benefits are and how to adopt the six-week release cycle and all that. I talked about that in more detail because, even though I think it's a natural consequence of being diversified, it's also something that you have to think about if you want to do it well. BRANDON: Yeah. It seems to me that that would require, like it's kind of a chicken and egg deal, but to me it seems like there was a lot of discipline in switching to a six-week release cycle, and that's important. It seems, for us at least as consumers of Ember as an open source framework, that's benefited us greatly. We find the framework much, much easier to keep up with on the six-week release cycles than pretty much most other open source projects we've worked with. YEHUDA: Which is kind of like a paradox, right, because you expect that six-week release cycle means you can never keep up with it because it's always changing. But in fact, six-week release cycle means you don't have time to ever change that much. BRANDON: Well, and even for apps that go dormant for a while, we find that, okay; we'll bring it up to one. Bring it up to the next one. The upgrade path becomes extremely obvious. YEHUDA: Yep, exactly, and there's deprecation warnings, and there's ... I think people should watch my talk on this specific area because it took me 15 minutes or something to lay out the whole thing. But I think the basic idea of just doing things incremental, and incrementally has this bad sense. It's like, oh, maybe you're hunting for the local maximum or something. All I mean by incrementally is the same way that the human body replaces its cells, right? You don't do it all at once. Maybe over an extended period of time, the thing that you're looking at is completely different. But because you did it a little at a time, you were able to move the whole community together in the direction instead of people, many, many people getting left behind, which is what used to happen a lot with Rails. I think Rails has gotten better at this over time. But it used to happen, like Rails 3 came out and a lot of people were stuck on Rails 2.3. BRANDON: I think when people hear incrementally, they can think about possibly incrementally be led in circles, right? You could incrementally be every day wake up and decide to change one degree or the other. What matters is if you have a compass that's pointing somewhere. For the Ember project, that incremental stuff doesn't work unless it's pointed somewhere very clear. And you and Tom are basically the keepers of that vision. And I wanted to ask about that, what the vision of the framework is that keeps guiding everybody. Is it sort of implicit to the project? As you use it, you recognize it. Or is it something that you've explicitly outlined somewhere? YEHUDA: I'll take this for a second and then Tom can jump in. I think, fundamentally, the main vision is just we ultimately wanted to have a full stack solution that solved the majority, the vast majority of the problems that a regular person would have writing a Web app, but we knew from the beginning that if we tried to take on that whole project, I mean even Meteor, who took on that whole project, is still struggling to have to complete the vision. And they tried to sort of boil the ocean. And so, we knew from the beginning that we were going to get it wrong if we tried to do a CLI tool and a framework and a data library and all this stuff all at once. And so I think we started off with the V in MVC, basically, right at the beginning and added routing and other stuff over time. But the mission always has been to build the thing that's a full stack of what you need to build front-end tools. Tom, you can take it from there. TOM: Yeah. I think, in the JavaScript world, I think, because JavaScript for so long was treated as a toy language that people didn't do serious stuff in, it attracted a certain type of developer who is -- which is a totally legitimate opinion, but they tended to be kind of hackers who would do these one-off experiments. And because of that, the notion of convention over configuration and having shared solutions is still a somewhat surprisingly controversial opinion in the JavaScript community. And so I think the role, as you said, for Yehuda and I, is to basically be willing to stand up and take the tomatoes that get thrown at us and say, "You know what? No, there is benefit in having a shared solution, especially when it's not just one-off hackers in their basement, but when it's a team of engineers working at a company, and you have a product that you need to ship, and it needs to have good interaction. It needs to be done yesterday. Those people need tools too. People like that deserve tools." And I think that's our goal is to have a framework that will last for at least the next ten years that is willing to incorporate good ideas as they come out and as they're embedded, move the community together, as Yehuda was saying, but without chasing the hype dragon where every six months: "Throw away everything you know because the next big thing is coming out. Rewrite your apps." I see Ember as a way of kind of tempering that instinct for engineers to chase the new and shiny constantly in a way that basically we have a community that agrees together what the next big thing is, and then we start moving towards that. I think, right now, major things that we're thinking about are one server rendering, as we talked about. Getting the CLI tools in place, that's a thing that we've wanted for a long time. But as Yehuda said, we didn't want to try boiling the ocean. And then the new HTMLBars view layer, which unlocks a lot of the cool things that React is able to do around, like, DOM diffing and so on. YEHUDA: Yeah. I usually tell people -- recently, I've come to a line, which is, if you want to tell me that there's not a place for shared solutions in some area or some abstraction, I think the burden is on you, actually. I think people in the JavaScript community, and there's a small group in the Rails community that feels the same way, they assume that the burden is on the person who is trying to abstract, right? If there's a common problem that a lot of people have, they think it's your job to prove that abstraction is a good idea. I think it is your job to prove that a particular abstraction is a good idea. But I think my de facto, my default position is that if a lot of people are solving the same problem that there's a shared solution worth hunting for. And I would say the JavaScript community is really -- big chunks of the JavaScript community are pretty anti this approach. But I think it's really the only way that you could build -- like Tom said, the only way you could build projects with large teams is to have some sense of what the shared answer is and to not have it be some genius on the fourth floor somewhere that does everything. And if you want to make any changes, you have to go to them. I've seen a lot of companies that work like this, and it works fine. Anther facet of this is that pretty much every company deciding to adopt, like, Ember, Angular, React, or Backbone, whatever, they do like this "taste test," right? A taste test is like a two-week project where they see which one is faster. By definition, the taste test doesn't successfully analyze what happens over a longer period or when you have a bigger set of developers, right? It's by definition optimized for short projects with a small number of developers, and so -- TOM: And usually it's the guy on the fourth floor conducting the taste test. YEHUDA: He's either conducting it or he is actively attacking it, right? He is saying we should not -- for example, Firefox OS refused to adopt any framework for an extended period despite the complaints of many people on the Firefox OS team because of the fact that they had a religion against frameworks. They didn't like frameworks as a concept. I've heard this from large numbers of people working on the periphery of Firefox OS and many complaints, right? And so I think we, Ember, one of the things we had to learn was that we can't get away with just saying that. We can't get away with saying, oh, you'll learn. If you just use Ember for a year, you'll figure it out. We had to really improve the getting started experience. But I think, on the flipside of that, there's no way that we could ever -- even if we get to be as nice as to optimal getting started framework, getting started tool, we're always going to have benefits that are not part of that that are very difficult to see when you're doing a quick analysis. Actually, recently we've seen a lot more big companies come out and talk about the benefits of Ember for long-lived projects, and I think that helps a lot just having people testify that they used Ember for a year within a team that wasn't three people, and they found it to be productive in these specific ways. I think that's helped a lot of people feel comfortable. BRANDON: That's been my experience, certainly, as well, just seeing that increase. I think everybody should -- honestly, I believe everybody listening to this should drop what they're doing and go watch the Hack Summit talk. I thought it was phenomenal, and I think it made me think a little differently because it's a little confusing out there, like what some of the tradeoffs are in these open source projects that are run in that kind of echo chamber. And the fact that you guys work so hard to pierce the echo chamber is really cool. I know that there may be some technical questions. We don't get a chance to have you guys on the podcast very often, obviously, so I wonder if anybody has any more questions. STANLEY: Before we get back to technical questions, I just want to cut in and say I really like Yehuda's talk from Rails Conf as well. It was really eye opening for me as somebody new to the Rails community, even though Rails has been around for a while, and kind of understanding the value of shared solutions and kind of the philosophy behind that. YEHUDA: Yeah, that was definitely the first time I tried to formulate a general theory for what shared solutions look like and why they're good, and essentially why Rails hit the nail on the head with the right amount of shared solutions and where the experimentation is happening and all that stuff. STANLEY: Cool. Back to you, Charles. CHARLES: I just had a quick question I wanted, before we wrap up. I had another question about the server side rendering, kind of a general one. I know I've definitely been burned by server side rendering in the past, you know, because it's been something that people talk about on and off, it seems like, for the last five, six years. I remember when mustache first came out. The first time that I tried it, it's like, oh, I've got this templating thing that I can run inside on my Rail server, and I can run it. There's a JavaScript implementation too. One of the things that I found was I was able to get up running very quickly, but then I felt like I was eaten alive by the edge cases. It was actually -- I think it was a blog post that you wrote, Tom, where you were talking about kind of the justification for resolving, always resolving RSVP promises asynchronously. Because, to not do so, have a different context, different stack sitting on top of the resolution was like releasing Zalgo into your application. I actually, when I read that thing about promises, it actually made me harken back to my experience with server side rendering. I was like, oh, with server side rendering I was releasing Zalgo onto my client. I had a very different context. TOM: Yeah, the thing you're describing is sharing templates across two different apps, right? CHARLES: Right. TOM: The data model diverges, and then the things that you need diverge. That specifically is something that we are going to avoid. The idea isn't, oh, you can reuse your model on the server, and you reuse your templates on the server. The point is it's your app, the same exact app, same code base that you would run in the user's browser just happens to be running on the server. YEHUDA: And I think there's also -- I think there's another important point, which is that if you look at how people do SSR, I think historically people have said, "Well, I'm going to use a view layer that's very good at SSR." And then you would have this pile of hacks that was involved in booting up your app. Honestly, Ember, in the beginning, had piles of hacks used to booting up your app. I definitely remember that period. Now the view layer maybe is very good at running on the client server and, like you said, originally was just like the template. But now maybe the whole view layer is good at it. But now the process of actually booting things is a source of non-determinism. You're saying Zalgo. I'm saying non-determinism. Zalgo is a better word. CHARLES: [Laughter] YEHUDA: And Ember has definitely held off on tackling server side rendering seriously until we felt confident that we had the full stack handled. In other words that, as a framework, we had the whole lifecycle handled. Then actually, if you look at technically what we've been doing recently, a lot of it is like separating out. We have an application right now, an application only -- there's only ever one instance of it. Now we're saying, well, there could be multiple sessions. And so we're really looking at the whole lifecycle of the application and, because we own the whole lifecycle of the application, we can actually feel confident that the path that we're going through is correct, so that's one part of it. The other part of it is essentially what React figured out at a high level. I think what we're doing is equivalent, which is you don't necessarily assume that you got exactly the same thing on the client server because probably in practice there's always going to be some thing or other, like the clock case that Tom talked about, or the hello Yehuda case that I talked about before, the authentication case. What you do is you rerender the template, and you don't say if it's not exactly the same, throw it away and start over. You say parts that are the same you can keep, and parts that are different you replace. Therefore, it's not so much a whack-a-mole problem. It's more like how much replacement can I tolerate and have it not feel janky, right? So you go use it, and if you see that there's an area that's popping in and replacing, that's an area that you have to go and figure out so, first of all, it will work. Right? It will work. It will not be broken. It might feel a little bad, and that's an area for you to go and improve the Zalgoishness of your solution. In practice, in Ember, it will almost always be something weird like you're relying on a non-deterministic DOM API or something like this, or you're relying on some XHR that even though we serialized it, you're getting a push notification, and it's different, and it happens quickly, so it's janked. Right? I think the basic point of try to control everything and also only replace things that are needed will get you to a much better starting place out of the gate with Ember than you will have if you try to do the old solutions. It may turn out to be a lot of work. And if it turns out to be a lot of work regardless, then I think it will still, even with Ember, be a thing that is used by people who really need it and not so much by people who don't. But I'm hopeful that the fact that we own the whole lifecycle of your application will let it be useful for a bigger set of people than people who are desperately in need of it as a solution. BRANDON: Awesome, so I think we're going to wrap up. Is there anything you guys want to give a shout-out to or anyone? YEHUDA: Please sign up for Skylight to make your Rails apps faster. TOM: Yeah, please. Make my Christmas a merry one. YEHUDA: We didn't talk about this at all. TOM: And sign up for Skylight. YEHUDA: We didn't talk about this at all, but Tom and I, much of our day job is working on Skylight. And if you watched my talk at Hack Summit, one of the things that I advocate and I really feel it in my gut because of Skylight is I advocate spending, even if you're full time in open source, spending some time, even a day a week or two days a week, would help a lot working on something that you have to maintain over the long haul because, like I said before, maintenance over the long haul is very difficult for you to market. It's something that you have to feel in your heart. If you're working on an open source project, work on -- use it for a real thing that you spend significant time on that you have to maintain over the long haul so you could feel, in a year, whether you're practice is holding up to being maintainable. And, yes, now that I've talked about Skylight for a second, please sign up. This is how we fund our ability to do any open source. Working on Skylight has definitely been the most enjoyable thing I've done in my career so far in the sense that I've had a lot of control over it, but it's also the most harrowing in the sense that we are responsible for getting all the revenue, so please sign up. BRANDON: All right, well, thanks very much, you all, for coming on. Everybody, go sign up for Skylight. It's very cool, very beautiful, and very actionable insight for Rails apps. Tom, Yehuda, thank you so much for joining us on this. It's been super enlightening. Again, everybody, please go watch Yehuda's talk on keeping the Web Indie. And if you've got a little extra time, the Rails Conf talk on layers of abstraction is also, I found, something that changed my views on a lot of stuff as well. Thanks again, both of you all, for coming on. YEHUDA: Thanks a lot. TOM: Thank you, guys. BRANDON: All right, talk to you later. CHARLES: Thank you, guys.