Jon (00:06.746) Welcome back to another Gone Mobile. Hey, Alan, I heard recently that you were, well, one, you build apps. I know that much, I think, right? You still do build apps sometimes, every once in a while. Right, so I heard that you also recently built some things in Disney. Allan Ritchie (00:17.494) Yeah, just occasionally. Allan Ritchie (00:25.906) Oh yeah, I just got back from Disney. I'm going back there with my kids in two weeks. But if you have the chance to go to Disney, I've been bugging John about this, you need to get one of these things built. Hopefully he hears that, but yeah. Nothing like a light saber. It's my big child toy. Jon (00:41.842) So what did that look like? What's the anatomy of building a lightsaber? What's that experience? Allan Ritchie (00:48.298) Well, to be fair, they do a whole show around it. It takes, like the show's like a half an hour, but there's actors, you're in a building that feels like you're in frigging Star Wars. It's epic. I totally was losing my mind. But to build a lightsaber, so they do the whole show about how you put things together and you pick your crystal, if you know anything about Star Wars. But to build the thing, you can actually do it in like 30 seconds. But during the course of the show, it takes a half an hour. And... Jon (01:04.996) Mm-hmm. Jon (01:11.749) Mmm. Right. Allan Ritchie (01:16.374) They do all this cool stuff. You pick little parts here and there because it's supposed to be like junk, right? Star Wars junk. Basically, fancy, very expensive lightsaber. But oh my God, dude, you have to do it. Jon (01:22.482) just choosing from a pile of junk to make your fancy, yeah. Jon (01:33.538) So the 30 seconds to build a lightsaber, I figured that was kind of an equivalent to like what it takes to build an app too, right? You do those in about the same time. Allan Ritchie (01:43.634) Um, sometimes, yeah. Yeah, sometimes. Just doing my reprozer. Jon (01:45.874) Sometimes. Yeah. So today I thought we would, you know, in the spirit of building things and talking about how things are put together, we would talk about mobile apps. What goes into a mobile app? Allan Ritchie (01:58.39) That was, I swear to God you've been planning that all week. That was an epic lead in. Good job, good job. He's gonna cut that out. Oh yeah, that was awesome. The anatomy of a mobile app, huh? Jon (02:05.183) rolls right off the tongue. Jon (02:10.082) And yeah, and I want you to tell us how to do it, because I think every time that, you know, I've shared with you parts of how my app is built, you're like, that's one way to do it. Allan Ritchie (02:24.438) Well, you build stuff from scratch. That's what John does. He builds everything from scratch. And that's all right. That's how innovation happens usually, right? Or at least you learn how to do it wrong and then you learn how to do it right. Jon (02:29.192) always. Jon (02:34.406) It's like, yeah. I mean, I like to consider what I build as, you know, kind of that artisanal, handcrafted, you know, implementation of a navigation service or something, right? Allan Ritchie (02:47.486) Right, but you know as we go out there there's other people that have done this, not me, I don't do the navigation stuff, I don't do UI period, but you know there's a lot of a lot of apps or open source stuff out there that handle this for you right. There's there's, but I think I think really we want to jump back here and say well what's what is in an app and then we can kind of go after the subtopic right. Jon (03:05.799) Yeah. Jon (03:11.938) Yeah, no, absolutely. Like, so going back far enough, how do you, when you sit down to start a new app, you know, not been built before, like what is the first thing that you will do? Allan Ritchie (03:24.97) Well, obviously I have templates now, which we've covered recently. But if we start from ground zero, right. Jon (03:28.271) Yeah. Allan Ritchie (03:34.102) The first thing I want to do, obviously, you know, if you're doing a product properly, now if we're building POCs, you and I are just, who cares, we don't need the layout. We know the page flow. But really, probably you get something from Figma that looks pretty, it smells pretty, it flows pretty, it's all great. But now you got to take that translated into something, right? So does that look like? Jon (03:42.011) Yeah. Jon (03:56.434) So is that at that point, like if you've got like a designer or somebody that's given you something, that's already kind of then been like wireframed for you? Is that, like I guess, yeah, hopefully. I mean, is that an exercise that you usually participate in too to try and kind of make it make sense before you get to the point of saying like, oh, that's not gonna work. Allan Ritchie (04:09.43) Hopefully. Yeah. Allan Ritchie (04:23.702) Well, let's be fair. If you've ever worked with a product designer, they have this thing in their head. So sometimes some of them go crazy. I love most of the product designers I work with. I love all of them. I'm supposed to say that, right? Anyhow, some of them go a little bit crazy and you got to go, you know, we can do that. But do you really want to spend the time on doing that? So it's that there's absolutely a case to be made to say, okay, well, there's time and money in building that. The page flow doesn't quite make sense to me and if it doesn't make sense to me and I'm the guy building it It's probably going to be challenging for the user, right? So yeah, you're absolutely right. So the designer would go away Build a page flow build something that's beautiful Jon (04:55.623) Yeah. Allan Ritchie (05:05.01) And then you get into the talk about, well, you know, what does that look like? You know, this is going to take me a lot of time. Where can we cut some corners? Or, you know, if we do this, if you do this, it's going to take a lot of extra time. But if we do this instead, right, it's going to shave off a bunch of time. It's going to look pretty close. Right. So a lot of designers, or at least ones that I've worked with that like to go wild, they don't use the navigation page, the navigation bar. Jon (05:26.299) Yeah. Allan Ritchie (05:34.614) which that sucks, right? Because you get so much out of that, right out of the gate. It makes your app look native, right? It doesn't matter. Like now he uses the navigation services in Android, iOS and all the other 10 million platforms. Flutter has it. React Native obviously has it. All of the mobile architectures out there, he used the nav bar. Jon (05:38.819) Yeah. Jon (05:46.746) Mm-hmm. Allan Ritchie (05:57.214) And there's so many ways to customize that now. You just gotta keep the damn thing at the top, right? So things like that is you'll learn to give and take for the page flow and design. But from there, you start thinking about, well, how am I gonna wire this thing up? What's the code gonna look like, right? So some people, you know, if you come from Windows Forms or I don't know, did WPF? I did WPF, but the view models were popular then. Jon (06:02.811) Yeah. Jon (06:24.743) Yeah. Allan Ritchie (06:24.754) So you generally tend to plan how am I going to glue the logic of my pages to the logic of my app. So with Maui, you know, the popular one is obviously MVVM. So model, view, view model. There's other cool ones like MVU, which is Comet and there's a couple of flavors out there, I think. Some deprecated. Jon (06:37.039) Right. Jon (06:52.331) Yeah, and that's kind of a popular model I think Flutter is a little bit more like that. Allan Ritchie (06:56.542) Yep. And there's some great stuff out there from like the community, Maui Community Toolkit, which you can't really have an episode without mentioning them, right? They have some great coding standards, but even that plugs in with MVVM, right? So if you want to do code, anyhow, the point is, is kind of gluing that together with your logic, right? So MVVM is great. I love that platform specifically or that methodology specifically, because very easy to unit Jon (07:04.921) Yeah. Jon (07:23.536) Yeah. Allan Ritchie (07:24.042) And it kind of sits in between all your services, like how you get data, how you, I don't know, request permissions, et cetera. Like it really sits well between the glue, the sandwich. It's the melted cheese in the middle. Jon (07:37.402) Yeah, it's kind of, yeah, I like that better. I was gonna kind of call it, you know, the orchestration of kind of things between it, but Melty Cheese is so much better. Allan Ritchie (07:47.218) Yeah, it's, I'm thinking about food, right? So it's a great one. Yeah, melty cheese. So it's the stuff that gets it all nicely layered together and puts it all together, right? So MVVM kind of sits there in the middle. How you do those view models? Well, that's debatable. There's so many ways to accomplish it. So kind of sits outside of the anatomy of an app, but there's really some great, great things to help you work through MVVM. There's even Shell. Jon (07:49.8) Hmm, yeah. Jon (08:04.868) Yeah. Jon (08:14.631) Mm-hmm. Allan Ritchie (08:15.526) Shell is there to help kind of glue some of that together. It's not quite enough if you're doing a lot of rich MVVM, but it covers kind of the next topic, which is like navigation, right? Jon (08:28.09) Right. Yeah. I was going to say like there's, there's not really, you know, the there's an, uh, it's, it's maybe poorly named from the forms days, right? There is like navigation, uh, is there navigation services that even called that at their navigation manager? I forget. Um, like on, on the, the navigation page, right? There's, or maybe it's just navigation. Uh, but, but yeah, you can, you can do your navigation from there, but as I kind of learned over the years and had. Allan Ritchie (08:47.338) Yeah, navigate. Jon (08:56.454) gone that way and sort of the keep the app because I'm the single developer on it, keep it, you know, lean and just use what's in the box and don't try and, you know, separate out concerns too much and just like dive in and get coding. Uh, but yeah, eventually it's like, well, but that doesn't really help you do what you just said was like, keep some of the logic and stuff separated and be able to have it unit tested and, and go that route. So. Yeah, in the box there's not really navigation except Shell's version, which, you know, maybe you can speak more of why there's some shortcomings there from how you want to use it. Allan Ritchie (09:34.038) But here's the thing, right? So out of the box, Maui now gives you DI anyways. So it's really good at helping enable kind of what we're talking about, getting the melty cheese together with the pieces of bread and any of the meat, right? But when we talk about a navigation service, obviously, like you said, you have that navigation page. The goal is to never have that thing get back to your view model. Your view model is supposed to be pretty lean. It's not supposed to know. Jon (09:38.811) Yeah. Jon (09:44.999) Yeah. Jon (09:58.106) How do you do you usually like to set up your projects a certain way to sort of, you know, enforce or like cause that as a natural consequence of how it's set up? Like, do you use a separate project that's, you know, net eight only, for example, or doesn't have Maui in it at all so that you can be sure to not kind of leak across those boundaries. Allan Ritchie (10:21.147) I try not to separate too much. So a lot of people tend to have the view models directory and a views directory. I like to put I like to have a feature area. So I'll say like orders, for example, and I'll have an order list page and I'll have an order list view model right beside each other. Right? Jon (10:38.408) Mm-hmm. Allan Ritchie (10:39.838) I don't need to go outside of that box too much. Now for unit testing, that's a whole other topic, right? I don't necessarily wanna bring my page, but I wanna still test my unit, unit test my view model. That's, you can do. Exactly. And I do that quite successfully now, but at the same time, I'm able to stay right beside my page, right? Because you're almost working in them in tandem. I always hate trying to find, okay, here's the view model. Where the heck is the page? Jon (10:49.358) Right. Which you can multi-target your project to do, right? Jon (11:01.086) Mm-hmm. Jon (11:06.618) Yeah. Or vice versa. Allan Ritchie (11:09.13) Now there's libraries where you kind of marry the two. So Prism is a big one that comes to mind. Reactive UI likes to marry them join them at the hip which is great. But still if you're coding these things you've got to go looking for them. And I don't know about you but I've encountered times where the view model name doesn't really follow the convention of the page. So you're like where what am I what am I touching. What does this affect. Right. Jon (11:15.043) Mm-hmm. Jon (11:30.895) Yeah. What one is this? Yeah. Allan Ritchie (11:34.654) So this is kind of one of those architectures, I like them just being right beside each other. This is what this guy works with. Jon (11:41.018) I prefer that too. Unfortunately, when I tried to re-architect my pool math app, I couldn't land there simply because I was trying to make a blazer front end that shared that view model layer as well. And to your point of like, it's nice when they're beside because everything's just easy to find. Like that is one of the frustrating things that... Allan Ritchie (11:58.62) Okay. Jon (12:06.858) I end up doing is like, oh yeah, like all of that is in its own separate project because it's not easy to share kind of the things between two properties without putting them that way. I guess, I mean, I could do like linking in and stuff and there's ways I guess I could achieve it. It's just, uh, I dunno, I don't like doing linking files and sharing them in multiple projects for some reason. Allan Ritchie (12:18.326) Well, there's. Allan Ritchie (12:30.446) Yeah, that's fair. There's a lot of argument these days too that MVVM could be too split apart. I personally have had a ton of success with it. I love it. Sometimes I see it's shortcomings and if you're out in the web world, so I do a lot of web work as well. I love React. I try not to go about the 10 million different flavors of React, but React is a pure kind of app. Jon (12:47.687) Mm-hmm. Jon (12:55.848) Mm-hmm. Allan Ritchie (12:55.87) right? The way they mix code and markup and all that stuff and their component architecture. I love it. It's fast, but it marries code and markup. Right? So there's a lot of, I don't know, if we go back to the PHP, ASP, classic ASP days, the markup was mixed and we do, we had some success, right? You build on the shoulders of giants. Jon (13:05.147) Yeah. Jon (13:09.92) Yeah. Jon (13:14.862) Yeah. And at the same time, you know, like there's always like the simple case of something like, Hey, I want to display, you know, a value from my view model into my page, but I want to do some formatting or something to it. Right. Like, you know, so then you get into a world, I feel like anyway, where you start to make these decisions of like, well, can I do, how far do I want to take it? Do I want to be, you know, the XAML, you know, Allan Ritchie (13:30.744) Yeah. Jon (13:41.834) handles every aspect of it right like the xaml has the two string kind of format string in the in the binding or something like that or you know if that starts to get too complex to try and do what i'm trying to do i just like add another property to my view model that exposes things how i want it to format i know it's not quite tying the two together but like you start to kind of bleed that line at some point anyway Allan Ritchie (13:42.158) purist. Allan Ritchie (14:06.614) Well, and that's the thing, right? Like I'm not a big XAML purist. I hate converters because now you're breaking outside of it. They're there for good reason. I get it. But I will always tend to get as much into the view model. Right now it shouldn't have a concept of styles, but you can bring constants in, you can bring. I want as much logic and formatting stuff to exist in, in the view model as much as possible, because even something like, I mean, once you, sure. If you put out a date time, for example. Jon (14:13.339) Yeah. Jon (14:19.367) Yep. Jon (14:27.483) Right. Jon (14:36.326) Mm-hmm. Allan Ritchie (14:36.668) Right? You probably want to see that in local, but let's say we've got logic and this is one that I've dealt with recently. Right? I want to see that time zone agnostic. Right? I'm not going to want that logic sitting in my view or in some sort of converter where I have to pass like 10,000 parameters. That's the view model do that. Right? Even so much as the formatting, because that might be some sort of funky string format or some sort of translated version. It's a lot. Right? Jon (14:46.567) Yeah. Jon (14:53.795) Yeah. Jon (15:02.938) Yeah. Well, and if you're sharing something like that, like even in my app example, if I'm sharing the timestamp, you know, between the Blazor version and the Maui app version, like I kind of want those generally to be the same in both places anyway. So if I'm putting that logic in the view side of things, Well, now I've just got to maintain that in two places instead of one. So there, I think there's a lot, a lot to be said about putting that some, you know, some of that in the shared layer anyway, in the view model anyway. Yeah. Just to, to kind of have that consistency and maintenance and nowhere you're looking for bugs when someone says it's not showing up right in that kind of stuff. Allan Ritchie (15:42.538) Right and you could say that putting that logic, I mean again going back to the React, yes the way they've architected it, it's great, it kind of goes into the flow of your components but Vue models because we have that power of dependency injection and testability and the 10 million kind of services that could come in. Now I know a lot of peers out there are like, you don't need DI. Jon (15:57.717) Mm-hmm. Allan Ritchie (16:06.086) You know, in small apps you don't really, but here's the thing. When you start working in teams, there's so many times where I've got people that just, they're like, I don't know how localization works. I don't care. Right. Or I've had cases, I don't know if you've ever had this, but I've had cases where sure, our ESX files are fine for a majority of your Jon (16:16.603) Yeah. Jon (16:23.72) Mm-hmm. Allan Ritchie (16:26.018) your localization, but I've had ones that were dynamic based on the tenant that you logged in or like the company that you're logging into were there like, well, you're the way you do French sucks. Our French is better. Use our French. Use our wording. Right. I've had business cases for that where I've been like, Oh, that's going to be a fun one to change. Right. Jon (16:31.23) Oh, yeah. Jon (16:38.006) Yeah. Jon (16:44.4) Yeah. Allan Ritchie (16:44.918) But your general UI developers these days, cause I don't know about you, I'm a full stack developer. I don't know when this term got coined, but to me it's just, you gotta dev that path. But nowadays you get people that are like, I know XAML, I know ViewModel, I don't care how you get data. I don't care how you get localization. Just do it, just present it to me. Jon (16:53.671) Yeah. Yeah, yeah, it's like. Jon (17:00.198) Yeah. Allan Ritchie (17:09.282) So there's lots of cases for that right but navigation kind of getting back to that is that that's one of those purest things where do I now from do I do I send out a message to tell the page to do it do I don't know I can't even think of all the ways to do I bring the navigation page back to the view model well no but there's things like shell out there which shell doesn't have an abstraction I don't believe Jon (17:21.655) Mm-hmm. Jon (17:25.082) Yeah. Allan Ritchie (17:36.718) kind of, kind of not. It's not something that's injected anyways. Because it doesn't work with, it's not meant to work with your view. It's not meant to be part of your view models out of the box. But it gives you that sweet URI navigation. You can easily put an abstraction around it anyways. I think it's like two or three, you know, go to async. And I don't even think it has a go back because you can do that all through the URI. Jon (17:40.423) Yeah, right. Yeah. Jon (17:47.412) Right. Yes. Yeah. Jon (17:53.862) Mm-hmm. Parameters and all that stuff. Jon (17:59.398) Yeah. Yep. Well, I think it's like you use dot to go back, right? Yeah. Allan Ritchie (18:06.462) Yeah, so you don't really need a lot about it. And if we talk about something like Prism, which I've already brought up, that's another popular one. They've got a good navigation service that works off a URI and you can do the same things there. Now you had asked about what I feel Shell's shortcomings are and we've had this talk with Shane, a pure ween. Jon (18:13.544) Mm-hmm. Jon (18:27.11) Mm-hmm. Allan Ritchie (18:28.334) right? He's, what is his title there? He's the, if John doesn't know the answer, then Shane does. Jon (18:31.434) He's an engineer on the on the Maui team. He is also a principal software engineer on Team Maui. Allan Ritchie (18:40.983) and he does a lot of good things. So if John doesn't know the answer, then you talk to Shane. You just gotta get his attention. Jon (18:44.954) Yep. And usually it's I, if I gave you an answer, I probably ask Shane anyway. Allan Ritchie (18:50.102) So him and I have had talks about it where it's great. Like Shell does a lot of those things. What it doesn't do as we talk about, as we go back to the view models, you still need life cycle there, right? A lot of people try and do the work in the constructor, but it's like, it's too early? Yeah, you don't do things in constructor. You don't do logic in constructors. Jon (19:01.787) Mm-hmm. Jon (19:05.142) Yeah... Nope. Yeah. Allan Ritchie (19:11.634) Right. So what's kind of some of the life cycle you want? Well, when my page loads, I want to tell the view model, the page is ready. So I'm going to do, you know, kind of some of the stupid easy stuff. We're not going to go advanced here, but I'm going to say is busy true. You know, I'm going to load my data service, whatever that looks like. I'm going to say, get me data asynchronously because I don't want to block my UI. Jon (19:34.342) which is another reason that this isn't great for putting in the constructor. Allan Ritchie (19:38.334) Yep, so I'm going to go out. I'm going to ask for data, whether it comes from HTTP, some sort of SQLite, who knows, right? I don't know, I don't care. I'm not the implementer of the data service. So I go out, I ask for this data. I load it into my list and then I say is busy false. If there's an error, maybe I display a pop-up to say, yeah, sorry, dude, we screwed up. I don't know what happened. Jon (19:43.72) Mm-hmm. Jon (20:01.742) Yeah, yeah, exactly. Allan Ritchie (20:02.422) But we also logged it at the same time too. And that logger is built into, say, App Center. So all these services plugging in, as we talk about the anatomy. You need a logging, you need a pop-up, you need data service, and then you need to glue all those to the list and the busy, et cetera. Now, Jon (20:09.714) Mm-hmm. Jon (20:23.89) Yep. You know, I gotta say too, like I, I was originally fairly team. I don't want this DI service stuff in my app again, like, and, and I think that came from historically for one reason, like that was never a fast thing to do in, in older Xamarin apps and stuff. Like nobody ever optimized for that. And partially, I think as the developers of these frameworks and stuff, without going and building your own apps enough. And like most people on my team have done a decent amount of app building. I don't wanna make it sound like nobody uses our product, but it's not something that we obviously do day in and day out as our main job. And so it's not always easy to get yourself in the mindset of somebody else and what's useful to them, right? So that was never super prioritized. I will say in talking, in doing, I started converting my app from like, you know, I was doing two things at once. So my, my pool app was written in Xamarin forms and it was written when I was, don't care about DI, I don't want to do, you know, separate properly my view models, you know, my navigation from the page was passed into my view models, all that good, bad stuff. And as I was starting to re-architect it with the idea in mind of okay, maybe I want to be able to target the web with a lot of this logic too, and have a different UI for the web, and started talking to you a lot along the way, and this has been an ongoing thing for like a couple of years now, just because I never have enough time to sit down and actually do all of the work, but it's close now. Going through that process and kind of having the somewhat open mind, not fully open, because you said RX, and I went and said, nope. But having an open mind to some of the service stuff is like I started using it and started seeing the value in some areas that it created. And to the point where it's like, yeah, now doing the separate implementation for a bunch of services for web versus Maui apps has made that a really easy thing to do. Doing the navigation too, right? Allan Ritchie (22:14.07) try. Allan Ritchie (22:35.926) The great one for you is I remember you were doing the object database. What was it again? Light, light DB. Is that what it is? Jon (22:46.071) Oh, yeah, I was using LightDB for quite a while, which was nice, it's good, it's a C-sharp thing. But two things with it, like one, doing the expression stuff that it uses to kind of create things dynamically. It works in Maui, but it doesn't always play nicely with AOT. Allan Ritchie (22:49.362) And yep. Jon (23:08.282) And so I was having to do some tricks to say like, oh, when the building the app for release mode, like don't AOT this particular library. And on iOS, that means use the interpreter, which is a little bit slower. And the thing isn't the super fastest to begin with anyway, because it's not native code. It's C-sharp writing a whole database implementation. And so when the app starts, yeah, you can do some tricks to kind of defer doing some of the stuff or do it on a different thread. But at the end of the day, Allan Ritchie (23:08.31) Yeah. Jon (23:35.794) the main screen on my app needs to display data from that database and so the path to get there was a little bit slow. But I think I know what you're gonna say about this. Allan Ritchie (23:42.038) Now, did you not have that light dB connection in all of your view models reasonably? Jon (23:50.939) I did, but at the point, I mean, I did in the forms side of things. Oh no, I think I did abstract it then already, but, you know, moving it over to Maui, I created, you know, kind of a data layer service interface. And then I filled that out. And so, you know, at that point, it didn't matter that it was light DB under the hood. And I think Allan Ritchie (23:58.673) Okay. Allan Ritchie (24:06.956) Yep. Jon (24:14.279) your point maybe was going to be to the effect of, hey, swapping that out for SQLite wasn't so bad, right? Which is true, which is true. And I even, oh, I have. Allan Ritchie (24:19.55) Yes, that's it exactly. Right. And the other case, the other case could be made there is, are you going online to get data too, because that happens, right? Building offline is a hard thing. That's a lot of people know. Right. So again, as the consumer, I don't care if you're using SQLite or light DB. I don't care if you're going out to the web. I just know I'm going to wait for you to give me data in the structure. You're telling me it's going to come back for. Jon (24:30.574) Right. Yes. Yeah. Jon (24:44.782) Yeah. And to, yeah, to that point, no, I was going to say like, one of the things that was kind of neat about that. I think it was maybe almost two years ago now or a year ago, we were, we were flying to another province to go do some family stuff. And, you know, I'm on the plane and I'm like, okay, I want to sit down and work on, on my app a little bit. Uh, well in Canada, we don't have every, maybe it's better now. Allan Ritchie (24:47.666) So sorry, keep going, keep going. Jon (25:13.642) We flew a budget airline too, so I'm sure that didn't help. There was no Wi-Fi on the plane. And so I sit down and I open up my laptop and I start to go debug my app. Okay, yeah, no, I can't really get too far because my data source, part of that is syncing stuff offline and the instance I had didn't have a sync from before. So it's like, okay, well. Hmm, if I want to actually do some work on this part of the app that I was intending on, I need a way to, to kind of stub out essentially like the, the data layer and do something smart. So I ended up like just writing some JSON content that had like a few records for each type, or I serialized them out based on my models, and then just wrote another layer that was like, just load this from JSON instead of from a database. And then I could swap back and forth between them. Right. Allan Ritchie (26:04.37) Exactly and that's good because now you're not going to change 10 million things. You're basically changing one point. Your app continues to run. Now the challenge can be there sometimes and I know kind of some of the purists again like Miguel Díazcaza, the good Xamarin creator, he's anti-DI as it gets but really again for teams we've got many touch points working on it. Jon (26:20.332) Mm-hmm. Allan Ritchie (26:29.162) I still swear by it. I think the challenge though, is that some people tend to overdo their abstractions. And that's a fine line to juggle. Like even think about what you could do with LightDB, right? Like you might wanna include sub models, you might wanna filter on them. But if you define a contract that says, look, it's async, you're gonna get a list of things, chemicals, right, for your pool app. Jon (26:36.593) right. Allan Ritchie (26:55.022) I don't care how you get it and I know exactly what you're giving me and if there's certain things that could be nullable, I mean that's awesome now you can mark them as this could be null. You probably want to be careful. All of those things come back from the contract. You know what you're getting. Your data service doesn't have to be all this massive queryable super extraction because good luck writing and plugging around iQueryable. It's not going to happen. Jon (27:04.891) Yeah. Jon (27:15.246) Right. Jon (27:18.798) Yeah, like a JSON implement. Yeah. No, and I, like, I think that raises a good point. And I, that makes me kind of think the way I would say that I moved from being kind of the, don't care about any of this stuff, like just write the thing that I need to, to make things work, right? That I think that the school of thought always was a little bit, let's not spend time. trying to over-abstract things. Like I think that was always the logic of, hey, I don't wanna use this because I don't really wanna get buried in the details of, oh, I've got all these interfaces and I would have to, it's just over-complicating things. So applying that to where I went with the data layer was exactly what you're saying. Like I kinda took the approach of, I'm just gonna, like I need. to return this data for this thing, I'm gonna make a method very specific to doing that in the interface. And over time, I would say like that data service interface has grown a bit, but it's certainly still manageable and it's very kind of purpose built and driven, right? Instead of trying to make it all this, yeah, like you said, like this generic, like, well, what if we use like a queryable thing and I can link over stuff from wherever I need it? Like, no, just do the thing you need, but like there's a balance. Allan Ritchie (28:25.847) Right. Allan Ritchie (28:38.77) Exactly. And think about like there's a lot of things that come from this too, like cross platform and where your database is stored, right? There's so many ways that DI can help there, but keeping it simple. Now when you're your own architect, like you're essentially for your pool math, you're the architect, you're the designer, you're the, I don't know what else is in there, designer, architect, developer, you're everything. You are the app. Jon (28:48.702) Mm-hmm. Jon (28:57.307) Yeah. Jon (29:00.978) Yeah. Every, I don't know, whatever, everything, developer. Allan Ritchie (29:06.954) It's John on an app, right? So it makes sense for, you don't need the abstractions until you do, right? So you still don't need to go crazy, but even from a cross-platform perspective, we used to do this cool thing and you get called the bait and switch, right? You remember that? And it basically, you had this implementation, you tricked the compiler and the compiler would say, yeah, give me the iOS. Oh, there's no iOS, I could get the net standard, right? Jon (29:08.54) Yeah. Jon (29:13.991) Yeah. Jon (29:22.227) Yeah, yeah. Allan Ritchie (29:35.398) Oh, there is an iOS. Okay, I'm going to take that one. And then you did the same for Android. And then you kind of had the static thing that would go, just give me it, right? Give me the, I'm going to load up whatever DLL I'm in. And it worked great, but you had to kind of do some trickery. It was a trickery. It worked really well. Linkers started getting at it because it didn't understand that you were kind of tricking. You were cheating. Right. Jon (29:51.162) Yeah. Jon (30:00.462) Yeah, it's like this is the same assembly, right? No, sure. Allan Ritchie (30:04.802) But then when you enter DI, it's you've got that interface and your implementation has to match it. So you know what you're getting. And you can do that from a cross-platform perspective as well, right? So DI can help you out. You don't have to do this trickery of bait and switch. It's just, here's my Apple implementation. Here's my Android implementation. Here's my Windows implementation. And then you could use all your compiler tricks to, you know, if Windows, if iOS, et cetera. Jon (30:12.828) Yeah. Jon (30:34.106) Yeah, exactly. Yeah. Allan Ritchie (30:34.154) And it just works. It's fantastic. And then you're taking that interface and you're applying it places. So it's kind of hitting that killing that two birds with one stone. Right? So you get the easy plug ability, not going overboard of your data service, whatever that looks like. Jon (30:51.47) Mm-hmm. Allan Ritchie (30:52.07) and you're still getting the cross platform stuff, right? Which essentials obviously does, right? You've got connectivity, which is, I said to you guys, do you either rate or do you cheat? Do you cheat kind of. Jon (31:02.81) Uhhhhhh Jon (31:06.542) I forget offhand, part of the problem was kind of maintaining compatibility, right? So there is like a singleton instance, but we did actually move things so that there are interfaces and you can, you know, DI them. I think we do inject them maybe as well. I forget. Allan Ritchie (31:10.763) Right. Allan Ritchie (31:18.721) inject. Allan Ritchie (31:25.094) It doesn't matter anyways because the interfaces are still there. So I still know at the end of the day. I can put it to my view model that doesn't care necessarily what platform it's running on probably doesn't need to. Jon (31:28.147) Exactly. You can still do it that way if you want. Jon (31:37.796) Mm-hmm. Allan Ritchie (31:37.834) right and it could just say give me a connectivity give me an event that tells me when that's changing right so I can say user you're offline you know too bad whatever right and I don't need to worry about how that works either because I don't I forget you know one day iOS has the NW link path that's how it tests connectivity I don't even think you guys use that yet you do now and it used to be like a like a Jon (31:43.867) Yeah. Jon (32:00.486) Oh, yeah, we don't use the latest API yet, I don't think. Allan Ritchie (32:06.114) ping, basically would issue a ping and everybody used that for years, right? That's the point. Like I don't even remember anymore what the heck I'm using. Does it matter? Well, if I need to upgrade it, it does. I sure as heck don't want to go change the implementation in 10 different places. I just want to know that essential is doing the modern reasonably modern or at least working way of doing it so that I can use that within my app, right? So that's. Jon (32:08.131) Yeah. Jon (32:21.787) Yeah. Jon (32:31.418) Yeah, I will say the only thing that I did find, and it's not a problem necessarily, but it's more of like a learning, is once you kind of go down the path of, I'm gonna start injecting stuff, especially if you're using constructor injection, right? Which is the kind of default that we throw in. Like I know there's other DI libraries and frameworks you can plug in and use that maybe support property injection and stuff. but I chose just the path of least resistance is like, you have to buy in completely at that point, right? Cause if you try and start to be like, oh, I'll use it here and here, but maybe I don't need to use it here. It's like, well, but then you got to figure out how to get that stuff in there. And so these like the observation was really just go with the flow at that point. And then you're on the happy path, but you know, you try and kind of. Allan Ritchie (33:24.81) You could still use the statics. You can. But. Jon (33:27.99) Oh yeah, yeah. I'm just saying like even from my own stuff, it was kind of like, oh, I've got, you know, I implemented my own window instead of using like the, setting the main page for reasons. And like, so all the way down, right, it's all like layered. It's like, okay, if I do that, that window is going to create, you know, the main page instance. So how is it gonna do that? Am I gonna, you know, either get that from DI or I could new it up, but if I do that, I still need to pass the right stuff to that constructor. And at that point, my window has to have the services injected into it that it can pass along and like it just, it kind of is a domino. Yeah. Allan Ritchie (34:03.294) It can balloon, right? A lot of view models too, what I tend to see is that people inject like a massive amount of services, right? And there's a good possibility, there's a good possibility that you are going to use all those services, right? Like the things that I usually think about that I need on every page is navigation. I need a page dialogue so I can say, sorry, we screwed up. Here's a toast, something that I don't even care what it looks like, right? I probably want to measure connectivity because that's important. Jon (34:11.767) Yeah, I'm guilty of that too. Jon (34:20.771) Mm-hmm. Jon (34:34.535) Mm-hmm. Allan Ritchie (34:35.378) Or that they are offline because sometimes you just don't know, right? Maybe it can't reach a server, your servers down. So it's saying, look, we were, you're disconnected. This is when the data is from, but I can see it. Um, you need your data service, whatever that looks like. Um, I don't know. There's so many other things, camera, uh, like all those things. What I generate. So people get annoyed because they're like, my God, I have all these, these things I got to put in and for unit testing, that can be hard as well. Now. Jon (34:52.583) Yeah. Jon (35:02.704) Yeah. Allan Ritchie (35:04.386) The thing is, is that people do this big thing. They do the 10,000 injections. What I tell people is, if you know that those services are core to every, pretty much every page, and they will be, put it in like a base set of service, right? So it's got a bit of an allocation there. It's got another allocation, but it's gonna have all those services. So I'm injecting one thing, and then maybe something. Jon (35:16.615) Mm-hmm. Jon (35:20.222) You got top level service kind of right? Jon (35:28.954) Yeah, if you're doing that anyway, like maybe there's cases where, oh, I don't, I don't, you know, maybe I only use two thirds of them on this page, but on all my other pages, I use them all, right? Allan Ritchie (35:38.878) Right. I mean, I use localization everywhere too. I wish I didn't have to, but localization is part of an app. Right. My data service part of an app connectivity is part of my app. I need all of those all the time. And so I have a core service that I inject everywhere. It's not interface that doesn't need to be. It's just a placeholder for everything. Right. Jon (35:42.343) Mm-hmm. Jon (35:59.462) Yeah. So like it, that, that thing is the thing that has like a million, you know, things in the constructor to be injected. Right. Allan Ritchie (36:04.402) Yep. And then that way, if I need something custom that now becomes a core service, right? I don't, I haven't ever had to expand on it in most of my apps, but at least then I'm doing it in one place. And now all of my pages can benefit from that. You know, a logger, that's another one. You know, everything benefits from it and I just need to start using it. Jon (36:10.718) Mm-hmm. Jon (36:21.723) Yeah. Jon (36:25.35) Well, yeah, I was gonna say that way when you're actually like you decide, okay, I wanna add this thing and I wanna use it a bunch of places, like you're not going into every class and like adding another constructor parameter, right? It's just in the one thing. Allan Ritchie (36:36.51) Yeah, and all your unit tests start going wonky because now you have to go into all your unit tests and add that constructor. Right. It's just there. Right. It's easy to mock it. Right. Because you know exactly what you need to mock Jon (36:41.554) Right. Jon (36:48.125) Yeah. Allan Ritchie (36:48.194) for all of that, you do it in one place, you give it to everything and then you can play with it. And your unit testing becomes a little bit easier. Still big, but as your app becomes more complex, that's what's gonna happen anyways, right? So that's kind of some of the great things about this. So when we talk about the Anatomy app, again, we have all those core services, we have all that cross platform. Jon (37:06.674) Mm-hmm. Allan Ritchie (37:11.938) You know, we need MVVM or MVU or whatever that looks like to glue our UI together. We need a way to monitor or to work with cross-platform services. We need a good navigation service. Like I said, Prism's out there. Shell gets you a lot of the way, not quite all the way. It doesn't plug your view models automatically, but it's pretty darn close. You guys will get there. Jon (37:17.201) Mm-hmm. Jon (37:24.115) Mm-hmm. Jon (37:28.594) Right? Jon (37:31.886) And like you said, like you can write a pretty simple wrapper around that, you know, if that's what you want to use, right? Allan Ritchie (37:35.69) around it. Yep. And it'll do all that pretty UI navigation or URI navigation. You can have your connectivity to decide, you know, am I going online for my data? Am I getting it from cash? Am I getting it from a database? Right. That's the anatomy of adapt to me. Right. Is the ability to do all of this. And then you're able. Jon (37:49.95) Mm-hmm. Right. Yeah, it's kind of the underlying, like everything almost kind of but the display of the UI, right? But that's part of it too. Allan Ritchie (38:03.126) But Maui does that. It is part of it and Maui does it, right? So that's at the top of, that's the top bun, right? That's your sesame seeds in your bun. And then everything else is putting it together. Putting together the hamburger, the cheeseburger. Cheeseburger. Jon (38:13.818) Mm-hmm. Jon (38:19.105) What would you call the lettuce? Allan Ritchie (38:23.874) lettuce. That's the gym. Jon (38:25.222) Like it's kind of essential, but it's like you wouldn't want it on its own necessarily, you know? Allan Ritchie (38:33.306) said the cheese is the view model the services are you know what maybe that the burger the burger is the view model the services are your cheese no because they glue everything together we're putting too much thought in this so what would be the lettuce it's essential connectivity that's a good one right people take people take that for granted Jon (38:35.461) Yeah. Jon (38:40.762) The lettuce is too thin to be this. The service is, well maybe the, yeah. Yeah. Jon (38:53.719) Okay, yeah. Allan Ritchie (38:57.162) and they don't really look at it. I always see it in apps. They just blindly call off to the server, right? Probably nude up an HTTP client, which is also bad, and just kind of fire from the hip. And then they're like, well, how do we know it errors? Oh, we'll just add a try catch. Yeah, what a try catch. Jon (39:01.382) Yeah. Jon (39:12.046) Oh, the app crashes. Something went wrong, the app crashed. You know, you'll figure it out soon. Allan Ritchie (39:17.358) We'll put a try catch in and then we'll call app center. Oh, app centers now deprecating, right? Which it probably is at some point in the future. Right. So now you've got to go and change all those. Right. But connectivity. Exactly. So you have I logging or whatever. But the ultimate thing here is that connectivity, I think, is the lettuce because, you know, you have to have lettuce on a burger. It's just kind of weird without it. Yeah. So. Jon (39:29.723) Yeah, so like what's your crash reporter now, right? Like. Jon (39:42.822) Yeah, you need that crunch. Yeah, it's not, but I think that's good because it's, your burger is still mostly there without it, but it's not quite right. Allan Ritchie (39:52.466) So it's maybe more specific as your cross-platform services because you really do need that help of the platform without kind of jumping too far out, right? Just tell me when you're connected and tell me when you disconnect. And then also give me a flag that I can check right away to say, are you connected? Right? And then I can decide, do I want to display something to the user? Do I want to? Jon (40:01.32) Mm-hmm. Allan Ritchie (40:16.466) load it from cache. How do I want to do that? But that's often I'd say that people forget about the lettuce like it just becomes assumed. But that's like the things you're always using is those cross-platform, especially in a Maui app, whether you know they're there or not, they are. And there's a whole whack of stuff happening behind that interface, right? That you just don't realize there's so much driving it like cameras, right? You've done, you've done a lot with the camera. I say, go get me a barcode from zebra crossing. It's like one, it's like one method with Jon (40:34.831) Yeah. Jon (40:41.967) Yeah. Jon (40:45.254) Yeah, you're like, go scan a barcode. Oh, well, that's easy. Allan Ritchie (40:52.19) a couple flags and arguments and you're like that's great. That's easy John come on man. What are you doing over there? Why can't you have my future? Jon (40:58.494) You know that what though, that's not what we do in Maui now, unfortunately though. I got away from that because there's too many people that were like, yeah, but I want to make like customize the UI and I want to do this and that. It's like you could have, but now it's a view. Now it's a view you have to use in your Maui app. Allan Ritchie (41:14.594) But that's still awesome and that's the evolution anyways, right? Is because there's so much that goes on and then there's so much customization. I mean, I did something called user dialogues, which I spit on now. I don't use it, but that was kind of the starting point for me as I just need a dialogue to come up cross platform. I don't care how it does it just give me an alert. Right? So, you know, that's the evolution. Jon (41:17.499) Yeah. Jon (41:23.482) Yeah. Jon (41:32.444) Right. Jon (41:36.191) What do you do now for things like, like I know one of the things in my app, I do a lot of networking calls just to save data off and get data. And I have kind of like a pop-up, you know, HUD. I think I still actually use my HUD view thing that now, Cheese Baron, yeah, he's been kind of keeping the lights on there. So I'm using that, but like, is that? Allan Ritchie (41:55.686) I stole for dialogues as well. Jon (42:03.662) What do you do for that kind of like, it occurs to me that part of an app sometimes might be like a more foundational part of that where you have a kind of a constant state that you want to display off and on like loading something. Allan Ritchie (42:18.43) Right, so I mean we didn't really talk about controls but they're a great one like collection view, right? So this is going back to the page flow as your designer is usually going to want something wild, right? So that's why I kind of got away from user dialogues because they, you know, they're skeleton layouts now which is like the... It looks like a list view and it's like it's trying to read something. It's kind of cool how they work. I don't know how to describe it. Jon (42:23.996) Mm-hmm. Jon (42:29.755) Yes. Jon (42:35.151) Yeah, yeah. Jon (42:40.122) Yeah, yeah, and it's, ideally like it almost looks like the, I mean, it looks like the skeleton, like of what the data should look like, right? If there's like a, you know, a title label and two detailed text labels and an image beside it, like that would all show up as like gray rectangles. I'm sure people will understand, you know, oh yeah, I've seen that in an app, right? Allan Ritchie (42:49.365) Yeah. Allan Ritchie (43:01.234) I equate it to like the old 8-bit Nintendo newspaper, right? It looks like an 8-bit Nintendo news. You're going to get some data there, and then it's going to turn into something beautiful when it's all loaded. But... Jon (43:06.128) Yeah. Jon (43:11.61) Yeah. And here's what it might, you know, the data is gonna kind of look like just to, to. Allan Ritchie (43:15.586) kind of yeah this is how it's how it should lay out there should be a picture there should be some text here right and it but a lot of designers go that route so I can't you can't really just do a loading as easily anymore a lot of people do the is busy which sometimes that isn't enough because you might want Jon (43:18.813) Mm-hmm. Jon (43:28.707) Yeah, yeah. Allan Ritchie (43:36.05) You might want something like a percentage, how much is loaded, how much is coming in, etc. I don't know. There's so many things I've seen. Jon (43:41.659) Yep. Yeah, so there's not like one way to do it, but is that something that you still, I guess, yeah, you wouldn't always be able to like inject that as a service, because if it is a skeleton view or whatever, you have to do it that one way. Allan Ritchie (43:54.818) But that's, and that's where MVVM works well, right? I can probably say my state is loading or is busy as true, which usually isn't enough anymore, but I can say it's doing something. Jon (44:00.977) Mm-hmm. Allan Ritchie (44:07.554) and then when it's done doing it I could say it's done doing it and then that turns into the pretty list right and then you might want it to fade into a pretty list right there's so many that's why you can't do general purpose as well now alert or a toast that's a bit different an alert and a toast looks the same way all the time confirm Jon (44:12.52) Yeah. Jon (44:16.442) So that... No. Jon (44:22.03) Yeah, they're kind of, yeah, it's kind of a standard enough thing. But this, this part of the conversation makes me, me kind of think of another small subtopic, which is probably that small, you know, as you're, you're building, you know, these apps, and especially when you get into the space of something like, like the controls, the UI part of it, what, like, how do you navigate? the problem space of, okay, the designer has this envisioned for how the app is supposed to flow and lay out. But like, I often see people trying to build, you know, things in a Maui app that they're like, okay, no, I want it to work this exact way. And they're having trouble making that happen. And it occurs to somebody maybe with an outside perspective to say, well, that's like, if it's not working that way, like maybe... approach that problem differently? Like instead of trying to use a certain control, a certain way, what if you did it differently? How often do you encounter that? How do you navigate that in an app? My thought is that people are maybe not willing enough to kind of think outside of the tunnel vision they have towards doing something a certain way. Allan Ritchie (45:26.199) Yes. Allan Ritchie (45:41.118) Well, and that's really the cool part about this, right? So if we talk about, so I had user dialogues, right? We talked about how do you customize those or the people want to customize. The fact is, is you can't really, right? So user dialogues kind of died because it just, it was the boring looking stuff. So when we look about, well, how does that change? How do we evolve that? Do it in Maui, exactly how you did your pop-up. We were talking about how you did that article, once upon a time for a toast, right? Jon (45:46.536) Mm-hmm. Jon (46:06.072) Mm-hmm. Allan Ritchie (46:10.946) but it didn't happen with the service, it happened with Maui. So the view model is still able to facilitate that forward instead of trying to figure out how to do it from the back. And I guess the point there is thinking outside of the box is not everything has to be a service, not everything has to be in the view model, not everything has to be in the UI. You have to really pick, is this a one-off? Can we reuse this? And there's many ways to reuse it from all parts of that layer, all parts of the burger. Jon (46:39.77) Yeah, yeah. Allan Ritchie (46:40.96) do it. You can do it up front. You can do it in the back. You can do it in the middle. Pick your poison, but you don't get set that things have to be done that way. Don't get set that everything has to be extracted abstracted beautifully. Right? Just pick what works. Jon (46:55.483) Yeah. Allan Ritchie (46:59.186) find some clever ways to make it reusable, but that's also not the end goal. Sometimes you, you know, you may do 98% of the work making that thing reusable and you only needed it 2% of the time. So sometimes just solve your problem. And then if you see that pattern repeating, then figure out how, Hey, how can I reuse this? Maybe it's a data template. Sometimes it's that easy, right? Data template in Maui. Sometimes it is, okay, well, listen, we need, we need this to Jon (47:21.297) Yeah. Allan Ritchie (47:29.04) alerts work the same way. Don't get stuck on an architecture. It has to be that way. Solve the problem then see the patterns on how to abstract. Jon (47:40.906) And I think, you know, to, to can expand on that a little bit too. Like, I think that as you're building out UI for things, and I know I've seen it enough where, you know, maybe a Maui control has a bug, I know shocker, right? Um, and, and something as simple as I've seen someone try to use a collection view. For instance, I know I've, I've been really working with collector with, you know, lists of things, right? As we talked about in that other episode with my, my virtual. uh, list view and somebody I think asked, okay, well, how would I do, how would I use this if I wanted to, you know, constrain, like, figure out what the height of it is and make the thing only the size of the content that, you know, is in the list. Um, and then it's like, yeah, that's actually a really hard problem to solve on some platforms. And then, you know, for instance, on iOS, as soon as you try to do that with their UI collection view, they're like, yeah, well, we'll tell you how big of the content is after we measure every item in your list. No, right? So I might have a list of like 5,000 items that's no longer virtualized because I said, hey, how big is that list? Because if it's not bigger than the space I have, I don't want it to take up the whole space. But I have 5,000 items in it, so it's way bigger than that. But we'll tell you what it is after we figure it out. So there's things like that too, where it's like, okay, if something's not working perfectly for you in the way that you want to do it, Allan Ritchie (48:52.396) Right. Jon (49:07.194) Why are you, maybe you shouldn't be using that control for that situation. Maybe you should be thinking about like, why do I need it to, to collapse down, you know, when there's only two items. Um, but I also need it to display 5,000 items, like, you know, to kind of go at these problems from a little bit different of a perspective and have some, you know, uh, I guess creative openness to approaching like, Oh, maybe I could do it this way instead, right. Allan Ritchie (49:33.282) Well, Maui is really the ultimate abstraction, right? It really truly is. D-I aside, it's a collection view. It's gonna dig into the platform one way or the other, right? And you're trying to accomplish a lot of things for a lot of people. And sometimes that one size fits all, doesn't really fit all. So for instance, I had, and this is a good segue, is I had a collection view recently where each item was dynamically sizing. Jon (49:35.986) Yeah. Allan Ritchie (50:02.916) And it was funny because the performance issue wasn't really showing up on any of the standard. It wasn't showing up on Android, which it usually always does. Wasn't showing up on iOS in the regular form factor. So the non tablet phones, so the non Pro Max, like this thing that can actually fit in your hand and doesn't like consume your face. And so we saw it. I'm like, John, this is weird, man. I see it only on the Pro Max. It's like it's just measuring something weird. Jon (50:10.126) Yeah. Jon (50:17.455) Mm-hmm. Yeah, you don't need like two hands to type on it. Jon (50:28.766) like. Yeah. That is weird. Yeah. Allan Ritchie (50:31.41) And John was like, have you tried my list view? It is weird. And it's actually, it's a good test case for the Maui team. But again, the collection view is trying to solve all possible problems. And I'm like, dude, we need to just, I just need a list view with dynamic sizing. Jon (50:38.351) Mm-hmm. Jon (50:47.484) Yeah. Allan Ritchie (50:48.934) So John's got kind of the smaller abstraction. He's only trying to solve with, with your virtual list view, a very specific subset of problems without trying to be right, like go outside of that box too much, right. And we bound data up to it and it just works. It's fast. It zips through everything. It's solved the customer problem. Jon (51:03.067) Yeah. Allan Ritchie (51:15.21) just like that with a very simple change because your horizontal list view pretty much matches the way the collection view does most things, but it doesn't try and do your grids or your responsive layouts. It doesn't try and do, it does grouping. You got a little wild, but it's a list view. It's a list view. Jon (51:29.966) Yeah. Well, I, you know, in this, in the spirit of, uh, all of the things I think we've talked about lately, it's like, I built it for the thing that I needed it to do. Right. So. Allan Ritchie (51:40.242) And it just works. It's not trying to solve all the problems. So it's nice and fast. And it's again, it's an abstraction that does exactly what we need to do. So I got out of the box and my collection views having trouble with this one particular case, you know, I can choose to fix it, but here's this other component that does a smaller subset of cases that is working, right? And it's just a pop in, pop out. Jon (51:56.209) Ooh. Jon (52:03.234) I have, I have another, you know, good example of that too. Um, you know, there was, I forget some customer I think we were working with was trying to do something very specific with like the image button and how the image was laid out compared to the content. And, you know, had just a bunch of kind of more edge case things and, and kind of to your point, right, like image button. Yeah, it's a control. Um, but it's one, that's a really hard thing to do across platform because buttons hosting. varied content, you know, native controls of buttons doing that is just weird. There's, there's very different, weird rules on each platform and how things work. And to try and make them consistent is hard. And so in this case, you know, we kind of said, okay, well, let's sit down and think about this problem for a minute. There's this isn't working and there's no clear like change within the Maui handlers that's going to make it do what you want to do. How else can, can we help, you know, help you help yourself to approach this? Essentially. Allan Ritchie (52:44.631) Great. Allan Ritchie (53:02.638) And this is so easy to solve too. Jon (53:03.058) And yeah, and so we ended up, you know, doing the thing of like, okay, well, let's make a, a custom control and let's, uh, you know, use a, a border in that custom control, we'll add a tap gesture, recognizer, we'll add a grid into that. And you can add your image and your, your text and whatever other content you were trying to do, we can give you the rounded corners, we can do all the stuff. We can use the visual state manager to change the colors as you tap it and press down and whatever. And at the end of it, we could make it so that it's a templated thing, so that you could say, here's my button, it's this kind of composite control, but at the end of it, I can reuse it in my code and I can say, oh, the image is going to be this value and the other content is going to be this. At the end of it, it was like, yeah, this works fine. This looks how we want it to. We could add the accessibility stuff with some of those APIs that we have around semantic properties. And like that, it wasn't hard to do. It was like dozens of lines of code at most. And at the end of the day, it was, I think another good example of, okay, well, let's think about the problem from a different perspective before we decide that like this in the box thing that's kind of purpose built. doesn't work for us when we try and like really push it outside the lines of what was intended for it. Allan Ritchie (54:29.698) Exactly. And, but people still try and jam it in the box. You need to update button. It has to include this. Jon (54:36.83) And, and, you know, arguably if, if most, you know, if, if half of our, the, the Maui developer, people using Maui developing with Maui said, yeah, we all want it to do this, then sure, it should. I think, but you know, it's, it's kind of identifying like, Hey, maybe I'm, I'm a little bit more edge case than most people using this thing. And so, yeah, let's, let's think about it a little bit harder. Allan Ritchie (54:49.634) Sure. Allan Ritchie (55:00.354) But I think, but think about how simple the solution is that you guys applied, right? What is a button at the end of the day? If that's the box you kind of get yourself out of and you go, what the heck is a button at the end of the day? It's a thing that responds to a tap event, whether it changes color, changes text, whatever, triggers the command, talks. Jon (55:05.434) Yeah. Jon (55:15.976) Mm-hmm. has some accessibility integrations that do the things you need to do. There is more to think about it in those cases, but I think the point is it's not by any means an insurmountable problem. Allan Ritchie (55:25.682) Yep, for sure. Allan Ritchie (55:32.858) But at that point, I can also decide how that looks like for my business. Maybe they don't, you know, maybe they choose not to solve certain problems or maybe, you know, it doesn't have to respond to that tap per se or maybe it doesn't have to have an image like there's so many you can invest as much as you want into that custom control because it's your custom control. Jon (55:36.518) Yeah. Jon (55:47.229) Mm-hmm. Jon (55:52.763) Yeah. Allan Ritchie (55:53.826) There's another great one I like to talk about when we talk about servicing and DI. So you're talking about a great point from the upfront. The one I like, the one I see so often in the back end is people trying to make reusable data syncs. You don't see many of those anymore, at least not many that go very successful. So Azure Mobile Services is out there, guess what? That doesn't work for very big databases. They try. Jon (56:00.286) Mm-hmm. Jon (56:06.674) Uhhh... Jon (56:12.657) Yeah. Jon (56:16.862) Mm-hmm. Allan Ritchie (56:18.902) But what about conflicts? How did your business resolve conflicts? There's so many things. I'm gonna say this, it's gonna be spicy. Stop trying to solve, make data sync across all apps, reusable across all apps, because guess what? It's just never gonna fly, right? It's like. Jon (56:34.075) Yeah. Jon (56:37.838) Yeah, everybody's data models and database structure and everything are going to be unique enough that at some point, you know, to try and have some reusable thing, you're going to have to like decide on, like you said, conflict resolution like that. We can't decide that for you necessarily that easily. Allan Ritchie (56:56.302) That might be on a model level, it might be on a, right? You don't need to solve everything to be reusable, like this button. Yeah, it's got a border, it's got accessibility, but maybe I don't want shadows on it, or maybe I don't wanna invest the time in that right now. Maybe I just say the shadow is hard coded to this because that's our standard, right? I'm not gonna make it some bindable property. I'm gonna code it for what my app needs. Jon (56:58.544) Right. Jon (57:05.179) Yeah. Jon (57:17.819) Mm-hmm. Jon (57:22.086) Yeah. Allan Ritchie (57:22.506) not everything needs to be abstract or plugged in. Just do the work. Jon (57:28.886) Oh, I think that is a, maybe a good note to end on even for the, the idea of architect in your app. Right. I like that sentiment. Allan Ritchie (57:38.338) solve the problem, find the patterns, do code smart. I still use my DI and my patterns. I'll use a default button until I figure out that I need more and then I'll start to go out of the box. But don't think that everything has to be solved with Maui or with DI or with MVVM. There's so many paths you can take. Solve the business problem first. Just... Jon (57:40.732) Yeah. Jon (57:54.235) Yeah. Jon (58:06.266) Mm-hmm. Allan Ritchie (58:08.722) have a general thought pattern of where you want to go but do the work. Jon (58:11.73) So I think the nice pick this week for our plugin package or product has got to go to Prism because it, you know, in talking about your app architecture, it has some opinions of how to do that. And I think it's one of the better examples in the community if you're looking for something that helps you implement some of these patterns and is reusable in the right places. Prism is a pretty good go-to. I don't know if you want to say any more about that. Allan Ritchie (58:42.014) Yeah, Dan and Brian, they're great people. I love them to death. They've built this thing over years. You know, they're really, I don't want to call Dan the burger flipper, Brian the burger flipper, they'd probably kill me. But they're the guys that put all the burger together, right? So they've got your nav service, they've got your view model life cycle, they've got... Jon (58:55.774) I'm sorry. Allan Ritchie (59:04.934) a whole bunch of other things in there. Prism does all of it and it's really good at putting all of the layers together for you. Page dialogues, that's also in there. And it just does a great job of that. So go out there, support them, they're a great open source project. They have free licensing if you're under a certain amount. I don't know that dollar amount off the top of my head but... Jon (59:08.808) Mm-hmm. Jon (59:15.862) Oh yeah. Jon (59:29.371) Mm-hmm. Allan Ritchie (59:29.706) It's a great thing to learn. And if maybe they don't solve the problem or they're too expensive, they're still shell. You can still abstract it. It's easy. But Prism is a beautiful, beautiful open source package. Jon (59:41.45) Awesome. All right. Well, I think that'll do it this week. As always, please subscribe to our podcast. Give us a review on Apple Podcasts, the thing that gets us the most, I think, attention and more viewership so we can keep doing this. And if you have a topic, if you have a suggestion for a show idea, if you have a plug-in package or product, do you think that would be good to highlight? Drop us a line on our website. You can contact us there in a number of ways or email if you still use email. You can do show at gonmobile.io as well. That actually goes to us, believe it or not. Thanks everyone for listening. Alan, we'll see you next time. Have a nice architecture filled day. Allan Ritchie (01:00:19.434) Always a pleasure, John. Allan Ritchie (01:00:24.564) always though.