Jon (00:03.322) Hey everybody, welcome back to another Gone Mobile. Alan, is it Halloween? I've been reading the show notes, the episode title. Allan Ritchie (00:09.208) No. I came up with a good title, didn't I? It's pretty good. Jon (00:14.586) Reminds me of watching, there was a cartoon version of Tales from the Crypt Keeper. Yeah. Allan Ritchie (00:22.841) I do remember that, but it was always the late night show as a kid that I liked, because that guy was crazy and he had the most hilarious voice. I don't remember the show at all. wow, that's a blast from the past. That is. Jon (00:26.81) Yeah. Yeah, exactly. Classic. Jon (00:35.386) That was that was that that that wasn't on like part of the same show or maybe it's just that they were all on late night but do you remember the one where they had like the The alien sitting in the audience of the movie watching the movie and commenting on it. Did you ever watch that one? I Don't remember what that one was called. I have to find that now later Allan Ritchie (00:51.223) No, what the hell? Yeah, I have no idea what you're talking about. You're gonna look it up now, aren't you? Jon (00:56.186) so good. Well, I mean, I'll wait. Allan Ritchie (02:12.01) What just happened? Jon (02:13.978) I just saw a big OBS screen pop into place. Allan Ritchie (02:16.49) I unplugged my phone and then... Jon (02:21.754) did it do something funny with like, you have it tries to use the webcam sometimes or weird. Don't touch anything. That was fun. Allan Ritchie (02:26.154) Yeah, but it's never happened before. All right, sorry. Yeah, no shit. I just, well, it was beeping at me and I couldn't shut it up, so. Jon (02:33.946) All right, I'm going to hit a marker when we're paused and ready to go. So maybe it's helpful. We're just kind of, yeah, I think we can jump in. Allan Ritchie (02:37.257) Okay. Allan Ritchie (02:42.889) Okay. Jon (02:44.666) So what, I mean, Tales from the Crypt is the title of the episode. What does that mean? What are we talking about? Allan Ritchie (02:50.537) So, well, we've probably both seen our fair share of interesting stuff. That's a nice way of putting it, right? This is a bit of a spicy topic, but I said I would be nice. I said I would be nice. Jon (02:58.906) Well, mobile tends to be a place because it's, I mean, it's a constrained computing environment, right? So it's less constrained than it was maybe, but that doesn't mean that, you know, we're not still using the increased power and everything at all in the other places. So people tend to do some things sometimes in their app that aren't best practices. Allan Ritchie (03:09.897) Yep. Allan Ritchie (03:26.793) Yes. We do. Jon (03:28.538) And so we want to help people today. We want to help them understand what's not a good idea and maybe share some fun examples in a jovial manner that we've seen. Allan Ritchie (03:38.887) Okay, John's being really nice about it, but I also do consulting, right? And I've been, I don't know, I've kind of, Maui's been a niche point in Xamarin in general. So John will be nice about it, but I think I've seen more stupid stuff. There's my spicy. And you know, the thing is, is that it's like, if you just stopped and thought about what you're doing sometimes, you know, you wouldn't point the finger. Always look at yourself first. Always look at your code first. Jon (03:51.226) You've probably seen more, more, you know, battle. Yeah. Allan Ritchie (04:08.839) and then branch out. If you always assume it's the vendor or this third party stuff that you're bringing in, you know, that's the problem. Jon (04:17.85) Well, one thing that I like to say too is if you're not finding a bunch of other people in the same boat as you with a particular problem, that's kind of indicative too of that. Maybe it's not, you know, everybody, it's not, it's not the thing. It's maybe your stuff. That is not always the case. I mean, people hit unique situations and unique bugs and stuff that are not, you know, their, their own making, but there's an, yeah, there's enough times where it's like, you know, well, my startup, performance is bad and you know, that must be something wrong with, with Maui. Well, I mean. Allan Ritchie (04:49.838) That's a good one. Okay, I think we've covered it in the past where I've seen like an app, an Android app that took 30 seconds to get going. And it sat on a black screen. I don't know how Android didn't just kill it, but it didn't. The app kept running. It would spin up its 30 services or 300 services with like automapper and which I assume is doing a whole lack of, well, I know it's doing a whole lack of reflection and 30 seconds. Jon (04:58.842) Yeah. Jon (05:18.586) Yeah. Allan Ritchie (05:20.198) It was an older Android tablet, but 30 seconds. Jon (05:25.274) Well, and that's kind of an interesting point too, where I know I've seen cases too, where we'll have a report that's like, you know, this thing is, is taking like, not that's a drought dramatic example, right? Three 30 seconds. Like, yeah, that's okay. But there there's other times where you might see someone like, Hey, this, this thing is, you know, taking several seconds and we want it to be faster. And, you know, by the way, we're testing on a, you know, galaxy S two. Right. And so, and for reference, that's a really old device. yeah. So you got to kind of temper expectations a bit on, on the environment you're running on, right? If it's a slow Android device, I mean, it's going to take longer no matter what. So like in that example, yeah, 30 seconds maybe is the worst case because it was a slow device, but yeah, still something, something's amiss there. I mean, we're not seeing everybody's. Allan Ritchie (05:59.366) get blood out of the stone. Allan Ritchie (06:10.15) Right. Jon (06:21.114) complaining about, you know, my app takes 30 seconds to load. So probably you want to look at your own code in that case. Allan Ritchie (06:26.918) Always start there. Always start at your own code. It doesn't matter. You should never assume third party. And if you are using third party, try it out first. POC it outside of your app before you bring it into your app. And then you assume that the component's done something wrong, right? Jon (06:39.938) Right. Jon (06:46.618) And I think, you know, as a good like steward of the, to the community, if you run into something where you're pretty convinced that it's some, you know, you know, underlying framework or third party thing, like it's kind of on you to do your extra due diligence to, to kind of prove out that yes, that's actually the case. Right. so that's another thing that, that you can see often, and I'm sure you get bug reports like that too, and shiny stuff where you're like, maybe there's something there, but. Allan Ritchie (07:11.142) Mm. Jon (07:15.898) you're not helping me understand, you know, how you're hitting this particular case and providing a nice little repro that doesn't have all of your code in it, but also has enough of it that is actually showing, you know, the real case that you're running. Like that's, that's something I see a lot where we'll ask for someone to make a reproduction and to their credit, they go and do it. And it's, you know, they, they try it and it's not always easy to understand the parts that you're, you're leaving out, you know, and how they, they play a role, but often enough it's like, yeah, Allan Ritchie (07:34.917) Hehehe. Jon (07:46.33) You kind of gave us reproduction and then you're saying, well, it doesn't really show the same as in your real app. Well, then it's not really a reproduction. Yeah. Allan Ritchie (07:54.63) It's not really reproduction, right? You have to show the issues so that you know what you're working with. Jon (08:00.89) Yeah. And that can be hard, but like that's kind of the bar to getting something fixed at that point, right? If you're kind of saying, well, it's not me, it's you, you got to help understand, you know, what, what the you part is that needs fixing and, and provide the example. Allan Ritchie (08:13.461) Exactly. Not what psychiatrists spend all the time figuring out what's wrong with you, but you gotta let them figure it out. You gotta let them know about you. Jon (08:20.922) Right. So, you know, you've had some, you've seen some things. What, what kind of, do you have some you want to share? Yes. Allan Ritchie (08:27.876) seen some things. tail from the crypt. You know it's funny the ones that I always see and I've seen this a lot and I know you've seen this too and people do it because they think it's engineering it saves them lines of code but sometimes the thing that you're engineering I guess I don't want to call it over engineering because this one isn't really over engineering but it is it's a fast it's a it's a shortcut to getting done. So I tend to see a lot of things like assembly scanning, right? So back in the old days in ASP .net, you know, we used to have like an iPlugin. You go ripping through all the DLLs to find the iPlugin interface. You'd load up that DLL, you pull stuff out of it. We still can do that on a server that's wired for high processing. You can get away with that. So what your app takes a few seconds to start. Doesn't matter there. Jon (09:01.978) Mm -hmm. Jon (09:09.882) Mm -hmm. Jon (09:23.002) Right, that's worth it. The cost is worth the value you get from it there. Allan Ritchie (09:27.204) But and I see this a lot when you get developers that come over from the web and server world. They're just like, Hey, we'll do the same thing here. We got to register all these screens. And it's like, well, no, because that takes some time, right? In an app that you want to start in like a second, if you start doing that stuff right out of the gate, it's going to, it's going to pause the starting of the app, right? Usually what I tell people is if you've got to do anything complicated like that, have like a startup page. Jon (09:34.042) Right. Allan Ritchie (09:57.028) do it asynchronously and let it load. But generally what it is is they'll do this assembly scanning for, so one for like view models, maybe some, you know, I plug in, they might go hunting for it. And then they put it into their dependency injection container. And they're like, well, look at all the lines of code we saved. Well, two problems just happened. One is you scanned, whether you know it or not, hundreds of DLLs, even if you filtered it with like where clauses and link, link doesn't care. It's not like SQL server. Jon (09:57.114) Mm -hmm. Jon (10:05.498) Right. Allan Ritchie (10:26.755) It's like, here's all of it, go through the predicate. All right. Jon (10:30.138) Yeah. Well, and, and so that's, I think you kind of touched on it. but one interesting thing that can happen, right, is depending how stuff compiles down, like, I don't know if you do a, like a, you know, type of, you know, whatever random type, you know, is in your, your main assembly where all your other things are that you're scanning for. I'm not sure either way, if at some point some of those things can kind of get jammed together, like in, in, in an AOT context or something like that, where you're, you're actually, yeah. So there's, there's, Allan Ritchie (10:57.379) potentially. Jon (10:59.77) There's like that side of it to watch out for, right? You don't really know how that kind of compiles down to the particular platform. If it's, you know, if it's jetted, if it's AOT, if it's interpreted, all these things. So like you're, you're, they should all be, yeah, no, no, no, the types of work. I just mean like you're scanning an entire assembly for all of its types and then you're filtering down over it, right? Like, and that, that gets, it's just not the fastest thing to do. Allan Ritchie (11:12.195) Types should work. Allan Ritchie (11:25.924) Well, the thing is that if you look at all of the assemblies that actually do go in to a mobile app, if you really look at the BCL, there is a lot. It's at several hundred libraries. Jon (11:38.138) Well, yeah, so going in the app domain and getting all the assemblies and scanning through all of them, yeah, first of all, that's just the worst way you could do it. But even if you're still scoping to one or two of the assemblies that you know have them, you're still looping through all the types. Yeah. Allan Ritchie (11:50.98) Yep. But then there might be several hundred types in each one of those assemblies. So it's still, it's like a big query and it's like an N plus one. You know, you used to be really bad in SQL or lazy loading with like entity framework. It's not good. It's, it's a hit. Jon (12:05.85) So what we used to do in forms was because that was a hit, right? And actually, I think you see this extending into like when you, if you ever wrote a source generator too, right? It's, you'll start to see the use more of like, if you really want to do the scanning thing, which you shouldn't, but like if you really wanted to do it and you didn't want it to be the worst, you know, performance, you can always do global, like assembly level attributes, right? Allan Ritchie (12:16.579) Mm -hmm. Jon (12:33.594) so that's, that's what we did in forums eventually where if you wanted to declare like your service and your implementations of those, you, you add, you know, assembly level attributes that kind of pointed like, okay, for this service type, here's the implementation type. Right. And so to go in and scan the assembly for just the assembly level attributes is much faster than going and walking through all the types in an assembly. So that's, that's one avenue. If you're sold on like, no, I can't write that extra line of code to like, Allan Ritchie (12:34.435) Mm -hmm. Allan Ritchie (12:55.78) Mm -hmm. Yep. Jon (13:03.738) register the service for the thing that I want to get later. I guess you could do that, but you're still writing in a line of code then too. Allan Ritchie (13:10.469) Well, well, that's the funny thing. We missed this. So I was getting to this one point is that by scanning all those assemblies for view models, you're not necessarily linker safe anymore because it won't see that that view model is being touched. At least when you had assembly level attributes, the compiler could see the type. Okay, the type is being referenced. I'm not going to touch it. I don't know how it's being used. I don't care, but I can see it's being touched externally. So leave it alone. But when you're doing an assembly scan, it's like it doesn't know better. Jon (13:34.874) Right. Yeah. Allan Ritchie (13:40.421) It's already removed it because it couldn't see it in the active path. Right? So there it goes. Jon (13:44.762) Right. And, and even like if you've got the, if you wanted to do the assembly level attribute, like at the same time, does that, does that really save you much over writing the, you know, services .add, you know, transient or singleton or whatever you're doing. Allan Ritchie (13:56.228) Ye - It does save some cycles in terms of coding because there can be, I'm working in projects that have like several hundred view models. That's a lot of registration code, but you can also do source generators, right? Source generators are beautiful and yeah, they're complicated to write. They're complicated to unit test, but once you figure it out, it's like a tool in your belt and you only pay that cost at the beginning when it compiles. Jon (14:12.698) Yes. Jon (14:24.282) When if I was going to say if you screw something up in terms of performance, it's at compile time, not at runtime, right? Allan Ritchie (14:31.319) Exactly. And it's done. You'll notice it real quick because you'd be like, man, my compilers are slow. We've seen that, right? Where when we started to do source generators, they're just like, here, go do everything. Go scan everything. Go run it. We weren't doing it right because nobody could figure out how to use them. The documentation was pretty garbage at the beginning. So we just thought, hey, just go scan everything there and generate it. Well, it turns out you didn't need to do that. That's why they've kind of forced us into these incremental generators. Jon (14:36.954) Hehehe Allan Ritchie (14:59.204) which is just the underlying source generators doing it properly. It's weird, but it works. Jon (15:03.354) I wonder if anyone's made a source generator that's like a little bit more generic in terms of like like we're talking about like, I know every view model implements this interface or base class. I just want to go add those and register them. Allan Ritchie (15:13.957) Kind of. There is a plugin -ish library called Source Generator Kit that I found. I am using it so it has like a couple of the syntax receivers. So if you have syntax receivers, which generally is what you have just based on what you just described, right? Find me all of classes marked with this attribute. Find me all classes marked with this interface, etc. Jon (15:23.706) Okay. Jon (15:29.658) Yes. Allan Ritchie (15:42.565) So it has a whole bunch of these syntax receivers. And then it even has an aggregate, right? So you can say, I want a couple of syntax receivers on this. And it'll say, OK, well, here's syntax receiver one. Here's syntax receiver two. And it runs them both, which is kind of cool. Jon (15:42.586) Yep. Ooh, that's handy. Jon (16:00.282) Yeah, I mean, it would be neat. Allan Ritchie (16:03.076) I just do two source generators, but you know, some people might just want one. I don't know. Is this? Jon (16:07.098) Yeah, yeah. I'm already thinking, you know, down the road of like, well, yeah, maybe, maybe there is something here to like make some generic pre -built source generator. I don't know. Allan Ritchie (16:19.299) It's hard. Source chain readers are, they're a bit of an art form still. They're still really complicated. Jon (16:21.146) Yeah, yeah, they're hard. Well, and that's why I say, like, it's easy to say, don't do it this way and consider the other way. But like you said, writing a source generator is hard. So it's maybe not the most approachable solution to somebody who's not familiar with the area. Allan Ritchie (16:28.821) Hehehehe. Allan Ritchie (16:36.484) rate. But you know, once you figure it out, it can really, if you're trying to save lines, right, because scanning all assemblies isn't, again, I'm not saying over engineering, but it's pretty borderline, right? It's an unnecessary thing to save lines of code. Maybe it's worth investing that time for source generators, because once you start using them, you can use them in a lot of scenarios. And instead of paying this runtime or even run during, Jon (16:50.906) Mm -hmm. Allan Ritchie (17:06.468) performance costs, it's just, it's done all of it for you, right? So that's a way to get out of the scanning. It's just let it scan at run or at build time instead of runtime. Jon (17:10.17) Yeah. Jon (17:17.786) Yeah, yeah, exactly. Allan Ritchie (17:18.468) That's ways to get out of it. So don't be stupid. Don't scan all the assemblies. That's tail from the crypt. One. Jon (17:22.938) So that's one thing. That's one tale that we've seen. What's another one? Allan Ritchie (17:31.3) I know this one. We've all seen this one. I've seen a company where they loaded up the most massive JSON file from the startup synchronously. And they would be like, Hey, iOS is crashing off the beat because it was taking longer. I think it's that 17 seconds or whatever that you get. Jon (17:52.378) Ooh. Yeah, yeah, cause the operating system will say like, nope, you can't take that long. Which is pretty generous to begin with 17 seconds. Like if I'm a user of your app and it doesn't start within five, I'm already annoyed. Allan Ritchie (17:57.955) Set 17 seconds and or it would memory panic. EEEH Allan Ritchie (18:08.867) Yeah, well, and again, if you got to do those things like with assets, just go to like a like everybody thinks that you have to do it when the app is starting. That's true, but you have the option to route to a starting page. So route to a startup page that's no longer splash screen that's in Maui. You can do your large file loading, which let me let me explain why this large file loading was there like it was about 200 300 megs. Jon (18:22.714) Right. And show some progress, be like, yeah. Jon (18:37.754) Wow. And then using, I mean, yeah, I have other questions. Allan Ritchie (18:38.179) Okay, JSON file, big textual. But hang on, hang on. So a 300 meg file, let's be honest, if that was all loaded, it's not really the end of the world. Like we might do API calls that can pull in several hundred kilobytes. That's not really, truly a problem. But taking that file and loading it into memory one, it is going to take some time. At the ass end of it, it's not going to be the worst thing in the world. That's not a bad. That's not a dangerous cache size. What is dangerous, though, is if you're doing like we have options to stream JSON results, right? So it can do all the JSON allocation, but get it right over to the object that you really need. But back then, that didn't exist, man. It was like, take all of this, allocate absolutely every single thing you need, and then turn it into those objects. Right? So the allocations on top of that 300 and Jon (19:21.018) Right. Allan Ritchie (19:40.773) 300 meg file turned it into like a 600 meg and then your virtual memory was like my god what are you doing I'm gonna buffer you because it wants to scale the memory it doesn't know how to do it now you've you've you've chosen violence right Jon (19:45.402) Right, because you're kind of duplicating things. Yeah. Jon (19:56.73) Well, that was kind of what I was thinking too. I'm like, well, 300 megs fine. There's a file there, but how do you even load it with, you know, that you, you need to be careful about how you would load it and not just like, here's the whole thing in memory. Allan Ritchie (20:10.693) And that's what would happen. It would take so long, it'd either go into memory panic or it would take too long and it would crash. And the target, instead of looking at it and commenting out that one line, this customer chose violence times two and decided to blame Xamarin. Xamarin's slow. It's the mono runtime, et cetera. Just comment out that line. I think John, we've got to hit a pause here. My cat is pissed off because I've closed the washroom. Jon (20:15.162) Mm -hmm. Jon (20:35.93) Heh. Allan Ritchie (20:40.132) I'm going to pause. Jon (20:43.578) Yeah, go nuts. Allan Ritchie (20:44.164) Okay, hang on. Allan Ritchie (21:16.354) My God, it's like I'm still married. She spilled her water all over the floor and walk into a puddle. That's what she does. And then she's mad that her water is empty and yelling. I don't know if you could hear her in the background just screaming away, but all right. Sorry. Hopefully that's the last crap. Jon (21:21.398) Yeah. Jon (21:29.306) Nah. Jon (21:33.978) And we'll fix it in post. So yeah, I mean, JSON files are a thing. Like, and I just can't even imagine having that big of a JSON file. But one thing that I, you know, was a little bit more imaginable when I saw it, although like same problem was I've seen in the past, somebody would try to do the same with like video files. It's like they had, you know, they shipped the app with like a MP4 or something. in the bundle and then they wanted to go and copy it somewhere so they could do something with it. I yeah, but I mean. Allan Ritchie (22:05.026) They could read it. Yeah. Because normally when you're touching embedded resource, you've got to pull them out, right? Jon (22:11.226) And well, maybe that maybe it was an embedded resource like in the dotnet assembly app because my first thought is like, well, if you had it in the right spot in like the native app, like it's going to, you can just read it from there anyway. Like so, but you know, that, that one was kind of the same thing. It's like, well, you're doing this on app startup. Like that just, that's not going to be fast. Like it's not, it was seconds at least, right? It wasn't like loading it all into memory, like the JSON file that you saw, but it still took like, I forget like a good five seconds or something. It's like, well, yeah, you're, you're. Allan Ritchie (22:15.138) Okay. Jon (22:39.29) doing this every time. And then that wasn't even just the first time and cashing it. It was every time the app started, they're like, yep, let's load. Let's move that file over. so, but that also had me thinking too, in both of these cases, like I know Android has some facility for downloading additional assets outside of the like app store download. And in fact, if your app is big enough, you have to do that or, you know, get them from the internet some other way. But like, if you use their built -in thing, at least it kind of, Allan Ritchie (22:42.465) every time. Yep. Jon (23:07.162) does it for you, it waits for wifi, you know, all those nice kind of little things. Did, have you ever used that? Allan Ritchie (23:12.738) I haven't had the need to yet. It's coming up. But again, those assets, like I tend to, so if you have like a white label app, so something that runs for multiple companies, often what happens is if you're releasing under just a single banner, it will pull those assets. You either have them built in or it pulls those assets after logging in, right? So then. you download them, you put them in the app storage and you don't have to worry about that, right? You don't have to have these packaged assets because then you're kind of dependent on. Jon (23:44.922) But those aren't necessarily huge though either, right? I mean, I guess they could be. Allan Ritchie (23:50.754) Not really, but they might have like a ton of images. They might have some resourcing in terms of like multilingual. There's a lot of stupid stuff that can come in, but they're usually external because if you have like 100 companies on your app, you don't want all their assets built into the app. So there's ways you can solve it. So that's just one of them. So we have seen that one. Jon (24:00.058) Yeah. Yeah. Jon (24:10.89) yeah, for sure. Jon (24:17.466) So start, yeah, that's another good tale. What else we got? Allan Ritchie (24:22.225) Well, I saw this one on a bug the other day and I have seen this before. I think there was, I think when they started and I'm going to blame James, Mr. Montemagno for this one, cause I know I saw him do a demonstration with the hosting cause I brought in hosting with shiny and that's when I think it started to become like this where you guys were had decided, okay, well we're also going to do it in Maui, et cetera. So then the question started coming up, how do we load pages to do pages participate in di? Well, for me, they always have. And it's like people got on this this thing where if I make the page singleton, it'll load faster. OK, no. Well, kind of, yes, but no. Jon (24:51.002) Hmm. Jon (25:08.122) I was gonna say like. Well, if you, if you resolve that when, so here's my, my kind of new at DI still question. If I register a singleton, when does it get instantiated? Allan Ritchie (25:17.217) Okay. Allan Ritchie (25:22.753) well when it gets first hit technically yeah Jon (25:25.69) So when it first gets resolved, right? So your first page load would still be slow. Allan Ritchie (25:32.449) Yeah. Jon (25:33.786) And then subsequent ones, the idea would be that it's already made so it's faster. Allan Ritchie (25:42.881) sure, but it was already in the nav stack. Right? So. Jon (25:44.218) Yeah. It was already in the nav stack and it's already, you know, potentially got changes in state and who, whatever you've done to it. Allan Ritchie (25:55.424) Well, and let's look at that for a second, because if you dissect that problem, so let's say, yeah, I pop and push a page that's a singleton onto the stack. If I entered a stuff in a form and I now have back to that page now, what's that value? What's the value of that form? It's exactly how I left it. Jon (26:19.258) Yeah. Right. Allan Ritchie (26:21.216) So now I have to write routines to actually clear the state of the page. Whereas if I had Jon (26:27.61) Or or new up the view model again and rebind it, which is going to take time as well, right? Allan Ritchie (26:33.12) Well, usually, okay, so when I've seen this problem, it's been a case of both view model and page being singleton. It's the same damn problem. And if either end of those is Mark Singleton, it's all over. Like the you could have the page be a singleton in your view model be a transient. But guess what? When you have a singleton and you pull in a scope or a transient, you've just pinned that also as a singleton. Good job. So just just just don't you're not being clever. Jon (26:39.386) Right. Jon (26:57.946) Yep. Yep. Allan Ritchie (27:02.207) Right? Just think about what you're doing and why. Because if you, let's go to a webpage for a second. When I hit a URL, is that a singleton? No, if I close a tab or if I open another tab, it's a new instance, it's going to go react, generate all that stuff and. Jon (27:15.258) Not really. If you hit it again, it's a new instance of the page. Yeah. You got to work to make it something that's shared between page loads, right? Allan Ritchie (27:28.065) I'm not even sure you can to be perfectly honest. If somebody knows how to, I'd, well, I guess PWAs maybe you could do. I don't even. Jon (27:32.474) Hehehe. Jon (27:36.846) Yeah, there's ways you can do weird stuff like that. Allan Ritchie (27:43.2) Yeah, you really got to work at that one. You're right to figure out how to do it. So why would we have our pages in a mobile app be any different? If they're so transient is the case where the DI resolves it and doesn't track it, doesn't care. It'll never clean it out. It just kind of throws it off into space. I call it the can factory, right? It'll just keep printing those Coke cans till the end of the day, but it never takes them back and crushes them. It doesn't care, right? Jon (27:45.914) Yeah. Jon (28:03.258) Yeah. Jon (28:11.898) Yeah. Allan Ritchie (28:12.994) So it'll just keep printing out those cans, the transient. But if you're in scope of a Maui app or whatever, where there is a nav stack, that transient is essentially acting as a singleton or even scoped, right? Because it's going to sit there in the stack. And if you've got like a main landing page, chances are that page may never go away, right? Even the only time it might go away is if I've got a log in log out scenario. But. Jon (28:33.722) Mm -hmm. Allan Ritchie (28:39.233) If I'm logged in and I can, you know, next time I visit the app, I would expect to still be logged in. It's going to be the same page. It's going to sit on the bottom the entire time. It's never going to go away. Same with tab pages. Right. So even though it was a transient, it's still technically under the hood of Singleton. The difference is that I don't have to clear state. So every time I go to like a form page, I'm going to resolve it. I'm going to navigate to it and then it's going to be fresh state. It's a fresh, fresh batch. Jon (28:49.978) Mm -hmm. Allan Ritchie (29:07.009) and then I actually have to do work to load it if I want to. But not this other way around, because then you have to clear it and then load. I don't know. Just. Jon (29:07.418) Yeah. Jon (29:15.098) Yeah, well, you're just adding more complexity to right. Like the chances of you doing something wrong there to just grow. Allan Ritchie (29:21.406) Just, yeah, it just keeps getting worse. You'd have like a reset method and it would just keep getting bigger. Forget it. And don't do it. The best code is the code that you don't have to write. Less maintenance. Jon (29:30.842) Yeah, don't work so hard. Jon (29:40.442) And and speaking of DI stuff, you know another another one and you touched on it the one that you saw that you had some several hundred services or something like that so like lots of services in and of themselves Yeah, I mean like if you Allan Ritchie (29:43.841) Alright. Allan Ritchie (29:49.825) Yes. Allan Ritchie (29:57.633) But there's not really a huge cost to that though, believe it or not. Jon (30:00.826) Right. That's what I mean. Like, so like it, that might not be bad. Like if I say I have 300 services, that might be no worse than somebody who has 10 services, but they didn't write those services super thoughtfully. And by that, I mean, you know, kind of the same idea of giving a good repro. Like, if you're going to have a repro that has like, here's the, all the services in my app, right. But then like, Allan Ritchie (30:14.561) Right. Jon (30:27.994) You don't want to share the logic of them because it's hard to separate that out from a repo. It more hard. It can be more hard, right? Or, or maybe. So like stub them all out and it's like, here, here's my, my a hundred services that I still have. but it doesn't really show, you know, the problem that I'm seeing because like, okay, so digging into it, well, what do you do in those services? Right. And what do you do in the, the constructors of them? Allan Ritchie (30:33.537) Wait... No, you're not wrong. Allan Ritchie (30:52.96) Well, and that's it. Yeah. There we go. You hit the key point because a lot of people, let's not cover that one because I'm going to cut. I don't have it on here, but we're going to come to that one. Can we leave that demon out temporarily? It's a, it's a crypt. It's a crypt. I don't know whatever note we're on, but point part two of that. Jon (30:57.69) Are you right? Like, yeah. Jon (31:09.434) Alright, alright, alright. Jon (31:15.994) Okay. What do you got then? Well, we put that one off. Allan Ritchie (31:17.634) Well, going back to going back to the services, right, like having 100 services, not really a problem. Now, if we go to your open source, steward kind of thing, like what you should be doing, right, maintainers don't want to look through 100 lines of code. You have to start peeling back the layers yourself, because at some point you realize where it got slow. Like somebody needs to be put. Jon (31:41.338) Well, yeah, I was gonna say, and sometimes that leads you to the problem and a solution and then you don't even have to wait for somebody to help you, right? Allan Ritchie (31:48.897) Right. And as an engineer, you should be able to figure that out. Like, okay, well, this is where it happened. This is what we've done. And you can trivially go through those and go, when did it start? When did we start seeing this? Start taking some stuff out. You should be looking at PRs, any ways to cover that, right? Like you can generally spot where things are going to be a problem, right? But let's go back to your other point about like there being too many services or not. Jon (32:06.234) Mm -hmm. Allan Ritchie (32:17.762) cleverly thought through that maybe you've got too many services. And I could honestly say I have seen a lot. Like I've seen a main thread service. I've seen, you know, the normal ones like a dialogue service, like, you know, all that stuff. It makes sense. But people spend so much time writing technical services as opposed to business services, right? So. Jon (32:19.578) Mm -hmm. Allan Ritchie (32:45.026) Like I'll often see like a key value store of some sort and then an authentication service of some sort and then a navigation service. So that doesn't sound bad, but let's think of the, we're supposed to be separating concerns, right? So all of a sudden you're like, okay, well I logged in and I got an auth token. Well, does any of the other services really have to care about that? Cause you're going to take that auth token, you're going to shove it in your key value secure storage, which you probably didn't need an, like a. Jon (32:48.442) Mm -hmm. Jon (33:06.202) Right, and then. Allan Ritchie (33:12.769) abstraction on anyways. Now he already has it. But so you go ahead and you put it in there and then now you have to have a constant because you need to be able to pull it out. Right. And you need to make sure you're not using magic strings. So we do that. But then we got to figure out where those constants are every time. And now I have to go and add it everywhere. But if we separated the concerns properly, we didn't have a secure storage service and a B2C login service. And, you know, we just had an off service. Jon (33:16.57) Yeah. Jon (33:24.058) Yes. Allan Ritchie (33:43.074) And in that auth service, it said, look, I'm going to take a secure storage implementation and an API definition. And I'm going to call it, I'm not going to return the, I'm just going to return, you know, the login was good or bad. And then I'm going to store the access token internally because I'm going to have services that use it, but you don't need to see that in the front. And you don't even know, I need to know how I stored it. Right? So all of a sudden I've, Jon (34:08.506) Yeah, you don't care. That's implementation. Allan Ritchie (34:10.561) All of a sudden I've reduced it, which means it's easier for my devs to work with, right? So any devs that are working with my service go, neat. I'll just tell it, I passed it an email and a password and it said, yep, or nope. And it's dealing with all that stuff. Great. Jon (34:25.786) Well, that's, that's kind of, I got to know how to, I think you've summarized the, the, the thought or feeling that I often have when trying to figure out how to design these things, which is like it, how can you kind of make it, even if it's just for yourself, how do you make it kind of feel like enjoyable or magic or, you know, pleasant to, to consume it. Right. And so like what you're saying is, is just that I take, I get, you know, my reference, my instance of this service. And I ask for login or I say, go fetch me something. And it deals with all of that stuff behind the scenes, right? Like you, you're aiming for that kind of like, this is really nice feeling right. When you use it. Like that's, that's, that's like the goal. Like that's, I think the thing to always keep in mind, which is, which is kind of funny. I mean, I it's going to sound cheesy, but I always really liked this kind of mantra that Xamarin had, which was like delight developers. Allan Ritchie (35:00.865) Great. Allan Ritchie (35:04.929) You And that's it. Allan Ritchie (35:16.321) Jon (35:22.714) And that's something that's stuck with me ever since, because I think it actually is a really concise description of that goal, right? Which is just like, make it nice. Allan Ritchie (35:33.601) I don't want to know how the implementation, because the implementation is the details, right? And sometimes it can be very difficult. Jon (35:38.426) Yeah, and so like. For something like this, yeah, one option, depending on what you're doing. If you're just building a Maui app, then sure, yeah, why even have a service for secure storage or whatever because it just uses the APIs that are there. I mean, there's cases. I have an abstraction in Poolmath because I do want to use the same kind of layer on Blazor, Wasm, and Maui. And so it's like, well, the Maui one doesn't work there, so I have to do something. Allan Ritchie (36:11.681) Right. Jon (36:11.706) Now you could argue I could still do that all in, you know, that, that one service and not have a separate thing that, that deals with that. But I think, I think there's reasonable, you know, separation of concerns there, but, but at the end of the day, like you're saying, don't, don't make it like, don't make the secure storage thing, the thing that other services then use to get the token to then figure out how to make the request, right? Like do it. Yeah. Allan Ritchie (36:32.641) Yeah, just make it smart, hide it, right? Because there are cases where you're gonna wanna have an abstraction. So secure storage abstraction does make sense, because you need to go cross platform. That's why we do it. It's not because we need a secure storage, because we could just do an implementation of it, right? We're never gonna plug it out, it's all gonna work the same. But in this case, like if you look at the secure storage, it's nice. It's really nice because I put a key in, I get a key out. And if you look at the implementations, okay, the iOS one is really just works. It's nice mostly, but you look at the Android one and you're like, boy, right? So you don't want to know that that's what the delighting the developer part is because it's simple, right? But I don't need to over -obstract it, which comes to the next point. And this is the last point on this loading a massive ton of services. Jon (37:23.994) Okay. Allan Ritchie (37:30.947) The PR, the issues I hate getting. I hate getting these. If you send them to me, don't expect me to be nice because like, dude, I don't want to figure out your spaghetti. If you're going to write, if you're going to take in a third party dependency, don't abstract the abstraction. And if you're going to submit a repo, don't give me your abstract of an abstraction, right? So I tend to get these in shiny usually around Bluetooth, right? Because people don't like observables. I don't care. There is async versions you can use, but don't try and wrap it to make everything void. I've seen that, believe it or not. Just because you don't like working with async or you don't like working with observables, that's not my problem. Don't use it. Maybe this library is not appropriate for you. And if you don't like that answer, go f... Well, and you're trying to abstract me out in case you need to go to another plugin. Jon (37:59.738) Yeah. Jon (38:12.826) Mmm. Jon (38:19.322) Yeah, yeah. Yeah, well, but I want to use it. I just don't like this part about it. Allan Ritchie (38:29.058) right? Somebody else's code. But then you end up losing the common denominator of it, right? So and you think you're saving yourself some code, you're actually trying to write, you're going to end up writing more and you're going to end up having more bugs. Stop it. Either take the dependency or don't. Right? You could say, okay, well, what if what if shiny disappears tomorrow? Well, if you had a stuck to the business services. So when I write something, Jon (38:45.338) Yeah. Allan Ritchie (38:57.219) that's gonna work with a particular device. So let's say, I don't know, I have a rock. I have a rock, it's got my daughter's name on it. I have a rock, I wanna scan for this rock. So how do I scan for the rock? I have to know that I'm looking for a particular type of rock. It's called a service UID. So, my, wow. Good. Jon (39:16.73) Yeah, I wanna rock. Allan Ritchie (39:23.842) I'm gonna have to let that go, I'm almost gonna lose my train of thought. So I scan for the rock and now I wanna connect to the rock and I don't know how the rock works, right? I don't wanna have to send bytes to it. Just translate all of that gibberish and all those bytes, because .NET devs don't like to work with bytes, I don't know why. Do all that stuff for me. I just wanna send it an int or an enum or... Jon (39:25.594) Come on. Allan Ritchie (39:51.65) You know all those things. I just want to send that stuff and not worry about how it did it. You know, did you serialize it? Did you send it with? I don't know in 20 bytes. Did you have to stream it? Who cares just async? Here's the need I'm figured out so I can hide all that stuff and still be abstracting the abstraction, right? So if I needed to swap that out for a different Bluetooth library because I stuck to a business service. Jon (40:07.162) Yeah. Allan Ritchie (40:20.578) My business is the rock. Exactly. And now I can mock all that and no. Jon (40:22.202) Right. That's the abstraction, right? Well, and, and this, and this almost kind of like gets into the classic territory of, you know, I think it's a, it's well known enough, right? Like you always, everyone jokes about creating a, an abstraction over your data layer or your database. Right. And it's like, for every project that you ever do that for, how many times have you actually gone back and changed out the database in the backend? And, you know, for the time, Allan Ritchie (40:49.699) Well, for the server, yes. Jon (40:51.45) For the times, maybe, and for the times you have, like, okay, was it more, you know, did you save more time by abstracting every project you've ever written out from the database layer, or could you have just gone and swapped the one or two that you changed out, right? Like, it adds a little bit of a old kind of thing now, right, with like, there's layers now that are kind of standard. Yeah. Exactly, yeah. Allan Ritchie (41:08.291) right. Allan Ritchie (41:14.659) Entity framework. Do you really need a repository? Some would argue the purest that you want to have dependency injection and testability, which is not wrong, but there's different ways to achieve that nowadays. Right. And if entity framework is not fast, you can still, if you've, if you've abstracted or mediated your problem, mediation is a good way to deal with it. You can put that one particular query on a stored procedure. Now that store procedure, Jon (41:24.186) Mm -hmm. Jon (41:27.738) Yeah. Allan Ritchie (41:43.811) probably going to be pretty custom to the platform or the database you're using, but so be it, right? That's how you get out of it. So you're right, why try to so hard to do it? I mean, Microsoft has done it. Any framework's great. There's stuff like Dapper and all that cool stuff. And. Jon (42:04.794) Yeah, but that's, that's even a whole other thing than like, I had to feel like back in the day. And I know I did this too with projects where I'm like, I might want to allow people to use whatever database they want. And I'm the only user that ever used the thing anyway. So who cares? Yeah. Allan Ritchie (42:17.283) Well, we live and we learn of what's too complicated. Jon (42:22.714) It's kind of like the optimization rules, right? Like first rule don't. Allan Ritchie (42:27.619) Yeah, well, that's always the first question you ask. Do you have a performance problem? And nine out of 10 times that answer is gonna be no. Well, then why are you solving for it? You're just gonna create the problem that you were trying to fight in the first place. Just chill out. Don't. Follow John's advice. Don't. If there was a shirt you could get that said, Red says no or don't. Jon (42:35.546) Yeah. Jon (42:41.114) Yeah. Jon (42:48.666) Yeah, should I? Don't. Allan Ritchie (42:51.075) Don't. So going back to your constructor one, okay, because we promised we'd get that one. Let's hear it. Do you have a story there or are you just wondering? Jon (42:55.354) Mm -hmm. Yeah, I'm waiting. not specifics, but like, you know, I mean, there's, there's a case that I looked at, I know where the kind of, like I said, like trying, you know, person's trying to create a repro, give them all the credit for, for doing the work to get us something. But then, you know, at the end of it, it's like, well, it doesn't, it doesn't really repro that quite like, yes, you can kind of see it, the difference. but it's not as pronounced as in the real app. And it's like, yeah. Allan Ritchie (43:14.979) Hehehehe Jon (43:26.074) All these services are empty. So, and I don't know, I don't know the case if, you know, I never got to the point of, of hearing, you know, did they, do you find something? But like just one of the suggestions is like, go look at what your services are actually doing. And, and maybe you think perfectly well, nothing nefarious, but who knows? Like maybe somebody threw a, you know, you've got a constructor and maybe it does a connection to a database or some backend in the, like, right? Like, Allan Ritchie (43:34.594) you Allan Ritchie (43:50.069) In synchronous synchronous connection. Jon (43:52.826) All it takes is one, yeah, all it takes is like one, you know, not well -placed decision or line of code. And if you're working on a big team, like maybe you've got a developer that's more junior and didn't realize any better. And so now you're in this world of like stuff taking longer. And when you're talking about, you know, app startup or something and the difference of like one second, that that's all it takes. Right? So like, Allan Ritchie (44:00.289) logic in the constructor. Jon (44:21.21) There's there's different areas. You know, it's really just a case of like if you're really for startup performance, like go look at the hot path of what you're doing. And like you're saying to kind of make that repro, you're going to have to peel back layers and kind of watch what's going on anyway. So at that point you're probably going to find the answer you're looking for in your own code. Allan Ritchie (44:41.345) Because if you send that to a maintainer, first of all, if that maintainer does that for free, they don't have time to go through it, man. Give them the minimal viable product to repro that issue so that they can get it done. And chances are they will fix it for you. Give them a good issue. But. Jon (44:59.61) Well, yeah. And, and you know, we're, we're in a bit different of a position because yeah, we're maintainers of a repro, but ever repo, but, but we have, you know, there, we have customers who are, well, it's, it's cycles. I just mean like, we want to help make people successful with their apps and stuff, but yeah, you still have to go do that work. And, and one of the other things like thinking about this too, that's related, I know I've seen in, in other issues too, is, as we have, as people are migrating more from Xamarin forms to Maui. Allan Ritchie (45:09.985) Limited cycles. Jon (45:29.242) there's often like an apples to apple or seemingly apples to apples comparison, right? It's like in Xamarin forms, this thing worked like this, in Maui it's slower or it doesn't work the same or, you know, we're having problems with it. And anytime it's really around performance too, it's like, there's so many differences between. The old mono and we've talked on on previous episodes about the different runtimes, right? Like there's this, it's all mono, but there's that there's two different model runtimes and they're not equal. It's changed a lot. And it's not necessarily like the, the low level runtime details themselves. So those, those have changed to, you know, part of the change has been like the, the runtime library layer, right? And the implementation of things. Allan Ritchie (46:02.401) Well, it's changed a lot. Just even from net six to net eight. Think about it, right? Jon (46:19.802) Is more common now to the rest of .NET in the new model runtime. And so changes there can have a dramatic impact depending on what your code is doing on mobile, how it gets compiled to AOT or just in time. Like there's all these factors, right? So the unfortunate reality and you know what kind of this is my tale from the crypt of like, I can't, I can't tell you why your app is 500 milliseconds slower on Maui than it was on forms. When you're telling me everything is all. all the same between the two, right? There's just, there's too many variables. And in most cases, or a lot of cases, a lot of the code is faster on Maui, but when you hit a case that isn't, you gotta kind of dig into it and look at your own code and figure out, you know, what's on your hot path. And so there's no easy fix. Allan Ritchie (46:49.76) You Allan Ritchie (47:07.072) Well, here's the thing too. People submitting bugs with like dependency injection and stuff to Maui and then complaining that it was faster in Xamarin. It's like, you guys do UI, you do rendering. Right? Like probably want to vote. Yeah, exactly. Like send it to the appropriate team. Jon (47:21.05) Yeah, yeah, it's more of a runtime question, right? Yeah. And then there's like variants of that too, or it's like, you know, some third, again, like you're talking about bringing your dependencies over, right? Or it's like, well, this, you know, DI implementation is way slower on Maui than it was on, on forms and like, okay, we don't, we don't build that thing. Like, I don't know what they're doing in it. Like if it, you know, use the built -in one and find the differences, and then we can kind of talk about what we can figure out and why it might be slower. But again, even there, it's usually kind of like a case of. Allan Ritchie (47:44.224) Yeah, and it's complicated. Jon (47:55.706) stuff's different enough between old mono and new mono that it's, you're not gonna, you're not gonna find, you're not gonna go like have this aha moment where like, that's the thing that made it slower, right? Like it's just not, that's not how it works. Allan Ritchie (48:08.64) But it's also not your area of expertise either. So how the heck are you gonna even know? Don't be dumb about it. Just figure out where your issue belongs. Jon (48:12.794) Right. Yeah. Jon (48:20.058) Yeah, so figure out what you're doing in your services when you register them all too, because who knows? Yeah? Allan Ritchie (48:24.802) Well, I've got some constructor ones. I've seen some really good stuff there. You know, it's called a constructor for a reason. You're supposed to assemble. You're supposed to assemble your object. You're not supposed to do logic. You're just supposed to set things up. I have seen so many things get instantiated, thread locked, you name it. Don't Jon (48:41.018) Right. Allan Ritchie (48:53.025) Do logic in the constructors. Just don't wire things up. That's what it's for. Construct your object. you just you're taking my good one. Jon (48:59.066) and especially like, you know, no async calls and stuff too, right? There's, there's a reason why you can't put the, the async on a constructor. Allan Ritchie (49:08.193) Right, because it's not going to wait. But it's funny you say that, John. I have indeed seen async calls. Now, no awaits like a continue with or it's a fire and fire and forget. But that's not you. Jon (49:10.394) Yeah. Jon (49:17.786) Right. Yeah. Fire and forget. Yeah. Fire and forget is the critical thing that needs to happen. Allan Ritchie (49:26.017) Yeah, because and you know why I see it. And this is kind of like, it's kind of because shell it's kind of because they don't understand view models, etc. That issue aside, what made you think that running an async fire and forget in a constructor was a good idea. And the reason they did it is because they didn't know how to get lifecycle to their view model. So they were like, what's on appearing? Dude, you have to wire it through. Jon (49:33.37) Mm -hmm. Jon (49:50.202) Yeah. Allan Ritchie (49:54.433) It's just, just you have to, if, if you want to work in a view model, you need life cycle, right? Cause it's tied to the page. Do not call an async method in the constructor. Stop it. Just stop. If you're doing synchronous, it's an even worse. Then you're filing an issue saying it's slow and John's going, well, you, you, you, dude, you're doing a synchronous database connection in your constructor, which by the way you can do. Why? I don't really know. But I've seen some strange stuff and yeah just just don't construct don't it's not a logic it's not a logic tour it's a construct tour that was pretty bad. I want to rock. Jon (50:23.194) I mean, shouldn't, yeah. Jon (50:35.002) Eh. No one and and Yeah, I was that was worse than the one and whatever the bad joke I just said was yeah. yeah that one that was good I quite like that one. See it was so good. You didn't forget So like the other part of that is you might okay fine. Maybe you're not doing anything in your constructor But you know that doesn't like in this case where like I have no insight into what what's this thing? That's slowing their app down here, right? Allan Ritchie (50:47.169) I didn't forget yet. Jon (51:06.778) But like what else is on the hot path, right? Like as you're resolving these services, as you're, you're like doing things and maybe a page on appearing, like, are you, are you making sure that the stuff you're doing there is reasonable too? Right? Like that's another thing. It's like all, like you're saying before, like have a, a, a page that, you know, loads fast and do the things you need to do on the, on the background or, you know, whatever. Allan Ritchie (51:29.089) You can sit in a nice little spinner there. You can launch it at a task so that it doesn't lock up your UI. And you can be like, yeah, we're waiting for that 300 meg file to load. It's still going. Heck, you can even count the amount of memory it's using while you're there. Just reactively do the engines. We're using now 800 megs for your 300 meg file. Jon (51:31.386) Yeah. Jon (51:43.61) Sure. Yeah, you can be like, and then you can show the percentage likelihood of the app crashing while it's doing that. Allan Ritchie (51:54.657) Yeah, you could. You probably could, actually. Jon (51:56.346) Right, as the memory goes up and maybe you can see like available and then you can be like, I don't know guys, we might not make it. Yeah. Allan Ritchie (52:00.225) This is it. We're going to hit the end. All right, what else have you seen? I know I've picked on this point before. I've picked on this point before. Observable collections. Jon (52:09.498) Hmm. Jon (52:12.986) I think I see your favorite one. I mean, I've grown to be unfond of it as well. Allan Ritchie (52:21.696) Well, I still think people don't understand and I know we've covered this probably a ton because I hate them. That's right. I don't hate it. It's like people use it for everything and you don't need it for 95 % of your use cases. Maybe. Jon (52:35.802) Yeah, it's a very specialized type that you should use in a very specialized way. Allan Ritchie (52:42.24) And what's worse is that in order to make observable collections worse at work, every control has to obey them, right? So it has to go, are you a normal enumerable? Okay, you are bind. Are you an observable collection? Okay, let's hook all those events and we'll have to deallocate them at some point too, just to be sure. And I will start watching remove and I'll make sure I get it under the index. And what about the scroll position and. Jon (52:51.514) Yeah. Jon (53:00.314) Yep. Right, yeah, there's the other part. Jon (53:11.225) Mm -hmm. Allan Ritchie (53:11.936) adding where does that go? Does it get appended? Does it get inserted? How the hell do you even do it? Insert you have to update that logic and. Jon (53:17.626) Yeah. well, so here's the problem is that like, I think observable collection has a number of, change types, right? In the, the event. But like, yeah, like you're saying, like everything that's, that's gonna use and accept an observable collection has to understand all of those as well, if it's going to do them properly. And, and I think what often people do in myself included, like I, so for virtual list view, I made a, Allan Ritchie (53:28.192) Yeah, add, remove, update. Jon (53:47.674) observable collection adapter, right? Cause I, yeah, it's something somebody's going to ask for it, right? Actually, I even used it myself one time. I forget why. but there's places for it, but like, you know, in that it's like, I'm not going to do all the work to implement all of the different like change types. And so like, it's just gonna, no matter what the change type is, I'm just going to reset the underlying, you know, native adapter because it's going to figure it out. Allan Ritchie (53:49.2) People use it. Yeah, fair. Allan Ritchie (53:56.608) There are places for it though. Allan Ritchie (54:11.52) Heheheheh. and that's a good, that's a good segue because when are you going to, if you're going to see in a, a performance problem, this is where you're going to see it. Now I don't know why this has never been solved in the BCL to be honest with why there isn't an ad range. I think it's really because of the eventing. Sorry, go ahead. Jon (54:31.418) so it's, that's an interesting one. There isn't necessarily a great reason why that doesn't exist. The reason mostly now, I mean, one, it, it's, you know, it's something that people can work around and figure out. so it's not like a top priority for the team that would be responsible for that, to do that work, given the other priorities that they have, right? Like we all. All of the teams in Microsoft, like everyone loves to think like, it's this massive company and there's these huge teams of is I know that's not how it works. And like, even if there were bigger teams, it doesn't necessarily make like more. You can't just throw more people at every problem and expect it to move faster or better. Right? Like there's there, there's obviously a, you know, a exponential curve of some kind of, you know, value to, resources and all that. Right. So I know I've, I've spoken with, Allan Ritchie (55:21.713) people. Yep. Jon (55:27.258) somebody on that team in the past and actually they brought it up. They're like, Hey, you know, we, we, we always see there's a one massive issue that talks about it. And there's some level of appetite to, to add that kind of functionality into the BCL. One of the main problems is like, there's such a strong set of opinions that don't concur on how to do it. And so it's like, it's one of those, like you're, you're going to off, you know, Allan Ritchie (55:53.053) It's deadlocked. Jon (55:56.826) 70 % of people, no matter what decision you make. So it's like, right. So. Allan Ritchie (55:59.995) Don't make any decision. So I mean, basically what ends up happening here to go to the problem is for apps that have a binding to an observable collection, we'll talk about why don't use an observable collection in a second. But for those that do have the binding, if you're doing a loop because you're going to get data from, say, a service and you're like, there's no ad range, you're going to start for reaching it. Well, Jon (56:25.818) Mm -hmm. Allan Ritchie (56:26.907) The problem is every time you call add, it triggers the notification change event and redraws that UI. And then if you brought in 300 items, even if those items are virtualized, right? It still has to do a redraw. It doesn't know any better. It doesn't care. I mean, that's an optimization you could make, I guess. It'd be like, hey. Jon (56:31.034) Right. And if. Jon (56:37.978) Mm -hmm. Jon (56:41.658) It's one that's going to redraw. Well, it's going to redraw at least the eye. Like so if you if you think about how I mean collection view, but like I'll use virtual my virtual list view because I have more intimate understanding with how all the bits fit together. If you look at how that's done like. OK, in my adapter. It's only going to tell the platform adapter to to invalidate itself in the platform adapters going to look and say OK. You know, I have, I can show eight items on the screen right now. here, you know, that's the index I'm at scroll wise, probably worst case it's going to have to like figure out where it is and maybe draw like, you know, all of those eight items again or something. Right. so it's not going to do it for everything. However, still doing that like 300 times isn't great compared to doing it one time. Allan Ritchie (57:36.507) Ha ha ha. Jon (57:38.202) For no benefit, right? Like if you're drawing the same eight items 300 times, that's gonna be slower than one time, I think. Allan Ritchie (57:45.467) True. Yeah, it's pretty, pretty good assumption. If you do something more times, it's, it's going to be slow, but people keep doing this and I keep seeing the same issues and it's like, dude, you need to understand what you're doing. And. Jon (57:49.114) Yeah, I think the logic works out. Jon (58:00.442) Well, and so adding items to that collection like that is going back to the, so it's the notification notify collection changed event args. And in theory, if you add a new item, it should tell you that it, you know, I think there's, there's, there's an ad or a replace. Yeah. Yeah. So like, and then there's like, here's the new items that were added. Right? So it gives you, it gives you a proper view of kind of the change set. Allan Ritchie (58:16.634) It added there's there is a there is an enum that says here's here's the event that took place. Yep. Allan Ritchie (58:29.882) Mm -hmm. Jon (58:30.17) However, almost nobody actually uses that. And like I said, everybody just kind of like, I'm just going to go reset because that's the easiest thing to do. Allan Ritchie (58:36.186) But and that's the thing, but it's really hard to do right. Like even when we think about an update operation like a replace, it doesn't really even in Maui, it's got to go. OK, there's the index. It's there. I'm just going to say, look, this this this element change. I'm going to rebuy that control if it's invisible. Right. It's complicated. It's not it's. Jon (58:39.93) Yeah, well, yeah. Jon (58:53.626) Right. Jon (58:57.05) Yeah, because how does it know unless you tell the collection with the thing that, you know, here's what I'm replacing, right? Otherwise it's not going to know. Allan Ritchie (59:02.65) Right. So it's really complicated to do and I don't think people really understand that. Now the question usually comes up when do I that I thought that's the only way I could bind a collection. Do you know how many times I've heard that from people that have used Xamarin and WPF for years that that's how they think they bind lists. I'm like dude do you understand it's just it's all every single item is based on I notify property changed. which is nothing more than a string property of the property that changed, including lists. So, I mean, I tend to see a lot of people use observable collections. You could, you could have the argument that yes, it's easier, but I often see people do a clear redraw number one and then the four each ad or ad range if they have an ad range. So they now just, they went through all that operation. Why didn't you just say, Jon (59:51.29) Mm -hmm. Allan Ritchie (01:00:01.815) you know, load API, transform it any way you need to do, stick it on list, notify property, change list, we render list. It's the same thing. It's still memory efficient and it's, it's actually technically faster. One redraw, not the clear redraw one and the add range giving benefit of the day, draw two. So observable collections were made for data in motion. Jon (01:00:12.154) Yeah, that's not any more code. Allan Ritchie (01:00:31.382) So what I mean by that is I might have multiple threads. So when I do a Bluetooth scan, I have this thing that returns an observable collection. I call it a managed scan because people don't understand it. And it's also, they have trouble thread locking or making it thread safe, this collection. So I have, I'm hitting it with updates and new devices that I find. I'm hitting it with updates of those devices. And then if I don't hear from that device, cause it's a scan, right? Jon (01:00:46.266) Mm -hmm. Allan Ritchie (01:00:59.83) You can't tell when something's at a range. You just don't hear it anymore. So if it's been 10 seconds since I've heard it, right, I remove it, right? I can kick it off the list. I got threads blasting at it and I can thread safety that and lock it so that that collection doesn't implode because you can't have two things touching a collection at the same time. That's bad. So, but because I'm constantly adding, removing, updating that data is in motion. So that's a good place to use it. But for clear and add range, don't stop. Jon (01:01:17.722) Mm -hmm. Mm -hmm. Allan Ritchie (01:01:29.494) use a list man please please it would make your life so much easier it really would. Jon (01:01:31.61) Yeah. Jon (01:01:36.314) But that's one area. So I I've had kind of a wish for awhile that we would have Roslyn analyzer support in XAML. And I think it's it's on the radar of that team anyway. I don't know if there's any plans or you know, it's ever going to actually happen, but these are the kind. Allan Ritchie (01:01:55.454) there's too many ways you can do it. Jon (01:01:57.754) Well, no, but just to be able to write some analyzers for some of these scenarios, right? Where something like, I mean, you could do this one probably more in C sharp, I guess, because it's not. But even just to say, hey, we see you're binding an observable collection type, can we do something to just make sure that you understand what you're doing here? Allan Ritchie (01:02:05.718) Mm -hmm. Allan Ritchie (01:02:21.046) We just saw a single add. we saw a clear and then an add range. Not that the add range is there, so you'd have to watch for it, but... Jon (01:02:29.466) But we have, but yeah, I guess we, I mean, we could do the C sharp one and that would be helpful probably. Right. Like just to be like, well, just even to look for like, okay, so you've, you're, you're doing your, anytime you're touching add on an observable collection, we'd want to go and look at, is that inside of some kind of iteration? Allan Ritchie (01:02:32.854) Yeah, yeah, like a view model. Allan Ritchie (01:02:50.23) be tough to find but yeah I see where you're going with it. Well because people tend to put it off in different methods right they might have like a thing that's binding or pending to the collection so the collections getting passed around and I think it's as be I think you're more Jon (01:02:52.378) I don't know, I don't know if it'd be that bad. Jon (01:03:00.826) Yeah. Jon (01:03:05.402) Yeah, maybe. You might be able to detect the cases where somebody does like you said, like the clear and then is like add, add, add, add, add, right? Allan Ritchie (01:03:12.758) Yeah, find the ad, look at it as an observable collection, go, did you mean to do ad? You may want to inherit the observable collection and add an ad range. Just thinking. Jon (01:03:18.426) Yeah. Jon (01:03:23.13) Yep, or replace with a list. Allan Ritchie (01:03:26.134) Yeah. Jon (01:03:28.09) Yeah. So that one will forever be, I think, something that we see and then have to cringe a little bit at. Allan Ritchie (01:03:35.67) Well, and again, you don't need an observable collection. You just need a list. Just do a list. Don't make it hard on yourself. Jon (01:03:47.866) Alright, are there any other big egregious offenses that we've seen that we're missing? I'm sure there are. Allan Ritchie (01:03:54.198) I think this could be like Tales from the Crypt, the first episode of it, and probably have more of these in the future because, I mean, this is just a small portion. I've seen things that make your eyes bleed. You never quite recover. Jon (01:04:00.666) Yeah, season one. Jon (01:04:10.732) And to be fair, I mean, I'm sure I've done some of these things too. Allan Ritchie (01:04:14.323) Well, you don't, you don't get better without doing the mistakes, right? So at some point you have to invent and you have to go down the path. I think really how it is nowadays is that when we screwed up, when we were kids, there was no, you didn't go out to stack over. There was no stack overflow. Like you just, you pick up a book, you might find an online form that would tell you you're being stupid. but for most of the part, we had just had to figure it out and. Jon (01:04:17.946) Right. Jon (01:04:33.21) Yeah, yeah. Jon (01:04:39.258) Yeah. Allan Ritchie (01:04:44.018) I don't know, this generation seems to have, like. Jon (01:04:46.17) When there wasn't as much of a record of our stupidity following us around forever either. It's kind of like the whole, you know, pictures and phones and stuff of kids these days. If you use an observable collection wrong once, that's going to be on the internet forever. Allan Ritchie (01:04:50.418) Yeah. Allan Ritchie (01:04:54.61) every Allan Ritchie (01:05:02.61) Well, I did take a screenshot of you saying you had bought into DI, so I still have that forever. Forever. And I'll keep it for RX. Jon (01:05:08.186) That's right, see? And if you're interviewing for a new job and some employer is looking at your profiles and your commit history and they see that, just don't do it because you don't want them to have to see that. Allan Ritchie (01:05:23.57) There you go. Jon (01:05:26.906) All right, do we have a plugin package or product this week? Allan Ritchie (01:05:30.194) Well, I did say during the episode source generator kit. So that was a nice little plot. It's not out on Newgate. So and also doing Newgate with source generators is hard. There's that's not even go down the reasons for why. Just trust me, taking a new get package inside of a source generator, not the easiest thing in the world. So I think that's why this isn't on Newgate. I don't know. Jon (01:05:33.146) Yeah, I thought that was interesting. I want to look at that. Jon (01:05:44.282) Hehehe Allan Ritchie (01:05:55.794) But you know, I copied the code. I put it in my source generator. It's well, it's it's doing mostly what I needed to do right now So definitely worth checking out Jon (01:06:06.138) Yeah, it looks cool. I was just kind of searching it right now. And yeah, there's one that I thought would be great to have, which is specifically find all classes which implement specific interface. Allan Ritchie (01:06:17.614) Yep, or an abstraction. It's got a base class class. It's got a bunch of little scans and it does the because the syntax receiver is kind of like this big. It's this big beastly class that you need to override everything. Like you look at it and you're like, OK, what do I need to override? Well, it depends on what you're doing. It depends. Jon (01:06:19.706) Yeah. Yeah. So that's cool. Jon (01:06:30.842) Yep. Jon (01:06:40.922) Yeah, no, this is really cool. I think I'm going to have to find a way to use this somehow. Allan Ritchie (01:06:42.414) Yeah. And really it's what makes using the syntax generators, the syntax receivers is what makes, I think that's how the general, the incremental generator technically works under the hood. It makes it a little bit easier. Jon (01:06:56.762) I was gonna say, does this support the incremental stuff too? Okay. Allan Ritchie (01:07:00.142) No, syntax receivers are a pure source generator thing. The incremental generators. I don't know if the intent I think was to make it faster, but certainly did not make source generators any easier at all. No. Jon (01:07:06.106) Okay. Jon (01:07:15.961) No, no, it didn't make them easier for sure. I know we forever ago when they introduced them had to switch like the XAML code behind generator to use incremental. I didn't do that. Thankfully that was Stefan figuring that out, but that was, that was not, you know, an easy, an easy switch to make either. Allan Ritchie (01:07:26.35) Yeah. Allan Ritchie (01:07:35.246) There would have been a lot of four letter words probably in that word. It's not easy. Once you figure it out, you know what I still find, cause I've written a number of them now. I still can't remember how to do it. Every time I go in, I was like, what did I do? How did I do this? Like it's, they're not easy. So I get why people aren't writing them necessarily, but really it's worth looking. If you can find packages like this, it's worth taking a look at. Jon (01:07:46.842) Mm -hmm. Jon (01:07:53.818) Yeah. Jon (01:08:02.266) Yeah, no, for sure. That's cool. Really love that. Looks like it hasn't been updated in a while. Maybe somebody will find inspiration. Allan Ritchie (01:08:09.037) Because it doesn't support the incremental generator, which... Jon (01:08:13.146) Yeah, that's what I was thinking. I'm like, maybe somebody will see how cool this is and make an incremental supported version of it. Allan Ritchie (01:08:20.3) Like I said, I'm pretty sure this is what it's doing under the hood because it's the the syntax receivers are nice and fast, right? So it only notifies it when one of those things changes. Which is it's that's cool. Maybe that's what maybe that's what it's doing. I don't know. Don't quote me on it. Jon (01:08:27.482) Yeah. Jon (01:08:35.61) Yeah. Yeah, it looks neat. And yeah, this would be pretty easy to pick up and wire in to do the thing that we talked about, right? To like generate all the registrations. So that's neat. Nice, nice. Allan Ritchie (01:08:47.436) I'm already doing it for one of my projects right now. I'm trying this out right now, but I'll save that shameless plug package for another time. It's not done yet. It's in preview. When it comes out, one of it. I am excited for it. The mediator, the mediator for apps. Future episode. Jon (01:08:54.074) Alright. Okay. Well, and we'll probably do another episode at some point on it too, right? Yeah. Cool. I think, I think that'll do it for today for this first, episode of tales from the crypt. So. Allan Ritchie (01:09:11.884) Leave them in the crypt. Jon (01:09:13.402) If you're not, you know, if, if we didn't, touch on something that you've done and you're still not too upset with us, if you are too upset with us, please don't listen to this next part. You know, if we called you out and you've, and you've done the thing that, that you shouldn't have done and like I've done in the past, but I'm okay now I got over it. Don't, don't listen to this, but if you haven't and you're happy to learn about the things that you shouldn't do and you're not too upset about it, you know, we're looking for those, five star reviews. but if it's going to be a one star, just, you know, don't, it's not worth your time, honestly. Allan Ritchie (01:09:46.476) You know what? The next episode will be stupid things I could remember doing. I have taken down production a couple times because of stupid things I've done. So we'll save that. We'll save that. But I don't mind being in the butt of the joke. Jon (01:09:50.65) yeah. Yeah. Yeah. Well, I don't either, but I just I have a bad memory. And I've done so many dumb things that I wouldn't be able to remember half of them. I'll just have to try. Allan Ritchie (01:10:04.844) They never leave me. They're part of my soul. Jon (01:10:08.73) All right, yeah, so five star reviews only and if you can do that, that would be great I don't even know if we have had any for all my begging and pleading. So please somebody hear me Somebody listen to this part Allan Ritchie (01:10:20.457) We're getting the audience. There's a lot of you out there, so... Jon (01:10:23.962) Yeah, yeah, there's a bunch. So that means that, you know, you, you, you kind of owe it to yourself to, to help us. Well, I was trying to, yeah. Okay. Fine. I won't be so polite. All right. Yeah. So there you go. gone mobile .io is the website. You can find all the links to all of the things. we w what was, I sent you some, we had some feedback the other day again. Do you remember what it was? I have to find it again. Allan Ritchie (01:10:30.793) You're with us. Hit the damn button. Otherwise, I'll find a reason to put you on Tales of the Crypt. Tales of the Crypt, yeah? Allan Ritchie (01:10:51.081) Yeah? I don't, we'll find it. Maybe we can save that for the episode where I made, okay. Because I wanted the shameless plug for it. Because it's gonna be, okay. Jon (01:10:55.13) Well, I want to find it quick now because we're already here. I mean. Yeah, okay. I found it. I found it. So this one was from Matthew. I'm not, I'm going to, you know, keep, I'm not going to dox anyone here. So I'll keep last names and everything private just in case. And actually Matthew is looks like a fellow Canadian. If that's not too revealing, based on the .ca email address that I see, Matthew says that, they rather enjoy the episode on app, app architecture. last few episodes have been excellent. So thanks. Hey. Hopefully you've got the one -star review, or if not one -star, the five -star review. Yeah, yeah, yeah. So it sounds like Matthew would like to hear more about the mediator pattern as he's using it in his apps, at least to some extent too. So I think you got one fan for the mediator pattern and plugin. So. Allan Ritchie (01:11:30.153) Yeah, dude, dude. Allan Ritchie (01:11:47.433) now for four days it's already at 500 downloads so I'm feeling pretty good about it. Yeah it's it's good there's an alpha out there but I'm almost ready to publish that puppy out almost. Jon (01:11:52.282) Is it public? Is it like the repo? Okay. So, so maybe if. So maybe we can put a link up too so that Matthew can find it as well. Cool. Allan Ritchie (01:12:03.303) All right, we can do that. But I think we've got to do an episode, maybe App Architecture 2, and we'll put that guy in. Because I'm going to convert John. Couldn't get him on RX, but I'll get him on this. Jon (01:12:07.194) yeah, definitely. Jon (01:12:12.698) Well, no, I like the pattern. I like where it's going. I just have to find the time and need to put it to swap in, you know? Allan Ritchie (01:12:17.838) John already messaged me if you put Rx in it I hate you or something. Something violent. It was... Yeah, he did. He was quite violent the way he said it too, just for the record. He's not a complete nice guy like you might think. Jon (01:12:24.218) Then I'm putting you on the next episode of Tales from the Crypt. Yeah, that's right. Allan Ritchie (01:12:35.718) That's alright, I can live with it. Jon (01:12:38.234) All right, Al, thanks for listening. We'll catch you next time on Gone Mobile. Allan Ritchie (01:12:41.862) Bye everybody.