If you’re a .NET developer, chances are you’ve come across discussions or articles about .NET MAUI, a framework for building cross-platform applications. Have you ever wondered why having a shared codebase between various frontend distributions and the backend is a game-changer or what prompted the decision to replace Xamarin in the first place?
The Importance of a Cross-Platform Framework
Shared Business Logic/Models
Regardless of team size, DRY (Don’t Repeat Yourself) programming should always be considered. While certain tasks, such as trimming leading and trailing whitespace, may not need to be abstracted, it becomes crucial to eliminate code duplication when dealing with more intricate operations like generating financial statements, building complex queries with 10+ search parameters, or performing any other complicated business logic. Having code duplicated, even once, introduces risk and adds unnecessary overhead when it comes to making modifications due to refactoring or maintenance.
Apart from shared business logic, what’s the hype for consolidating mobile and web codebases or even just multiple platform-specific codebases? To illustrate this, let’s take a new feature request involving a handful of new entities with a semi-complex set of relationships between them and a corresponding user interface. Initially, creating a proof of concept may seem straightforward: adding the models to the database, implementing backend functionality, selecting a platform to build the UI (web/iOS/Android), and adding the API endpoints.
In the case of larger projects, you may have distributed teams, such as backend, web, iOS, and Android, each with its own codebase. While this approach can be effective when there are sufficient resources to have enough developers to maintain each codebase, it eats a huge chunk of time for any smaller team. Not only is this a time sink, but also presents a learning curve if all these platforms are being supported, as developers must be familiar with multiple languages to implement a singular feature. For instance, the backend could be C#, while the web is mostly TypeScript, iOS requires expertise in Swift, and Android is using Kotlin. Imagine being a support developer on a low-budget project trying to maintain this kind of technology stack – it’ll have your head spinning.
Here’s the magic with frameworks like Xamarin or MAUI: all mobile development can be consolidated into a single codebase. Being able to share Data Transfer Objects (DTOs), interfaces, business logic, and languages between frontend and backend can make the path from spec to deliverable a much smoother process. With this approach, one developer can be in charge of implementing a feature in one codebase, and depending on the complexity, it can be ready for testing on all platforms.
Out with Xamarin
To be transparent, I have not personally used Xamarin.Forms, but I have used Xamarin Native. For reference, this article outlines the differences between Xamarin.Forms and Xamarin Native (Xamarin.iOS, Xamarin.Android).
In short, Forms is simpler and more limited in functionality, but has a shared codebase from start to finish. On the other hand, Native allows a shared backend for native implementations of the mobile frontends (which are more responsive and capable).
With this context in mind, I will outline the benefits and difficulties of using Xamarin Native.
Shared Backend (Yay!)
we initially thought we would have to write an entirely new front end from scratch and get some iOS developers to maintain a separate project that was on a budget. However, with a shared backend, this problem was resolved. A significant portion of the C# web backend was available to us on the iOS app we were building, which made things super convenient for our team.
Independent Frontends (Boo!)
Unfortunately, we still had to write a new implementation of the front end that was specific to iOS. We knew that opting for better performance and integration with UIKit would require us to create a new project to interface the new native libraries to support Android. Not ideal for a small project team.
Our project interfaced with iOS, and as a result, this is how we configured our development environment to look:
- Storyboards (iOS UI design) in Xcode
- Xamarin Views and UI Controllers in Visual Studio for Mac
- Backend and Blazor web framework in JetBrains Rider
Our team experienced a lot of jumping around and context-switching. We ended up implementing what I’ll call a “mobile feature estimation tax” to anything that would use Xamarin. Even though this was our best option for a small team, our product was 90% web functionality. As a result, we rarely looked at the Xamarin side of things and knew unfamiliarity would cause significant delays in development compared to a project that was strictly web-based. Let’s just say I was not surprised when I saw that Xamarin was the second most dreaded “other framework” according to this developer survey. Something had to give at some point.
In with MAUI
After researching both MAUI XAML and MAUI Blazor, we ultimately decided to go with Blazor due to the advantage of shared components with our web app. With that said, I want to note that this is where my perspective is primarily coming from. However, all aspects other than the shared component library is still true in MAUI XAML.
To begin, let’s address the issue of having separate frontend implementations for each platform. With MAUI, all the UI elements are built right into one project. Want to incorporate native functionality into the UI? You can easily add partial classes or a platform-specific compilation, all within the same project. Native libraries are available when you need them, and it’s convenient and fast development when you don’t. In essence, it combines all of the benefits of Xamarin.Forms and Xamarin Native into one solution.
This is the aspect of my MAUI experience that has felt like magic. MAUI will allow for the usage of Blazor components that are compiled down to native code. I’ve been working on a mature project that is nearing completion after 4.5 years, with a final deliverable before the project transitions out of active development. At least 90% of the code is in the .NET Blazor web app, and it looks almost identical to the mobile app. It is all run from the same IDE. This unified approach proves invaluable if a support ticket comes up or the project goes back into active development, as any new developer will only have to familiarize themselves with one framework, one language, one mobile, and one web project.
Remember that “mobile tax” I talked about with Xamarin? When one of those rare mobile features came up, it had been months since the last time we touched the mobile app. However, since we recently migrated to .NET MAUI, we were able to deliver the feature in just 4 days, a process that would have taken us a couple of weeks in the past. And this wasn’t just because of the shared components.
In MAUI, we only needed to add the entities, services, and new UI components. It was a total of 6 files added to the mobile project for a whole new workflow.
In contrast, with Xamarin, accomplishing the same task would have required the entities, services, UI controllers, Xamarin View Model, UI Components, and Storyboard file. It would have been hard to do in less than 15 files.
Note that all of the differences are UI-specific. If we need to change how something looks in the mobile app down the line, we know where to start, and it’s not looking into the maze that was Xamarin.
MAUI is filling the void that was left behind by Xamarin. While this post was not written to address all that MAUI leaves to be desired, it is a huge leap in the right direction in the development of cross-platform frameworks. Out of the ashes, comes the next generation.