Hello Thank you very much. Hi guys, I'm Connor Justin And I'm Igor Puskaric and here we are here to tell you about Limitations of real-time 3d art how to overcome them how to solve them optimize for them And maybe who knows maybe improve your art with them first a little bit about us I'm musician and 3d artist with traditional art background. So if you see me with a sketchbook like a lunatic Then that's normal Here's my succulent Fifi you guys gave it to me at last year's conference. And as you can see it's doing quite well Despite the fact that I dropped it once or twice and On the right you see me in a hand-to-hand combat with a rabbit peco That of course happens in a traditional Swedish homestead and I've been doing 3d art for 11 years now and Using blender to do it for four since the legendary 2.8 release And here you can see examples of my work some colorful dioramas Asset packs game environments and recently a movie. What about you Igor? Basically, I've been an artist my whole life doing 3d for only 15 years and Some Best kind of fact about me is that I like ideas. I like to merge Different things that are perhaps not mergeable and create something new for this I use tools of drawing tools of animation and tools of 3d modeling and And they combine each other and inspire each other In terms of software first, I first I used 3d soft 3d Max and then I also taught Z brush and then lately I tried the blender and I so far never looked back And for for a while over the years I have been Growing growing in terms of public presence. I won some awards got features bucks by some big and smaller name companies Worked with some really awesome people had some cool blogs and podcasts Lately I now have permission to set I had the honor of participating in creating a curriculum for the Croatia's school system However, I also work as a Blender teacher in the Novská Pismo which is Basically understood as a Croatian Gaming Center. I'm also a sketch web seller and a master just like Conrad My utmost Excitement happened when my model worker 12 Became head model on the sketch web's main page All right when you create a 3d scene for real-time Usage like video games AR on the web You face hardware and software limitations Those could be GPU not being able to render high res textures or too many polygons or your game engine not supporting Soft-body physics or dynamic lighting and we all use work arounds optimizations illusions and tricks to get around these limitations now Imagine that you have a very beefy PC very strong PC and very powerful game engine So you have no limitations whatsoever You might want to still take these detours because there are interesting to explore and they determine new art styles and We're gonna need example and together with Igor. We have created a movie But not just any movie. It is an interactive short 3d movie on the web in a browser We published it on Sketchfab and you can find it on my sketchfab profile if you're interested and In there you can zoom in pan around orbit and inspect the scene as the movie plays out You can check out what are what are the PBR maps? What you can check? What is the topology and everything like that? There is a whole article how the movie was made so if you're interested you can check it out on sketchfab.com slash blog and You can see the movie itself on my sketchfab profile. Maybe maybe not now, okay? So what are those limitations that we want to talk about today? So since Sketchfab was not Originally meant to do what we were intended to do We had to face some basically low-poly budgets lighting low texture budget and Animation restrictions. Yeah, those are all limitations. We have to face starting with low-poly budget So when you create art for 3d real-time graphics Best way to optimize Huts off is using LODs. LODs are lower resolution models that replace original mesh as you get further and further away from it And this is LOD zero the highest resolution Ld1, Ld2, Ld3 and so on Some engines like Unreal are going to generate those LODs for you, but most not so it's good to know how to create them You can do that by decimating loop cuts in Blender or by decimating topology using the modifier Just don't decimate it too much For our project. We didn't have LODs So and the top and the budget is very low. It's on the web So it's only 500,000 triangles for mobile and 2 million triangles for average came in PC Somehow we managed to keep this is the final scene of the project and it has only 180,000 Triangles, so how did we do it a first step and the most important is creating blockout blockout is a simplified geometry without any details no textures and You can see iterations of it and this one is being the final the blue line Let's call it a focal line Represents the path that robot protagonists heroes of the movie take and this blue line represents And it it affects blockout as well as block out affects it But more what is more important is this blue line determines Objects and their distribution and distribution of detail in the scene Within the block out there are so-called placeholders and one of them some kind of a pipe system We separate and finish it have a proper topology Fully fledged model and this becomes an example a template of a sort for every other model in the in the project But not every model is going to have the same density of topology something that is close to the focal line is going to be higher resolution and The objects further away are going to need only enough to keep their form and to have a good silhouette against the background That creates a distribution of topology This image Showcase is actually what Conrad was saying right now High poly mid poly and low poly are the divisions So we gave our robots the highest poly since they're the main attraction in terms of action and moving Then we have the mid poly which is the near approximate environment and the green Represents low poly things out of the main focus just sort of to fulfill the scene but to be there Mm-hmm to summarize this chapter Best way to optimize is using LODs if you can't do that create a block out then within the block out have Placeholders and one of them maybe you can turn into some kind of a template model which serves as an example a system of topology for your project and Last but not least is having a proper smart topology distribution dense where it matters and scars where it's far from the focal line and Some artists who embrace the limitation of low poly art kept on lowering and lowering and lowering the topology and And they figured out that we don't need millions of them to create something that is appealing and beautiful. Thank you, Paulie perfect Next chapter light limitations in real-time 3d graphics light calculations are heavy So this is why we bake them bake lighting Bake light is not physically in the scene, but the data from it is so this could be both volumetric data and flat and Volumetric one is captured by so-called light probes This is screen shot from unreal and those light probes are responsible for illuminating objects that move like like the player for the environment And then we have a flat data as is screen shot from unity and this shows light maps This is they are used to illuminate objects that are static and this is being saved to a second UV channel In our project we have both moving objects and static, but we have no light maps nor light probes So what did we do take a look? This is final version of the blender scene in here We had 44 light sources and Extra shadow casting planes to darken some areas of that cave over there and the bottom of the pit Now on Sketchfab, however This is how the final final scene looks like as you see all the lights have indirect lighting contribution light Scatters all over the place in in the final scene on Sketchfab We only are limited to free light sources and HDRI and we have no invisible shadow casters as well as none of these light sources actually contribute indirect lighting pass So how do we transfer all that lighting data from Sketchfab from blender to Sketchfab? We do it by baking light into textures This is how one of these textures with light baked in looks like it's not just any light It's indirect light and you can do it in blender by using cycles combined in bake. Just make sure to uncheck the direct lighting option This big looks pretty, but it's quite dark And the secret ingredient of this method that doesn't use light maps or light probes is to Input this thing into a massive slot on Sketchfab on the web So one two three those are directional light sources that are responsible for dynamic shadows in Sketchfab Everything else all of these 44 light sources all of these invisible shadow casters all that indirect lighting contribution is done by emitting light through textures So we have a problem because if our character our hero hero is in light It's all good. He can read a book, but when he gets to the shadow He becomes completely dark Now for moving objects, we also need to use emissive input So it is good to find a balance in this workflow to have if you have too strong emission for objects that move They're going to look too to light too bright in areas that are lit. However, if you have too weak emission They're going to be too dark in shadows There's another lighting limitation that we stumbled upon when working on the on the movie and that is We have dynamic shadows, but we are not allowed to move light how to go around with it Our friend from Ireland Tyco He experimented with this stuff and he came up with a bunch of nice solutions that we want to present to you The first one is if if Mohammed cannot get to mountain Maybe the mountain can get to Mohammed. So light can't move. Let's move the environment instead Here we are at three spotlights to these light orb and it is static and violent moves Don't ask me why spotlights It could be a point light, but for some reason it doesn't cast shadows But we want shadows and if the camera stays close the illusion just works What if you have a multiple light sources that move independently from one another? You can no longer use the environment moving because it moves on in one vector So for that but you can do at the strong emission to the sphere then in post processing and bloom Now it appears as the sphere is actually emitting light. We are using illusions tricks But unfortunately the light is not actually illuminating surfaces around it unless We put a fake sphere behind the rock and add very strong bloom to it Make it bigger and make it and mirror the movement of the sphere that is visible Now if we add a translusive Refractive translucency to the surface of the rock We have that bloom of the hidden sphere scatter through and it this creates illusion of light illuminating surface of the object Speaking of illusions, there is also a third way This way we have a spotlight that cast a shadow How well even though we cannot control the light itself We can control the condition conditions the light passes through so we get this plane We can animate it through blend shapes or through object-based animation or through texture-based Shape that just alpha keys basically and we can also control it through the any underlying geometry such as this fan and Then it gets such a tool that we produced on the surface below. We mentioned those limitations because discoveries while exploring solutions to these problems and They determine identity of your style they can determine identity of your style. Thank you Taiko for your lessons to summarize this chapter Have your key lights the main most important lights real-time and bake everything else into lightmaps light probes Or if you can't have those use emission, but just remember if you use emission, you can only add lighting You cannot make things darker Keep it in mind. If you if you have bright scene, it's not gonna have any effect You can bake emissive Indirect lighting in blender you can do it with cycles combined bake and When you use this technique you find the balance between receiving light the PBR and Producing light the emission setup if light can't move move the environment instead I use the emission and bloom in post-processing and refractive translucency to to create illusion of illumination upon the surface and animate the shadow casters Next chapter textures textures among among the most demanding things in CGI both with their size and their Amount so what did we do we do that by putting them in a spare? Sorry in a square space based on power of two so 1k 10k doesn't matter as long and it can produce midmaps Which is a similar? optimization that LODs do with 3d models meaning that they Recalculate based on the camera distance You can also tile textures this means that they Transition into repetitions of themselves they can tile horizontally vertically or both ways this allows you not to create extra texture every time You run out of the UV space You can also create one texture. That's valid enough to create Multiple models or parts of models which you can practically create infinitely after having that one texture and Last but not least you can pack textures into atlases This is one of these what this is atlas and they're being rendered in one go just one draw call on the right You see the unity our engine forcing us as artists to shove individual maps into separate channels of RGB a texture This is also a form of optimization, but then it looks ugly You can't tell what the hell is going on here unless you open it in Photoshop or gimp and inspect each channel individually What a mess for sparking BB for the movie we were Restricted to a square of dimensions 12k on 12k that relates to 9 4k textures And somehow we managed to fit within How did we do it? The first important step is to group geometry into materials This could be rock metal sand by the resolution of the object by whether the object is moving or is static By whether what is the position of the object in the scene? How how it's being lit or by their purpose and here's the example me and Igor made asset pack and Here you see how they are divided so material rock rope metal and then within the metal part What is their purpose? structural metal sheets metal pipes decorative In the movie we divide based on position in the scene and Lighting this is because how we bake light into textures This just makes it easier for us to work like that and then we have renders very basic renders and paintovers I do those paintovers in Krita and in blender So here's one here's another And Based on those paintovers. I know exactly what texel density. What is the resolution of the texture that I need? So you might see that this giant rock The face of the giant it might seem important, but it actually is in a shadow So it doesn't require as much texture resolution and thus its UV islands can be scaled down Leaving more room for UV islands of the engine or the hand Now these paintovers are used to create diffuse textures and based on diffuse We make all other maps such as metal leak roughness specularity and so on Last step is to convert them into JPEGs and make them smaller some of them. So they all can be shoved into this square To summarize this keep your textures in a power of two so that midmaps can be generated Tile your textures horizontally vertically both ways reuse textures just like Iggy did with his drone pack Use atlases and use separate channels of RGB texture if you want Now it's probably good to know the budget of your engine and When you finish modeling group everything so that you don't have 400 textures for when you have 400 models That would be just crazy Figure out the texture distribution. We did it with paintovers. You can do it with Just thinking what is important in our scene. What is close to the focal path? That's gonna be higher texture texture texel density And last step is to generate all needed maps and pack them into the top all the texture budget and By embracing this limitation as well as the previous one the low poly a Beautiful art can be created windmill by Wacky on Sketchfab. Here's the prime example of the voxel art every single voxel cube is just one color sphinct on radit and Here's one more. This one uses a very simple gradients of value and color and to project on to very basic topology and creates appealing and beautiful results Thus chapter animation restrictions As such Blender does not have restrictions But there are morphs. There are armature. There's soft body mechanics. There's hard surface Particles in object transforms however Not the point point is what we needed in this project is Is Only what we what we needed What we didn't compared what we had Was limiting meaning we had constructions We only had the object transforms and we had armature and we had morphs like it. What do we do? Like it it turns out that every animation that we don't have can be somehow done with the one we have and this means that rigid body Simulation can be done with simple object transforms key framing those Particle simulation like it can be done also with key framing individual instances of particle objects Soft body like rope swinging on the wind can be done with simple armature rig and light light turning on and off We don't have dynamic light, but we can fake it with using shape keys For the rigid body you can simulate it in Blender Then you have to bake it right into cash Then you have to bake it again into keyframes and those this is how the screen frames looks like look like you have to optimize them Further by decimating them. It's a bit messy. You can skip that limitation completely by manually animating Objects falling down and for this motion paths turned to be very very useful So they show you trajectory as long as it looks like a parable and this you know, we know that's relatively believable, but we can do whatever we want. We have full control Basically, it's all about simple tricks. For example, we did lights turning on and off, which we cannot have obviously However, we approach that trick with having two plates one one is not a missive one is a missive So we just animated the emissive one in front of the non-emissive one which gave the effect of his eyes turning on So what's the ropes? I'll show you the ropes So in the project we have a rope that is anchored on both ends now It's it's middle swings gently on light Martian breeze. This is normally done Well, it's not normally done because we don't have ropes on Mars But if you had we would use cloth simulation, right or soft-body physics to achieve that effect Instead we can have two bones chains of bones that meet in the middle in the control point And then we just simply animate the control point in the elliptic pattern adding extra swaying motion and that gives us a believable motion of work rope swinging in summary When an engine doesn't have all benzels bells and whistles You there's always some that it does have and you can transform in a way for it to seem as though They had all of them Mm-hmm. You can simulate things like simulate a soft-body physics or rigid bodies, but it's a long lengthy process and you You can skip it entirely by my doing this manually By and that and with when you do it you have great help from motion motion paths Or you can use for example bones for for the rope a rope simulation All right, last notes All these things in the bag the topology restriction text the texture this is a restriction lighting and animation limitations They determine Unique feel of real-time 3d graphics a field that we learn to recognize and love and So even in the future with technological limitations gone. We might still want to choose to limit ourselves There are not so many things in this buck just a couple But amount of solutions and work arounds and optimizations are Infinite and they're yours to take and they determine your art style Just like the determined art style in our project and hopefully after this short presentation You see how these everyday limitations affect your art and who knows? Maybe this realization can help you build upon your artistic expression Thank you


functional JavaScript today but before we dive into monads and get into some complicated stuff I want to talk about just a little intro about learning to program as a working programmer which is I don't know I feel like that's something that we don't talk about enough because it's like it is like simultaneously the most exciting and stressful and anxiety inducing thing in the world to be a working programmer who's been doing it for a long time and then to have to try to learn an entirely new way of programming to be a beginner again and so it's a lot different like if you've never written a line of programming before and you start to look at like you know doing things in a functional way I will say that it's probably easier for you because you just you don't know any other way and you can just kind of like you kind of like build and go from there does this program look familiar to anybody not those specific syntax but I've probably written this a hundred times like every intro to object-oriented programming class has some sort of variation on this where you you know they try we're trying to demonstrate inheritance here so we have a base animal class with some properties and some methods and and then we do something like exhilarating and amazing like create a dog class that can override some of these methods and if you were able to stay in your seat with the excitement on that you know you can extend it even further and create a person class that does things like we can tell it to walk it complains and says I really have to and so like this is how we learned how to program right and but when you think about it now like does that get you fired up as a programmer like using object-oriented techniques like you get like who wants to leave this talk right now would go like write code because you're just like motivated by that it doesn't happen at all right but at the time we didn't think that it's because we didn't we didn't really know anything right and so the reason why we went on to build these amazing complex systems in object with object orientation and the whole reason why you're here today is a working programmer is because we put in the work we you would go home and you didn't know anybody like this is how I build programs and so we thrashed and we built things we built real things and we ship some stuff and that is the whole reason why it became valuable and why hopefully we get paid to do the work that we do every day but hidden under those like that tiny original example were some big ideas like inheritance of polymorphism that the instructor was trying to get across it's just now it's just it looks silly to look back at it so these are big ideas but we put such small examples right and I think the same is true when we try to learn a new paradigm and this is a common thing that they'll show you when you learn a functional approach and as a working programmer so if you're at the beginning like oh curry this is kind of a cool thing but as a working programmer now you're like cool this literally helps me do nothing as part of my job and so we don't get excited right we have a higher bar now and it's a lot harder to get us to change our minds about about writing things and it's funny if you ever ask somebody oh have you used X framework or library how many people have heard the answer oh I've played with it or like I've toyed with it that's like the new you put on the resume when you've played with it which is like a weird thing because it just pretty much means you typed out the example but never used it in a real in a real life setting and so and that's because we did it but we didn't really see how to apply it in the real world and there some amazing functional tutorials and books like functional JavaScript by O'Reilly is an amazing one but I and I think you have to start there but I think there isn't enough from going in the reverse angle so what I want to do is kind of like reverse engineer the hype to talk about building a whole system in in JavaScript instead of starting from the ground up and so hopefully it's just a little bit of a different take but adopting big ideas is hard right this is the reason why we toyed with that functional language or framework and didn't actually start doing it is because how many people have seen this book before yeah I figured we'd have something like that but this is Douglas Crawford so he actually gave a talk a year or so ago and he called the better parts which was pretty interesting and he talks about this idea of adopting big ideas big new ideas and he says it's way back when it took a generation for us as the programming community at large to agree that high-level languages were a good idea which is funny to us now because like you could just picture like some assembler some assembly program which like why see like really do we really need to have like that level of of sort of sophistication in our abstractions it just seems like a waste like why would I waste my time to learn a whole new language for that now that's obviously it's we consider that silly right and then it took another it took another generation to agree that objects were a good idea so when we consider to be you know how we build apps today was once thought about it's just unnecessary right like we had we had programs with functions and we could do all these different things and so like why would we go through the trouble of like creating a dog that inherits base animal like I just don't see the but now we sort of take it for granted right because we are the generation that adopted that and then he says it took two full generations to agree that lambdas were a good idea and and so but now lambdas are in every language they're in like in dotnet these core object oriented languages are now everything has lambdas right and so he makes the argument that lambdas took two generations because they have the best idea in the history of programming and so I didn't really follow that logic maybe we just wanted to get it right so twice as long not really sure but what what I really took away from this was his next quote which is in order for us to wait for the next big thing to catch on we need to wait for the previous generation to retire or die before we can get critical mass on the next idea I'm this is a quote I'm sure I got every word right because when he said this the audience started clapping and laughing and they went crazy and I was just like this is getting dark how did this happen so quickly and so I I understand the sentiment like I know what he was going for there and it's the same thing it's like you get home from your job you don't want to learn a new thing or you're interested in it but it's just it's a lot of work and so we'll wait for the next people to do it and I'll just hang on to my my language isn't doing things the way the way I do it but I did take a different approach I'm gonna be a little more positive and like we're here a lot of us are here on a day off or like we could get work we're taking our time to further ourselves professionally we are not the programming community at large this is a group of people who is here today interested in making themselves better and so I think that for us to adopt big ideas the real thing we need to do is we need to make real apps with it because we need to see it all the way through instead of that little utility function we need to see the end result and so that's this is what I'm gonna talk about today so here's here's the agenda I'm gonna briefly cover why now and why JavaScript just because you're gonna have you you're gonna get confronted with this all the time so let's just squash it then we'll talk about functional patterns for real apps this I hope to be the meat of this talk today and then lastly we'll talk about revisiting the mental model because we're sold on object orientation as being the only way of doing things because it models the real world because of that mental model where we can make the relation of it is this thing in my program that models a thing in real life and so I know how to program it and we'll just talk about how or if that changes and we start unfortunately with this public public service announcement that this is a talk by a practitioner for pro for practitioners we're not going to talk about math or like any sort of like crazy high-level concepts because that's been covered a because it's been covered enough by everyone else and b because it would be disingenuous for me to do anything else I'm building real apps and I want to build apps in this way and so that is what I'm going to talk about and it's unfortunate that we even have to have that as a PSA public service announcement because for reasons like this right Uncle Bob Martin who's like this guy's no slouch he knows what he's talking about he says the arrogance of some functional programmers is a significant barrier to entry right so God forbid you post a question about functional JavaScript in a forum and you just get torn apart by some of these functional guys and it's not just him this is the creator of low-dash says you know unfortunately this mirrors my experience too again this guy knows what he's talking about he is not you know some beginner person and if these guys feel that way when you first start going down this path I need you to be aware of of these people because this is forever like this is just every programming forum ever and there's a million memes like this but I really like this one not even a soccer fan but like particularly look at this like look at this guy's face he's just happy and these guys are just like look at this he's trying to write functional JavaScript start even a real language it's a toy language like why is he wasting his time well every time someone does that to you I want you to feel like this guy right because this guy just shipped something he just shipped a feature something is real in production he's just gonna go have fun now while these guys are just gonna hang back and whine and complain so realize that when when haters hate on you in the forums or whatever you feel like oh I'm not smart enough to do functional programming because these guys say monad over and over again it has nothing to do with being smart enough it's just this is this is the the world that we we live in sometimes so so then why bother right if it's like this I just made it sound like this incredibly harsh landscape so why do we want to do functional anyway Dave Thomas is a guy that I've I've sort of like looked up to my career he's the he wrote the pragmatic programmer and so he says there's no longer any debate the future has to be functional immutable data and it has to be concurrent it's the only way to grow and then Uncle Bob Martin again it's almost certainly true that functional programming is the next big thing I like this one just because Uncle Bob Martin authored the solid principles like to me he is the object-oriented guy and so how many people here feel confident and certain that the JavaScript libraries are using today is going to be what they're using next month like we don't have certainty like in front of them but there's a whole lot of certainty in these two sentences the future has to be functional it's almost certainly true and so why how can they have so much confidence in this does anyone know what this is I'll be surprised I didn't it's Moore's law right that's pretty good thing I can spot that and so this is just it's the transition coming up over time and talking about how it doubles every two years and I looked at this and like this is a pretty good slope if this was my bank account I'd be pretty happy but the even the more interesting thing is if you like dive into the data here right so it's like we started off in the 70s and 80s going from two thousand to ten thousand which is like a huge jump and then we go to a hundred thousand a million and then all of a sudden we're at two point six billion right so this is impressive but then you realize this is not even a linear graph this is meant so we can like read the lettering and stuff if we actually plot it linearly this is what it looks like this is the same time span in the same actual data plotted linearly has much more of an impact for me but JavaScript is single threaded like why why do we care about transistors or anything like that and so just to be clear the argument there is that in order for us to grow going forward and to get to reap the benefits of Moore's law we're going to have to program it in a parallel and concurrent way that is the that is the argument that we're just otherwise we won't be able to take advantage of of all that new power but the reason why JavaScript is as capability meets opportunity right it's like I'm such a sucker for sports analogies I feel like this is such a sports thing but the opportunity is that it is that the future has to be functional for for every other language right and so then you have this little tiny engine that could in JavaScript that's like it did one thing extremely right and it's the best thing about JavaScript is its implementation of functions it just got everything right in this regard so it's the capability of a language that just happened to nail every the it does a lot of things wrong don't get me wrong but the things that it got right all lend itself towards this functional way of programming and then there's also this other side benefit that I'm not going to spend much time on but familiarity is a big thing otherwise we wouldn't be writing classes in ES six the only reason why these exist is for familiarity for Java programmers in C shop programmers but what happens when the future is functional familiarity is not going to look like this as much anymore and so having familiarity in JavaScript this is a much lesser argument I'm not gonna this is not a building a block of my argument here but it's just something to observe but I promised that we talked about real apps so enough of the intro I want to talk about I created a demo app and it's I swear it's it's the example app that I recreate every year but I reword from scratch so this is a stock ticker and the way the reason why I find it interesting is because you have many different types of concepts that you can demo so this is actually like there's no database it's actually live it's like live streaming data it has so you have to solve like the domain problem you have to have some queries that are live updating on the right whole bunch of rendering things that are interesting in a nice small package so we're going to use this as our demo app today so at first I want to just kind of take a look at this thing as from a holistic perspective this is the real app running let's see if we can boost this up well that's not what I wanted all right so just to show that it is a real thing this is the app running locally and you see it behaves as expected we've got a whole bunch of stock transactions coming in we have opening prices which is just like the you know the price that each stock started at and as you see as we get more and more data and we're able to crunch some of these more advanced calculations that will sort of flesh out on the right so I'll just stop this for now and so what I want to do so the source code of that is completely available because I wanted people to be able to like poke at it and kind of look at what it looks like but I want to talk about this entire UI container and mainly because I just want to get this out of the way functional UIs there's a huge problem and it's that if anyone was here last year I won't rant about this again but the DOM is stateful and imperative and that's just flies in the face of all the functional techniques that you're going to try to use it's going to undermine your functional quest the only way unless you're just using like low-dash is in like your functional paradigms limited to your utility folder you're going to want to solve this problem and by having a functional rendering layer so for me that's react I'm known as the rack I a lot I spoke about it a lot last year but this talk is not about react I promise I wouldn't be that guy today so there are other there are other options as well elm is like one that's huge right now what on the on a come up I should say and there's plenty of other implementations too so if you want to use these other ones be my guests I'm not going to talk about that today I'm going to talk about the surrounding functionality around it but when I do have to rent reference a render layer I'm going to use react just because that's what I know and love so but this is as long as your rendering layer can implement this I'm happy so it should your UI layer should be able to take in all of your app state and be able to render out the same UI as long as the same state keeps coming in and there should be no surprises there that's that is what we'll call functional UI and we're getting there right so like this is the new version of react that just landed I'm pretty fired up about this I mean this is this is everything we want with no boilerplate this is a real component where's this each row in that table is a transaction which just takes in the transaction model and you just return the representation of what you want the UI to look like so that's this is why I like react so much but that's it no more react what I want to do is dive into the other parts of the app I want to talk about this first mainly just because this is the bulk of the app this is where all of our app data lives and I also think that this is where this is where I tripped up at first and so I'm hoping to kind of throw some minor cautionary tale in there and also just kind of point at functional domain logic and how to set that up in sort of a reliable way so this is the data this is all the data in your app and we'll first talk about collections of models and we'll talk about them in those terms because that's the easiest way to understand I think it's fair to say that everyone understands collections of models when I say that so when you think about that table that is just that's that's the collection of each row being a model with only one caveat in that it's all of the data has to be immutable and you'll hear that throughout the presentation and we'll find out why this is important later I use immutable JS I happen to love it and use it every day but you don't have to there are other ones too and you can also just not mutate plain JavaScript objects if you want I just think that takes more discipline and your you could it could be more frustrating to you at the beginning so if you're just starting off I think that this is a more friendly way to go so from the collection perspective what this gives you is gives you like real data structures which is pretty cool list stack map ordered map set ordered set a whole bunch of ways of organizing your data that map that match your business model and it's easy they behave just like you'd expect what's more interesting to me are models mainly just because this is usually where we build our applications around models but first a little side note this is a term I wish I could remember the origin of it but this term primitive obsession has been in my vocabulary for a while from the old object oriented literature I used to read and it's I couldn't remember the quotes so I just paraphrased but it's the idea that your app or your domain model no matter how complex can be described by solely primitive values at the language level so this is things like okay I have a transaction what it should just be a plain JavaScript object like why would I bother like I could just it's a key value and a list of it is just a race and that's fine at the beginning but like as we're going to want to add behavior and different things to that and if you don't have a home for it it's going to end up bleeding out through all different parts of your app and this is where the dry principles come from to kind of reel that in and I'm also going to say that this applies to the library level as well so we have maps list sets stacks etc in immutable but I don't want you to just think like okay that's cool so I'm just going to do everything that way you will fall into the same exact trap and this is exactly what I did and it's also a second trap because what I did was I fell prey to one of these this is a post-written by David Nolan who is the creator of Ohm and he's pretty active in the closure script community and when I was first getting into functional JavaScript I read this and I was like really inspired by it and so I'll just read it so you can hopefully see where I got lost so he talks about tangible data in Ohm it's this object-oriented programming as a paradigm has many real benefits but one of the worst plagues that has inflicted on programming is obscuring data functional programming is not a silver bullet but it's emphasis on unadorned data is a guiding light no models and so that no models part is I was just like yeah he's right you know like we have map and that's like it's similar to a JavaScript object and like I can model my entire domain using that key values and then a list is the same thing as Ray like yeah this is good and maybe I'm sure I'm missing something here but I think it's a trap if you're going from object-oriented an object-oriented style and you go directly into that because you will end up with your business model your business logic living in a bunch of different places and you'll just start to be like okay wait I need a real I need a like real something in here I need a home for all this functionality and that's where immutable records come in and they are just like other models except you can't change them which is kind of funny because people think of models as being the home of your business logic with some helper methods and that's where you change them you call methods you update the values on it so this will seem strange at first but when you actually look at the code that it takes to create an immutable record it's actually the weirdest thing about this for you will probably be the ES6 syntax not the actual record but you just essentially you give it some default values and then you just can provide some helper methods over it if you want to find out if it's a loss like you can put your business logic here and I get that you could put this in a folder with functions somewhere else but I promise that coming from another framework or something like that this will feel more at home to you'll know where to put things and things will let be less strewn about and you'll be less stressed out just by having an answer for where things go and so what are the benefits of using immutable records instead of just instead of just like a regular model like why can't I just use backbone models well first you can trust them and this matters more in a like a concurrent paradigm where you just like hand off your models and like if anything changes that you're screwed like you can't you can't trust it in JavaScript you just get the minor benefit of like you can pass this object around your entire application and not worry if anything tries to mutate it can't and you can count on knowing that you can accurately find the source of bugs because understanding that nothing in your core domain can modify these objects and that really helps you narrow it down but I think the more important but we're to concept at first will be that your app can trust immutable objects does that sound weird that your app can trust them it did to me when I wrote it so so what do I mean by that well let's look at a different part of UI and talk about where that comes into play so as opposed to our core data which is our models and collections we've got these alternate views right the opening price the RSI calculator and you'll see the average loss calculator these are sort of queries on our core data right there functions that you would you have your core data to and you sort of like and you can like process it and transform it so I want to talk about how we do that sort of thing in the functional world since our models are immutable and we need to have and we can't change them so we have to have something to hand them off to something else to do this well this is pretty easy so if the last part was the data this is the functions part of our domain we'll call these services and queries just to give them a name but you already know what they are a service is just a stateless function that accepts and transforms immutable data to fulfill a business operation so if you used to have an order model and a method that says place or finalize or something you you can't do that on an immutable model because you can't change it so you just pluck that thing right off and you have a function called the finalize order or create order and you pass your model into it it will transform it and return a new version of that model that is that is now updated and finalized that's what we'll call services queries are a little bit different they start off sounding the same they're stateless functions that accept immutable data and they transform calculate reduce or repurpose data much like that sidebar we're just taking a different view on it and there's a pretty the big difference here is like we want to really actively cache queries whereas like a service you don't really want to you still kind of want to let the service handle what it's going to do in business logic but a query when you're dealing with immutable data and pure functions if you receive the same object you know that the same it's gonna be the same end result no matter what that is a guarantee that we get and so we want to be able to short circuit that for performance so just to be thorough I want to show you what one of these looks like this is actually the function that calculates the initial stock prices there's nothing interesting really here it just maps over the stock objects and it transforms it to an object that looks like this and we just pass this down to the UI layer and it just knows how to render it there really nothing interesting the more interesting one is the RSI calculation and at first when I created this screenshot I I don't know I just like it from a distance it looks just such like spaghetti code and it just feels like you're gonna be going backwards and but I promise you I assure you that it's not this is actually a module that has about four pure functions in it that easily could have been broken out that are just pipeline together and so I want you to think about if you want to think about who here is kind of like new to immutable data so there's more people than I thought that are kind of sold on it but if you want to kind of understand how this works imagine that you worked at this company that created this app and before this app was created you it was your job to manually do this right so at the beginning at the at the beginning of the week you're handed this folder it's full of data and it's like here's a list of five stocks and I need to find out what the RSI is on on this by the end of the week how would you do go about doing that you would say alright so let's figure out what stocks are there so well first we'll pull out which stocks that I need to figure this out for and then let's figure out the average loss and gain for the last two weeks because that's what's needed and then let's then from that we can deduce the RSI that's pretty easy so you write up your report you leave running just for your boss you come in on Monday and your job depends on this being accurate and then you come in and your boss says I love it the report looks great I modified some of the numbers in there but the end result like it still looks fine I think you should present it as is how many people feel comfortable going in that meeting and presenting their findings you'd have to do it all over again like there's no way you can know what changes like God damn it so there's no shortcut here you have to recalculate everything because you don't know what has changed but imagine that instead of that folder you you were smart and you brought a briefcase to work and you locked that thing before you left your boss he might have some ideas about how it could be different but your calculations are sound it's impossible for the end for the result of this calculation to have changed because no one could have changed the source and so in functional programming we talk about memoization and caching and that's all that it's about if get stocks is like hey this is the same thing I received last time it returns the cash version then this returns the cash version and that turn turns the cash version it needs to do no more extra work until the thing has actually changed that it receives and so that this is a big reason why immutable data is important and when the core of your entire app becomes immutable data you get all of these queries get to benefit from this sort of caching automatically like you just don't have to worry about it because you're not you're only mutating have to and and these functions can tell when it's mutated and when it needs to do actual work so you don't have to write any caching logic it just it works that way and so for the last part of the UI we've talked a lot about immutable data and different things like that but how many people have written a program that never mutates anything or like anything interesting anyway other than a calculator like there's no real world apps have to mutate things and so I want to talk about this sort of interactive part right so we're going to start we can reset configure like this is going to change the state of our app so we want to examine sort of how it impacts that core domain how do we get changes into an immutable ecosystem like this so when we've been talking about no change no change no change immutable immutable immutable pure functions now we're going to talk about change where does we're in our app to these mutations and changes so this part so we've covered the data and the functions now let's talk about the actions and how we change the outside world outside of this well this is where I think we need we we really should like we should rely on libraries to be able to help us in this regard just because it has been such a good idea for me I use redux like I've used flux for the last year or so pretty pretty much every day redux is sort of a slight take on with some pretty good improvements and so it was just I love this title redux is a predictable state container for JavaScript apps that that just sums up exactly what I'm looking for it helps you write applications that behave consistently and are easy to test on top of that it provides a great developer experience with live code editing combined with time traveling debugging that sounds that sounds kind of crazy you can use redux with react or with any other view library this they're actually adapters for angular or like whatever you want to use and this is my favorite part it's like we all it's like oh he's pitching another framework but i'm not this thing is 2k 2k so for by comparison we all think of backbone being like the the smallest of the ui libraries backbone is four times bigger than this so this is not a framework this is not anything this is just like a pattern that you can use to put over your core immutable app that you're creating that is your business logic that will let you trigger actions that update state in the outside world and participate in this in this flow so i wanted to create my own diagram but this guy andre staltz he did such a good job that i figured i'd talk about his and this is just how it works i said this is react for me it could be whatever you want but when the user clicks a mouse it just fires off actions into this store which just has a bunch of feel like your eyes are glazing over but this is where you put your services and things like that so if you want if you you would trigger an action and say like i've got this order and it needs to be finalized and that's it you just pass it into that store your services live in that store and it's like hey i know how to do this thing and so it will accept your order object it will modify it into the next version which is the finalized order version and it will stick that in the store in place of the old one this is how data is changed in in this sort of unidirectional functional flow system so it is completely inspired by flux but i'd argue it's more inspired by elm which i don't know if anyone is really with that but it has way more to do with elm and cqrs which is coming in query responsibility segregation than it does with flux at all it just uses the same terms as flux and so there was there was one mention of time travel debugging and stuff in there and that that can be like a pretty funky concept has anyone seen time travel debugging before so most people haven't okay cool um what i want to do is simulate like these are all nice terms and my goal here is to not give people to buy into like the buzz or the hype behind something what i want to talk about is like making our jobs easier and so i want to actually simulate fixing a bug in this app i left a bug in here on purpose like i always do so that we can go in and fix it and we can see what the difference is if there's any difference between like your existing workflow so if you notice when i ran this app previous to this uh this probably slid right by you but like everything looks fine here we've got our opening prices and then we've got google's rsi is negative infinity uh and i don't like i don't know what that is uh and by the way i don't even know what rsi rsi was before i did this i just needed i googled an interesting financial calculation that i could use to just demo this app um but negative infinity you're gonna get a bug report for that like that's not right even even if it is right you can't be displaying it like that right so what was the first step you do what if this was your app where would you start someone someone said something say it louder yep putting into buggers um and also probably putting in some console logs to like to just look at the state of your app um well one of the cool things about using uh leading on a framework like a 2k library i should say is that uh we get some of these things that are that are built in so this it has nothing to do with my app uh this the only thing this does is it says since you're using immutable data i can rely i can count on you not changing it and every time you emit an action an action is a is a thing that we can point to it is like a little json object that says here's the type of thing i want to change and here's the payload you need to change it almost like you would save off in um like a distributed system if you want to like run a task on like a task you you would like give it enough information that it knows how to perform that job later so every action instead of it being like a function call like like uh events like we're used to it sends that off it goes through that unidirectional pipeline changes the the data and anything that it changes um since immutable immutable data cannot be changed it just leaves that one behind and moves forward with the new version right so every action that goes through leaves a snapshot of state at that exact moment when the action went through the system and since we're saying we won't change anything i promise uh redux can actually keep track of all the stuff force and provide us with some development goals which are pretty cool so um let's see i need to probably see a little better now all right so negative infinity how do we get here so if we want to play with some of these dev tools um we can essentially undo actions that happen as part of the our app so if we toggle off this tick or stop that's when i click the stop button and you see the ui just reacts um because the only thing that we changed was when you click stop it just sets like a boolean flag and so we change the state of that button the bottom right that's all that happened all right but our bug is still there it still says negative infinity so let's start plucking transactions off of our list here so we're we are doing time travel debugging uh by essentially just moving back to that snapshot of state at that exact moment and if we have one giant blob of mutable state we cannot do this because it's still still the same blob we and we don't know what changed from one step to the next and so we can essentially so we've still got this bug and we can just keep walking through until we oh okay so we plucked off that last action and now we're back to a real value okay so now we know where to start we haven't even thrown a debugger or anything like that yet we know that something happened here with this particular transaction that caused our ui to get wonky and then so what we can do from here is we can actually like open up this action and we can inspect like okay this is what happened this is all the metadata that came in um but you know we don't see anything strange but if you'll notice like when you when i'm toggling this you'll also notice that average loss for google is going from 50 around 50 to zero that's the only other thing so we don't know is it related okay all right let's figure let's figure this out so we want to actually dive into what just happened there all right so then what we would do is we would come into our rsi calculation and uh we can actually take a look and we're like okay well so what happened here it's kind of like the rsi like we need to do a bunch of different things blah blah blah but it's all relies on this one thing where average gain divided by average loss and so it seems like something happened where when average loss changes to zero this becomes a problem does anyone know what happened here divide by zero right so it's like okay i think so i wonder if i was smart enough to leave the real working version of the code commented out right below the bug i wonder if that is the case so if we uncomment that and save and come back um we we now see google is 100 okay so by definition that is that the that is the correct thing to do if you cannot calculate if it's divide by zero the value is 100 that is our business domain says so right and now we can actually keep rewinding back and just make sure like this thing it didn't break anything else we can go back in time forward in time and just uh essentially you figure out what's going on and if if you've ever worked with like a live reloading system or something like that you've seen something like this before but there's one big difference though and it's that like this app doesn't persist any state so if this live reloads it's going to blow away everything this is a live feed you can't pause the real world and so uh how can how can we get this sort of like this behavior um without any sort of live reloading and that's what we'll talk about we'll talk about next um i want to talk about uh the mental model of static versus dynamic and also how we got into that world where we could do that time travel debugging and i'll give you a hint it all has to do with the way we we look at actions as they go through our system but first um i want to talk about static and dynamic uh have do you remember the first console program that you wrote that might have just like been calculated two numbers and spit something out how complex was that did you worry that if you ran it and like at a different time that it would like it would be weird and like not output the right thing or like maybe would hang that didn't happen because it's a static program it's pretty easy it does one run through it does its job it prints stuff out and it's done it's over a dynamic process something that runs over time like a daemon how many people have had a problem with a daemon before something like is it dead it just goes rogue it won't respond to anything like this is so much different from that simple console program that you wrote and that is the difference between static and dynamic um as far as as far as we're going to talk about it today and so redux if you read it when we read the docs it used words like predictable and behaves consistently which are big words that don't mean anything really until you can actually like back them up so so how does it make things more predictable and behave more consistently and we'll go back to that requirement that had the very beginning which is we need functional uis and this is why we need functional uis if you remember it takes the entire app stayed in and it spits out the same UI this should be deterministic we should be able to rely on this as a function um and in most systems that can kind of be the case right and so if we're in like backbone world or whatever you have it like if you refresh the page it's always good no matter what the state was right um and so that function of state equals the UI is first it's true the first time you run it but the difference is that this happens in between the first run in your bug and i showed this that same rat's nest of actions in the event slashers because they're fire and forget we just trigger them off their functions that get executed and you're just like if something broke you have to do a debugger or do a console.log and if you're in the middle of 10 actions deep like we were in that stock ticker if that if we made a change and it reloaded we just lost every all of our detective work to get to that state in the app it's gone it's blown away because these things are not persisted these are just ephemeral just events that happen once and you can't really trace them if you contrast that with the system that we just looked at which it actually every action across the system is a thing that you can point to it hold it is an object that goes through that system and you can store it with the data at the time that it went through then this doesn't become so much of an issue anymore this is part of your app state right and so if these are persistable and we can point to them we can look at them we can replay them rewind fast forward then this really becomes true with a function of state plus all of the actions that are happened that have happened since you reloaded equals your UI we can count on that rely on that and that is how we can get these sort of amazing debugging tools and be able to like really rationalize about our UI at any point in time and not I remember how it was and these 11 things happened and I think I still remember how it should render but there's a bug and I don't know how to reproduce it and so I I was debating this is one of my favorite quotes of all time and I think I still don't even fully understand it but I think there's so much in here and I debated not talking about it today but it has to do with that static versus dynamic difference when we're writing programs so it's long so I want to break it up into parts but it's by Dijkstra and I'll read the whole thing at first and it'll likely be confusing but says our intellectual powers are rather geared to master static relations and our powers to visualize processes evolving in time are relatively poorly developed for that reason we should do as wise programmers aware of our limitations are utmost to shorten the conceptual gap between the static program and the dynamic process to make the correspondence between the program spread out in text space and the process spread out in time as trivial as possible and so think about that static as being that console app simple dynamic process that daemon that is very hard to predict over time he's talking about shortening that gap and trying to make it so with pure functions if you look at an ad function you can see the input and you already know the output with long running processes with mutable state you cannot do that and he's talking about shortening that gap so if we take a look at this one at a time first of all I just want to applaud him for even saying this because it's something that we don't say enough but like we're not super like no one's super human like we all have limitations and this is about our program's getting too big for us to hold in our head and not being able to like rationalize what's going on anymore that is that's what he's going for here so our intellectual powers the way our brains are wired are geared to static relations that predictable given this one thing this other thing should happen not most of the time it happens but like yeah every once in a while it's a totally weird different thing and a strange outcome so our brains are wired that way to visualize processes involving in time they're poorly developed we're just not good at it as a species it's not you and so for that reason we should do our utmost to shorten the conceptual gap between the static program meaning we take everything into account when rendering out that UI all of the actions all of the state everything comes into play that is a static a static relationship we we understand everything going in so we can predict what's coming out versus the dynamic process where everything's fine at the beginning and then a whole bunch of mutation and things happen in the middle that we can't measure or see and we're supposed to predict the outcome and so I hope that you come back to this quote and maybe glean some more insight from it but this is how this is why I like this so much when I read it and when I I didn't even heard of redux yet and so when I sort of saw these functional principles I was like this is I think this is what this guy's talking about and so with that I just want to say thank you I'm Ben I'll be hanging around afterwards if you want to talk about some of this stuff the source code for the app is available online slides are online if you want to talk about any of this stuff I think we're going to do questions too all right yes do some questions do we have a question back there hey Ben great talk so I just started using redux recently huge fan awesome everyone should use it but one of the biggest like hurdles I've had is with like the rails community it's very easy to know like how to do things the rails way I guess if you will and I'm kind of struggling to figure out like how to do things at the redux way often I just wondering if you like had any good resources or like specific people I should be following in order to be doing things more of the redux way I guess sure I think my favorite thing like I mentioned before is that redux is only 2k and so it's really so much conceptual rather than having to like having this like huge plug-in ecosystem I'm sure you already followed Dan Abramov people who don't know who Dan Abramov is I'm convinced he's not an actual person because he does way too much work I just don't get it I'll show you his twitter I'm guessing that that's it nope that's definitely not him anyways his name is Dan Abramov he he created redux and it's just a huge like a pillar of the react community if you follow him on twitter you're going to get most of the updates then if you uh I'm trying to think who else honestly that's how I get most of my redux information and there's also a guy named ACD light which so there's a flux library called fluxor no there's so many of them fluxor yeah okay so he wrote that library and as soon as you saw redux he's like I give up I'm not doing this anymore someone else take this over his is way better and so he actually has contributed like a ton of modules the good thing is they're all on github as a redux dash something and so there's like one called like redux rx so if you don't like react or you want to do this in a different way you can integrate it with like an rx system or there's just like a whole bunch of like middleware but I would follow those two guys and I swear from there you they'll you'll it's like it's like a graph like that's the entry point you'll figure it out from there we had a question up here I think there's a microphone but as someone who's relatively new to javascript trying to grasp these functional programming concepts is kind of tough at first just because you know I read different resources I don't know which one to apply or which one to use what are some starting points that you could give you know some fundamental concepts to grasp strongly first great question as you can see this is about half the list because I went off the end of the slide I have I did like a list of things that I referenced or talked about during this talk but there's a whole other list which would be here's here's how to start and I promise you and I'm saying this in public so I have to do it I will absolutely send one out on Twitter if you want to follow me maybe that's easiest way and I'll say like functional javascript the book by O'Reilly is the first one because it's foundational and then from there like you can work your way up but I'd actually I made the argument that it's easier for you you because you can come into it this way instead of like having to unlearn habits again I'm but that's that's just me because that's my perspective but I don't really know I'm sure it's a little overwhelming but I promise you I'll send that out cool thanks there's another question here what yeah no problem we've got some microphone confusion thanks for the great talk Ben I noticed you were using ES6 classes despite classical inheritance and classes kind of being at odds with functional programming at least conceptually how do you see the future of ES6 classes and then kind of playing nicely together okay so I used ES6 classes for two examples one to demonstrate the inheritance polymorphism thing at the beginning I don't usually write apps that way let me find it here this is a great question I want to address it I talked about it in models so here this is the only example that I actually use ES6 classes I do not use ES6 classes for react components not because not for any fundamental reason I just don't I don't think it gives me anything additional for this for models I like it and I like it here because number one they're immutable anyway so I can't shoot myself in the foot in a lot of the ways that I can with traditional classes so that has my back so I feel comfortable doing it in this way because if I shows you how you instantiate these and you work with them it is it's super clean and very easy to use when you when you structure things this way and so like I said I'm not a purist and I think that like I don't usually use ES6 classes but I'm not opposed to them but for for immutable state and like for your domain stuff if you do this way like you won't shoot yourself in the foot just because immutable has your back so in terms of what the future is for them I have no idea I think they're fine as long as you don't abuse them but I just don't see the huge benefits so I don't like seek them out all the time but in the back we have one more yeah so it's working okay great the way you demonstrate redux looks really cool and powerful but I was wondering if there are ever cases where an app state is too prohibitively large and storing it becomes a large waste of memory or something yep sure so the question can be interested in two parts really one is is the what is the memory pressure I guess on on this like if you are if every change that you make creates a whole new copy of your app state is that the primary question okay that's actually an immutable question and then the redux part is it keeps track of your entire history so that you can do replay and rewind so I'll address those two separately number one in production those dev tools are completely compiled out they're they're non-existent they're in no op so like there's no performance penalty of like shipping that to production because they're just not there once you get past development mode and you can actually just turn them off in development mode if you find that it's a little sluggish but I mean they're pretty damn useful and then in terms of memory for this is another important one so immutable it doesn't actually do a full copy of the object these are called persistent data structures so if you were to do like a clone you could do the same thing but in an immutable data structure and now this is gonna this could be a whole talk on this and it usually is but it will follow the path that you change and only make copies of the few nodes that you actually changed and everything else is just copied over by reference so there's no real shared anything and then once those old ones are not referenced anymore they're just garbage collected just as usual so there's like a little bit more memory but this is how this is actually how closure does data structures like this is where it was inspired from there's a lot of like academic this is not a new idea it's just new to JavaScript and so when it comes to that I have to defer to the really smart guys who work on immutable but in Redux the answer is it gets factored out for for production so as we were just closing out your answer you mentioned this is not a new idea functional programming has been around since the 60s early 60s Dijkstra's quote was 1968 if I my eyes are working well that's correct um but functional programming got a lot didn't get a lot of attention in the industry or in academics until recently so what's changed you know in the recent you know what what kind of um precipitated this newer I don't know I'm tempted to say fad but that's also a little bit dismissive but this new wide interest in functional programming over the past 10 plus or minus years yep exactly right so I covered it quickly because I didn't want to waste people's time in case they weren't they didn't see the value in it but this is mainly what I was talking about Moore's law just because we don't have it's not as much pressure as it is in JavaScript but in every other programming language the you know parallel computing is like the only way forward is the argument because of Moore's law otherwise we won't be able to take advantage of the processors the processor power that we get and so that's why every other language is sort of pushing that and it is just becoming you can say it's a fad but it's also it's also a very valid way to write programs and and that's why I where is it one more thing I talked about familiarity right and so if functional is the future of programming in general sometimes it makes sense to share those across languages and if you can do so and not pay a penalty or much of a penalty at all which I think is the case in JavaScript like I wouldn't be I write my apps this way and I'm not a masochist like I wouldn't want to submit myself to something if it was that much more painful so if you can do the same exact sort of paradigms that you do in in other ways and it makes sense that this is the way you were starting to think about programming now that I think that that's a win and so that's why the old is new again and the one other cool thing I didn't mention that I wanted to demo but ran out of time is that when we saw that list of actions going down the right hand side where we can like replay and rewind you can actually serialize out and because uh and you're going to take it and email it to somebody in a developer so if you're a QA person you can serialize out all of the app state so the starting state in all of the actions and you can email to somebody and they can load it into theirs and get into the same app state so how we were sort of time travel debugging without reloading you can actually send that to someone so you can do some pretty cool things when when you follow this sort of uh this guideline these these kind of rails I should say all right in the interest of time one more question if there are any more no looks like that's it all right great thank you Ben thank you