Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.
Don't Solve Problems, Eliminate Them
Transcription
Hello, everyone. Yes. My name is Kent C. Dodds, and I'm a software engineer. And I'm going to talk about how we should avoid solving problems and instead try to eliminate them. But before we do that, I'd like to have everybody wake up. So please stand. We just had lunch. Your body is like, oh, it's time to sleep. No, it's not. It's time to stand up. Stand up. Come on, come on, come on. Put your arms out in front of you like this, and squat down, and come back up. This is exercise. We didn't have to do that when we were locked in our rooms. So we're going to do 12 of these together, and I want you to count out loud. Ready? One, two, you're not counting, three. There you go. Four, five, six. This is so great. Seven. Your legs are like, what are you doing? Nine, 10. Is that 11? Should we start over? 12. No, just kidding. Stretch up as high as you can, and stretch over. And to the other side. All right. Now, before you sit down, just introduce yourself to the person next to you and thank them for coming. And if you're online, then you can talk to your cat. Thank you for that. OK. First, I just want to mention that I rewrote my site and relaunched it recently, and it's really great, and I want you to take a look. And in fact, I've even got the logs running right over here. So if you want to make these logs go nuts, go to kentcdons.com right now, and we'll see crazy stuff, please. No? All right, fine. My health check is hitting my server, so that's good. Yeah, there we go. Yeah, that's what I'm talking about. So when I was building kentcdons.com is when I started thinking about how we want to eliminate problems rather than solve them. And I'll get to that a little bit toward the end. So that's where the idea for this talk came from. My clicker's not working. It's mine. It's not theirs. It's my fault. So I will just use the keyboard. So what this talk is, I'm going to be talking about problem solutions and trade-offs and how solving is great, eliminating is better, and avoiding is even better if you can manage it. I'm not going to be giving code examples. This isn't a live coding thing. As much as I enjoy those talks, in fact, it's not even about code necessarily. It's more about life in general and problems. And yeah, not domain specific. So I know that we're at a react conference, but this doesn't have a ton to do with react except toward the end where we try to apply it. So this is a problem tree. You're not supposed to be able to see what's inside of those little squares. But the blue icon right here represents the core problem that you're trying to solve. So whatever the mission of your company is, that's what this core problem is, or what the core goal is. And off of that, we have different problems that we need to deal with. And each one of those extra nodes is another solution. And sometimes the solutions that we develop lead to more problems. And so eventually, we get to the terminal solution that doesn't have any problems that we care to solve. And these are way bigger in real life. If you were to try to map out all the problems that your company has, or whatever it is in life, then you would have many. So here's a simplified version of a problem tree. And we're going to be referencing this a couple of times throughout this talk. So first off, I think that it's important to acknowledge that you are a problem solver. That's part of why humanity is the dominant species on the planet, because we solve problems and we have, I guess, dominated the planet. But we're so good at it that we also become problem seekers, where we're looking for problems to solve. And I have a bit of a story about this. And maybe you can relate to this. So when the pandemic hit, my sister, who's a very accomplished violinist, saw all of her professional musician friends totally out of work. And they weren't sure what to do. And so she came to me and said, hey, can you build me an app that can help solve this problem? And I won't go into the details of it. But she basically needed me to build a Tidok Google Calendar and Zoom in a single integrated thing. Not integrate those, but build them all. We always underestimate the amount of work that these things will take. And she said she'd done tons of market research and looked at what solutions were out there and everything. And she felt like she was willing to hire somebody to work on this problem. And I told her, you know, maybe you need to actually just manually work through these tools and be the one facilitating what you're trying to do here. And she said, no, no, I just want to automate all this stuff and scale it and everything. And I just said, I just don't know. And so ultimately, what she ended up doing was nothing. She decided she didn't want to invest into it. And I think that was a wise decision. But one thing that I've learned as I've been living, I guess, is that it's way easier to solve a problem when you know what the problem is. And we kind of assume that we understand what the problem is on the outset. And so we assume that we're going to need a ticketing system, and we're going to need a calendaring system, and a video chat thing. And we have all these assumptions. And maybe you do, but you don't know all the intricacies of what features those different things are going to need. And so I suggest that you first feel the pain of the manual solution, and then you solve those pains as they come. And so problem avoidance is this. You avoid solving or avoid the problem altogether by not creating the solution prematurely. And Elon Musk recently had an interview, and I just really love this quote. He said, possibly the most common error of a smart engineer is to optimize the thing that should not exist. And I thought he was talking about me. So it's better to avoid problems than to solve them. So here's our problem tree, again. If we're avoiding a problem, let's say that we want to avoid the problem or solution 1B here. And we just decide we're not going to solve it. That's what problem avoidance is. You just don't solve it. And here's the takeaway that I want you to come away from this talk. Often, we get down in this problem tree, and we get down to one node. And we're working on this solution right here. And it is a beast of a solution. This problem right here is just super duper difficult. And as we're working through this solution, we're like, man, this is hard. And sometimes you might even say to yourself, if I'd known it was going to be this hard, I never would have done it. And so that's the moment where you think, do we really need to solve this problem at all? And often, you do. This whole thing doesn't even work if we don't solve this problem. But maybe this whole thing doesn't need to exist either. And so you can go up in the problem tree until you get to one solution that you're like, you know what, we don't actually need that. So the users don't even use this feature very much. So we can just get rid of this feature altogether. If I'd known how expensive it would be to solve this problem, I never would have added this feature in the first place. And so reevaluating our problem tree can save you a great deal of time and ultimately be better for your users. Because every minute of every day that you spend, or everything that you can do has the same currency, and that's your time. And every minute that you spend doing one thing is a minute that you can't spend doing another. And so it's totally cool to just say, you know what, we're not going to solve that problem, because we have other things to deal with right now. And this is why I tell people that, hey, I don't test everything that I write. Lots of people think of me as the testing guy in 100% code coverage and test-driven development. That is not me. I see testing as a mechanism for automating code quality and confidence, but that's not the only thing that I'm doing. The code doesn't exist for itself. And so you have to be practical about the sorts of things that you spend your time on. And so problem avoidance is fantastic. I recommend it if you can avoid problems. But sometimes the house is on the cliff, I guess. I don't know how this happened, but I'm glad that somebody was there to take a picture at least, and then maybe they dropped their camera and went and helped. I don't know. But sometimes you can't avoid the problem. And so in this situation, before you try to just solve the problem, see if you can eliminate it. I don't know, blow up the house. I don't know. This is a bad metaphor, I guess. And so here's the reason. Solutions hold you captive to their maintenance forever. And I'll give one example in the real world. So here's an internal combustion engine. And there are a lot of problems that we've faced over 100 years that we've been working on internal combustion engines that have been solved in remarkable ways. So first off, we have exhaust. When you burn gas, there is exhaust, and that exhaust is not good for our lungs. And so we don't want it coming into the cabin. So we have all of this piping going to shoot it into the back of the vehicle, where certainly it will do no harm. That was sarcasm. So that's as far as we've gone on solving that problem. Stopping also. We have brake pads. They squeeze the disc brakes or the discs, and we can stop the vehicle. And that's worked, except those disc brakes don't just magically disappear, and you have to replace them, right? That rubber is going into the air, and we're all breathing it. But that's as far as we've gone to solving that problem. Cars will actually catch fire. That's amazing that when you're literally burning stuff and exploding things to make you move, that maybe it'll actually catch fire. But they've put a lot of work into avoiding this problem, or trying to solve this problem as much as possible. And then sustainability. Well, this is the problem that we just decided we will not solve with internal combustion engines. It is not possible to make this sustainable. So what if we look at our problem tree, and we say, you know what? This sustainability problem, or the car fires, or whatever else, this is just a really difficult problem to solve. Let's go up the problem tree and get all the way back up to mobility. Now, of course, you can ride bikes, and you can jump on the subway, or whatever. But at some point, people need to have individual mobility. So how are we going to solve that problem? Well, what if we just totally change the approach altogether? And this is the Tesla electric engine. This is the engine that powers the fastest mass production car in the world, the Tesla Model S. And here are the problems that they've pretty much eliminated. Exhaust is absolutely eliminated. There's no exhaust. Now, people talk about the long tailpipe, but the fact is that eventually, all of us are going to be powered off of sustainable energy, so that long tailpipe is cut off. We have no exhaust problem, period. My home, I do have a Tesla, and my home is solar powered, so I'm driving on sunshine, and it's awesome. Yeah, when we got the system turned on just last week, I started driving my car and singing, I'm driving on sunshine. Just like, yeah, such a great victory. And then stopping, the cool thing about electric is that you can actually turn that kinetic energy into actual electrons and stick it back in the battery. And so yes, while we do still have brake pads on electric vehicles, we probably never actually need to replace them, because most of that energy is going back into the battery. And so we haven't eliminated that problem altogether, but we've drastically reduced the impact of that problem. So that's super awesome. Car fires, as far as the, I know that electric car fires get in the news a lot, but as far as the data is concerned, you're 11 times less likely to have your car catch fire if it's a Tesla Model, or yeah, a Tesla. I don't know about the other manufacturers, but the data I have seen is a Tesla. That's pretty significant. And then sustainability, ultimately, we can make this sustainable. And that should be the only reason that we do this. If all the other things were fine, this is reason enough for us to make this change. And so by going up the problem tree a little bit and saying, hey, what if we don't actually need to solve this, or what if this is too hard of a problem to solve, and we go back up the problem tree a little bit and say, hey, what if we change our approach, and now we have a new solution, so we haven't eliminated it. We haven't decided we're not going to solve this problem of personal mobility. We are just going to change it so that we have a smaller problem tree. Now certainly, there are many problems with electric vehicles as well, but the problem tree is smaller, and the problems are smaller. And that's why this elimination is so great. Tesla's actually a really great case study for problem elimination. So if you ever want to see the amazing things they're doing with manufacturing, it's really phenomenal, very interesting. OK, so let's talk about software now. In software, we have some examples, particularly in react, of problem elimination. So how many of you all have written class components, class react components? Any react Create class folks out there? Got a handful of you. Yeah, that was fun. Yeah, and then we got class components. And this screenshot here comes from Amelia Wettenberg's react Hooks blog post, which is very good. I recommend you go take a look at it. But one of the big problems that we had with class components was code reuse. And you would have a single concern in your class component that would be spread between these three life cycles. You'd have your componentDidMount, componentDidUpdate, componentWillUnmount. And so if you wanted to subscribe to Firebase, or you wanted to update the document title, you had to spread all of this stuff up in your component. And so reusing that was a little tricky. Did we use a higher order component so that we can make a component that does all that stuff, and then we just pass our component to that so we can accept that as props? Well, there were a lot of problems with that. You'd have prop name spacing issues. It was very difficult to type. And so we started doing render props. And those were fun, really powerful. But then we have these giant trees, or a pyramid of doom, trying to get all of these things composed. They just didn't compose very well. And so it worked, and it wasn't bad. I lived through that, and it was a good time. I had a lot of fun with that. But wouldn't it be great if we just didn't have the problem in the first place? So Hooks came around and co-located all of the concern into a single bit of code. So it could be like a useState and a useEffect and a couple other things in there. But it could all be in the same snippet of code. And so what do you do when you want to reuse code? You can create a function out of it. And you couldn't do that with our cost components, because the concern was spread through multiple lifecycle hooks. But with these hooks, you can just take that and stick it into another function. That was brilliant. It made an enormous impact on the ability for us to reuse code. And it drastically reduced the amount of stuff that I need to teach in my react components patterns workshop. And things became so much easier when we just went up the problem tree, decided, hey, what if we did things differently, and then went down that direction. Now, there are problems with making those sorts of migrations. We all felt the pain of having to move over to classes, and should we even bother, all of that. But by the end of it all, we're much better off. And I'm really grateful to the react team for creating hooks. It's made my job a lot easier. So now is my favorite part. And I want to talk to you about remix. How many of you have heard of remix? How many of you who are raising your hands heard of it because I tweet about it nonstop? Yeah, most of you. So I tweet about remix nonstop because I love it. So full disclosure, because people always want that. There has been a transaction between me and the remix team. So I had to pay them money to access remix. But that is not going to be the case. They say in a few weeks, remix will be open source, completely, and free. And so you will be able to use remix as well. So let me sufficiently hype you up about this. I don't have a ton of time to go through everything, but I want to just give you a high level, because remix is the reason that I started thinking about problem elimination in the first place. So the first thing that remix does that just makes it phenomenal is nested routing. Now, one nice thing about this is you no longer have a route that's like slash users, slash ID, slash contacts or something. Now you have in that route file, whatever framework you're using, you probably have to render your layout route. And that'll include your header and your footer and everything. With remix, you have nest routing. So each one of those is going to just be the component that cares about the part of the route that this part of the route URL cares about. That's really nice. But to take it even further, that's just like a nice developer experience sort of thing. But because of nested routing, remix can do a lot of really awesome optimizations as far as loading your data, invalidating the cache, and loading the right data so it doesn't load more unnecessarily. Lots of really cool things, because remix has nested routing built in. Another thing that I love about remix is the seamless client and server interaction. So just like Next has the get server side props, you've also got a loader with remix. But remix does a really great job of making that connection very seamless, as I say here. So it can be fully typed. You can go make all of your requests to database or graphql or whatever it is. And then all of that data is just available in your component. And they have really nice declarative error handling. And so as far as your component is concerned, the data is there. And you never have to even worry about error states or loading states, because all of that is declaratively handled for you. So by the time it gets to your component, you just don't use useEffect. That's all I need to say. Like, woo, yeah, no useEffect, all right. And you don't need a tool like react Query as much as I love it. If you're not using remix, you should be using something like react Query. Let me say that. But if you are using remix, you don't need it. Because react Query solves a really big and awesome problem. Thank you, Tanner, for creating it and those who are maintaining it now. But wouldn't it be great if we didn't have the problem to begin with? And that's what remix gives us with its really awesome client server interaction. The other thing I love about remix is that it's based on the web. So everything is fetch api stuff, even on the server. You have a request and a response. And if you need to learn something about that, you're not going to the remix docs. You're going to MDN to learn about how the web APIs work for that. And aside from the transferability of knowledge, you also get the fact that because they're using the web APIs, we can run this in a cloudflare worker or in a service worker eventually. cloudflare workers are currently supported. Service workers, eventually, they'll support that. And so just nailing that abstraction has opened a lot of really awesome opportunities with remix. And what's cool is that you don't really have to change any of your code. Now, if you're going to work in certain environments, some of them like serverless, you can't have a long connection to a database or something. But as far as the remix-specific code, none of that needs to change because it's all based on the web and remix smooths out everything for you. It's kind of like jQuery for the server. I've never said that before, but it's, yeah, kind of like that. Other thing I love about remix is its simple mutation. So all mutations in remix are you have a form. And so even like your Delete button, the way that we do this is we have the little trash icon. We click on that, we have an onClick handler that will go do the fetch request or the delete request or whatever to delete the item. With remix, you just use a very declarative, here's my form, here's the delete icon, and you click that, that submits the form. And then remix takes care of all of making the requests, and what if I make another request and we're loading data and remix will cancel the right one, make sure everything's loading in order and everything. But what's even cooler about it, well, that's pretty cool, but what's also cool about it is that even if javascript fails to load, which that does happen sometimes, most people don't disable javascript. But failing to load javascript does happen. Or if javascript takes a while to load, which that happens even more, all of your mutations still work because you're using regular forms and they're doing regular posts or regular deletes. And you'll end up with a full page refresh, so it's not as awesome an experience, but this is what we call progressive enhancement. And so your app still works even without javascript, and it doesn't take a great deal of effort to make that happen because it's just the way that it works. And then also, I just love the css story with remix. Here's the big secret about how css works with remix. It just blows my mind how simple this is. So to get css on the page, you have a link tag and you point to the style sheet. And all of us, we're using webpack and bundling it all, or we're using styled components and having it part of our components. And it's really nice to have that co-location or whatever it is. But in every app that I've ever used, if you've got regular css, it's all going to be bundled and it's going to be available on every page. In remix, each route can define the link tags that it wants to have active when that route is active, or wants to have on the page when the route is active. And when you navigate away from that page, then those link tags are removed. And so if I want to have some special css that's applied to only this particular route, then I can say, hey, here's the link tag for that. And I say, here's the css file that I want on this route. And when I navigate away, remix removes the link tag. And that's it. That's the whole secret. But here's why it's so cool. It's because that when I'm in that css file, I know exactly which routes that css file is going to impact. And so normally, at any other company that I've worked at, any other significant project that I've been at, any css file you were working in, or SaaS or whatever, you just knew that this css would apply to every single page. And so you were always worried about removing something because something might break. You could, as you're developing, of course, you're looking at what's happening here. And so you're worried that you might break something that you're not looking at. But with remix, you know exactly which pages this is going to be active on. And so you know exactly which ones to look at. And in practical terms, it's normally just on a single route. And so as you're developing it, you can make any change you want to the css. You look at the page. And if it looks the way that you want, then you know that your css file is good. And you don't have to worry about it impacting other pages on the rest of the app. This is another great example of problem elimination, where we've eliminated the problem of unexpected css clashes. It's just phenomenal. Like all of the work that we've been doing for all of these years to try to make css easier for us to use, especially as react developers, with css and JS and css modules and everything in between, has been to help us avoid css clashes. And remix doesn't completely eliminate the problem. You can still, even within a single css file, you can have clashes in there. But it makes it predictable. And I love that about remix. Side note, just skip to the end and use Tailwind for everything because it's amazing. But it's really nice to know, if I wanted some one-off css that I could add it to the single route and not worry about it impacting any other page. And I don't need any runtime or any extra build tools or anything. It just works. And it's the web. It's fantastic. There's so many more things I want to tell you about remix, but I just don't have the time. So we're going to wrap this up. And actually, if you do want to know more about remix, I am more than happy to talk your ear off for the rest of the conference about it. And I've got a billion stickers that I got myself. So again, remix is not paying me for any of this stuff. I asked them, can I print stickers? And they're like, well, we can't send you stickers. I'll buy them myself because I just am so jazzed about this framework. So a lot of you might be thinking, well, problem elimination just sounds like choosing trade-offs. And yeah, that's what it is. That's what problem elimination is. And so the idea behind problem elimination is to eliminate big problems in exchange for smaller ones. And the reason why this is talk-worthy for me is that I don't know about you, but when I'm involved in a problem, I am not thinking about whether or not that problem needs to be solved or if I can go back up the problem tree and rethink the problem back up at the top. That's why Hooks was so phenomenally awesome. It was because we're all working, how can we solve this code-sharing problem down at the bottom of the problem tree? And the react team just went up a couple levels and said, hey, you know what? Maybe we could just take a completely different approach. And it worked, right? We all love it. Most of us do. I do. So in conclusion, solving problems is great. Please keep solving problems. There are so many problems in the world, and I want to see you all being problem solvers. Eliminating problems is even better. Find different trade-offs and take the thing that's easier. Avoiding problems is even better. So if you can't avoid the problem, then try to eliminate it by changing your approach. And only if that fails, then solve that problem. One last thing before I go to my last slide. I forgot to introduce you all to Cody the koala. So this is Cody. And people often ask me, what's with the koala? So when people ask me that, I know they haven't been to my workshops. Because Cody helps you go through my workshops, all the workshop material. So anyway, I felt bad having this random koala next to me, and I forgot to introduce him. So that's Cody. You can actually get your own. Store.epicreact.dev and get your own, and it's adorable. Kids love it. Thank you all very much. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Mr. Kentsey Dodds. Hot seat, please. Oh, yes. Oh, yes. We've got a lot to talk about. Oh, OK. Only solutions, though. No problems. OK. Well, actually, one of our first questions was, what's the story with the koala? So I guess we solved that. I didn't know you had a merch shop. Yeah. That's very exciting. There's shirts and jackets, the most comfortable jacket that I've ever worn. In fact, a quick story on the jacket. I got a jacket like it at react Rally a few years ago. And I tore it up really bad when I crashed on my one wheel. Like, the entire shoulder was just ripped up. And I was so sad that I asked the conference organizers where they got the jacket. And I found the company. And I created it on my merch store so I could buy it. That's why it's on the merch store. Because I like the jacket so much. It's soft. It is soft. It's super comfortable. We're going to have to check that out. Do you know if it ships to London? Yeah. I'm not sure how much it costs, but it's probably too much. You heard it here first, folks. All right. Adil asks, any remix workshops coming? Oh, yeah. Yeah. In fact, if you go to kentseydodds.com to workshops, you'll find I have two scheduled already, as well as a typescript with react workshop coming up. Incredible. Yeah. Fun stuff. That's pretty much all I'm going to be talking about for the next I don't know how long is remix. I'm going to teach you all how great remix is. Mac asks, how do you approach the sunk cost fallacy? At what stage would you say it's too late to eliminate the problem you're working on? I mean, it's never too late. Unless, like, the sunk cost fallacy is basically, oh, we've sunk so much into this, we can't quit now, whatever. But if you just evaluate it right now as it is, like the work that I need to do to solve the problem and the benefit that I get from that, and the work I need to do to change my approach and the benefit I get from that, you just do the cost benefit analysis of that. And yeah, I wouldn't say that it's ever too late to solve a problem. It's just like, how are things now? And let's go with the better direction. That makes sense. Gabriel asks, when you eliminate a problem, how do you leverage the unknown? You don't know the problems you're going to face down the other path. Yeah, that's actually great. That's kind of my story with my sister, who is trying to solve the problem for musicians who are out of work. And this is where I say, do it manually first. Like, just go on forward, and then just make sure that you're evaluating as you go. And you realize, you know what, if I had known this, I never would have done it. And I don't feel like it's worthwhile going forward or whatever. That's good advice. That's good advice. A little bit related to our previous speakers from our last slot, how does remix play with micro front-end approaches? So remix is pretty new, so it's hard to say. And I have basically no experience with micro front-ends in a practical sense, so I can't actually answer. But remix in general is very abstractable. That's one of the things I like about it. And so I am guessing it would actually be quite possible to make it play nicely, but nobody's done it yet. Like, my website is literally the biggest deployment of remix. And it's not small, but it's like 27,000 lines of code. And it's the biggest one. So it's still pretty new. Kind of a popular one, in a nutshell. What is remix? remix is a framework to help you build better websites. And yeah, it's most comparable to Next. Yeah, server rendered. Yeah. And do you think remix will get rid of everything we learned so far? Next, graphql, Redux, react, react Query, et cetera? Well, not everything. One of the things I love about react in particular is that, and remix uses react, to be clear, but one of the things I love about react in particular is that the better you get at react, the better you get at javascript. And yeah, I love that coming from other frameworks. And with remix, one of the things I love is that the better I get at remix, the better I get at web development, because it's based so much on the web platform. And so I think that all of the nice things that you've learned about the web platform with whatever framework you've been using, you bring all of that with you to remix. And then remix will teach you more. Any of the other things, like yeah, you're not going to probably be using react Query with remix. You could. There are potentially use cases for it. So yeah, any react Query specific thing that you know, that won't carry over. But it's not because there's a different approach or a different api you need to learn. It's because there is no api that you need to learn. And that's even better. There's following up on that a little bit. There's a couple of questions about comparing remix to different things like Next or Recoil. Do you have any sort of rough thoughts on that? Yeah, well, so Next compares most of that. In an app that's like, quote unquote, finished, not in the process of migrating, you wouldn't use them together. Recoil is a state management solution produced by Facebook to solve a very particular problem. And you could absolutely have that problem when building a app with remix. And so then, yeah, you could use them together. But like the typical like CRUD application that you're building, you don't need a state management library, certainly, because remix manages the server cache for you. And everything else works nicely with context. And yeah, so it compares well. And then also another big one is gatsby. remix is server rendered. And I know that gatsby now can also do some server rendering as well. But yeah, remix takes a drastically different approach. And I think that leads to a better user experience. A lot of remix questions. remix is the best. I love it. Do you think it's ready for a wide scale production app? Well, they're not officially open source. And there's technically no way to get access to it until they do become open source, because they close down new subscriptions and stuff. So I mean, if you want to work on it today, then yeah, no. But in the next couple weeks, then certainly. I think that it is definitely missing some things. I don't want to make it seem like it's the perfect solution for everything, especially now. But those things will come. And I got excited about remix when it was first released. In fact, even before. In fact, I bought the test subscription, because I was so eager. And I accidentally bought a test subscription for $1. So I have two subscriptions to remix, actually. But yeah, I knew from the very beginning that remix was based on a really solid foundation. And that all of the holes that were in remix at the time, and some holes that are still there, will easily be filled in because the abstraction layer that they're operating under. And having worked on it now for your site, how do you feel it would integrate with, perhaps, a legacy code base? I think there are various approaches that you can take for integrating remix. So for one thing, you could say, let's start doing remix for these routes. And then we'll just have some redirection there. And it'll be like a separate app. That would be a really easy way to do it. But there are also ways. I was talking with somebody recently about integrating their PHP rendering with remix. And you could totally do that. Have PHP render some stuff. remix will server render some stuff along with that, and send all that html to the client. And that would be possible, too. So you've got a lot of flexibility. Awesome. You heard it here first, folks. Before we switch to a couple questions about problem solving, Alex asks, is the squat stretch routine part of your daily stand-up? No, I don't have daily stand-up, because I work for myself and by myself. It's very lonely. But I got the air squats from Ben Ornstein years ago. He gave a talk called How to Talk to Developers back in 2013, I think, at RailsConf. And it was a phenomenal talk. I recommend it if you want to get better at talking to developers. And that was one thing that he did. And I borrowed that from him. Wonderful. Well, there you go. You should all give it a try. I've given almost 100 talks now. And I get nervous before every one, which makes you wonder, why do I even do this? But the air squats helped me loosen up a lot. So thank you for indulging me. Let's talk about problems. Hastu asks, how do you identify a problem that needs eliminating without having gone through x iterations of solutions and associated problems before deciding we might need to rewind? Yeah, that's tricky. That's kind of related to the sunk cost problem. So this is where the term spike comes from. So you time box a certain amount of time that you're going to spend researching a certain solution or finding solutions to a problem. And yeah, sometimes this is why I think this is where funding can actually help the entrepreneurs, where they're like, we're not sure this is going to work, but we think it will. So give us some money to let us try. And there's risk involved in that. And so hopefully it does end up working, or you learn enough to find another way to do it. And sort of related is, do you have a set of criteria or heuristics that you use to evaluate a problem when deciding whether to tackle it or eliminate it? Not really. I think it just needs to become a part of your regular routine where you just re-evaluate your problem space right now and think, man, I worked really hard on that solution, and I'm still not done with it. And just take a few steps back. Why do we have this problem? Well, because of this. Well, why do we have that problem because of that? And just keep going backwards. Now, we're out of time for some of the questions, but a couple of things. First, any other pets coming up, or will it only be Cody? Well, there are a lot of actually emoji in my workshops. We have Marty the money bag. That one might be fun. Just like bags of money for you. Take it. Yeah, I don't have any plans for extras. Cody is kind of my favorite. Right. Right after this, Kent will have a speaker room for folks at home. You can join on spatial chat. For folks here, if you want to keep chatting to Kent, follow him after this talk. Right after, we will also have the hybrid discussion room with Alex and Ruben about micro frontends right in the discussion room. Thank you. Thank you. Thanks, everyone. Good luck. Thank you. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks.