POPULARITY
Evan Bacon joins to the pod to talk about the latest advancements in React Native and the Expo Router. He discusses React Server Components, state management, and the new features coming in Expo SDK 52. Links https://evanbacon.dev https://github.com/EvanBacon https://x.com/Baconbrix We want to hear from you! How did you find us? Did you see us on Twitter? In a newsletter? Or maybe we were recommended by a friend? Let us know by sending an email to our producer, Emily, at emily.kochanekketner@logrocket.com (mailto:emily.kochanekketner@logrocket.com), or tweet at us at PodRocketPod (https://twitter.com/PodRocketpod). Follow us. Get free stickers. Follow us on Apple Podcasts, fill out this form (https://podrocket.logrocket.com/get-podrocket-stickers), and we'll send you free PodRocket stickers! What does LogRocket do? LogRocket provides AI-first session replay and analytics that surfaces the UX and technical issues impacting user experiences. Start understand where your users are struggling by trying it for free at [LogRocket.com]. Try LogRocket for free today.(https://logrocket.com/signup/?pdr) Special Guest: Evan Bacon.
In this supper club episode of Syntax, Wes and Scott talk with Steve Sewell about Builder.io, Qwik, Partytown, and the tricks and tips he's learned in building apps for the modern web. Show Notes 00:37 Welcome 01:14 Guest introduction Steve on Twitter Steve on GitHub Builder.io Builder.io/demo 04:07 Builder works with any tech stack? 06:29 Where is the structure of the site coming from? 07:28 What is Builder.io? 11:34 What's the workflow for updating content? 13:03 What is Builder built in? Mobx 14:36 Moving from Figma to HTML 18:41 Is an app like this divs all the way down? 24:55 Stories of browser gremlins building? 26:29 Advice for anyone building drag and drop Fullstory 29:04 Does FPS play a part in development? 33:31 Do you use SVG? 36:15 Where does Qwik and Partytown fit into all of it? Qwik Partytown 46:45 How does accessibility play into Builder? 49:44 Supper club questions 54:30 SIIIIICK ××× PIIIICKS ××× ××× SIIIIICK ××× PIIIICKS ××× Dead Space Remake Tweet us your tasty treats Scott's Instagram LevelUpTutorials Instagram Wes' Instagram Wes' Twitter Wes' Facebook Scott's Twitter Make sure to include @SyntaxFM in your tweets
In this episode of the React Native Show, Łukasz Chludziński (https://twitter.com/loginlukasza) and Ola Desmurs-Linczewska (https://twitter.com/p_syche_) discuss state management in React Native apps. As there's no magical formula for handling it, don't expect straightforward direction or easy answers from this episode. Instead, get ready for: - an overview of state management in React Native & React apps - a deep-dive into state management libraries based on different philosophies, including Redux, MobX, XState, Jotai, and React Query - an insight into how Ola compared these libraries when writing “Simplifying State Management in React Native” - a few words of the book-writing process as seen by Ola You can find Ola's book on Amazon (https://www.amazon.com/Simplifying-State-Management-React-Native/dp/1803235039) and GitHub (https://github.com/PacktPublishing/Simplifying-State-Management-in-React-Native). New state management libraries keep appearing, so choosing the one that best suits your project and taste may be challenging. We hope to help you make this decision and get a broader perspective on state management in React Native by having Ola and Łukasz discuss the following aspects of a few libraries: - the people behind them - the category they belong, e.g. flux vs. proxy vs. atom, mutable vs. immutable, battle-tested vs. experimental - how they work and what it means to the developer Resources that Ola and Łukasz mentioned in this episode: ➡️ Dan Abramov's Fundamentals of Redux Course https://egghead.io/courses/fundamentals-of-redux-course-from-dan-abramov-bd5cc867 ➡️ Michel Weststrate's courses on Mobx https://egghead.io/courses/manage-complex-state-in-react-apps-with-mobx, https://egghead.io/courses/manage-application-state-with-mobx-state-tree ➡️ State explosion https://statecharts.dev/state-machine-state-explosion.html ➡️ Daishi Kato's course on Mobx https://egghead.io/courses/manage-application-state-with-jotai-atoms-2c3a29f0 ➡️ Dominik Dorfmeister's blog about React Query https://tkdodo.eu/blog/practical-react-query Enjoy the episode, and don't forget to subscribe to our channel for more content like this! How about boosting performance of your React Native app with the help of our ultimate guide? https://www.callstack.com/campaigns/download-the-ultimate-guide-to-react-native-optimization?utm_campaign=RN_Performance&utm_source=youtube&utm_medium=social&utm_content=State_Management_podcast If you feel like learning more about state management with Redux, check out our training: https://www.callstack.com/training/state-management-with-redux?utm_campaign=Podcast&utm_source=youtube&utm_medium=social&utm_content=State_Management_podcast_promo_1 Need help with your React Native project? Give us a shout! https://www.callstack.com/services?utm_campaign=Podcast&utm_source=youtube&utm_medium=social&utm_content=State_Management_podcast_promo_1 Check out other episodes of our podcast: https://www.callstack.com/podcast-react-native-show?utm_campaign=Podcast&utm_source=youtube&utm_medium=social&utm_content=State_Management_podcast_promo_1 Do you want to work with us? We're looking for Senior React Native developers! Check out the details and apply here: https://www.callstack.com/senior-react-native-developer?utm_campaign=Podcast&utm_source=youtube&utm_medium=social&utm_content=State_Management_podcast_promo_1 Follow us on Twitter to stay up to date with upcoming episodes: https://twitter.com/callstackio
Hi everyone! We had a great time with Pavan Podila. Pavan is an experienced frontend developer, speaker, and mentor and is currently a GDE for Flutter, Dart, and Web technologies. In this episode, he shared with us about a state management he created "MobX"! Listen now and share it with your friends!Resources:https://mobx.netlify.app/https://github.com/pavanpodilahttps://developers.google.com/community/experts/directory/profile/profile-pavan-podilaCredits:
This week Jamon and Mazen are joined again by Mark Erikson to discuss RTK vs MST and some of the benefits and downsides they each have.This episode brought to you by Infinite Red! Infinite Red is a premier React Native design and development agency located in the USA. With five years of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter), Infinite Red is the best choice for your next React Native app.Helpful Links:Gist with interesting early discussions on GHReactifluxRTK docs Modern ReduxRTK 1.0Redux Essentials Connect With Us!React Native Radio - @ReactNativeRdioJamon - @jamonholmgrenMazen - @mazenchamiMark - @acemarke
Should you use Redux or MobX-State-Tree? Robin, Mazen, and Jamon do a breakdown of the various tradeoffs of these two popular state management libraries.This episode brought to you by Infinite Red! Infinite Red is a premier React Native design and development agency located in the USA. With five years of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter), Infinite Red is the best choice for your next React Native app.Helpful Links:https://www.loom.com/share/9e3afe0547824e42bada06191e891ae1https://mobx-state-tree.js.org/intro/welcomehttps://redux.js.org/introduction/getting-startedhttps://reactnativeradio.com/episodes/175-state-management-in-react-native-sLR6hN_vConnect With Us!React Native Radio - @ReactNativeRdioJamon - @jamonholmgrenMazen - @mazenchamiRobin - @robin_heinze
This episode is all about hooks within React: useState, useEffect, useReducer, useContext, useRef, useMemo, and useCallback.SponsorsVercelVercel combines the best developer experience with an obsessive focus on end-user performance. Their platform enables frontend teams to do their best work. It is the best place to deploy any frontend app. Start by deploying with zero configuration to their global edge network. Scale dynamically to millions of pages without breaking a sweat.For more information, visit Vercel.comZEAL is hiring!ZEAL is a computer software agency that delivers “the world's most zealous” and custom solutions. The company plans and develops web and mobile applications that consistently help clients draw in customers, foster engagement, scale technologies, and ensure delivery.ZEAL believes that a business is “only as strong as” its team and cares about culture, values, a transparent process, leveling up, giving back, and providing excellent equipment. The company has staffers distributed throughout the United States, and as it continues to grow, ZEAL looks for collaborative, object-oriented, and organized individuals to apply for open roles.For more information visit softwareresidency.com/careersDatoCMSDatoCMS is a complete and performant headless CMS built to offer the best developer experience and user-friendliness in the market. It features a rich, CDN-powered GraphQL API (with realtime updates!), a super-flexible way to handle dynamic layouts and structured content, and best-in-class image/video support, with progressive/LQIP image loading out-of-the-box."For more information, visit datocms.comShow Notes0:00 Introduction4:55 What was before React Hooks5:14 Class Based Components5:28 Functional Components6:19 Experience with Classes9:14 Benefits of React Hooks11:31 useState16:17 Sponsor: DatoCMS17:11 useEffect22:37 useReducer29:22 useContext32:42 Sponsor: ZEAL33:34 useRef35:42 useMemoWeb Dev Simplified, useMemo in 10 MinutesBen Awad39:08 useCallbackWeb Dev Simplified, useCallback in 8 MinutesBen Awad41:15 Sponsor: Vercel42:08 Grab Bag Questions42:27 Question #1: useState vs useContext44:28 Question #2: How can we pause rendering?46:51 Question #3: useRef vs. useState and in what condition will useState cause an infinite loop?48:19 Question #4: Do you actually use useCallback and useMemo?49:44 Question #5: What are some powerful ways you guys have used custom hooks within React?Custom Audio Player on YouTube51:44 Question #5: Forms with mobX, useState, mvvm, and Validation52:50 Picks and Plugs53:01 Amy's Pick: Paper Like Screen Protector53:26 Amy's Plug: SelfTeach.me YouTube Channel53:37 James's Pick: iPad Keyboard Case54:52 James's Plug: James Q Quick on YouTube
In this episode, my guest is Waleed Arshad and we talk about state management in Flutter.Waleed is Pakistan's first Google Developer Expert in Flutter and GDE in Dart. He's the author of the book “Managing State in Flutter Pragmatically: Discover how to adopt the best state management approach for scaling your Flutter app“.At the time of recording this episode, I couldn't read the book yet, it wasn't public yet, but since we recorded I bought the book and read most of it, and I can only recommend it.Guest: Waleed ArshadTwitter @wal_33dGitHub @wal33d006LinkedIn @waleed006Web wal33d006.github.ioBook: Managing State in Flutter PragmaticallyPacktamazon.comamazon.deGoogle BooksHost: Vince VargaTwitter @vincevargadevGitHub @vincevargadevLinkedIn @vincevargadevWeb vincevarga.devFlutter 101 Podcast on Twitter @flutter101devMost relevant past episodes from Flutter 101Flutter State Management Overview with Waleed Arshad (Episode 26): Waleed Arshad is a Google Developer Expert in Flutter and Dart. He's the author of the “Managing State in Flutter Pragmatically“ book. We talked about different state management options: setState, InheritedWidget, Provider, Riverpod, Bloc, Cubit, MobX, and more.RVMS architecture, get_it, commands, and more with Thomas Burkhart (Episode 3): Thomas Burkhart is a GDE for Flutter and Dart. He's the author of popular packages, like get_it, and flutter_command. We talked about the RVMS architecture.Flutter Development Experience with Chris Sells (Episode 16): Chris Sells is a Senior Product Manager at Google on Flutter. Chris is responsible for the end-to-end development experience, as well as tooling, the package ecosystem, and the desktop platform support.ResourcesTop 30 Flutter State Management options tweet by @RydMike
In this episode, my guest is Waleed Arshad and we talk about state management in Flutter.Waleed is Pakistan's first Google Developer Expert in Flutter and GDE in Dart. He's the author of the book “Managing State in Flutter Pragmatically: Discover how to adopt the best state management approach for scaling your Flutter app“.We talked about why state management is such a hot topic amongst Flutter developers and we talked about different state management options: setState, InheritedWidget, Provider, Riverpod, Bloc, Cubit, MobX, and more. We also discussed whether choosing this or that state management library is even so important as we previously thought if we layer, design, architect our application correctly.At the time of recording this episode, I couldn't read the book yet, it wasn't public yet, but since we recorded I bought the book and read most of it, and I can only recommend it.Guest: Waleed ArshadTwitter @wal_33dGitHub @wal33d006LinkedIn @waleed006Web wal33d006.github.ioBook: Managing State in Flutter PragmaticallyPacktamazon.comamazon.deGoogle BooksHost: Vince VargaTwitter @vincevargadevGitHub @vincevargadevLinkedIn @vincevargadevWeb vincevarga.devFlutter 101 Podcast on Twitter @flutter101devMost relevant past episodes from Flutter 101RVMS architecture, get_it, commands, and more with Thomas Burkhart (Episode 3): Thomas Burkhart is a GDE for Flutter and Dart. He's the author of popular packages, like get_it, and flutter_command. We talked about the RVMS architecture.Flutter Development Experience with Chris Sells (Episode 16): Chris Sells is a Senior Product Manager at Google on Flutter. Chris is responsible for the end-to-end development experience, as well as tooling, the package ecosystem, and the desktop platform support.Mentioned packagespub.dev/packages/provider: A wrapper around InheritedWidget to make them easier to use and more reusable.pub.dev/packages/bloc: A predictable state management library that helps implement the BLoC (Business Logic Component) design pattern.pub.dev/packages/flutter_bloc: Flutter Widgets that make it easy to implement the BLoC (Business Logic Component) design pattern. Built to be used with the bloc state management package.pub.dev/packages/get_it: Simple direct Service Locator that allows to decouple the interface from a concrete implementation and to access the concrete implementation from everywhere in your Apppub.dev/packages/mobx: MobX is a library for reactively managing the state of your applications. Use the power of observables, actions, and reactions to supercharge your Dart and Flutter apps.pub.dev/packages/redux: Redux is a predictable state container for Dart and Flutter appspub.dev/packages/binder: A lightweight, yet powerful way to bind your application state with your business logic.Other resourcesFlutter state management for minimalists by @suragch1Flutter Docs: State Management
Jany Koščo je zkušený PHP a Go vývojář, který už hezkých pár let působí jako CTO českého footwear a lifestylového obchodu Footshop. A rozhodně se nenudí, protože jeho zaměstnavatel se v posledních letech stal e-commerce leaderem ve svém segmentu (nejen) ve střední Evropě. Footshop už působí v 18 zemích světa a jeho e-shop tedy jede v 18 jazycích!
In this episode of The Techloop Podcast, we are joined by Pavan Podila. He is an Open source developer and author. He talks about his exciting journey from developing an Open Source library called MobX, Flutter, 3D designs, and more! Thinking of developing an Open Source Library? Flutter, in or out? Listen to our full podcast to find out!
[קישור לקובץ mp3] שלום רב וברוכים הבאים לפרק מספר 416 של רברסים עם פלטפורמה - התאריך היום הוא ה-27 ביולי 2021, ואנחנו נפגשנו ביוקנעם באולפן הבייתי יחד עם יונתן ואסף - היי חבר'ה, מה נשמע? - יונתן, מה שלומך? מתאושש מהג'ט לג הקטן? - (יונתן) כן, הבאתי לך טובלרונים לאחרי . . . (רן) איזה כיף זה הטופי הזה שנתקע בין השיניים . . . - אז אסף - ברוך הבא! (אסף) תודה רבה(רן) היום אנחנו נדבר על נושא Frontend-י - אנחנו לא מדברים הרבה על נושאים Frontend-ים, אבל היום אנחנו נקדיש את כל הערב הזה ל-Frontend - ובעיקר, באופן ספציפי - ל-State Management ב-Frontend.אז עם זה אסף מגיע אלינו - אז אסף, בוא נכיר אותך: מאיפה אתה בא? מה אתה עושה? ספר לנו קצת עליך וקצת על החברה שלך.(אסף) אז אסף קרינצה, אני בא מתל אביב עד לפה ליוקנעם . . .אני מתכנת - התחלתי לתכנת מקצועית בערך לפני עשר שניםהתחלתי את הקריירה ב-CheckPoint, הייתי שם בהתחלה בתחום שהוא יותר Security, אחרי זה עברתי להיות מתכנת ואז ראש צוותאחרי זה עבדתי ב-Microsoft וב-Soluto [עדיין טרי - 413 GitOps with Yaron from Soluto]לאורך השנים עבדתי גם ב-Backend וגם ב-Frontend - וב-Frontend יצא לי להתעסק בהרבה State Management Solutions: לחוות אותם ב-Production, לעבוד איתם בצוות - וגם בפרוייקטים בבית התנסיתי בכל מיני.אחרי Soluto - בעצם בספטמבר האחרון - עזבתי את העבודה, אני ועוד שני חברים טובים שהם גם שותפים, אחד מהם עבד איתי ב-Soluto ואת השני פגשתי עוד ב-CheckPoint - והקמנו חברה בשם livecycle.כש-livecycle זו חברה שעוסקת במוצר עבור צוותי פיתוח - אנחנו מרימים סביבות - Preview Environments - מתוך ה-Source Code של הלקוחות שלנובעצם, הרעיון הוא שעבור כל Change, כל Commit - אנחנו עושים תהליך שהוא דומה לתהליך CI, של לבנות - לעשות Build - למוצר, ואנחנו גם עושים לו Running, בענן.בעצם, יש “סביבה חיה ובועטת” של כל גרסא של המוצר - בענן - שאפשר לשתף אותה.מעבר לזה, On top that - אנחנו שמים כלי קולברציה (Collaboration Tools)לדוגמא, אפשר לדמיין שיש מעצבת בצוות, ומתכנתתהמתכנתת עשתה שינוי בקוד - ושולחת למעצבת, שאולי עיצבה את הפיצ'ר הזה - לינק.המעצבת תוכל להיכנס ללינק, לראות גרסא חיה שלו - ממש גרסא של המוצר, לא איזה Mock - וגם תוכל להגיב שם, עם הכלי קולבורציה שלנוהיא תוכל לשנות CSS - נגיד “ה-Margin לא מספיק טוב”היא תוכל לעשות Screenshot ישירות, בלי Tooling חיצונילהקליט וידאוכל הדברים האלה באים “בחינם” - בלחיצה של לינק . . . וכל זה רץ לו על הדפדפן.(רן) אז אתה אומר - יצרת Pull Request או Merge Request, תלוי באיזו פלטפורמה אתה משתמש - ואז באופן אוטומטי נוצר לך איזשהו Preview link שאותו אתה יכול לשלוח, עוד לפני שעשית Merge, זאת אומרת - אתה לא צריך ללכת ועשות Deploy כדי שהסיפור הזה יעבוד, ופה חוסך זמן ומייעל את ה-Cycle . . .(אסף) נכון . . .(רן) בסדר . . . אצלכם, דרך אגב, יונתן - יש פתרונות בסגנון הזה?(יונתן) Preview כזה אין לנו . . . יש לנו סביבות Pre-Production, שלשם אנחנו מעלים גרסאבאמת בדרך כלל אחרי Merge, כמו שאתה תיארת.(רן) כן, אוקייאנחנו בעצם נפגשנו פה כדי לדבר על State Management ב-Frontend.עכשיו, אני מניח שכל מי שמפתח Frontend בעשור האחרון מבין על מה מדובר, אבל בוא נחבר גם את מי שהוא לא מפתח Frontend, זאת אומרת - למה צריך State Management?יש לי CSS, יש JavaScript, יש HTML . . . על איזה State בדיוק אנחנו מדברים פה? למה צריך State Management?(אסף) אחלה . . . אז אפשר באמת להתחיל מלהגיד מה זה State, ומה זה בעצם עושה באופן כללי, וספציפית באפליקצית Web.אז אפשר להגיד ש-State זו איזושהי “פיסת אינפורמציה”, שמגדירה איך נראית האפליקציה בכל רגע נתוןאיך היא נראית ואיך היא מתנהגתלדוגמא - זו הדוגמא הקלאסית, כשמדברים על State Management, יש כזה את ה-”Hello World” שזה ה-To-Do Applications - כשיש לך רשימת To-Do's כזאת, ה-State יכול להיות האינפורמציה, Array של To-Do's, כשכל אחד מה-Item-ים ברשימה יכול להיות אובייקט - שיהיה לו Title ויהיה לו “?Is Completed”, האם המשימה בוצעה או לא.זה ה-State.עכשיו, יש לנו את האפלקיציה - היא לוקחת את ה-State הזה, ומרנדרת (Rendering) איזשהו View.אפשר להסתכל על זה כמו איזושהי Pure Function, שעבור כל State תייצר אפליקציה אחרת, ועבור אותו ה-State תייצר בדיוק את אותה אפליקציה.הרעיון של ה-State Management זה איזה-שהם כלים וקונספטים שעוזרים לנו לנהל את הדבר הזה.(רן) הזכרת מקודם View - אז יש את המודל הקלאסי, ואולי קצת ישן ומאוס, של Model-View-Controller - אז באלגוריה הזאת, ה-State הוא למעשה ה-Model?(אסף) נכון - ה-ה-State הוא למעשה ה-Model, ה-View זה יכול להיות . . . אם זה נגיד, MVC שמתרדנר (Rendered) בשרת, כמו Ruby-on-Rails או PHP או Laravel או כאלה דברים, ה-View הוא HTML, שהשרת מחזיר ללקוח - והדפדפן “מצייר” מזה אתר.(יונתן) אני חושב שפעם, בעצם . . . יש מעיין Shift כזה ל-Frontend . . . פעם, ה-Database באמת היה ה-Database, ה-Server היה עושה את הלוגיקה, מרנדר אפילו JSP וכל מיני כאלה - וה-Browser היה רק מציג.עכשיו, יש Shift כזה שמאלה ל-Frontend, ששם כבר הלוגיקה - ולכן חסר שם איזה משהו . . .(רן) כן, אני מסכים - ככל שיותר לוגיקה עברה ל-Frontend, ככה נדרש יותר תחכום, ולכן גם נדרש איזשהו State Management - וכנראה שעוד הרבה דברים אחרים. לא רק זה, אבל זה לגמרי אחד מהם.עכשיו - State Management גם מגיע עם רכיבי View בדרך כלל, נכון? יש איזשהו קשר הדוק - אני מניח, למשל, שכל מי שכתב אי-פעם ב-React, כנראה גם מכיר את Redux ואולי גם עוד כמה חבילות.למה . . . נשאל את השאלה הזאת ככה: האם באמת “הצימוד” הזה הכרחי? מה המוטיבציה לצימוד הזה? מה אנחנו מרוויחים מהצימוד הזה? או לחילופין - האם אפשר להפריד ביניהם, לצורך העניין - להשתמש ב-Redux עם Angular או Whatever, והאם אפשר להרוויח מזה משהו פה?(אסף) אחלה - אז כמו שאמרתי, יש פה שני דברים שונים: אחד - זה האם כשאתה משתמש ב-React, צריך להוסיף לזה, On top of that, גם Redux?; והשני זה “האם Redux עובד גם עם דברים אחרים?”.אז אם אני אענה על השאלה השנייה קודם - Redux הוא לא Coupled ל-React: זו ספרייה שיכולה לעבוד עם כל מיני ספריות, והיא יותר High-Level.יש Binding מ-Redux ל-React - זה נקרא React Redux, שזה מצמד את React ל-Redux, אבל באופן די גורף - לרוב ישתמשו ב-Redux עם React, וזו גם הספרייה פופולארית ביותר.אני הסתכלתי לא מזמן ב-npm, ב-Weekly Downloads, ו-Redux הוא 90% בערך מהנפח של הספריות שהסתכלתי עליהן.אני לא יודע כמה קורלציה יש לזה לשימוש אמיתי, אבל אם זה אומר משהו, אז Redux היא סופר-סופר פופולארית.(רן) כן - ואני חושב, דרך אגב, ש . . . מי שמפתח Frontend בודאי מכיר, אני אתרגם רק למי שאינו מפתח Frontend כנראה - אחד הדברים שהכי קוסמים ב-Redux זה הפשטות שלהזו ספרייה שהיא (א) מאוד מאוד קטנה ו-(ב) יש המון המון Tutorials על איך לכתוב Redux בשביל עצמך - מתוך מטרה שהמפתחים יבינו באיזה כלי הם משתמשים.אז לא כל ספריות ה-JavaScript פשוטות, אבל Redux זו שפה פשוטה - אבל אלגנטית, וזה היופי שלה.אבל Redux זה חדשות של לפני . . . כמה? 6-7 שנים?(אסף) 2014 זה היה, אם אני לא טועה [2013?] . . . זה היה ההרצאה של Dan Abramov, שבה הוא הכריז על הספרייה.(רן) כן, אז 7 שנים, אולי יותר - ומאז הרבה מאוד דברים קרו - אז בוא נדבר על מה קורה היום . . .ביום-יום - מה אתה עושה? אתה הולך ופותח פרויקט ו . . . ? דבר ראשון אתה מביא Redux? איך זה נראה?(אסף) אז זו שאלה מצויינת, ובאמת זה תלוי מאוד בצרכים שלך, של האפליקציה עצמהצריך לשאול מה עושה האפלקיציה? מה המורכבות שלה? האם בכלל צריך State Management?אפשר אפילו לקחת קודם צעד אחורה - ולשאול האם בכלל יש State? לא לכל אפליקציה יש State, כמו שיונתן ציין.פעם, אם אנחנו הולכים ממש אחורה, ל”תחילת האינטרנט” - אז אתרים זה היה משהו מאוד פשוט: זה היה הטקסט, התמונות, מדי פעם היה איזה Form . . . אבל זה מה שקרה.וככל שעבר הזמן, הדפדפן ניהיה דבר מאוד מורכב, מעיין “מפלצת” - זה היום חזק כמו מערכת הפעלה שלמה כמעט, אפילו דפדפנים יכולים היום להריץ Server-ים . . . אני ראיתי ש-StackBlitz מריצים את Node בתוך הדפדפן - אתה יכול להריץ Node Server שמרים לך Web Server, וחושף IP שאתה יכול, דרך הדפדפן שלך, להיכנס ל-IP שהדפדפן מרים . . . זה די Mind-blowing.(רן) רקורסיה . . . זו הכותרת.(אסף) בדיוק . . . אז דפדפן זה משהו מאוד חזק, ואפשר לעשות איתו דברים מטורפים.אבל קודם כל, השאלה שצריך לשאול, בכלל לפני ששואלים איזו בספרייה משתמשים, זה האם צריך ספרייה כזאת?אם החלטנו שאנחנו משתמשים ב-React, כספרייה - כי גם את זה אנחנו לא חייבים - אז גם React, לכשלעצמה, יש לה פתרונות לניהול State.כי React באה עם כמה APIs נוחים לניהול State - אני מדבר ספציפית על . . . אפשר לעשות את זה בכמה דרכיםאו בצורה הישנה, שזה דרך ה-Classאו דרך Hooks, שזה משהו קצת יותר חדש.אני אדבר על ה-Hooks, כי זה קצת יותר נוח, אבל אותם עקרונות בדיוק אפשר לעשות גם ב-Classes . . .(רן) נעשה פה רגע איזו עצירה - יונתן, דיברנו קודם זה שלפחות היסטורית, רוב ה-State היה נשאר בצד של השרת והיה מוחזק ב-Database-ים, והייתה איזושהי שכבת Rendering - שגם היא הייתה נמצאת הרבה פעם בצד של השרת.ואז הזכרת - אסף - שהדפדפנים היום הם דווקא די חזקים, ושאפשר לעשות בהם כמעט הכל - ובין השאר, יש בהם גם Database-ים.ועכשיו, נשאלת השאלה - האם יש קשר בין ה-State, שעליו אנחנו מדברים, לבין ה-Database-ים שקיימים היום בדפדפנים? לצורך העניין - האם הם שומרים ב-Database-ים המקומיים שלהם את ה-State, או שזה State שהוא מתדנדר (Rendered)? זאת אומרת - ברגע שאתה עושה Refresh לדף, הכל נעלם ומתחילים מחדש?(אסף) ה-State שאני אוהב וה-State-ים שאני מדבר עליהם - הם לרוב נשמרים ב-RAM, בזכרון, וזה אומר שזה יתנדף ברגע שירפרשו (Refresh) את העמוד.כמובן שאפשר את כל ה-State הזה להעביר אל ה-Local Storage או עם פתרונות Database-יים מקומיים שיעשו את זה Persistent over time.זה במיוחד יהיה יותר קל ויותר נעים עם ספריות כמו Redux, ששומרים הכל במקום אחד - אתה עושה לו פשוט Dump וטוען אותו בחזרה.בדרכים אחרות, אם אתה שומר את ה-State שלך בצורה קצת יותר מבולגנת ב-RAM זה אולי יהיה קצת יותר קשה, אבל אם אנחנו הולכים, נגיד, על משהו כמו Redux, או Recoil, שגם לו יש Snapshot ו-Store שמסדר הכל במקום אחד - או MobX-State-Tree, שזה גם פתרון כזה - יהיה מאוד קל לעשות Dump של הזיכרון הזה אל ה-Local Storage, לדוגמא, שזה Persistent Storage, כמו Database - ולטעון את זה בחזרה כשטוענים את האפליקציה.(רן) “מאוד קל” במובן הזה שזה פשוט String JSON, ואתה יכול לכתוב ולקרוא אותו לעשות Serialization או De-Serialization?(אסף) כן - בגלל שכל ה-State נמצא בעצם באובייקט אחד, אני יכול לעשות לה סריאליזציה (Serialization) ל-JSON, לשמור אותו כ-String ב-Local Storage, לטעון אותו, לעשות לו דה-סריאלזיציה (De-Serialization) - ולהשתמש בו שוב.(יונתן) אם אני, נניח, מתחיל לכתוב אפליקציה חדשה, ואני עוד לא יודע כמה היא תסתבך, כמה גדול זה יהיה . . . - האם היית ממליץ לי, מההתחלה, להשתמש ב-State Management, או לחכות שזה ממש “יצעק”?(רן) זה לא כמו השאלה על Unit Testing? . . . “אני מתחיל משהו קטן, איזשהו פרויקט-צד קטן, לא נראה לי שזה הולך להיות מסובך, אני לא כותב טסטים” . . . מפה לשם - אחרי שנה אתה לא מוצא את הידיים ואת הרגליים . . . (אסף) כן, לגמרי . . . אז זה עניין של גישה.אני, כשאני מתחיל משהו חדש, אני אוהב להתחיל את זה עם כמה שפחות Boilerplate וכמה שפחות דברים, הכי נקי שיש, וכשאני צריך עוד ועוד דברים - אני עושהאני אבין בעתיד, כנראה, גם מה הצרכים שלי, ואני אדע לבחור איזה מהפתרונות State Management . . . כי שוב - זה לא סטנדרט . . . אין סטנדרטיזציה בנושא, אז יש כל כך הרבה ספריות וכל כך הרבה דעות, וזה מסוג הדברים שמתכנתים אוהבים להיות מאוד דעתניים כלפיו.(יונתן) אז המיגרציה (Migration) הזאת, מלהיות בלי State Management לעם - למשהו ש . . . זה מסובך לעשות את זה? זה re-factor ש”ישכיב” את הצוות או שזה “מכה קלה בכנף”?(אסף) אז אני חושב שזה תלוי מאוד ב- State Management solution שאתה בוחר בולדוגמא, MobX זו אחת הספריות הפופולאריות - כנראה השנייה-הכי-פופולארית אחרי Redux - זה מאפשר לך לעשות את ה-Transition הזה בצורה די נוחה, כי זה משתמש באיזשהו “קסם” שמאפשר לך לעטוף אובייקטים רגילים של JavaScript ולהפוך אותם ל-”React-ביים”.מה זאת אומרת -”React-ביים” [חוץ ממשהו שממש קשה להעביר לטקסט ככה?] - זאת אומרת שאם ה-State הזה מעודכן, אז ה-View שלנו גם יתעדכןזאת אומרת ששינינו . . . נגיד בדוגמא של ה-To-Do List, שינינו את ה-Data, את ה-Array הזה של ה-To-Dos? - והקומפוננטות (Components), ה--ים האלה, שמציירות את זה על המסך, תתעדכנה גם כן.ובגלל שזה משתמש באיזשהו “קסם”, שנקרא Proxy Object של JavaScript או Getter ו-Setter של ES5 - אלו שתי דרכים לעשות את זהזה בעצם “דורס התנהגות” של מה שאנחנו עושים, De-reference לאובייקט, כשאנחנו ניגשים אליו.אז מאחורי הקלעים, אתה משתמש בזה כמו אובייקט רגיל, אתה עושה State.ToDos[7].Title - ועורך את זה.ומאחורי הקלעים, MobX עשתה לך Subscription כשהשתמשת בזה עבור הקומפוננטה (Component) שמשתמשת בזה, והיא תדע לעדכן את הקומפוננטה בכל פעם שעדכנת את ה-State.אז זה יהיה מאוד מאוד נוח . . . יכול להיות שכתבת את הדבר הזה כאובייקט JavaScript רגיל, ואתה רק מוסיף MobX ועוטף את זה בכמה פונקציות שהספרייה מביאה לך - ואתה די מסודר, יש לך State Manager . . . בספריות אחרות, נגיד Redux, זה משהו שהוא הרבה יותר opinionated, והוא קצת יותר מורכב.אתה צריך לנסות הרבה יותר דבריםוזו גם אחת הביקורות הכי גדולות שיש על הספרייה הזאת - זה שצריך ללמוד הרבה, ושאתה צריך לכתוב הרבה קוד בשביל להשתמש בזה.(רן) בוא נחזור רגע ל”קסם” - כי קסם זה כיף: אז יש Attribute - אתה אומר נגיד, ToDos[1].Value = “לאסוף כביסה”, ואז, בעצם, אתה אומר שיש איזשהו רכיב שעשה איזשהו Subscription ל-Setter הזה, והוא עושה “Hijacking” לקריאה הזאת או עם Proxy או טכנולוגיה אחרת שהזכרת את שמה, והוא בעצם “תופס” את הקריאה הזו, ואולי הוא עושה Set ל-Value - אבל הוא גם מפעיל איזושהי שרשרת של קריאות, שבסופו של דבר מפעילה את ה-UI.עכשיו, זה נחמד ברמת השימושיות . . . השאלה, אם אתה מכיר את הקונספט הזה, מה שנקרא The Fallacies of distributed systems - שבעצם זה בא ואומר שכאילו אתה מפעיל איזושהי קריאה, ואתה לא יודע שהקריאה הזאת רצה על איזשהו שרת מרוחק, ולכן אתה גם לא יודע מה כל הדברים הרעים שיכולים לקרות בדרך . . . אז אתה לא מטפל נכון בשגיאות, אתה לא יודע כמה זמן זה יקח, אתה . . . זאת אומרת - זה נראה קל, אבל אתה בעצם “מחביא” מאחורי זה הרבה מאוד דברים שגם יכולים להשתבש, ואם אתה לא מבין שזה מה שיקרה, אתה יכול לטעות, זאת אומרת - יהיה לך UI שהוא Sluggish ועוד כל מיני כאלה תופעות . . . אולי לא תטפל נכון בשגיאות וכו'.אז איך . . . יש פה איזשהו Trade-off בין פשטות השימוש לבין היכולת שלך לשלוט בהתנהגות בצורה שהיא Fine-grained . . . (אסף) נכון מאוד . . . MobX, כספרייה, זה משהו שהוא יותר Tool, שהוא נורא לא Opinionated.הוא מאפשר לך איזושהי יכולת, שנותנת לך לעשות Subscription ו-Reactiveness ל-State, בלי לעשות הרבה Boilerplate - אבל זה לא אומר שאתה חייב להשתמש בזה בצורה הכי פשוטה.אתה יכול לעטוף את זה בדברים שיעזרו לך לפתור את הבעיות שציינת - של Observability ושל Debugging יותר נוח.האמת שהיוצר של MobX כתב עוד ספרייה, שקוראים לה MobX-State-Tree, שהיא כן Opinionated, ומשתמשת ב-MobX בתור כלי, מאחורי הקלעים, לעשות את הפעולות היותר . . . של ה-Reactivness.אבל היא מאוד Opinionated - יש שם Store, ל-Store יש Type-ים שאתה רושם אותם, איזשהו מודל . . . אתה רואה בכל פעם לאן כל דבר הולך ואתה יכול ליצור, מתוך זה, Snapshots - בדומה ל-Reduxזאת אומרת - זה משלב, באיזשהו מקום, את הכיפיות והקסם של MobX, אבל את ה-Rigidness וה”נוקשות” הזאת של -Redux, שגורמת לך גם לדבג (Debug) קוד בצורה יותר נוחה וגם להבין מה קורה כשדברים משתבשים.(רן) כשדיברנו בטלפון, בשיחה המקדימה, דיברנו על ספרייה שנקראית Recoil, שהזכרת את שמה מקודם - מה מעניין בה? מה מיוחד בה? מתי אני ארצה להשתמש בה ולא באחרות?(אסף) אחלה, אז Recoil . . . אולי לפני שנדבר על Recoil, נדבר טיפה על קונטקסט, כי הרבה מהדברים שם הם סוג של פותרים דברים שהיה בעייתי עם קונטקסט, עם New State.אז אם מסתכלים רגע על ה-API ש-Redux מביא איתו Built-in, בלי להתקין שום ספרייה חיצונית, אז יש לנו שני דברים עיקרייםיש לנו useState, או useReducer, שזה תחליף ל-useStateויש לנו את Context.עכשיו - useState ו-Context עושים שני דברים קצת שונים - useState מאפשר לכל קומפוננטה (Component) לשמור State לוקאלי עבורה, שהוא Persistent בין Render Callsזאת אומרת שאם אני אקרא ל-Render עוד פעם, יהיה לי את אותו State.ובנוסף, זה נותן לי את ה-Reactiveness הזה, כמו שדיברנו - זה מרכיב חשוב בכל State Management.ברגע שעדכנתי את ה-State, עם פונקציה שה-Hook הזה מחזיר לי - ה-setState - אז React ידע לקרוא לי ל-Rendering - אם ה-State המחודשזאת אומרת שברגע שאני מעדכן את ה-State - אני יודע שה-View יהיה “טרי”, הוא יצייר לי את מה שאני רוצה עם ה-State “הטרי” והחדש.(רן) זאת אומרת - כאילו יש את המצב הראשוני, ואחר כך, על כל שינוי, יקראו לך ותעשה Rendering מחדש.(אסף) בדיוק - אני יכול . . . React מבטיח לי את זה, שזה אחלה, זה מעולה.הבעיה עם useState זה שדברים . . . שאפליקציה, כשהעץ-קומפוננטות של React מתחיל לגדול ולגדול, אני רוצה לפעמים להתחיל לשתף State בקומפוננטות שלפעמים הן גם במיקום רחוק בעץ . . . שני עלים שיש להם אב-קדמון משותף, נמוך ביותר, שהוא כמה רמות מעל.ואז זה אומר . . . .(רן) אוקיי - אז אני מסתכל על רשימת ה-To-Do - אז אתה רוצה, נגיד, להציג איזשהו View אחד גדול עם ה-To-Dos, ואולי מימין-מלמעלה גם איזשהו תקציר של הרשימה, נגיד כמה אייטמים נשארו un-checked . . . (אסף) בדיוק - כמה אייטמים נשארו un-checked, ואולי עוד סטטיסטיקות . . . מעיין כזה Dashboard, זו דוגמא מעולה.ובאמת, כדי ששתי הקומפוננטות הללו תכירנה את אותו State - כי אנחנו לא רוצים לשכפל את ה-State, אנחנו יכולים, תיאורטית, לשכפל את ה-State, אבל אז נוצר מצב שבו אני צריך לטפל בעדכון של שני State-ים שונים, וזה יכול ליצור באגים וזה קשה להבין . . . (רן) מה הבעיה? תיקח ספרייה, בטח יש אחת כזאת שעושה את זה, לא? . . .(אסף) יש ספרייה . . . ב-JavaScript יש ספרייה לכל דבר, לכל שורה של קוד יש ספרייה . . . (רן) ראיתי לא מזמן איזשהו API שנקרא is-odd - שמחזיר לך אם המספר זוגי או אי-זוגי . . .(אסף) יש את הסיפור המפורסם של left-pad, שזו ספרייה שהקריסה את כל npm, הקריסה מלא עבודה של מלא אנשים בכל העולם, בגלל שהשתלטו עליה ועשו שם כל מיני דברים . . [היה לא מזמן ב-398 with Danny Grander from Snyk](רן) בסדר - אז אתה לא רוצה לשכפל את ה-State וזה, אני חושב, ברור - אבל אתה אומר שיש פה בעיה עם ה-Set . . .(אסף) כן, ומה הבעיה? יש פה שתי בעיות - אחת זה שאם אני רוצה ששתי קומפוננטות, שנמצאות במיקום מרוחק בעץ, ישתפו את אותו State, אני צריך להתחיל להעביר את ה-State הזה ממקום למקום - זה נקרא Props Drilling, “קדיחת Properties” . . . זה לא נוח, זה אומר שבכל פעם שאני רוצה להוסיף State אני צריך להוסיף את זה בעוד “מיליון מקומות”, קשה לעקוב אחרי זה, מאיפה זה בא . . .(רן) כן, אתה צריך לקודד . . . למעשה, אתה צריך . . .עכשיו כשאתה אומר, אני נזכר שעשיתי את זה, וזה היה מה-זה מעצבן . . . בכל מקום אתה צריך ללכת ולעשות . . . “לפעפע” את ה-Attribute הזה למטה ולמטה ולמטה . . . .ממש עבודה ידנית מעצבנת . . . (יונתן) וזו בעיה גם לפעמים בקוד של ה-Server, נכון? כשאתה מאתחל איזשהו Bin, או איזשהו אובייקט, ורק למטה למטה אתה צריך להעביר אותו . . .(אסף) נכון, Dependency Injection כזה . . .(יונתן) ואם אתה “מתפתה”, אז אתה שם איזשהו משתנה גלובאלי או Database או משהו כזה, ואז אתה . . (רן) זה כשאתה מתכנן להתפטר . . . וכשאתה מתפטר אז אתה לא מגלה . . .(יונתן) אז מה האלטרטיבה ל-Props Drilling הזה? . . . (אסף) אז רק אני אגיד שבנוסף להעברה הזאת, זה גם עניין של Performance, זה בעייתי - כי איך ש-React עובד, ברגע ש-Props משתנה, הוא קורא ל-Render מחדש . . .הוא קורא ל-Render כש-Props משתנה וכ-State משתנה.וכשכל תת-העץ הזה, שבכלל לא משתמש ב-State - כל מה שהוא עושה זה להעביר את זה מפה לשם כשמתרדנר (Renders) - זה פשוט בזבוז של חישוביות . . .אבל באמת כדי לפתור את זה יש איזשהו API שנקרא Context - ו-Context מאפשר להגדיר איזשהו State . . .(רן) הנה המשתנה הגלובאלי שחיפשת, יונתן . . . (אסף) בדיוק . . . אז זה משתנה גלובאלי, שבעצם פותר את העניין של ה-Drilling, כי אני יכול להגדיר את זה ב”אב הקדמון” המשותף הזה, אני יכול להגדיר שם את ה-Context, וזה אומר שכל חלק בתת-עץ, שהוא צאצא של האב הקדמון המשותף הזה, יכול להשתמש ב-Value של ה-Context.וזה מאפשר לי לפתור את ה-Props Drilling - וגם עם זה יש קצת בעיות . . . אחת - גם פה יש קצת עניין של Performance, כי אם אני, נגיד . . . לרוב, מה שעושים זה שעושים Provider כזה, ובתוך ה-Provider הזה זו קומפוננטת React רגילה - שהיא בעצמה משתמשת ב-useState שדיברנו עליואז כדי לעדכן את ה-Value, אני מעדכן את ה-Value איפה שאני שם את ה-Provider, והוא ירדנדר (Render) את כל תת העץ.הוא עדיין ירנדר אותו - כי ככה זה עובד: כי ברגע שהתרנדר אב-קדמון, הוא מרנדר את כל התת-עץ.אפשר לפתור את זה בדרכים שונות, כמו נגיד עם React.memo שהופך קומפוננטות, שמשווה באופן Shallow את ה-Properties, ומרנדר את זה רק אם הם שווים - אבל זה מעצבן, כי אני עכשיו חייב לעשות את זה, גם יש בזה Overhead . . . יכול להיות שזה לא כזה מעניין, ברוב המקרים, תכל'ס, זה לא מעניין - כי זה לא שווה את ההתעסקות, כי זה לא משנה באמת את חוויית המשתמש, האופטימיזציות האלה.אבל כשיש אפליקציות ענקיות, ש-Rendering הוא מאוד יקר, והדברים האלה מתחילים להציק - אז זה מתחיל להיות בעיה, ואז מתחילים לחשוב מה לעשות.(רן) אבל זה כן משנה את חוויית המפתח, זאת אומרת - או שתצטרך לעשות Props Drilling, או שתצטרך להשתמש ב-Context, שזה - בוא, בינינו - זה משתנה גלובאלי, עם כל המעמסה שבאה עליו.אז כן - למפתח זה אומר איזשהו נטל תחזוקתי(אסף) כן, לגמרי . . . (רן) אז זו הבעיה . . . הבנו - האקדח מהמערכה הראשונה . . . . בסדר.אז Recoil היא זו שתיקנה את הבעיה הזו?(אסף) Recoil תיקנה חלק מהבעיות האלה, כן . . . ב-Recoil, זה התחיל מהרצאה שהייתה ב-ReactEurope, שזו אותו כנס ש-Dan Abramov עשה בו את ההרצאה המפורסמת על Reduxאז זה בחור מ-Facebook, שסיפר שיש להם כלי ב-Facebook, שהם עושים כל מיני סטטיסטיקות על user-ים.הוא סיפר שם על כל מיני דרישות שהיו להם מהמוצר הזה - והוא רצה להשתמש ב-State וב-Context אבל נתקל בכל מיני בעיות - אחת מהבעיות הייתה . . . עוד בעיה שלא הזכרנו בנוגע ל-Context זה שאם אנחנו רוצים שה-User ייצור באופן דינאמי State - בוא נדמיין לדוגמא שזו הדוגמא שהוא מביא - אז לדוגמא, יש לי אפליקציה שאני יכול לצייר בה צורות - אני יכול לצייר בה עיגול, אני יכול לצייר בה מרובע, וה-User יכול פשוט להכניס עוד צורההוא יכול גם לעשות לזה Drag, או לשנות לזה את ה-Size . . . אפשר לדמיין מעיין Photoshop כזה . . . עכשיו - לכל אחד כזה הוא רצה ליצור State משלו - והסיבה שהוא לא רצה את זה ב-State משותף זה בשביל Performance, דיברנו על זהכי אם יש State משותף אז זה ירדנדר את כולם, וכשאתה מתחיל לעשות דברים כמו Dragging, וזה קורה 60 פעמים בשנייה, אז זה כבר מתחיל לכאוב . . . אתה כבר לא יכול, אתה צריך להתחיל לשחק פה עם Performance Optimizations.אבל הוא אמר “אולי נשתמש ב-Context, ועדיין העניין ב-Context הוא שזה סטאטי, ואתה חייב לדעת מראש כמה Context-ים את צריך ליצור . . . אתה לא יכול ליצור Context באופן דינאמי מתוך קוד.וזו בעיה ל-Use Case שכזה . . . זו אחת הבעיות . . . וכמובן יש את כל הבעיות שדיברנו עליהן מקודם.אז מה שהם עשו ב-Recoil . . . הם עשו כמה דברים מאוד מעניינים - אחד - בניגוד לספריות אחרות, ברוב הספריות - זו ספרייה שהיא מאוד Coupled עם React - אתה לא יכול להשתמש ב-Recoil ללא Reactבניגוד, נגיד ל-Redux או ל-MobXויש לזה כמה יתרונות נחמדים, כי ה-API של זה מאוד מאוד פשוט, והוא מאוד דומה ל-API של React, אז במקום useState, אתה תשתמש ב-useRecoilState, וזה יחזיר לך את אותו הדבר - יחזיר לך State ו-setState - וזה מאוד Familiar למי שמכיר את React, אתה לא צריך ללמוד הרבה, בניגוד ל-Redux וגם ל-MobX, שצריך ללמוד דברים.והקונספטים מאוד פשוטים - יש בעצם את ה-State הכי פשוט, שנתנו לזה שם די טוב - קוראים לזה- Atom, כי זה משהו אטומי . . . ובו אתה מגדיר State.עכשיו, אתה מגדיר את זה באופן נפרד, במודול אחר, שהוא לא יושב בתוך הקומפוננטה שלך, ולכן אתה יכול לשתף אותו עם קומפוננטות אחרותפשוט עושים לו Import . . . אתה לא צריך לעשות איזשהו Provider שיושב בעץ-למעלה.כל אחד מהם יכול לעשות לזה Import בנפרד, מבלי שיש את התלות הזאת בעץ.(רן) אוקיי . . . אבל זה דווקא . . . זה לא משהו שיכול לקרות ב-Run-time - ה-Import קורה בזמן הפיתוח, נכון? אתה לא יכול להחליט Ad-hoc ש . . . אתה יודע, בזמן ריצה, לעשות Import למשהו, נכון? זה קצת מזכיר את הבעיה שהייתה עם ה-Context . . . (אסף) נכון - בגלל זה יש משהו אחר שקיים ב-Recoil ונקרא atomFamily - זו “משפחה של אטומים” . . .אתה מגדיר atomFamily, והוא מייצר לך Atom-ים באופן דינאמי . . . אתה נותן לו ID, והוא יביא לך את ה-Atom המתאים ל-ID, וככה אתה יכול, ב-Run-time, בלי לדעת מראש, אתה יכול ליצור עוד ועוד Atom-ים ולשתף אותם.(רן) אז למעשה, הוא נותן ל-JavaScript לפתור את הבעיה . . . הוא אומר “תעשה Import, אני לא רוצה לנהל לך את המצב” - תעשה Import, ואם יש לך State משותף, תעשה לו Import משני קבצים שונים או משני רכיבים שונים - ובכלל שעשית Import לאותו רכיב, אז ה-State ישמר . . . זה הקונספט.אוקיי, JavaScript . . . אני שואל את עצמי האם יש פה סכנה ל-Race Conditions למיניהם . . . אם שני אובייקטים מחזיקים . . . טוב, זה כנראה לא קורה ב-JavaScript כי זה רץ בסביבה נפרדת, אז יש לנו פה Event Loop וזה לא יכול לקרות.(אסף) כן . . . גם בנוסף, בדומה ל-Redux, האובייקטים האלה הם Immutable - הם לא יכולים להשתנות לעולם, מרגע שהם נוצרו.(רן) אז איך אתה מעדכן State, אם זה Immutable?(אסף) אתה יוצר חדש . . . בכל פעם שאתה מעדכן State אתה לא משנה אותו - אתה יוצר אובייקט חדש, למעשה.(יונתן) תזכור ש-State is Evil . . . אז . . .(רן) כן, אבל דיברנו על . . . . אז בוא רגע נחזור לדוגמא שבה יש לנו רשימת To-Dos . . . יש לנו בחלק המרכזי של הדף את הרשימה המלאה עם ה-Check-box-ים לידה, ולמעלה מצד ימין אני רוצה להחזיק רק את מספר האייטמים שעדיין לא סיימתי, אוקיי? אז אני כן רוצה לעדכן פה איזשהו State, נכון? אני רוצה שלשניהם יהיה single source of truth - אבל אתה אומר שזה Immutable, אז מה אני עושה? איך אני מעדכן?(אסף) מעולה, אז בוא נלך על הדוגמא שאמרת - אם אנחנו משתמשים בפתרון שהוא mutable, כמו נגיד -Redux או Recoil, אז יש פה שני דברים - א - יש פה את ה-Counter הזה, של כמה אובייקטים הם Completed - זה מה שנקרא Derived Data: זה Data שאמרנו שאנחנו לא רוצים להחזיק אותו פעמיים, אז אנחנו רוצים לחשב אותו, אנחנו רוצים לחשב אותו מתוך ה-Data האמיתי, שזה ה-Array הזה של ה-To-Do List.גם פה יש עניין של “אנחנו לא רוצים לחשב את זה יותר מדי פעמים, אנחנו רוצים לחשב את זה רק כשדברים ישתנו”, כי זה יקר לחשב דברים, אבל אם נחזור לשאלה הזו, רגע, של “איך אנחנו מעדכנים את זה?”, אז בעצם כדי לעדכן את . . . כדי להוסיף To-Do חדש, אני צריך להוסיף Array חדש, כי אחרת ה-State לא השתנה . . . עכשיו, למה זה חשוב ב-Redux? כי ב-Redux, הוא משתמש בעניין הזה של mutability בשביל ליצור Reactiveness . . . דיברנו על Reactiveness, שזה מתי . . . איך אני יודע שכשה-State משתנה, אני צריך להודיע על הקומפוננטות שמשתמשות בו.אז -Redux משתמש ב-mutability כדי לעשות Shallow comparison - הוא לוקח את ה-Reference של האובייקט, ומשווה את זה - כי זו השוואה מאוד מאוד זולה, זה להשוות שני מספרים - הוא לא צריך לעשות Deep Comparison, ולעבור אובייקט-אובייקט ולראות שזה בדיוק אותו Value, הוא רק משווה את ה-Reference.ולכן, אם אתה עושה את זה Immutable, זה מאוד פשוט ליצור את ה-Reactiveness הזה.כשאתה רוצה לשנות את ה-State, אתה צריך ליצור אובייקט חדש.עכשיו, הדבר הזה הוא נושא ב-Redux, שהוא קצת שנוי במחלוקת . . .כי שוב, דיברנו על Boilerplate - בכל פעם ליצור אובייקט חדש זה יכול להיות מאוד מעצבן, וזה גם יכול ליצור באגים, כי יכול להיות שבטעות שינית את ה-State, כי JavaScript היא שפה שהיא Stateful, אתה יכול לשנות State, הוא נותן לך את זה ואתה יכול לעשות את זה בטעות - ואז זה ייצור באגים, כי בטעות עדכנת את ה-State במקום לעשות State חדש . . . ואז ה-Comparison לא יעבוד, ואז תקבל View שהוא לא Fresh, הוא Stale, וזה לא יעבוד לך ואתה לא תבין למה, ואז אתה תחפש בקוד ועד שתמצא את זה . . . זה נורא מעצבן.(יונתן) זאת אומרת שהייתי יכול לקחת את המערך של ה-To-Dos, ולהוסיף עוד איבר ברשימה - וזה לא היה מרנדר את הקומפוננטות כי React לא היה מודע לזה . . .(אסף) בדיוק, לא היית רואה את זה - והיית שובר את הראש “למה זה קרה לי?”.(רן) דרך אגב, בניגוד למה שאמרת קודם על MobX, שבו אם היית משנה משהו, אז בסופו של דבר כן ה-UI היה עושה לזה רפלקציה (Reflection).(אסף) נכון - ב-MobX, הוא משתמש ב-mutability, והוא בעצם משתמש בהתנהגות הזאת כדי ליצור את ה-Reactiveness.(רן) וב-Redux או ב-Recoil זה למעשה Anti-Pattern - אם אתה מפתח שעובר מ-MobX לאחד מאלה, הולכים להיות לך כמה חודשים קשים בהתחלה . . . (אסף) נכון . . . אבל יש חדשות טובות! אותו בחור שעשה את MobX ואת MobX-State-Tree - הוא עשה גם ספרייה שנקראית Immer, שהיום היא באה בתוך Redux -בגלל ש-Redux . . . אחת מהביקורות הכי גדולות זה כל ה-Boilerplate וכל העבודה שצריך לעשות, Redux עבדו קשה בשביל להוסיף לתוך הספרייה כל מיני כלי-עזר שיעזרו לך עם זה.אחד מהם זה Immer - שמשתמש באותו “קסם” שמשתמשים ב-MobXזה גם אותו בנאדם שהשתמש בקסם הזה ב-MobX . . . כדי לעשות Immutable state - אבל בצורה שנוח יותר לאנשים לעשות את בצורה של mutable . . . מה זה אומר? זה אומר שאתה יכול להשתמש ב-API המוכר של JavaScript, של לעשות State.משהו.משהו = . . . לשנות את האובייקט הקייםבדוגמא שנתנו מקודם - להוסיף איבר למערךאבל מאחורי הקלעים, באמצעות אותם קסמים שדורסים את ההתנהגות של האובייקט, הוא ייצור לך אובייקט חדש, עם רפרנס חדש, וה-Shallow Reference Comparison יעבוד והכל יהיה כיף!אתה לא צריך ליצור Spread . . . מה שקורה הרבה פעמים זה שאתה יוצר Spread-Operator כדי לעשות Spread לאובייקט הקודם מתוך אובייקט חדש - וזה גם, פעם לא היה את זה, זה חדש, קיים רק כמה שנים, פעם היה צריך לעבוד עוד יותר קשה . . . אז זה עושה API ממש ממש כייפיהיום, Redux זו חווייה הרבה יותר כייפית ממה שהיה כשאני השתמשתי בזה . . . כשהתכוננתי לפודקאסט, ראיתי שהם עשו שם המון המון עבודה כדי לטפל בבעיות האלה.(רן) אני כבר מצליח לדמיין את הפרסומות - “להרגיש Stateful ולהיות Stateless!”, אבל טוב . . . [יש מצב . . . פרסומות הרבה פחות מוצלחות מזה כבר רצות היום על איילון]מעולה, מגניב - אז בוא נעשה רגע סיכום: בגדול, דיברנו על מה זה State Management, ולמה בכלל צריך את זה בצד של ה-Clientדיברנו על זה שלוגיקה עברה לצד של ה-Client, ולכן זה . . . הדברים מתחילים להיות מסובכים וצריך איזושהי דרך, ככה “לסדר את הקוד”, זה לא יכול להיות הכל ספגטי - jQuery Spaghetti, למי שיצא התענוג . . .אז קשה מאוד לנהל קוד כזה, ולכן נולדו ספריות של State Managementדיברנו קצת על React, דיברנו על MobX, שיש להן גישות שונות ובסופו של דבר על Recoilאז תודה רבה! כמה מילות סיכום?(אסף) היה לי ממש כיף, אפשר להמשיך לדבר על הנושא הזה עוד המון-המון-המון - זה נושא מאוד Debatable . . . יש המון פתרונות, כל הזמן קמות ספריות חדשות, זהו . . . תודה רבה!תודה לך אסף, ושהיה בהצלחה ב-livecycle. להתראות! האזנה נעימה ותודה רבה לעופר פורר על התמלול!
In this episode Shaun and I talk shop about random tech we use! This one is more focused on react but there a lot of good nuggets in here. --- Send in a voice message: https://anchor.fm/devtheory/message
This week, Jon ramps up his brewing plans with a logo contest, Spencer's girlfriend comes through and lands an XBox and hopefully is overcoming his motion sickness.In the React arena we discuss state management and if you've never used anything more than component state we got you covered. You'll learn when to up your state game and possibly which type of state management solution will work for you and your app.If you've gotten into Redux or MobX, this is still interesting because we discuss the differences between multiple solutions and you may hear something that may make you switch!0:00 - Introduction0:05 - Jon's update / Brewery news8:13 - Spencer's update12:58 - State Management in 202114:08 - What is State20:32 - Context24:24 - Redux / Redux Toolkit33:23 - MobX / MobX State Tree40:23 - Recoil43:38 - Apollo45:14 - ReactQuery49:38 - Zustand54:10 - When to use 'em56:58 - Migrating from one to another58:31 - Wrap Up Links:Jon’s logo contest at LogoMyWayhttps://www.logomyway.com/28555/friends/5dc00bc4e5https://kentcdodds.com/blog/application-state-management-with-reactZustandhttps://github.com/pmndrs/zustandMobX vs Reduxhttps://www.youtube.com/watch?v=UeRUT5H6XPII’m never using Recoil.jshttps://www.youtube.com/watch?v=XEYiYpASG2ASpencer's Shameless PlugsReact Native Fundamentals Workshophttps://youtu.be/rLmdmLhfwvQReact Native Schoolhttps://reactnativeschool.com Jon's Shameless PlugsFastLane Cheat Codes (Sign Up Now)https://fastlanecheatcodes.com
State management is hard. Why? First, some engineers may not consider the state of their apps. This can lead to apps that are buggy, difficult to test, and often face regressions when attempting to fix issues. Second, if you're managing control flow and state in your application, state in some applications can be complex and fast-moving. Determining what solution to use, whether to build your own solution or to grab an existing off-the-shelf solution can be a difficult decision. Third, state management libraries can be difficult to learn. Entire courses are devoted to managing state in Angular applications, whether you choose NgRx, NGXS, Akita, MobX, Redux-Observables, etc.We get that. Why? We've seen a thing or two. In this episode, panelists Jennifer Wadella, Aaron Frost, & Brian Love share some of their own struggles with state management, decisions that went awry, and some horror stories that they've lived through. Then, Brian sits down with Mike Ryan, core team member for NgRx, and Google Developer Expert in Angular. Mike shares with us some stories and some key takeaways for managing state, control flow, and code volume in your Angular application using NgRx.And that's a wrap! We hope you've enjoyed our 6-part series on State Management in Angular. What topics interest you that you'd like us to dive into on the Angular Show? Let us know! Follow us on Twitter, our DMs are open, and don't forget to subscribe!
While NgRx is the most widely used and adopted platform for state management in Angular, there are several other solutions that are available to Angular developers. In this episode, panelists Aaron Frost, Brian Love, and Jennifer Wadella are 'buzzing' with details on MobX, Akita, and NGXS. All three of these solutions can be used in Angular, are open-source, and are free to use. MobX is widely used with React, perhaps the second favorite after redux, for state management. Akita, from the team at Datarama, takes a slightly different approach from the redux pattern for providing a state management solution. Akita is popular within the Angular community, but can also be used with both React and Svelte projections. Finally, NGXS is inspired by redux and NgRx and makes heavy use of TypeScript decorators to achieve similar goals as NgRx with a potential lower code cost.Join us in part 5 of our series on state management in Angular and come along with the panelists and learn about various solutions that you might want to consider for your Angular application.
In episode 3, host Brandon Aaskov talks with Rocket Insights Software Developers Dave Oelfke and Ian Pirro about State Management on the UI. They go deep on Redux, alternatives to Redux, and where these tools should and should not be used. As always, we end with our picks (totally unrelated to State Management) for you to follow up on! Topics: 0:00 - Intros and a brief history of Redux. Opinions abound! Scott O'Brien - The Rocket Insights dev who (used to) troll Dan Abramov (creator of Redux) on Twitter 2:30 - What is Redux? 3:30 - GraphQL and Apollo as an alternative (or compliment) to Redux. 5:00 - When does using Redux make sense? 8:45 - Redux vs. MobX. 14:15 - Angular 1.3 two way binding, oh no! 16:45 - When should you reach for Redux? When are your components too complicated? 17:30 - Should you use React's Context instead? 18:03 - Will React Hooks do away with Redux? Note: This episode was recorded when Hooks weren't yet available for GA release. 25:14 - Back to Apollo - Subscriptions. 26:45 - Hot takes! Don't use Redux. Use Mobx, or Vue and VueX instead. 31:30 - Hot takes! Mutability is ok. 34:45 - I just want to use things that work, not the newest fanciest thing. 37:15 - Redux on the server!? 39:45 - You can write your app in jQuery and Redux (!?) 40:45 - Picks! Brandon - The Night Of on HBO. Dave - Subscribe to Pewdiepie on Youtube! Ian - WeWantPlates subreddit.
In this episode, Charles and Taras discuss "transparent development" and why it's not only beneficial to development teams, but to their clients as well. 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, the place where we talk about user interfaces and everything that you need to know to build them right. It's been a long summer and we're back. I'm actually back living in Austin, Texas again. I think there wasn't too much margin in terms of time to record anything or do much else besides kind of hang on for survival. We've been really, really busy over the last couple of months, especially on the professional side. Frontside has been doing some pretty extraordinary things, some pretty interesting things. So, we've got a lot to chew on, a lot to talk about. TARAS: There's so much stuff to talk about and it's hard to know where to start. CHARLES: So, we'll be a little bit rambly, a little bit focused. We'll call it fambly. But I think one of the key points that is crystallized in our minds, I would say over this summer, is something that binds the way that we work together. Every once in a while, you do some work, you do some work, you do some work, and then all of a sudden you realize that a theme, there's something thematic to that work and it bubbles up to the surface and you kind of organically perceive an abstraction over the way that you work. I think we've hit that. I hit one of those points at least because one of the things that's very important for us is -- and if you know us, this is things that we talk about, things that we work on -- we will go into a project and set up the deployment on the very first day. Make sure that there is an entire pipeline, making sure that there is a test suite, making sure that there are preview applications. And this is kind of the mode that we've been working in, I mean, for years and years and years. And where you say like if what it takes is spending the first month of a project setting up your entire delivery and showcasing pipeline then that's the most important work, inverting the order and saying that has to really come before any code can come before it. And I don't know that we've ever had like a kind of unifying theme for all of those practices. I mean, we've talked about it in terms of saving money, in terms of ensuring quality, in terms of making sure that something is good for five or 10 years, like this is the way to do it. And I think those are definitely the outcomes that we're looking for. But I think we've kind of identified what the actual mode is for all of that. Is that fair to say? TARAS: Yeah, I think one of the things I've always thought about for a long time is the context within which decisions are made because it's not always easy. And it's sometimes really difficult to really give it a name, like getting to a point where you have really clear understanding of what is it that is guiding all of your actions. What is it that's making you do things? Like why do we put a month of work before we even start doing any work? Why do we put this in our contract? Why do we have a conversation with every client and say, "Look, before we start doing anything, we're going to put CI in place." Why are we blocking our business on doing this piece? It's actually kind of crazy that from a business perspective, it's a little bit crazy that you be like, "Oh, so you're willing to lose a client because the client doesn't want you to set up a CI process?" Or in a case of many clients, it's like you're not willing to accept -- the client is going to say, "We want to use Jenkins." And what we've done in the past, in almost every engagement, we're like, "Actually, no. We're not going to use Jenkins because we know that it's going to take so long for you to put Jenkins in place. By the time that we finish the project, you're probably still not going to have it in place. That means that we're not going to be able to rely on our CI process and we're not going to be able to rely on testing until you're finished." We're not going to have any of those things while we're doing development. But why are we doing all this stuff? It was actually not really apparent until very recently because they didn't really had a name to describe what is it about this tooling and all of these things that makes why is it so important to us. I think that's what kind of crystallized. And the way that I know that it's crystallized because now that we're talking to our clients about it, our clients are taking on to picking up the language. We don't have to convince people that this is a value. It just comes out of their mouth. Like it actually comes out of their mouth as a solution to completely unrelated problems, but they recognize how this particular thing is actually a solution in that particular circumstance as well even though it's not something Frontside sold in that particular situation. Do you want to announce what it actually is? CHARLES: Sure. Drum roll please [makes drum roll sound]. Not to get too hokey, but it's something that we're calling Transparent Development. What it means is having radical transparency throughout the entire development process, from the planning to the design, to the actual coding and to the releases. Everything about your process. The measure by which you can evaluate it is how transparent is this process to not just developers but other stakeholders, designers or people who are very developer adjacent, engineering managers all the way up to C level executives. How transparent is your development? And one of the ways that we sell this, because I think as we talk about how we arrived at this concept, we can see how this practice actually is a mode of thinking that guides you towards each one of these individual practice. It guides you towards continuous integration. It guides you towards testing. It guides you towards the continuous deployment. It guides you towards the continuous release in preview. I think the most important thing is that it's guided us, by capturing this concept, it's guided us to adopt new practices, which we did not have before. That's where the proof is in the pudding is if you can take an idea and it shows you things that you hadn't previously thought before. I think there's a fantastic example. I actually saw it at Clojure/conj in 2016, there was a talk on juggling. And one of the things that they talked about was up until I think it was the early 80's or maybe it was the early 60's, the state of juggling was you knew a bunch of tricks and you practice the tricks and you get these hard tricks. And that was what juggling was, is you practice these things. It was very satisfying and it had been like that for several millennia. But these guys in the Physics department were juggling enthusiasts and I don't know how the conversation came about, you'd have to watch the talk. It's really a great talk. But what they do is they make a writing system, a nomenclature system for systematizing juggling tricks, so they can describe any juggling trick with this abstract notation. And the surprising outcome, or not so surprising outcome, is that by then, once you have it in the notation, you can manipulate the notation to reveal new tricks that nobody had thought of before. But you're like, "Ah, by capturing the timing and the height and the hand and we can actually understand the fundamental concept, and so now we can recombine it in ways that weren't seen before." That actually opened up, I think an order of magnitude of new tricks that people just had not conceived of before because they did not know that they existed. And so, I think that's really, as an abstract concept, is a great yardstick by which to measure any idea. Yes, this idea very neatly explains the phenomenon with which I'm already familiar, but does the idea guide me towards things with which I have no concept of their existence? But because the idea predicts their existence, I know it must be there and I know where to look for it. And aha, there it is. It's like shining a light. And so I think that that's kind of the proof in the pudding. So that's a little bit of a tangent, but I think that's why we're so excited about this. And I think it's why we think it's a good idea. TARAS: Yes. So what's also been interesting for me is how universal it is. Because the question of is this transparent enough? That question could be actually asked in many cases. What's been interesting for me is that asking that question in different contexts that I didn't expect actually yielded better outcome. At the end of the day, I think that a test for any idea is like, is it something that can help you more frequently than not? Like is it actually leading you? Does applying this pattern, does it increase the chances of success? And that's one of the things that we've seen, thinking about just practices that we're putting into place and quite asking are they transparent enough? Is this transparent enough? It's actually been really effective. Do you want to talk about some of the things that we've put in place in regards to transparency? Like what it actually looks like? CHARLES: Yeah. I think this originally started when we were setting up a CI pipeline for a native application which is not something that we've typically done in the past. Over the last, I would say, 10 years, most of our work has been on the web. And so, when we're asked to essentially take responsibility for how a native application is going to be delivered, one of the first things that we asked kind of out of habit and out of just the way that we operate is how are we going to deliver this? How are we going to test it? How are we going to integrate it? All the things that we've just talked about is something that we have to do naturally. But because this is not very -- like continuous integration and build is very prevalent on the web. I think that testing still has a lot of progress on the web, but it's far more prevalent than it is in other communities, certainly the native community. So when we started spending a month setting up continuous integration an integration test suite, spending time working on simulators so that we could simulate Bluetooth, having an automated process with which we could ship to the App Store, all of these things kind of existed as one-offs in the native development community. There are a lot of native developers who do these things. But because it's not as prevalent and because it was new to us, it caused a lot of self reflection both on why is it that we feel compelled to do this. And also we had to express this, we had to really justify this work to existing native development teams and existing stakeholders who were responsible for the outcomes of these native development teams. So, there was this period of self reflection, like we had to write down and be transparent about why we were doing this. TARAS: Yeah. We had to describe that in SoWs. We actually had really long write ups about like what it is that we're setting up. And for a while, it was, people I think would read these SoWs and I think they would get the what's of what we're actually going to be putting into place. But it wasn't until we actually put it into place and we've seen a few like really big wins with the setup -- one of the first ones was the setting up preview apps where preview apps in -- the web are pretty straightforward because we've got Netlify that just kind of gives it to you easily. CHARLES: Netlify and Heroku. It's very common. TARAS: Yeah, you activate it, it's there. But on the mobile side, it's quite a different story because you can't just spin up a mobile device that is available through the web. It's something kind of very special. And so we did find a service called Appetize that does this. And so we hooked up the CI pipeline to show preview apps in pull requests. So for every pull request, you could see specifically what was introduced in our pull request without having to pull down source code, like compile it. You could just click a link and you see a MVC stream of a mobile device and that application running on a mobile device. So the setup took a little bit of time. But once we actually put it in place and we showed it to our clients, one of the things that we noticed is that it became a topic of conversation. Like, "Oh, preview apps are amazing." "This is so cool." "Preview apps are really great." And I think in some ways, it actually surprised us because we knew that they were great, but I think it was one of the first times that we encountered a situation where we would show something to a client and they just loved it. And it wasn't an app feature. It was a CI feature. It was part of a development process. CHARLES: Right. So, the question is then why was this so revelatory? Why was it so inspiring to them? And I think that the reason is that even if we have an agile process and we're on two week iterations, one week iterations, whatever, there's still a macroscopic waterfall process going on because essentially, your business people, your design people, maybe some of your engineering people are involved at the very front of the conversation. And there's a lot of talking and everybody's on the same page. And then we start introducing coding cycles. And like I said, even if we're working on two week iterations and we're "agile", the only feedback that you actually have, whether something is working, is if the coder says it's done. "I'm Done with this feature. I'm on to the next feature for the next two weeks." And after that two weeks, it's like, "I'm done with this feature. I'm on to the next feature." From the initial design, you have the expectation about what's going on in the non-technical stakeholders minds. They have this expectation. And then they hope that through the process of this agile iterative development cycles, they will get the outcome that satisfies that hope. But they're not able to actually perceive and put their hands on it. It's only the engineers and maybe some really tech savvy engineering managers who can actually perceive it. And so they're getting information secondhand. "Hey, We've got authentication working and we can see this screen and that screen." And, "Hey, it works on iOS now." "I have some fix ups that I need to do on Android." So, maybe they're consuming all of their information through standups or something like that, which is better than nothing. That is a level of transparency. But the problem is then you get to actually releasing the app or whether it's on the web, whether it's on native, but this is really a problem on native. You get to where you actually release the app and then everybody gets to perceive the way the app as it actually is. So you have this expectation and this hope that was set maybe months prior and it just comes absolutely careening into reality in an instant, the very first moment that you open the app when it's been released. And if it doesn't meet that expectation, that's when you get disappointment. When expectations are out of sync and grossly out of sync with reality, even a little bit out of sync with reality, you get disappointment. As fundamental and explanation of just the phenomenon of disappointment, but it's an explanation of why disappointment happens so often on development projects. Is this kind of the expectations and hopes of what a system can be in the minds of the stakeholders? It's kind of this probability cloud that collapses to a single point in an instant. TARAS: And that's when things really hit the proverbial fan. Now, you have the opposite. So everything that was not transparent about your development process. So everything that was hidden in the opaqueness of your development process, all of those problems, either on a product side, maybe something didn't quite get implemented the way it's supposed to. Like you actually found out two weeks or three weeks before you're supposed to release that that feature wasn't actually quite implemented right. It went through testing, but it was tested against the Jira stories that were maybe not quite written correctly. So the product people are going like, "What the hell is this? It's actually not what I signed up for. This is not what I was asking for." So, there's that part. And then on the development side, you've got all of the little problems that you didn't really account for because you haven't been shipping to production from day one. You actually have like application not really quite working right. You didn't account as supposed to integrate with some system that is using Chorus or something you didn't account for. Like you have a third party dependency you didn't really fully understand. But because it wasn't until you actually turned it on that you actually started to talk to the thing properly, and you realize there's some mismatch that is not quite working. But now you've got everything that was not transparent about the development process, everything that was hiding in the opaque corners of your development process is now your problem for the next three weeks because you've got to fix all of these problems before you release. And that's what I think where a lot of organizations kind of find themselves in is this position where they've been operating for six months and like, "Everything is going great!" And then three months or three weeks before, you're like, "Actually, this is not really what we were supposed to do. Why did this happen?" That time is really tough. CHARLES: Yeah. That's what we call crunch time. And it's actually something that is lot of times we think of it as inevitable, but in fact it is actually an artifact of an opaque process. TARAS: Yeah. CHARLES: That's the time when we have to go, everybody's like, "We're ordering pizza and Dr. Pepper and nobody's leaving for a month." TARAS: Yeah. I think there are people that do that practice like functional testing as part of development process or acceptance testing, I think they could relate to this in some cases where if you had to set up a test suite on an application that was written without a test suite, first thing you deal with are all the problems that you didn't even know were there. And it's not until you actually start testing, like doing functional testing, not integration or unit testing where you're testing everything in isolation, but when you're perceiving the entire system as one big system and you're testing each one of those things as the user would, it's not until that point you start to notice all the weird problems that you have. Like your views are re-rendering more than you expected. You have things that are being rendered you didn't even notice because it's hard to see, because it happens so quickly. But in test, it happens at a different pace. And so, there's all these problems that you start to observe the moment that you start doing acceptance testing, but you don't see them otherwise. And so, it's the process of making something transparent that actually highlights all these problems. But for the most part, if you don't know that there are transparent options available, you actually never realize that you are having these problems until you are in crunch time. CHARLES: Right. And what's interesting is viewed through that lens, your test suite is a tool for perception. And to provide that transparency, not necessarily something that ensures quality, but ensuring the quality is a side effect of being able to perceive bugs as they happen or perceive integration issues at the soonest possible juncture. To shine the light, so to speak, rather than to act as a filter. It's a subtle distinction, but I think it's an important one. TARAS: About functional testing and acceptance testing. I think one of the things that I know personally from experience working with comprehensive acceptance test suites is that there is certainty that you get by expressing the behavior of the application in your tests. And I think what that certainty does is it replaces hope as opposed to having hope baked into your system where you think like you're hoping. I think for many people, they don't even perceive it as hope. They perceive it as reality. They see it as, "My application works this way." But really what's happening is there's a lot of trust that's built into that where you have to say like, "Yeah, I believe the system should work because I wrote it and I'm good. And it should not be broken." But unless you have a mechanism that actually verifies this and actually insures this is the case, you are operating in the area of dreams and hopes and wishes, and not necessarily reality. And I think that's one of the things that's different. A lot of the processes around highlighting or shining light on the opaque areas of the development process. And it's actually not even just development process. It's actually the business process of running a development organization. Shining light in those areas is then what gives you the opportunity to replace hope with real validatable truth about your circumstances. CHARLES: And making it so that anyone can answer that question and discover that truth and discover that reality for themselves. So, generating the artifacts, putting them out there, and then letting anybody be the primary perceiver of what that artifact means in the context of the business, not just developers. And so, that kind of really explains preview apps quite neatly, doesn't it? Here we've done some work. We are proposing a change. What are the artifacts that explain the ramifications of this change? So we run the test suite. That's one of the artifacts that explains and radiates the information so that people can be their own primary source. And look at it in a developer centric, although you can tell, any old person can tell if the test suite's failing, it's not a change that we should go with. But the preview app is something we take this hypothetical change, we build it, we put it out there and now, everyone can perceive it. And so, it calibrates the perception of reality and it eliminates hope. Which is like if your development process is based on hope, you are signing yourself up for disaster. I like what you said that it implies a huge amount of trust in the development team. And you know what? If you have a cracked development team, that trust is earned and people will continually invest based on that trust. But the fundamentals are still fragile because they still can open up a crack between the expectation and the reality. And the problem is when that happens, the trust is destroyed. And it's during that crunch time, if it does happen that you lose credibility and it's not because you became a worse developer. It's not because your team is like lower performing, it's just that there was this divergence allowed to open. But then the problem is that really lowers the trust and that means that unfortunately that's going to have a negative knock on effect. And reasonably so. Because if you're an engineering manager or a product manager, you're something like this and you're losing trust in your development team and their ability to deliver what you talked about, then you're going to want to micromanage them more. The natural inclination is to try and be very defensive and interventionist and you might actually introduce a set of practices that inhibit the development cycle even further and lower the team's abilities to perform right when they need to do it the most, then you end up destroying more trust. TARAS: Yeah, it's a spiraling effect I think because it's in the process of trying to make things better. And then you start to introduce practices. Like maybe you're going to have meetings every day reviewing outstanding stories to try to get everybody on the same page, but now you're micromanaging development team. The development team starts to resent that and now you've got this like people hating their job. It starts to get messier and dirtier and more complicated. And the root cause of that is that from day one, there was a lot of just [inaudible] about getting into it and just starting to write some code but what you didn't actually do is you didn't put in place the fundamentals of making sure that you can all observe a reality that is honest. And I think that kind of fundamental principle, it's interesting how when you actually start to kind of take this idea and when you start to think about it in different use cases, it actually tells you a lot about what's going on and you can actually use it to design new solutions. One of the things that Frontside does, I don't know if those who've kind of worked with us before might know this or might not, but we don't do blended rates anymore. Because we don't actually, one of the challenges with blended rates is that they hide the new ones that gives you the power to choose how to solve a problem. CHARLES: Yeah. There's a whole blog post that needs to be written on why blended rates are absolute poison for a consultancy. But this is the principle of why. TARAS: Yeah. I think it's poison for transparent consultancy because if you want to get the benefits of transparency, you have to be transparent about your people. Because alternatively what happens is that you start off relying on your company's reputation and then there is a kind of inherent lie in the way that the price points are set up because everybody knows that there is going to be a few senior people, there's going to be a few intermediate people, a few junior people. But these exact ratios of those or who is doing what, how much people are available, all of those things are kind of hidden inside of the consulting company so that they can manage their resources internally. And so what that does is it simplifies your communication with the client. But actually what it also does is it disempowers you to have certain difficult conversations when you need the most. And you could say, "Look, for this kind of work, we don't need to have more senior people working on this." We can have someone who is junior who is at like $100 an hour, $75 an hour as opposed to being $200 or $250 an hour. We can have that person working on this and we can actually very clearly define how certain work gets solved. It requires more work. But then what it does is it creates a really strong bond of honesty and transparency between you and your clients. And it gives you a way, like now the client starts to think about you as a resource that allows them to fulfill on their obligations in a very actionable way. They can now think about how they can use you as a resource to solve their problems. They don't need a filter that will process that and try to make it work within the organization. You essentially kind of become one unit. And I think that sense of unity is the fundamental piece that keeps consulting companies and clients glued together. It's the sense of like, "We can rely on this team to give us exactly what we want when we need it, and sometimes give us what we need that we don't know we need." But that bond is there. And that bond is strong because there is no lie in that relationship. You're very transparent about who are the people that's working on it. What are they actually going to be doing? How much is this costing us? CHARLES: It's worth calling out explicitly whether on the flip side of it is, is if you have a blended rate, which is the way that Frontside operated for, gosh, pretty much forever, is that people will naturally calibrate towards your most senior people. If I'm going to be paying $200 an hour across the board, or $150 an hour across the board, or $300 across the board, whatever the price point is, they're going to want to extract the most value for that one price point. And so, it means that they're going to expect the most senior people and become resentful if what I'm paying is $300 for a task. If I've got five senior people, it's a better deal for me. For the same price to get five senior people than two senior people to a medium level people and one junior person. And so, it has two terrible effects. One is that they don't appreciate the senior people to be like, "Hey actually, these are people with extraordinary experience, extraordinary knowledge, extraordinary capability that will kick start your part." So they are under appreciated and then they're extremely resentful of the junior people. It's like, "I'm paying the same rate for this very senior person as I am for this junior person? Get this person off my project." But if you say, "You know what, we're going to charge a fifth of the cost for this junior person and we're going to utilize them," then you're providing real value and they're appreciating it. They're like, "Oh, thank you for saving me so much money. We've got this task that does not require your most senior person. That would be a misallocation of funds. I'd be wasting money on them. But if you can charge me less and give me this junior person and they're going to do just as competent a job, but it's going to cost me a fifth of the money, then that's great. Thank you." So, it flips the conversation from 'get this god-damn junior person off my project' to 'thank you so much for bringing this person on'. It's so critical. But that's what that transparency can provide. It can totally turn a feeling of resentment into gratitude. TARAS: What's interesting is from business perspective, you make the same amount of money. In some cases, you actually make more money. I think in that way, it's a consulting company. But that's not the important part because the amount of value that's generated from having more granular visibility into what's happening is so much greater. It's kind of like with testing where any of those things where when you start to put, when you start to shine light on these kind of opaque areas and then you start to kind of flush out the gremlins that are hiding there, what you then start to do, what you kind of discover is this opportunity to have relationships with clients that are honest. So you could say, for example, like one of the things that we've done recently is we actually have like 10-tier price point model, which allows us to to be really flexible about the kind of people that we introduce. So, there's a lot of details that go into the actual contracting negotiation. But what it does is it allows us to be very honest about the costs and work together with our clients, like actually really find a solution that's going to work really well for them. And then this is kind of a starting point when we start thinking about transparency in this kind of diverse way, you actually start to realize that there are additional benefits that you might have never been experienced before. One of the things that we found recently is that one of the initiatives that we kind of launched with one of our clients is we wanted to bring together, there's a general problem that exists in large projects, which is that if you have a really big company and you have like, let's say 20 or 30 interconnected services, your data domain, like the older data, kinds of data you work with is spread over a whole bunch of microservices spread over potentially a bunch of different development teams spread over a bunch of different locations. What usually has happened in the past is each one of those problems or the domain, the data domain has been kind of siloed into a specific application. We worked with a bank in the past and that being had for every, they had 80 countries. In each country they had 12 different industries, like insurance and mortgage and different kinds of areas of services they offered. And then for each of the country, for each of the service, they had a different application that provided that functionality. Then the next step is, let's not do that anymore because we now have something like 100, 150 apps, let's bring it all together under a single umbrella and let's create a single shared domain that we can then use. And so, a GraphQL becomes a great solution for that. But the problem is that making that change is crazy complicated because the people on the business side who understand how all the pieces fit together. On the other side, you have the developers who know where the data can come from and how to make all that real. And on the other side is there's like frontend implementers who actually build in the UIs that are consuming all these services. On a project that we're working on right now is we're building a federated GraphQL gateway layer that is kind of connecting all these things, bringing all these things together. But the problem is that without very specific tooling to enable that kind of coming together of the frontend, the backend, the business people having coming together, creating a single point of conversation and having a single point of reference for all the different data that we have to work with and different data that is available to the gateway, without having something like that, without having that transparency in the actual data model, it is really difficult to make progress because you don't have shared terminology, you don't have shared understanding of the scope of the problem. There's a lot of dots in context that needs to be connected. And for anyone who has worked with enterprise, you know how big these problems get. And so what we've done on a project that we're working on now is we actually aimed to bring transparency to this process. What we actually did is put in place, start to build an application that brings together all of the federated services into a visualization that different parties can be involved in. And so I think one of the kind of common patterns that we see with transparency in general is that we are including people in the process, in the development process that were previously not included. So in the past, they would be involved in the process either very early on or very late in the process, but they wouldn't be involved along the way. And so what this kind of transparency practice actually does is it allows us to kind of democratize and flatten the process of creating foundations for pieces that touch many different parts of the organization. And so this tool that we created allows everyone to be involved in the process of creating the data model that spans the entire organization and then have a single point of reference that everybody can go to and have a process for contributing to it. They don't have to be a developer. There's developers who consume it. There are business people that consume it. There are data modeling people that consume it. Like there's different people parties involved. But the end result is that everyone is on the same page about what it is that they're creating. And we're seeing the same kind of response as we saw with preview apps where people who previously didn't really have an opinion on development practices or how something gets built, all of a sudden they're participating in the conversation and actually making really valuable suggestions that developers couldn't really have exposure to previously because developers often don't have the context necessary to understand why something gets implemented in a particular way. CHARLES: Something beautiful to behold, really. And like I said, it's wonderful when a simple concept reveals things that had lay hidden before. TARAS: Yeah. It's a very interesting lens to look at things through. How transparent is this and how can we make it more transparent? I think asking that question and answering that question is what has been kind of giving us a lot of -- it had been very helpful in understanding our challenges in the work that we do on a daily basis and also in understanding how we could actually make it better. CHARLES: I apply this concept in action on my pull requests. I've really been focusing on trying to make sure that if you look at my pull request, before you actually look at the code, you can pretty much understand what I've done before you even look at the diff. The hallmark of a good pull request is basically if by reading the conversation, you understand what the implementation is going to be. There's not really any surprises there. It's actually hard to achieve that. Same thing with git history. Spending a lot of time trying to think like how can I provide the most transparent git history? That doesn't necessarily mean exactly the log of what happened moment to moment, day to day, but making sure that your history presents a clear story of how the application has evolved. And sometimes that involves a lot of rebasing and merging and branch management. I think another area that has been new for us, which this has revealed those things that I just described are areas where we're kind of re-evaluating already accepted principles against a new measure, but introducing an RFC process to actually a client project where we're making architectural decisions with our developers, the client's developers, external consultants. You've got a lot of different parties, all of whom need to be on the same page about the architectural decisions that you've made. Why are we doing this this way? Why are we doing modals this way? Why are we using this style system? Why are we using routing in this way? Why are we doing testing like this? These are decisions that are usually made in an ad hoc basis to satisfy an immediate need. It's like, "Hey, we need to do state management. Let's bring in Redux or let's bring in MobX or let's bring in whatever." And you want to hire experts to help you make that best ad hoc decision? Well, not really. I mean, you want to lean on their experience to make the best decision. But having a way of recording and saying this is the rationale for a decision that we are about to make to fulfill a need. And then having a record of that and putting it down in the book so that anybody who can come later. First of all, when the discussion is happening, everybody can understand the process that's going on in the development team's head. And then afterwards and it's particularly important is someone asks a question, "Why is this thing this way?" You can point directly to an RFC. And this is something that we picked up from the Ember community, but this is something that open source projects really by their very nature have to operate in a very highly transparent manner. And so, it's no surprise that that process came from the internet and an open source project. But it's been remarkably effective, I would say, in achieving consensus and making sure that people are satisfied with decisions, especially if they come on afterwards, after they've been made. TARAS: We actually have this particular benefit that could experience that particular benefit today where one of the other things that this RFC process and transparency with the architecture, how that kind of benefits the development organization is that a lot of times when you are knee deep in doing some implementation, that is not a time you want to be having architectural conversations. In the same way like in a big football team, they huddle up before they go on a field. You can't be talking strategy and architecture and plans while you're on the football field. You have to be ready to play. And this is one of the things that the RFC process does is it allows us to say, "Look, right now we have a process for managing architecture so that with the RFC process you can go review our accepted RFCs. You can make proposals there." And that is a different process than the process that we're involved in on a daily basis, which is writing application, using architecture where we have in place. And so that in itself can be really helpful because well intentioned people can bring up these conversations because they really are trying to solve a problem, but that might not be the best time. And so having that kind of process in place and being transparent about how architecture decisions are made allows everyone to participate and it also allows you to prioritize conversations. CHARLES: Yeah. And that wasn't a practice that we had adopted previous to this, but it's something that seemed obvious that we should be doing. It's like, how can we make our architecture more transparent? Well, let's do this practice. So, I keep harping on this. But I think it's the hallmark of a good idea if it leads you to new practices and new tools. And we're actually thinking about adopting the RFC process for all of our internal developments, for maintaining our open source libraries. TARAS: There is something that we've been working on that we're really excited about. So, there's a lot of stuff happening at Frontside. But one of the things that we've been doing is working on something we call the transparent node publishing process, which is something that I think we originally drew inspiration from the way NativeScript has their repo set up. But one thing that's really cool about how they have things set up is that every pull request automatically is available, like everything is available. Very quickly, a pull request is available for you to play with and you can actually put it into your application as a published version in npm and actually see exactly if that pull request is going to work for you. You don't have to jump through hoops. You don't have to clone the repo, build it locally, link it. You don't have to do any of that stuff because if you see a pull request that has something that you want but then is not available in master, there's an instruction on the pull request that tells you, "Here's how you can install this particular version from npm." And so you essentially you're publishing. Every pull request automatically gets published to npm and you can just download and install that specific version for that particular pull request in your project. That in itself I think is one of those things I suspect that is going to be talked about. It actually can alleviate a lot of problems that we have on a development processes because like the availability of the work of people who are participating in the project, there is kind of a built in barrier that we are essentially breaking down with this transparent node publishing process. And so, that's something that we're very close to to having it all on our repos and we're going to try it out and then hopefully share it with everyone on the internet. CHARLES: I didn't know that the NativeScript did this. I thought that the idea that came from it is like how can we apply these transparency principles to the way we maintain npm packages. The entire release process should be completely transparent, so that when I make a pull request, it's available immediately in a comment. And then furthermore, even when a pull request is merged, there's no separate step of let's get someone to publish it. It's just now it's on master. Now it is available as a production release. You close the latency and you close the gap and people perceive things as they are. There is nothing like, "Oh that emerged. When do I get this?" This is something that I can't stand about using public packages is you have some issue, you find out that someone also has had this issue, they've submitted a pull request for it and then it's impossible to find if there's a version and what version actually supports this? And it's even more complex between projects that actually do backporting of fixes to other versions. So I might be on version two of a project. Version three is the most recent one, but I can't upgrade to version three because I might be dependent on some version two APIs. But I really need this fix. Well, has it been backported? I don't know. Maybe upgrading is what I have to do, but maybe downgrading. Or if I'm on the same major release version, maybe there's been 10 pull requests, but there's been no release to npm. And it can be shockingly difficult to find out if something is even publicly available. And the transparency principle comes in to, "Hey, if I see it on GitHub, if I see it there, then there's something there that I can touch and I can perceive for myself to see if my issue has been resolved or if the things work as I expect." TARAS: I'm really excited about this. I'm really excited about this kind of clarification, this crystallization of transparency. And I'm also seeing our clients starting to apply it to solving problems within their organization as well is very inspiring. CHARLES: Yeah, it is. It is really exciting. And honestly, I feel like we've got one of those little triangular sticks that people use to find water. I feel like we have a divination stick. And I'm really excited to see what new tools and practices it actually predicts and leads us to. TARAS: Me too. I'm really excited to hear if anyone likes this idea. Send us a tweet and let us know what you're seeing for yourself about this because I think it's a really interesting topic and I'm sure there's going to be a lot that people can do with this idea in general. 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.
Mit unseren ewigen, aufopferungsvollen Bestrebungen, gebildetes Halbwissen zu verbreiten, holen wir die eigentlichen Experten an Land. So auch geschehen mit dem heutigen Gast Timo Zöller der meinte, w…
In the last episode, we spoke a lot about the "why?" behind microstates. This time we wanted to cover how ideas in Microstates map to different patterns used to build JavaScript applications using frameworks like React, Ember, Vue and Angular. We discussed what you need to know about Microstates if you prefer component state architecture or global store architecture like Redux, as well as how setState in React can be refactored to use Microstates. We closed off with the comments about the trade offs that component heavy frameworks make by overemphasizing the view layer at expense of other aspects of the MVC pattern. This show was produced by Mandy Moore, aka @therubyrep of DevReps, LLC. Upcoming Conference Talks: Manhattan.js - August 8th (Taras) ReactJS Austin August 6th (Charles) Transcript: CHARLES: Hello everybody and welcome to The Frontside Podcast, Episode #107. My name is Charles Lowell and we are going to be following up with our Episode 106 with the exciting conclusion of 'Microstates, the Podcast.' With me today to wrap this subject up, at least for the near term, obviously we're going to be talking about it a lot in the days and months to come, are David and Taras, also co-developers here at Frontside. Hello guys. TARAS: Hello, hello. DAVID: Hi everyone. CHARLES: Before we get into that, we'll just make a few quick announcements. First off is here at Frontside, we are going to be having some availability at the end of August. If you or anyone on your team is looking to level up in the area of testing, especially testing single page applications, acceptance testing single page applications or if you need React or general JavaScript consulting, please get in touch. We would love to work with you and love to do some of the great things together. Second, we finally released this and this is germane to the topic at hand. We released a major version of microstates this week that's based on a new and simpler architecture. That's really exciting. It doesn't really change the content of the conversation because the API hasn't changed that much. It just means that the library, which was already very small is even smaller. I think we shaved almost 40% of the size off and it's just much simpler and it's much more harmonious with the underlying JavaScript runtime. It's even more just simple JavaScript objects. Unless there's any other news that you want to cover, we'll jump right into it. TARAS: All right. Let's do it then. Let's do microstates. CHARLES: I Love to talk about microstates. This is obviously the second podcast that we're doing on microstates, just because we ended up, I think it was two weeks ago and we'd been speaking for almost an hour and really, we're just laying out the problems that microstates solve -- the problems of state management and why you often run up against complexity when you have a single state management tool that doesn't account for a bunch of different use cases. We got into microstates a little bit but we left it as kind of a cliffhanger. We talked about transactionality and laziness and immutability, ease of composition, simplicity of API, performance, memory footprint, things like this. Those were all the problems and then we're like, "Yeah, microstates. It's awesome." We're going to talk a little bit more about actual microstates proper and what is involved like the adjustments in mindset that you need to make or don't need to make when adopting a tool like microstates. TARAS: Actually, it's been really interesting for me because I just gave a talk at Toronto JS on microstates and it was pretty cool to see. There was a panel at the end. I think the people that are representing just using component state as a way of architect implication. It was managing state and application and it's representing redux. It's really interesting to see, first of all, like how curious people were. Most of questions were directed to the discussion around microstate, simply because it is a new tool but it was also just interesting to see how curious people who really loves redux, he was like, "I really love redux but I really like that fact that you guys have types," so I was like, "Oh, that's cool." Even though you really liked your solution, you actually found something in microstates interesting but at the same time, I think he was kind of missing that what aspects of Microstates overlap with redux. I think one of the things that we can do today is talk about what microstates has and what API does microstates provides and how similar they are to what people already know. I think that's one of the things that I was thinking about this conversation is that there are some things around microstates API like how to use microstates but the architectural concepts that power a microstates, they are already part of the development process and development architectures for most people that building single page applications. I think we can do is try to map these ideas not what people really know and patterns that they use to ideas in microstates, just to show how close we actually are. I think that's a good way for us to go. CHARLES: I guess we can start with, maybe one particular mode of managing state and then, how that maps to uses with microstates. TARAS: Let's start with components state because that was kind of our starting point. One of the original starting points for microstates because so much of our work was in Ember and component state is where most of Ember development happens. I think that's a good place to start. If you're someone who uses components state, if you're using Ember or Vue without something that is redux-ish which is pretty common these days, if you use components state, then one of the features of -- CHARLES: And also, if you're using React, right? Ember, Vue and React pretty much are all the same in this regard. TARAS: Yeah. Well, Ember and Vue are a little bit different in that behalf. Their particular pattern is you have data coming into the component, then you're doing some work with the data so that in Ember and Vue, you might use computed properties to derive state on that and then you might pass that state further down into other components. In React, you would do something a little bit different because there is no memorized computed properties by default, so you, a lot of times, write your computations that you pass into other computers that are written as expressions in JSX. If you're using this pattern, then one of the challenges around using this pattern is the process of lifting state becomes quite complicated. Because if you have like a bunch of state that lives in the component, it's attached to your derivation of state and the properties that you can invoke are attached to a component object. In React world, it's called lifting state. In Ember world, it'd be essential refactoring it into the parent component and passing that state in. in microstates, you're essentially moving this state into the microstate and now, what you have is this object that instead of having the state live on the component, the state now lives on the microstate object and in all frameworks, when you do that in microstates, you can use the getters to get the memorized computed properties behavior on the microstate. If you use your computed properties, computed properties are available for you on the microstate. You can do it the same way. CHARLES: It's kind of like a wrap up of that idea, not a wrap up but a summary of that idea is that the microstate essentially is a substitute for your component properties. If you're working with a component, a component has state associated with it, so you're setting properties on a component and then using the computed properties of that component. Microstates is you have all those benefits where you can set properties directly. You can define methods that like set properties as part of a transaction and you can then have simple JavaScript getters, which are just like computed properties except there's no enumeration of dependent keys. It's just, that's all they do for you. TARAS: Then the next question that arises is like, "Do I make like one huge microstate or a bunch of smaller microstates?" I think the question is really depends on the role of your component and what's nice thing about microstate is in microstates, there's two things that are kind of cool. One is when you represent your status in microstate, it makes it very easy. If you need to lift that state from the component up into the parent, you can lift that type. You can take that type and you can compose that type into the parent's microstate, if you have to and in that case, you would pass this new object that's created from that type. You'd pass the state for that component to the component that would otherwise have its own state. Essentially now, the parent has the state that would otherwise be in a child component and now, the parent is passing a state from the parent to the child. There's two kind of benefits to that. One is it gives a parent a way to control the state of the child and it also gives you a really easy way to serialize and deserialize state. You start off with having ability to serialize state for a particular component and all of his children, now you can represent that serialized state as part of the components state, so you have an easy way to restore the state of the component tree at the parent component. CHARLES: Right and that's possible because a microstate is really just encapsulating a value within a type but the value is just a simple serializable plain old JavaScript object, right? TARAS: Yeah. CHARLES: I'm just not trying to say like this is the feature that microstate provide, so when you're creating a microstate, you just pass it a POJO and it off to the races with that POJO and you can access that POJO at any single point. TARAS: Yeah. This is part of the architecture that I think are helpful for people that are using components. Is there anything else for people who are using components state that we think would be helpful? CHARLES: I think we're just realizing that you get the benefit of the laziness and immutability and the transactionality and all kind of things that we talked about last time but actually, the mental model is very similar. I think the thing to realize is that if that's the way that you used to working with state, the bridge is not too far. It's actually quite a short one. TARAS: Yeah, that's good. CHARLES: It feels very natural. It's not a huge mental shift. It's just more about a very small mental shift, a very small shift in mechanics for a very large payoff. DAVID: For instance, say you're in an Ember application using component state, what I'm used to is you're going to be passing actions around between components. Whenever you're trading that out for microstates, is it more that these actions are just bundle in with the microstate as the transition? TARAS: Yeah. One nice thing with the microstate, because the transitions that you can perform on any data type are intrinsic to the actual data type, the part of the data type, when you instantiate a microstate, you get these transitions for free. When you pass the object into a component, you can now invoke transitions on that object, that are part of that object's type. It's hard to imagine how awesome that really is because the closest pattern that you would see for that would be like, for example, if you're using Ember, you have Ember object or Ember model that you pass into a component and then, you can work a transition and because it goes through the Ember data store, your component is going to update. With microstates, there's no observation of any kind but what you're doing is when you are invoking the transition, transitions going up to the top of the root and gives you the next microstate, which updates your component tree. You get that functionality of 'data-down, actions-up'' built into the entire system of the microstates and all of that is hooked into these transitions that you can invoke on the objects that you pass into your components. CHARLES: Right, maybe David and Taras, you all could provide a concrete example of what that looks like. Because I think it is something that when I was giving talks on microstates at Ember meetups, one of the first things I like to show is you've got all these actions that you're writing either on your router or your controller but they're really actions manipulating the same type of data. It really comes down to like you're pushing and popping things off of arrays, you're toggling Booleans, you're incrementing counters, you're setting this property on this object. These are actions that we're writing and in the kind of microstates world, that's boilerplate. Because the transitions are intrinsic to the data type of the microstate that you're working with, maybe we could provide an example, like what's an action that you describe that you would pass around. TARAS: I think an easier one would be like if you have a model for example, you're composing a model into your application state or you're compose a model into your components state, so you have this model type that gets instantiated and you pass it into component that represents a model. Off that model, you might have open status like is it open or not that gets consumed by the model component, to know whether the model should be visible. Then along with that is model is open state, there is a toggle transition that you can find inside your component that is going to automatically flip the visibility of open. What will happen when you bind that transition to some kind of action handler that you invoke inside your component, when you invoke that action, it will then trigger transition at the top of that microstates and then, it will create the next state, push it through which will cause your model to change the visibility. David, that does answer the question? DAVID: Yeah, it does and that's actually the example that I have come up with whenever asked. A very simple sort of Boolean toggle. CHARLES: In a couple of my earlier demos, I should dust off that talk that I gave to the Austin Ember meetup where I was able to create an input with a dropdown menu with basically, some pretty advanced mouse behavior, all without having any component state or like storing it all in microstates and a lot of pushback was, "Aren't you putting logic in the template?" and the answer is, "Absolutely not." The logic is in the models but what I'm doing is I'm composing the actions that operate on those models inside the templates but at the template level, the action is data. If you're thinking about, we always want to have, we always want to lift state and then push that state down to the application, what this is really saying is that the actions are part of the data. It is implicit to the value that you've got. TARAS: I think that's really powerful because we do think about actions as being something that you can invoke. Like with closures, it's an action that you can invoke but considering that operation, that piece of data that invokes a transition in microstates and is derived from the type of the data, I think it's a cool concept. That's probably, one of the things that is kind of new for microstates but how you use it in your application should feel pretty much the same as you would if you were creating action handlers on your components. CHARLES: Yeah, just like kind of bundled action handlers for free. TARAS: Right. CHARLES: Maybe the way that you wrap up on this one when talking about kind of what microstates has to offer for the Ember developer, the Vue developer is really, I would say someone who's used to working with like MobX. Would be another good example is when I first started using Ember back in 2012, Ember Object solved a whole lot of issues in a really profound fundamental way and I really, really was drawn to that as the best API to be working with state. What kind of became apparent was perhaps not the best implementation. This is not like bag on Ember Object. I think it was actually amazing technology for seven years ago when most of it was written and probably, even came from before like SproutCore. It's almost 10 years old, which is incredible but it's still under heavy use in 2018 and it speaks well of how well it was constructed. I actually don't have much of a problem with Ember Object API. I just think that the way in which it's implemented that API means that there are some problems that require a different paradigm, so very much I kind of see microstates as heavily inspired by those types of APIs but with, I want to say a modern implementation but an implementation that is designed to solve the problems that have come to light over the last five years of developing single page JavaScript application. TARAS: I want to add that, when you describe with Ember Object, it exists in every framework that uses immutability. In MobX, the observation introduces the necessity to wait for a bunch of things to resolve. In Angular zones, I saw a similar purpose to ensure that if there are kind of cascading or streams or all of that stuff gets settled in into kind of restful state before you can start to assert on what's going on and with Vue, their computed properties has something similar. I think because of the complexity of having to track lots of objects and then recomputing things based on the result, that complexity in microstates is simplified by the fact that you describe you transitions. When you write them, you describe exactly what changes, so we don't need to wait for things to settle down. When you invoke a transition, that transition is explicit and based on the path of where that transition is invoked, we know exactly what needs to change, so we need to only perform one operation to compute the next state. There is no other things that we need to wait. There's no other side effects that we need to resolve before we know what the final status. I think that simplicity can be applied to all the frameworks that are using immutable APIs and derived computations from those immutable APIs. CHARLES: Uhm-mm [affirmative]. TARAS: Should we jump into talking about what microstates has to offer for people familiar with redux? CHARLES: Yeah, okay. Let's jump right into it. For folks who are familiar with immutable APIs like Ember, like Vue, like other ecosystem using MobX, a shift to microstates might feel like what you can expect. What about people who are just using often React-land and they're just using like set state. TARAS: Set state is a little bit tricky because it does get complicated over time and then you get this kind of funky things going on after a while where you start seeing things like, "I'm going to set state on this component and then once the change happens, I'm going to change some states some other state," so this kind of cascading state changes. The other part that I find particularly more challenging in set state world than it is in, I think in regular components state, like what you have with Vue and Ember. I feel like the way that the transitions, the state change handlers become part of the component, I find that part particularly kind of fragile. When you start doing refactoring, when you need to lift up state, it's like -- CHARLES: What's an example of this? TARAS: When you start off and your component owned old state and now, you need to have that state being controlled by the parent, we get into a situation where like, "What am I going to do? Am I going to do something with props as they're coming into the component or I should probably just flip that state from the child to the parent?" and now, you're refactoring the internals of a component to lift up that state so you can then combined those operation with the parent's state transitions. But then, you have this kind of added complexity of the fact that you're working with immutable data in that place. You've got these three things going on: you're refactoring your child component, you are moving these things into the parent components, you modify a parent component and now, you're also managing the complexity of forming immutable objects. I think the fact that people make it work is kind of a testament to human resilience. The people are able to solve such challenging problems and this is not a super hard one but when a component is complex enough and when stakes are high enough, these changes can become fragile. This is what I think microstates simplifies is that by taking care of the model, it makes components much simpler and makes it possible for you to just render a lot of components that are functional components without their own state. CHARLES: It actually reminds me and like I said, we're talking about what it's like to use them, not so much the implementation but that's the exact same sentiment that the author expressed in his book that was very helpful in writing microstates, which is Brian Marick. He has this book called 'Lenses for Mere Mortals' and he's talking about the practical use cases of using lenses, which microstates leans very heavily on. What he says right in the introduction is it gives you by abstracting the location and compose it the way in which your data structures are composed, it makes them very refactorable. You can say, "I want to change where the state lives. I want to change the structure of this object and I want to move it somewhere else," and it's sounds weird to say this, because the structure of the object is not coupled to the structure of the object, it means that it's very malleable, so you can move and you can say, "You know what? I don't want this address to be embedded in this person. I want this address to be inside this address book and then my person has an address book entry." Being able to make those refactors make those changes is very easy because your method of accessing the data is abstracted. It's something that applies beyond even user interface as a component state but it's something that this is a problem that's very salient when you are authoring complex UIs and compose components. It's something that you can benefit very greatly from. DAVID: Taras, you were telling us earlier about a friend of yours who is learning React for the first time over the past few months and he's mainly been using set state as you would just starting out in this world. You said that he didn't really get why you might have to go and learn some other way to manage your state and I think Charles said it, whenever your application starts to get more complex and you've got a lot of different moving parts, that's really where microstates will come out and shine for you. TARAS: Yeah. My friend kind of feel bad because he's spent the last three months learning how to work with React and how to use set state, "And now, you're telling me, I need to learn something else? Like I'm going to start from scratch?" I kind of reassured him that especially when you're a beginner, when you're learning, you learn how to address very specific challenges but you don't know how complicated these things can get when your UI gets really intricate. In those intricate scenarios is when you have to leverage your experience and you'll be able to solve these problems but if you're learning, you encounter these challenges head on and your tool does not really, like set state. Although it can be used to build really complex UIs very effectively but the complexity that over time increases as you start to manage the state, increases much more later on than does early in the beginning. Basically, with microstates, even if you have some basic proficiency with set state, when you start working with microstate, the things that you can do with microstates, you will be able to do more sophisticated things easier when you need to use them than you might realize when you start. Because microstates API is so consistent, there are a very few concepts to actually learn and they cover a broader range of use cases so when you actually starts using it, you'll encounter these challenges. What you already know it will just work for you and always just continue to work for you. That was part of kind of fundamental design on what Charles and I have spent, a lot of time putting into place from a point when we started two years ago. CHARLES: I think, and you touched on this and this is kind of what I was speaking to earlier is that when you're working with a simple system, it's simple, it's easy to work with and then the complexity starts to grow, it's never a good thing when you have to reach for a more complex tool to manage the complexity. It's a hallmark of a good system and that it can scale with you from a very simple and easy use cases to actually being able to handle very large and complex use cases but your API doesn't have to change and your usage doesn't have to change. If you have a tool that can actually scale with you from a one liner to a hundred thousand liner, that reflects very well on the design of the tool. I think you see that with things like Ruby, you see it with things like Clojure. You see it with, I would say there's even people writing like Haskell, shell scripts now but not so much with like C++. I think the analogy is very similar with microstates in the sense that when I'm looking for evaluating a language, it's not the only thing I look for but I really am looking like how is this going to work for me as a one liner? How's it going to work for me as a hundred thousand liner? If the answer is pretty consistently, then that's something that is going to get a lot of bang for your buck, so to speak. If I invest the time in learning it, I'm actually able to reap the reward of having a tool that's got my back on a whole bunch of different use cases. We talked about, in React, if I'm using set state and that's kind of a sub case of component state because I would say that in the previous systems we talked about -- Ember, Vue -- they have components state but the component state is a little bit more rich in the sense that you've got computed properties and what have you. But if we look at a system that externalize a state like redux, where you have a global state atom in your application, at least that's the way most of the redux applications that I've encountered behave, what does it look like for you? TARAS: I think it's a little bit challenging when talking about redux is redux conflate a few different things together. I think it's helpful to split those things up, so we can talk about them separately. One of the parts is how the state is delivered to components. The way that redux does is the instance is this created so every time you use connect, you essentially wired together. You can connect through the context or... I'm not sure. I think they have an observation mechanism that's internal to redux as well but they essentially connect components to the store and then they view that to deliver the state. It's kind of worth pointing out that for that like microstates bindings for React actually give you something similar out of the box through context. For those who really like the ergonomics of connect, I think it would be pretty easy to make that available for microstates. Usually, we don't even know why they wouldn't be available. CHARLES: But I do think that connect can be problematic like you can encourage you to not make components that are reusable and have isolated state. It's very easy to hitch yourself to the redux store and now, you don't have components that are shareable. TARAS: I think I would personally prefer to pass microstates instances through props because of the stability that's built into microstates and structural sharing, you can get some free optimizations and allow it to use functional components in more cases like out of the box but some people who are really like redux, they really like connect. Although it might be my personal preference, there's no reason why that wouldn't work if somebody wants me to connect function and make it available for people. CHARLES: Right and I think, there's a happy medium there too, right? TARAS: Yeah, I think -- CHARLES: -- You can connect components and then fan out that state to a set of functional components that are not connected. TARAS: There are some places where microstates and redux are very similar. When you're using in redux, you have this dispatch mechanism, where you essential saying, "I'm going to dispatch this action and your action creator is going to create an action for you with the payload," and then you're going to match that action to a reducer. One of the things that I kind of hear redux people really enjoy about redux is the one with data flow that dispatch the action and then, it reduces this next state and pushes that through and you have this kind of ingress point where everything is going through this one point. I think what's really interesting with microstates is you essentially get that. That's exactly how microstates works, in a way. The only difference is that the API is different. Any action that you invoke is going to go through a single entry point, which is going for you. Because we know the structure of the data, we know how to transition that state for you, so you don't need to reducers, so you're just defining your transitions or use the built-in transitions and then when you invoke them, we know the path. We're essentially forming for you. The path where you invoke the transition, conceptually, it kind of forms the name of the action that you are invoking. The path refers to a place where the state is going to be transitioned, then you have your transition, which is the actual reducer for that part but it's contextualize, so you don't have to think about how you need to transition that state in a great, global redux state. CHARLES: There's no matching. The matching is automatic. TARAS: Yeah, the matching is automatic, so you get that same single ingress and one directional dataflow. You get those mechanics except the APIs that you use, instead of writing the actions yourself. Instead of writing, we just use yourself. You get to use microstate types. I've heard some people who use redux who are like, "I really love the fact that microstates has types," but other people don't like types for whatever reason. Microstates comes with 'from,' which allows you to take a POJO and from that POJO, it creates a microstate and then you can invoke transitions the same way as if you had a type microstate. The only thing you don't get is you don't get to create your own transitions. You have to use the transitions that are provided for the primitive types. CHARLES: I think that there's a couple of benefits that you'll realize for free. There's laziness, reducers by default, or eager. When you dispatch an action, it will run against every reducer in the store. If the reducer matches, you're going to run the computation that's associated with that reducer. Microstates by contrast is lazy. Basically, until you try and read the property that is affected by that reducer, the reducer won't run. There's some ways that you can get around this. When you're using redux and first of all, you can actually have your reducers return objects that have getters on them. You can realize some of that laziness but again, it's work that you have to explicitly put in. I think, didn't you actually say that there is a package of plugins? There are plugins. There's basically a set of libraries that you could bundle together, which would give us an experience similar to using microstates. TARAS: Yeah. If you wanted to combine redux and reselect and immutable JS together, you can get some of the benefits, except this benefits are not integrated that well because they're still separate systems that you are essentially using together. Also, like microstates, it's four times smaller than redux and reselect and immutable JS combined together. If size matters to you and ergonomics matter to you, you actually can get a lot of ease out of using microstates while still maintaining the benefits of having redux. CHARLES: But if those things, those packages, like reselect and immutable JS, are things that are familiar and you naturally gravitate for it, then you'll probably absolutely love microstates. Because honestly, one of the ways that I think about microstates is like, what if you could have immutable JS, if there was no cost for composing the types like list and record. Immutable JS has come a long way since I've last used it or it's evolved since I've last used it but I think there's still only about four or five basic types and actually, making your own new immutable structure, your own custom type with its own custom methods that still get the benefits of structural sharing and laziness that you have on immutable JS is not something that you can do. But you could think one way to think about microstates is an immutable JS where you can make any type that you want. You're not just constrained to the record types and to their list types and set types or map types. TARAS: It's worth pointing out that at the moment, microstates doesn't map perfectly to immutable JS simply because immutable JS has certain optimizations for managing lists that kind of a great value of immutable JS and microstates doesn't have some of those pieces but -- CHARLES: They're definitely on the road map. TARAS: Yeah. Because microstates is abstracted high enough, that we can actually change internals and some people who are using microstates now, they will get benefits of ergonomics and there's already performance benefits from the stability that microstates offers but there will be a time when by upgrading to newer versions, you will not basically, need to change anything in your op but you will get the benefit of improvements to performance that we will introduce over time. Some of those improvements might come from what we will learn from immutable JS. CHARLES: Right. I have a couple of thoughts before we wrap up. What are the ramifications no matter who you are? What kind of development background, some of the benefits that you'll experience with microstates that might be a pain point or something you hadn't thought about where you are currently? A couple of things that I have jotted down is first, and this is what brought it to mind is talking about stability. Something that you see in a bunch of frameworks is having to manually track the keys that are associated with data. If I've got a list or I've got an object, being able to say, if that object changes, then I need to actually have some sort of key object, which effectively amounts to a hashing function to say, "Did it really change?" Because no matter what system you're in, you need to know how you're going to re-render. If the reference to this object changes, then the default thing needs to be, "I need to re-render it," right? You see this in Ember, in Vue. In React, there's this ability to pass a key or ask the question, "Should this component actually update?" and with microstates, that's much less of an issue because basically, it keeps the key tracking instability for you. If you are using a model with microstates, if you think of an object as a graph of nodes, no node in the graph will change unless it absolutely has to, at least that's the goal. We still actually have some work to do when you're running queries against the state of a microstate. We can cover that later but that's most largely the way it is now and definitely, the way it's going to be going forward is you don't have to do any extra work as a programmer to figure out what has actually changed. TARAS: That opens up some interesting opportunities. Imagine if you had a rendering engine that did not expect side effects to be significant and you could just say, "If I know whence they'd changes, I will then re-render that." That will be really interesting exercise, seeing like what would that look like for a performance perspective, if you have a very clear picture of what has actually changed and what part of the DOM as a result, need to be updated without having to do diffing. The [inaudible] you could actually do a diffing at much higher up. Actually, [inaudible] to diffing because you know what's changed but you can push a lot of assumptions higher up on the architecture stack. CHARLES: Right. That's actually one of my favorite thing about microstates and one of the unwritten values is like triple equals used to work everywhere and by and large, it does. It's usually simplifying but when you don't have to manually tell the computer what equivalence looks like, you can just say, "Look, are they the same object? They're not the same. If not, then they're not," and keeping that consistent is huge. TARAS: I think this is a good segue for us to kind of bring this conversation to a close and also, kind of set up potentially a third full-on conversation, which we could talk about actual architecture of microstates and design decisions because for people who just want to use microstates, they don't need to know all these details but for people who are curious, they might actually want to understand what are the considerations that remain when we were designing microstates, so maybe in a next conversation about microstates, it could be about architecture and the pieces in microstates today and then where we are going with microstates and what it could give us long term. CHARLES: Yeah, I like that idea. It is a plannable subject that we've been talking about internally for the past two years, so it makes sense that there would be plenty to speak about on the podcast. There is one other thing that I did want to bring up and that is, I think enabling to have a state solution that is composable because it allows you to think about your state first. Because really, if you do have a functional UI, where your view is a pure function of the model, that your view follows the model and so, if the view follows the model, then really, the thing that you should be thinking about first is the model that's going to be required to drive your view. I shouldn't drive. I should say derive your view because that's the primary artifact of which the view is nothing more than a function. It's a reflection onto a surface. I don't think that we have a state management solution yet, that enables that mode of thought, where I'm thinking about my prime artifact first and working forward rather than thinking about my secondary artifact and trying to kind of wishy-washy way, work backwards and reconstruct the primary artifact. I think that we've talked about all the development ergonomics and I think there's a mechanic of thought there that's enabled by this that I hope to see in more and more applications. TARAS: I think that's a really well put. I think that's something that I've been thinking about as well, as how do you convey this shift that microstates allows in terms of how we're thinking about architects and the application. For some people that value, the model, like they'll find that shift easier but regardless, I think that making that shift has a potential of simplifying your view dramatically and I'm very excited about exploring this further and having more conversations about this. CHARLES: Yeah, that's where we really kind of open up the conversation about state machines, which is also central to the conceit of microstates and using state machines as an incredible design tool but anyway, we can all get into that later. You heard it here folks, Episode 3 is coming out, although probably not for a while. We're going to be mixing up and we will be talking about microstates at least for a while. I understand that next time, we actually teased it but we based on how much material there was on microstates, we ended up packing in a second episode. We teased it last time, we're going to be talking next time about running an online conference with Twitch, so definitely look for that. Thank you, Taras. Thank you, David. TARAS: Thank you. DAVID: Yeah, it's been great. CHARLES: This is a wonderful conversation and as always, we are Frontside. As I mentioned at the top of the show, we have availability coming in August, so if working with us is something that you would like to do, we have a range of services, please get in touch. You can get in touch with us at @TheFrontside on Twitter or Contact@Frontside.io. That's it for now. I guess we should also mention that Taras that you are going to be giving a talk on microstates at ManhattanJS. When is that? TARAS: On August 8th. CHARLES: I will be giving a talk on microstates at ReactJS Austin on Monday, the 6th, so that is right around the corner. I'm excited about both of those talks, especially following so closely on the heels of the TorontoJS meetup talk, which I understand is... Is that posted online yet? TARAS: It's recorded but it should be coming out soon. We'll definitely tweet it out. CHARLES: Okay. All right. Look for that and we will see you next time.
In part I of The Frontside's microstates series, Charles Lowell, Taras Mankovski, and David Keathley talk about state management that's easy and fun and transactionality. This show was produced by Mandy Moore, aka @therubyrep of DevReps, LLC. Upcoming Conference Talks: Toronto.js - July 30th (Taras) Manhattan.js - August 8th (Taras) ReactJS Austin August 6th (Charles) Transcript: CHARLES: Hello, everybody and welcome to The Frontside Podcast, Episode 106. My name is Charles Lowell, a developer here at Frontside and I'm going to be hosting today's episode and we're going to be talking about microstates with fellow Frontside developers, David Keathley and Taras Mankovski. Welcome you all. DAVID: Hello. TARAS: Hello, hello. CHARLES: I'm really, really excited that we finally get to talk about this but before we jump into this, just wanted to let everybody know that last week, we published our roadmap for Big Test, which is a JavaScript acceptance testing framework that we've been building right here, in-house at Frontside, which can work with both Ember applications and React applications, Vue applications. It's in alpha phase and we're looking for feedback but we're really excited about it, so we're going to leave a link to that in the show notes and please go check it out. All right. Finally, the moment has come that we actually get to talk about this publicly. We've been publishing things about microstates for a while now but we feel that it's ready to share with the world and that's really, really exciting. We should probably like wind the clock back a few years because that's about how long we've been working on this and talk about, kind of the why and the what of what microstates are. It's kind of a weird word. What are we doing here? TARAS: Yes. That's interesting question because we were working for so long and after all this time, what is this specifically we're working on. I can speak personally from my personal motivations because we have conversations over the last two years to why we were doing this and I think for me personally, it's always been that I've been mentoring building complex applications for almost five years now and one of the things that I find consistently is that there are patterns for how to build complex stateful UIs that the required solutions, that are fairly reliably consistent. I can teach people certain patterns and then they can use patterns to build complex applications and those patterns scale really well, the challenge is that, there's not an easy way to express them and it's different for every framework. The way that I would teach somebody how to do it, for example in Ember versus how they would do it in React, even though the pattern itself is the same but the implementation of the pattern is different but it's different in such a way that it's very difficult to see where the consistency is, what is the same about these two patterns. It shows me that there is room for improvement. In the same way that if there is an opportunity that in the future, components will get unified under one umbrella or what component spec. The fact that we do states differently across every implementation, across every opinion, it suggests that what we might be missing is something that would unify across frameworks, how we actually do statement management. CHARLES: Yeah, that makes sense because as much as people try to buck the trend of MVC, it can't keep coming back in the rear view. Hopefully, not like a horror villain but like a caring friend, like a reliable pattern. I remember when I was in writing Java applications back in the day, the most important thing when you were writing a swing application was making sure that you had your models right. If you were modeling either a form or a dialogue or a set of pages, the most important thing was to have those models. Back in the day, we modeled those things with event listeners, very similar to where the way like a Backbone application used to work or if you're familiar with Ember Object, the way that it worked basically, adding observers to some model so that when that model change, you were able to react to that. Your representation was able to be 100% dependent on this model. That was like a Java Swing Application, which was then inherited from this pattern from Smalltalk but we keep on seeing this again and again and again. There is this piece, this state, that if you're going to be representing something, then you need to be able to get at the meat of it. That's ultimately what the model is in the MVC pattern. I remember when React first came out, everybody was like, "Oh, MVC is dead," but now in terms of state management and all of the state management solutions that we see, what that really is, is the model trying to reassert itself. Because it's such an important piece of your application, it's going to rear its head and you cannot escape it. I make it sound like a problem. I guess, it is a problem but there's a proliferation of solutions out there that are attacking the problem in order to represent something you have to know what that something is. DAVID: I think when you only work with the one framework, your perspective might be very much shaded by your experience. If you're really good at building React applications and you have subscribed to POJO is king and you don't need anything beyond that, then you're going to get good at handling POJOs and you might not realize that there is actually limitations to what you're doing. I think the same applies to people who use Ember and they're using Ember Object and they have computer properties and now, in Angular, there is observables and subscribing to streams. What was really interesting with the work that we've been doing with microstates is that and one of things that have notice with other state management solutions is that a lot of them emerge as, "Oh, I had this insight. I spend a couple of days working on it. Here's my proposal, in a way, for managing state." I think that's great because insight and understanding is really important but sometimes, taking the time to design something can be really helpful. I think that one of the things that are really interesting with microstates is that because we've been iterating on it for so long, they've been testing it for so long, we've been able to do something in microstates that's really difficult to do when you have a production application that you're like, "I want something different. Something is not enough but I don't have the time to really make it better," or, "I have an idea. I want to release this thing but I don't have any other collaborators that I can talk to and really flush out these ideas," so what you get is a solution but it doesn't always touch on a lot of the angles that you want to touch on. It's really interesting when you think about -- CHARLES: I'd say, we should talk about those angles, like what are some of those angles? DAVID: Yes. You could think about this from a few different perspectives. I would say, from Ember perspective because that's been my personal starting point. For anyone who was listening. Ember and Vue, for all intents and purposes, in this scenario are very similar because they have the same primitive, which is the computer property. The computer property in Ember, the computer property in Vue is almost identical from the way that you actually consume. In Ember, you would use computer properties and in Vue, it's just computer properties to create derived state from data that's passed into the component and then, you would use is derived state to basically, decorate information that comes with the props, so you could present it in your component. This pattern is very nice. This pattern is being used to build LinkedIn, to build applications at Apple. There are huge implications being built by Ember community using this patterns and I'm sure something similar has happening now with Vue but this pattern doesn't really exist in React in the same way. You might opt in to start using this pattern if you start using [inaudible] but it's not quite the same. Writing computer properties in Ember and in Vue is essentially free because it's so effortless, where in React, if you're using [inaudible] to create cache computer properties and memorize computer properties, you are really opting into doing a particular way of computing this properties and writing selectors that's not trivial. I think that's one thing that is available in Vue and Ember and it's a really effective pattern and you can do it in React but it's actually not possible in Angular, unless you're using, I'm guessing something like ngrx, where you can do similar things to what you would do if with redux in React. Creating derived state that you can consume in your component is one of the things that is possible but it's not possible consistently across all frameworks. That's just one of the things. CHARLES: I agree. I think that was one of the things that drew me to Ember at first coming from Backbone as I did and honestly, from the models in Java was that, in order to compute anything, you had to install a listener and then eagerly make that computation and store it somewhere, where as those frameworks, it made you feel effortless where you can just decorate some state and derive it and the information is there, the computation is there when you need to reach for it but you don't have to do expend any extra effort aside from say, "This state is derived off this other state." I think another case that I came across was immutability. Immutability is a means but the end is to have consistency inside your application. I first really started running up against this when I was working with forms and since then, I've realized that actually, a lot of the pain that I was feeling was because things were not being immutable but this is where the fact that things weren't immutable ended up causing me a lot of pain and headaches and I was having the code into being a lot more complex. Essentially, when I wanted to make something transactional if you're editing a form or something like that, then you need to essentially store off a copy of your current state. If you're editing some object, I want to say, open up a dialogue and I'm going to edit it and then I'm going to commit the changes back to that dialogue. What I'm modeling there is a transaction so I kind of need to shave off a copy or make a Xerox copy of the object and then make the changes inside to that object and then somehow, try and merge those changes upstream and then, get them back into the main lines. Really, like a very Git-like operation. It wasn't just at the object level. When you're doing things like dirty checking, you need to make what is the original value of a field versus what does the input currently have. I might be doing any number of transformations in between the actual physical representation of the field, maybe it's a date but the user interacts with it in as a string, so there has to be this kind of parsing serialize thing sitting in between that value and you need to basically, keep a copy of that field as a mini transaction within your macro transaction because you want to say like, "Is it dirty? is it really the same object?" because if you can just do an object comparison, you have to get into all that hairy like equality checking and it gets really complex really fast but it turns out that a very clean solution to this is if you just never actually make the changes in place and whenever you are making changes, you're generating new information without destroying the old information because when a form is the case where we really come up against this, where we're modeling the same object over time, so a form explicitly models the change of an object. Change is part of what it is and so, the definition of change is being able to compare something in its prior state to be able to compare it to its current state. If you're making that change by destroying the prior state, then you're going to run into a lot of trouble. It just turns out that when you're working with forms and it turns out there are a lot of use cases like this but this was the one where I first really just couldn't even... Without immutability, you want to model your change as always rolling forward and not ever destroying prior states but being able to pick and choose and can always be able to look back to where you were and compare where you are now to where you were. That's where immutability comes when you're modeling change. It's actually much easier to model change when you have explicit states that represents what was and what is. But when you start doing that, then things get a little bit messy. You have to do the compromise. There's a tradeoff, like when I say, "Set this property on this object," that is easy and that's something that I think that we can all understand. We're not idiots. That's why immutable models are very conceptually easy to grasp, to wrap your head around. If I'm modeling myself and I'm saying, "Set hand position two feet up in the air and now I'm raising my hand." That's easy to understand and it turns out that when you're changing a data structure immutably, then you have to, for example model a simple set operation as duplicate and swap. Or if say like you're swapping out one property in an array, you actually model that as a map, where you swap out the one element at that index, rather than just saying, "Just set the thing at that index," or if I'm changing a property of an object, I want to copy over all the fields except for that one which I'm going to change. If you start to do that then, you realize the benefit of always being able to look backwards but you've now introduced overhead and complexity in your code, so you've made a tradeoff. I think that's a lot of people look at saying, "I want this to be immutable," then they actually have to come to the grips with the complexity that's going to introduce. There are libraries like Immutable.js that do make that a lot better but even they have the problems. I can talk about those but one of the cases is like being able to reason about a series of states for your object, rather than just only having one copy of it ever and being stuck with having to deal with it as it is. DAVID: Yeah and I think that really important too is being able to mentally track where you've been because in my experience on other large Ember applications, I've run into so many different bugs that I could really track down to people or rather, places in the code where things are just reaching in and mutating your model, where it wouldn't make sense, so as you're writing your code, you're in a completely different state than you might have expected. CHARLES: Yes and it's easy, right? But essentially, when you have some model, you've basically got a global object. There's a lot of recomputations that needs to happen when those things change. As a result, if you look at the actual code that supports computer properties in Ember and I'm sure other frameworks as well, some of the most hairy and complex. If you look at the chain watchers and the chain nodes and all the stuff that's required to support things like computer properties, it's amazing that it works as well as it does. I've tried to actually open that up and understand that code on a number of occasions and every single time, I had to walk away in defeat. TARAS: This problem exists in React applications and Angular applications because if you think of the challenges of working with set state, I think one of the problems with working with set state in React is that your complexity increases very quickly. It starts off kind of simple when you're using immutability with set state in React. They're kind of very light and then, as you start to add features, your complexity starts to grow very quickly in a way that you really start to run into limitations. You start to confront your personal limitations of your abilities to work with immutability, so you're limited to doing immutable structures that only a few levels deep because your ability to use destructuring to create new immutable object is limited by expressiveness of JavaScript. It's gotten a lot better with the destructuring but if you do it a few levels deep, I think everybody's familiar with what happens. It starts to get really hairy. You kind of loose track of where you are. CHARLES: Yeah. The signal-to-noise ratio increases because after probably, two or three levels, the majority of your code has to do with destructuring and restructuring and very little of the actual change that you want to make. TARAS: And this is kind of interesting because people talk about declarativeness versus imperativeness but at certain point when you have a complex immutable state change, if you're doing with destructuring your code, even though it looks declarative but there is so much processing that you're doing, it's actually kind of losing the benefit of its declarativeness. It's actually starts to look more like imperative code than it does what you would expect a declarative system to look like. I think this touches on the other aspect. It kind of compromise that when you work immutably, when it compromises, you make a serialization. Your ability to represent your state as a POJO becomes restricted by the fact that you have this complex system that's wired together and you have systems like zones in Angular and in Ember Object that are able to keep track of changes in these objects but you don't have a way to restore those objects. You don't have a way to do more sophisticated things that you might want to do, especially in situations where if a service feeding you, what do UIs going to look like. In that situation, it's really helpful to be able to say, "Here's a POJO that I got from the server. I'm going to use this POJO to build this component tree that the user is going to interact with and then, as the user interacts with it, I'm going to then, capture that state, serialize it and put it back in the server." When you're using something like Ember Object or if you're doing this kind of stuff in Angular or even if you're doing this stuff with React but without using something like redux, you essentially end up doing so much wiring to accomplish that. By the time you finished writing your application, you've written a ton of code just to handle this particular use case and if you have to do this again in another application, you just rewritten that kind of code in a new application as well. CHARLES: It reminds me of the concept of a Smalltalk image, like there's no way to really get at the state of a Smalltalk thing. It's almost like you're dealing in docker containers and not actually being able to write that state down into JSON or something like that. I'm trying to casting about for an appropriate analogy. Maybe that's not a good one but what's actually happening cannot be made orthogonal. It can only exist in that one run time that you're currently running. If something wrong manifests itself, reproducing it can be extraordinarily difficult, right? TARAS: Yeah. CHARLES: Imagine if there's some render cycle that's making a bunch of mutations and there's this process that you stood up and it runs in completion, some signal comes in and those effects are like ripple through the system, there's no way at any point to have any other representation of that system than the running system itself. TARAS: There's another element to this, which I find really interesting. When you're thinking about how to architect complex UIs, it's actually helpful to get really clear about what kind of changes are happening. A lot of times when I want to see beginners are writing, especially if you task someone who is a fairly junior at building a single page applications, a lot of times what will happen is because they don't have a clear mental model of what is going on in regards to state. They end up setting a lot of properties. Every operation, every time you have an event handler because they don't have a clear model of what's going on, they end up setting like five or six or seven properties. That kind of signals that they don't have a clear picture but what that also does is a lot of times, they usually comes together with cascading state changes. Usually they're not representing a single operation as a single state change because there might actually be a bunch of things that are happening because what they're doing is they're massaging the system into submission. Not like they're not in control of the state transitions, so they use, essentially time and their dedication to kind of sort it out and make it work and eventually, would that ends up looking like that if it works for most of the cases that they are able to test for or that they able to manually see. But then they AR, not accounting for problems that they're not able to understand right now, they become discovered by users when users start to interact with the system and with the components or with that application and the application is there to get into some funky states. The tools that we have, they don't prevent that from happening. They just -- CHARLES: Right. They don't force you. I think what you're saying is that ideally, you want to model your UI as a set of transactions on your state, that you want transactionality to your state so that I basically am saying, "I'm not going around and setting seven properties in reaction to this one event." I'm saying, "This event triggers this transaction and that transaction clearly bundles up every single operation that needs to happen and the tools don't enforce that." Is that a fair --? TARAS: Yeah and then, the problem is we're working with component trees. You start off with having a set of requirements and over time, the requirements change. As the business unit understands your application better, they give you more direction of how accounting should work and then you find out that there's more interconnect at stake but then what's happening now is that the cost of refactoring those state that spread throughout the components, whether that be with set state, whether that be with the actions in Ember or even in Angular. What you end up doing is you start to change the system but change is not trivial because the actual process of changing where that state lives is not linear. It depends on the complexity of the code that you wrote and it just gets really hairy very quickly. That's where companies end up losing a lot of time. A developer could start off with a requirement, you build something and then a new requirement comes in and instead of it being a simple change, it turns into a week or two weeks refactor because you now understand the state ownership should be different. The state that you have should be in a different place. You have to manually make that change. You have no obstruction to help you express that in an easy way. CHARLES: Another thing, because we are doing a kind of a roundup of all the things that you need to account for when you actually embark on managing your state. Another is actually constraining the amount of computation that happens. If your system is based on listeners and large chain reactions of things where it's like, "This property changes so I need to notify these other 10 dependent properties that change." You can do a lot of unnecessary computation, especially if nobody is going to render. That's kind of the thing that you have to do if you're going to be immutable. You have to eagerly walk those change to see which objects are affected so that you can then invalidate those caches. A system like Ember Object, I don't know exactly how Vue works, it mitigates this somewhat by the fact that the computer properties are lazy but you still have to walk all of those chains. That can actually get out of hand. They're eager, not lazy. Then the other concern that you have, where you normally have to make a trade off around is around composability. One of the things that's really nice about immutable systems is they're very composable. If I've got some object that does one thing, I can then just set that object onto another object just by mutating one of its properties and I've effectively composed them. I can then install listeners onto that thing or I can compute properties off of that property and they can post pretty well. That's something that you get but then of course, you're losing all of the benefits of immutability, so things like Immutable.js don't really compose very well or redux doesn't really compose very well. The concept of taking a redux store and embedding it into another redux store, you just don't see that. I would never distribute and I think ultimately, the litmus test there is would I be able to share it on something like npm. Nobody shares an npm package that's just a redux store that you can dispatch actions to and observe and use it with your other redux stores. When it comes to a system like Immutable.js, that does make transitions a little bit easier over lists and arrays and maps but you still run into the exact same set of problems that you have when you have lists of maps of records and you don't really get any help there, so you have to make this tradeoff between immutability and composability, whereas a system like MobX or Ember object actually quite composable. Before we start talking about microstates, I want to say that you just throw those in there because there is just a lot of concerns out there, a lot of edge cases that actually build up but through the course of a real application, you will encounter them all. You might be making tradeoffs at the beginning that you're not realizing that you're going to need or are going to get you into trouble later on. DAVID: This actually happens in the Angular community as well because there's something really great that's happening with observables in the Angular community. I think everyone's embracing them wholeheartedly and I think that's really been pretty great to see but observable streams of composable, but objects that have on them observable stream providers of some kind, like if you have something that you can subscribe to and that is part of a property in a class, composing multiple classes together and consuming properties from those classes, there is no mechanism for composing that. That kind of composition has to be done manually. Again, you're kind of manually wiring together a bunch of objects and the big challenge is that you are manually subscribing to all those streams and unlike what you have with components. Components have lifecycle hooks. When your components is being torn down, you know you can perform some operations. If you need to remove an event listener, you have a hook where you can do that when you have a class instances like JavaScript class instances that have on them properties that have observables that you subscribe to. There are no tear down hooks for class instances, so there are no obstructions from managing unsubscribing from those streams. You essentially end up having the foundation that you can use to build complex reactive systems and you can subscribe in there really fast but wiring those things together at a bigger scale is simply not there. It's something that you have to create and enforce yourself. CHARLES: Right and I think that's probably a perfect segue into talking about microstates, which is the project that we've been alluding to for the past 30 minutes, that is I think in attempts to solve these problems and make sure that you don't actually have to compromise on those things, so you can reason about things locally but have those things be composed into a greater state. But also have them be immutable so that you can look at past states and reason over a data structure over time as opposed to just in one instance. Also, have an intuitive interface that when you're making these changes, doesn't look like half of your code is unpacking some data structure, flipping some bit in it and then repackaging it back up again. That's the context. Should we start talking about what microstates is and how it addresses those? TARAS: That's a good next step and when I start working in the ReadMe, I end up actually, I think I wrote about 40 pages. One thing that's interesting about microstates is that and this was part of the design of microstates from the work that we've done is that we intentionally wanted to make the number of ideas that you haven't microstates very little, so when you use microstates, the number of concepts that you need to remember in your mind is very few. It is a conceptually a different way of thinking about organizing your state in the same way that shifting from managing DOM elements directly to having an obstruction like component that declaratively applies changes to your DOM tree. In a same way, microstates is kind of an abstraction that allows you to declaratively describe how your state will change and it will manage the transitions for you and allows you to give the state transitions names and it allows you to give your states names as well, so you can actually name things. You don't get a POJO that has a shape but has no name. You actually get to give things names. CHARLES: So, why don't we start? I have a list in my mind. I should probably write it down of the things that we just talked about but I think the things that we talked about are ease of representation, like conceptually easy, transactional, basically serializable and immutable, lazy and composable. Those are like five or six things. But I think there are kind of aligning principle around which we gathers that the state management should feel easy. It should feel fun. One of the things that is awesome about working with components, whether you're using web components or React components or Ember components is when you get it right, you're just snapping these things to feel together and it feels great. It's like I'm just passing properties and render blocks down the tree and the framework is just doing all of the grunt work for me and I'm just operating at a very high level. That's what organizing principle with microstates as it needs to feel easy. Maybe we should start there and just say, how does that easy and fun line up with each one of those kind of unique problems around which we typically have to make tradeoffs? We could start with the interface of making a change. TARAS: I'll go back to the starting point. I remember what got me first interested in microstates is Charles, when you said that, when you have a number, there are certain operations that a number can do. We really don't need to be writing an increment operation for every... Like if you a have a number, you can increment it and decrement it. CHARLES: Honestly, every time I see state management tutorial and they tell you how to increment and decrement a number with it and you write the increment code and you track the thing and you store it back into the store, at this point I'm still annoyed with those tutorials because I'm like, "It's a number. We know we can increment it. Just show me where to plug in the code. I should not have to be writing an increment method." TARAS: Yes. And that's the kind of starting point. There are certain operations that you can perform with the primitive types. If you need to add a number or if you increment a number, we already know how to increment the number. It's part of microstates. But that in itself is nice but that's not that important. I think what's really important is that when you need to put a number into another data structure, let's say you have a nap and you're like, "I need to..." I don't know -- CHARLES: Let's say, like a click tracker that has a number of clicks. TARAS: Right. By itself, you can increment the click tracker but if you need to put a quick tracker into another app, essentially you can compose it in and you don't need to figure out how to wire the actual mechanism of how to make sure that you can update the property, like it's part of another class, for example, you don't need the way you would increment the number. When it's a part of another class versus how you would do it when you're working with it by itself is an approximately the same. The amount of work that you need to do to actually perform that operation is the same. Your complexity doesn't increase as you compose one data structure into another. CHARLES: Right. You can just say, "This is an app. It's got a click tracker and this property is a click tracker and I have to do nothing else. I can register clicks on that thing. It doesn't increase the complexity of application at all." TARAS: There's no wiring. Now, you added some new state, that state is very explicit and it's really clear that it is not impacting other parts of the state. You can operate with this thing. If you change it, it's going to work properly with all the other things that are in the type that you are adding this counter to. Those things are just going to fit well together and it's not going to break if you need to transition one more thing. All of the other transitions will work the same way. I think that kind of consistency is really meaningful, over time especially when you start to increase the amount of state that you manage in your application. CHARLES: Just the ability to work with types and just have kind of those implicit operations and have those things compose, kind of indefinitely. Moving down, we talked about easy and the other thing I would put on that is that the way in which you express those transitions, for example if microstates comes bundled with numbers and Booleans and strings and arrays and objects and kind of the stable of types that you would expect in any JavaScript application but those types are expressed using this way for expressing types, essentially. When you actually do make a transition, it feels very object-oriented, I would say, even though it's not. It feels like you're mutating but you're actually doing a transition. Does that make sense? TARAS: I think for anyone who is familiar with what it's like to write queries for GraphQL, if you're not familiar with it, it's fine. You can get a sense of that from microstates but if you're familiar with the ease of just writing a query and if your backend knows how to retrieve the data, then your queries will just give you the data that you want. That feeling is really powerful and just being able to write the query and just gives you what you want. Microstates is kind of like that. Actually, the inspiration came from experiences with GraphQL, which is that sense of ease is what we wanted to have in microstates and so you get that seems sense of like, "I can just do what I want and it just going to work and with this other thing and it just going to work," and you're just like flying through, like adding states to your application and it's just working for you and working for you and working for you and you don't have to do monkey work like gluing things together. It'll change how you are working before because you have a way of opt working with these things at a higher level. CHARLES: Right. Let's talk about transactionally or should we talk about immutability? How does this make immutability easy and fun? TARAS: I think one thing is that you don't have to write reducers and you don't have to do destructuring by hand. I think you have a way of expressing. Thinking about this, if you have a component tree and let's say you have redux and then a bunch of components like your parent component, your root component has some state using sets date and then components further down the tree also have state. You could actually express that as a microstate. What you would do is, essentially the parent component state would be the root and then the children's component states would be composed into it. The nice things about doing that is that at the root level, you have access to transition state of the children declaratively. You know where the states for those children is on the route type and you can write transitions that are going to declaratively perform multiple operations on the children state and I suppose it'll restructure to what happens with components but if you don't use this, you might have multiple sets date operations. The process of wiring data from the root down to the children is kind of complicated, where here, you have a way to represent that and perform a lot of transitions in the way that is going to be just easy at whatever level you need to operate at. CHARLES: Right. I think, for people familiar with redux, in redux you act globally and then you react locally, if that makes sense, so you dispatch an action to the entire store and every single reducer can see that action. There's ways to manage that but effectively, you have this one atom and then you have the reducers that kind of act on local state, whereas with microstates, you're basically acting locally. You're reacting locally but the effect is global. TARAS: You're participating globally. CHARLES: Yeah, participating globally but you never have to consider the context that is above your own, so you never have to be mindful or cognizant of the context in which you're enclosed because from your perspective, it just doesn't exist. DAVID: Every microstate has a set transition which is the basic transition that you can invoke, essentially in any type, so what's interesting is that it's amazing how powerful -- CHARLES: So, we should break it down really simple. Basically, when you create a microstate, with a type, you say like, "I want to create a number with the value five," and then I can just say, "That returns a microstate," and I can say, "microstate.set 10," and that will return a new microstate who's also a number but the value is 10 and that's available on all microstates. DAVID: Yes. If you have a tree of components and your state is presented by a microstate at the root level, then what you can do is you can invoke the transitions on any part of the microstate and it will just know how to properly create the next microstate for you. The example that Charles you gave of one number so that number can be inside of a class that represents state for a particular component and then that can be a part of another class or represents a state for another component but then, when you invoke a transition on one of the leaf nodes, an equal sets state on one of the leaf nodes or equal set on one leaf nodes, it will respond locally but it will actually reflect the changes globally. At the root level you're going to get a new object that causes the components to update. CHARLES: You know what? I have another concern that actually just popped into my head, which is something that I've certainly struggled with in every single application of notable complexity is stability of value. We should put that on the list. We're almost out of time to talk about this. We spend too much time... Well, not too much time, of the issues of state management, which I think you can't spend enough time talking about but I did want to pile one more on there is when you're making that transition, where you're acting locally but you're participating globally. For things that are unaffected by your action, remain unchanged. That is a super power. It's actually very hard to do with a lot of state management, especially when you're cloning a bunch of stuff, being very judicious about what you don't want to clone. Where this really comes into play is if I want to re-render something. A lot of times you have to jump through a bunch of hoops to tell, did my model really change or did only referentially change? With microstates, when you make that local change, if you're embedded in a very large graph of objects, obviously all of the objects above you are going to be changed but what about things that are off to the side of your siblings. They're outside of that scope of that change. They shouldn't be cloned. They shouldn't be copied over. They should remain the same. If you're doing a re-rendering based on the changes that are happening, that's going to be a key feature because you're not going to have to write, basically any hooks to say, should I have to re-render my component. You can always rely on triple equals. DAVID: This quality is going to describe the structural sharing and some of the other tools that are available but I think that's how it's accomplished. I think one thing that's a little bit different with microstates is that when it comes to structural sharing, it's not that difficult to do if you just do structural sharing and value. Meaning that you can do structural sharing on a value using something like lenses and not a lot of people are familiar with lenses in JavaScript but it's actually only three functions that you can use and it can give structural sharing on complex POJOs. It's pretty easy to use relative to how little people know about it but what that doesn't do is it doesn't allow you to graph of objects that have their own operation that you can invoke and that will perform structural sharing. That part, I know that is not available in any solution, I think at the level of completeness and luxury that microstate provides when you write things. CHARLES: Right because every piece of the tree kind of comes bundled with its own things that you can do with it. DAVID: I don't think you should jam everything into this podcast because there's a lot to talk about it. I think one of the things and we've talked about this a lot, which what we want to do is create an implementation for an idea of what it would look like. What would it be like if we had a composable state primitive that we could use to describe state and share state solutions in the same way that we share components like react-virtualized or whatever your particular frameworks or popular component may be. What it would look like if we had solutions to state problems that we could share and we could -- CHARLES: I think the litmus test of an awesome solution is like you look at this current crop of MVC frameworks and what's so awesome about it is they're sharing. That can happen, right? If I'm writing a React component, I can publish it on npm and other people can use it. If I have an Ember add-on, I can publish it and people can use it. They can consume those components. That's awesome and I think it's the hallmark of a great system. What would it look like if I wrote just the state piece of a file upload and I could publish it npm and then anybody, in any framework, could actually use it with their framework without paying any penalty. What would it look like if there was some transactional data store that could be built and shared and the hooks into any framework were minimal. The possibilities are really exciting around that idea, whether it is realizes microstates or not. But clearly, we feel this is something you should be able to do. DAVID: I'll add one more use kind of use case that I personally find really motivating is that there's a lot of companies that are investing into building single page applications and a lot of times, what you see happening is they're building a very similar application to what they had before because their business hasn't changed. The technology has moved on so solutions have improved. The demands for better user experience have increased but the actual business and how the things that people have to do on day to day within their company hasn't changed. What we're seeing right now is we're seeing the same, like whatever was written before in jQuery or an AngularJS is now being rewritten in React or Angular or whatever you might Choose. But whatever you like to see is it has a situation where the domain specific logic of your business is represented as a data structure that knows how to, potentially, in the future talk to the server and retrieve data from the API because that's likely not going to change. But you can use that like that's been tested and published as an npm module within your enterprise and then you can then consumed that in any framework and it's actually easier to do it this way, than to implement it in a framework-specific version of their state management. That's the part that I find the most exciting. I think one of the things, just to connect to the goal is that, we would like to keep this conversation going. If you're interested and I think this is a kind of a call to our audience that if you're interested in this, we would love to have in our podcast to talk about these things because I think there's a lot of things that microstates really is a beginning of a conversation. It's not meant to be a statement. It's meant to be a proposal that we can just talk about this. CHARLES: I agree and that's one of the reasons we're keeping it very small at this point. The core library of microstates is not setting out to accomplish too much. In the core library, there aren't even any side effects. It's actually impossible to have side effects. It means that it cannot be used for anything except for the model but that's very liberating and it let us focus on what would a system like this actually look like. DAVID: It's really exciting because this has been the biggest metric but we have microstates in the JavaScript weekly and that was great and then it got circled around when people know and it's like 800 stars now, which is not a really big deal. It's funny because somebody commented like, "How can you put something in production that only had 100 stars?" CHARLES: I think it's just important to realize that this really is the beginning of a conversation. There's a really exciting set of things to come. We haven't even talked about how we're going to model side effects, although we're going to use microstates to do it. We haven't even talked about what the various framework integrations will look like and what are the best practices for using this to organize state in your application. We've had some lively discussions internally about what that looks like. There's still a lot of questions but it's going to be a really, really exciting and edifying experience to get to answer them. DAVID: Yeah, it's pretty exciting. I'm excited too. There's been a lot of interest from people in microstates, so it's going to really great. I'm looking forward to meeting people and having conversations about how we can use microstates because I'd love to have someone create a really great solution that I could just take off the shelf and just use and not have to implement them myself. CHARLES: All right. Well, I think we could talk about microstates for at least the next three hours but we have to give everybody an opportunity to, at least like go to the bathroom or something. Microstates will return but if you're interested in learning more about microstates and you happen to be in one of the many places on which we're going to be presenting on microstates in the future, who knows? Maybe you can come in and join the conversation in person. Taras is going to be speaking at Toronto.js on July 30th. He's also going to be presenting at Manhattan.js on August 8th and then, yours truly will be presenting on microstates at React.js Austin on the 6th of August. Come out and see us. We'll drop those in the show notes and it's guaranteed to be a good time and we'll have that conversation. Until then, we are the Frontside. We lead with the why, the how and then the what, if you're interested in working with us and that helps us that we guarantee the lowest total cost of ownership for your application. We're always looking for feedback. If you have news items that you'd like to see at the head of the show or just any feedback or questions, we would be happy to answer them. Thanks today to Mandy Moore for producing our show and next time, we'll be talking with Kristian Freeman about what it's like to run an online conference with Twitch, so I'll be looking forward to that. Bye David. Bye Taras. DAVID: Yeah, thanks for having us. TARAS: Bye. CHARLES: Yup, and bye everybody. See you next time. Next Time: Running An Online-Only, Free Conference on Twitch with Kristian Freeman
Добрый день уважаемые слушатели. Представляем новый выпуск подкаста RWpod. В этом выпуске: Ruby If you're upgrading to Ruby 2.5, you should know about this undocumented change to CGI.escape, Rails Asset Pipeline Directory Traversal Vulnerability (CVE-2018-3760) и Demand for Ruby on Rails is Still Huge Do You Know How Hash Table Works? (Ruby Examples), Caching counters with ActiveRecord's counter caches и Breaking Up a Monolith: Kong Case Study JavaScript Electron 3.0.0-beta.1 released, V8 release v6.8, ESLint v5.0.0 released, MobX 5, Introducing A-Terrain - a cartography component for A-Frame, A-Frame - a web framework for building virtual reality experiences и We analyzed the GitHub Issues from the most popular Front-End frameworks, here's what we found Sunsetting React Native, Introducing Teleport: Over-the-air hot reloading & debugging for PWA's и DevTube - The best developer videos in one place
Joel interviews Michel Weststrate, author of Mobx and his new library, Immer. Today they get into the power of Immer, its early success on Github, common mistakes in state management, and what is next for Mobx.Immer is a light-weight, immutable state-management tool. Michel talks with Joel about some of its capabilities. Immer takes an object and a function and can track all the changes made to that object, it then gives you back the original object and a mutated copy. Immer can replace reducers, Michel calls them "producer" functions as they "produce" the new state.Joel then asks Michel "what makes state management so hard for people and are they overcomplicating it?" This question leads to Michel explaining that people don't think enough about the structure of their state enough up front. When you talk about state, there are three distinct concepts, values, references, and identities. However, people tend to only think of state purely as data. "You have to think about what is going to store it and what is going to reference it."Michel talks about how the mobx-state-tree fits into an application. Mobx is unopinionated; it doesn't tell you how to organize your stores. mobx-state-tree, however, is very explicit about the three concepts of state, values, references, and identities. With mobx-state-tree you organize your data into models and tell it how they relate to each other. It's all about consistently organizing your state!What's next for Mobx? Michel is currently working on some exciting features using proxies to make Mobx even more transparent than it is now. Michel has also been thinking about improving on asynchronous processes and how to leverage async actionables.Transcript"Michel Weststrate creator of Mobx and Immer Libraries for JavaScript" TranscriptResourcesImmerMobxMendixMichel WestrateMediumTwitterGithubegghead.ioJoel Hooks:TwitterWebsite
Добрый день уважаемые слушатели. Представляем новый выпуск подкаста RWpod. В этом выпуске: Ruby Ruby 2.5 added delete_prefix and delete_suffix methods, Chain of responsibility design pattern in Ruby и Using elasticsearch in a Rails application ComfortableMexicanSofa - a powerful Ruby on Rails 5.2+ CMS Engine, Partitionable - gem adds support for using the PostgreSQL partitioning mechanism и Tracking Errors with Sentry JavaScript Announcing the Initial Release of Mozilla's Open Source Speech Recognition Model and Voice Dataset, MobX vs Redux with React: A noob's comparison and questions и How to Organize React Files Before It's Messed Up GiraffQL - an interactive GraphQL exploration tool built with React, Reactopt - CLI React performance optimization tool that identifies potential unnecessary re-rendering, Vuetron - a tool for testing and debugging your Vue + Vuex applications, Rapid.js - an ORM-like Interface and a Router For Your API Requests и JSRobot - learn to code by playing video games
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!
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.
Добрый день уважаемые слушатели. Представляем новый выпуск подкаста RWpod. В этом выпуске: Ruby Ruby 2.4 adds Set#compare_by_identity and Set#compare_by_identity? methods, Ruby 2.4 Released: Faster Hashes, Unified Integers and Better Rounding и The 15 most popular Ruby links of 2016 Concurrency in Rails 5.0, Scale Out Multi-Tenant Apps based on Ruby on Rails и Crystal new year resolutions for 2017: 1.0 Rails Security Checklist, Periodic Tasks with sidekiq-cron, RailsOr - support && Add syntax sugar to #or query method in Rails 3, 4, 5 и PluckAll - pluck multiple attributes in Rails 3, 4, 5, and can return data as hash instead of only array JavaScript The top rising JavaScript trends to watch in 2017, What to learn in 2017 if you're a frontend developer, 10 Web Predictions for 2017, Vue in 2016 и InfernoJS 1.0 Web bloat isn't a knowledge problem, Lazy Evaluation in Javascript, Let's use const! Here's why и From Sass to PostCSS MobX - Like React, but for Data, BunnyJS - Browser ES6 framework, Table-dragger - easily add drag-and-drop sorting to your table without jQuery, Markdown.css - CSS to make HTML markup look like plain-text markdown, AVA - a blazing fast, concurrent, and futuristic test runner, Leakage - Memory Leak Testing for Node и Rellax - a buttery smooth, lightweight, vanilla javascript parallax library