My company recently released Zenue; a solution for small businesses in the UK hospitality industry struggling to meet post-lockdown governmental guidance. In just 48 hours, a team of two were able to progress from initial concept to app-store submission having delivered on all the fundamental use-cases. In this post I show how this was made possible by .NET and the Uno Platform and why you should be considering these technologies for your next project.
Ostensibly Cogenity operates as a consultancy but, whenever opportunity arises, we like to "dog food" the services we provide to our clients by undertaking a project for ourselves. Such an opportunity arose a few weeks back when, following the easing of lockdown in the UK, we were contacted by numerous small businesses in the hospitality industry (e.g. cafes, bars and pubs) stating they were unable to find a means of effectively meeting government guidance for recording visitors to their premises.
During an idle "water-cooler" conversation, we realised there was an interesting challenge here: These businesses were of limited means and couldn't invest in the significant infrastructure required to support many forms of advanced visitor tracking capabilities. Furthermore, the data these businesses were being asked to collect and keep safe represented a legislative tight-rope for them and a potential privacy nightmare for their customers. The "water-cooler" conversation was soon superseded by a "tree-house" brain-storming session (yes, weather permitting we do occasionally meet in our on-site tree-house) and we decided to take a stab at providing a solution.
We were super-happy with the project not just because it delivered on all the fundamental use-cases nor because it did so using a service model which cost virtually nothing to stand-up and which will scale in a cost-effective manner. No, we found the biggest positive of this project to be the tech stack we had decided to use and how it allowed us to minimize cross-platform development effort while all but eliminating code duplication.
In short, the delivery of the constituent apps - along with their supporting services - on this timescale was made possible by eschewing a "full stack" approach and opting for "one stack" comprised of just two fundamental technologies: .NET and the Uno Platform.
Here's why you should be considering these technologies for your next project.
A note on terminology
As with many such things in our industry, the term "full stack" has become extremely overloaded. Initially coined to describe "an individual who has a good understanding of the technologies used to implement different layers and components in a solution", it could be applied to any developer comfortable with any set of technologies capable of implementing an end-to-end solution. In recent years however this definition has become increasingly narrow to the point where - should you see it in a job advert or on a résumé - it will almost certainly have been used to mean "a developer who can write an HTML+CSS+JS web-app along with an arbitrary set of back-end technologies".
This has lead to frustrations in many camps not least of which being desktop and mobile app developers who choose not to employ web-related technologies in their craft. These developers feel equally entitled to the term "full stack" but are met with confusion when advocating themselves as such to companies and recruitment consultants alike.
In this post I will be employing a measure of creative license with terms "full stack" and "one stack", and while some of these uses may lead a reader to think "Hang on a second...", I would argue that my uses are no more disingenuous than the limited one described above. To avoid confusion however, I would like to advocate for a definition of the terms along the following lines:
- Full stack: A heterogeneous set of technologies requiring significant and non-transferable training/experience in each.
- One stack: A homogeneous or complementary set of technologies within which training/experience is cumulative or easily transferred.
So with that out of the way...
If we were to have adopted a conventional "full stack" approach and employed (alleged) "best-of-breed" technologies for this project, we might have ended up with something along the lines of this:
Here we have:
- A mobile app for visitors to clients' premises written in Dart using the Flutter framework.
- Internal desktop apps written in C# using the WinUI framework.
- Back-end services for each of the applications written in C# using Azure Functions.
As you can see, to deliver an MVP using this stack we would have had to employ 3 different languages on 4 different frameworks. Each of these languages/frameworks require significant experience/training before a developer can be considered to be proficient in their use and each of these languages/frameworks would require its own DevOps pipeline to build and deploy the associated app/services. All this can vastly increasing the time it takes to stand-up a solution of this nature, complicating versioned deployments, increasing code duplication and, ultimately, slowing iteration.
(And lets not even think about the time/effort/complexity for a single developer to install and maintain the plethora of tooling required to develop on all of these stacks simultaneously! <Shudder>)
Now, admittedly we could have considered simplifying this stack by employing one of the following:
- Use ReactNative for the Mobile App
This would have reduced the language count by one but could have introduced significant cognitive dissonance given that, despite the name, React and ReactNative are very different frameworks.
- Use Flutter for the Web app
Yes, this might have been possible but web development in Flutter is very much in it's infancy and, at the time of writing, requires a "beta" channel version of Flutter which might have destabilized native app development.
- Used Xamarin for the Mobile & Internal Apps
This would have reduced the language count and the framework count but would have still left us needing to maintain a separate development stack for the web app.
Regardless, as you can see, developing and supporting a solution that operates across these myriad platforms can be extremely time consuming and can make solution-wide micro-iterations all but impossible. It was certainly a non-starter for us as we had very tight deadlines for getting this done and very limited budget for maintenance moving forward.
So, if "Full stack" wasn't an option, how were we going to deliver this solution? Well, that was easy: the Uno Platform.
For those that are unaware, the Uno Platform provides the means to broaden the reach of Universal Windows Platform (aka UWP, WinRT, WinUI, etc) applications beyond... well, beyond the Windows Platform. By standing on the shoulders of two amazing technologies - Mono & Xamarin - the Uno Platform is able to expose huge (and ever increasing) swathes of the UWP/WinRT API surface to other platforms. This allows apps written for UWP to be run - often without modification - on platforms as diverse as iOS, Android and the Web (via WebAssembly).
As regular readers of my blog will know, I am a huge fan of the Uno Platform and have been raving about its abilities for quite some time now. Suggesting that we use Uno for this project was an easy sell given it allowed us to write code in C# & XAML (which we know and love), run the same code across every platform required by this solution (and then some!) and didn't require any platform specific DevOps effort/management. In fact, short of installing the Uno Platform Solution templates from within Visual Studio, using the Uno Platform didn't even require any changes to existing development environments!
Effectively, using the Uno Platform allowed us to move from "full stack" to "one stack", as shown below:
Not to labour the point but here we have:
- A mobile app for visitors to client's premises written in C# using the Uno Platform.
- A web app for staff at client's premises written in C# using the Uno Platform.
- Internal desktop apps written in C# using the Uno Platform.
- Back-end services for each of the applications written in C# using Azure Functions.
All told, this amounted to one language and two frameworks - Uno Platform client-side, Azure Functions service-side. This simplicity made the project incredibly quick to iterate on and, due to the absolutely lack of friction between platforms, a whole lot of fun to deliver. Furthermore we were able to spend 99% of our time delivering use-case functionality instead of setting up multiple tech-stack development environments/workflows and worrying about how best to make them interoperate.
Why should I consider a "One Stack" approach?
Well, for us there were innumerable benefits to a "One Stack" approach which, in our experience, would be beneficial to many small teams employing rapid iteration (or "lean start-up") practices. These included:
Single Language, Tooling & Solution
All the apps and services for this delivery were implemented in C#, using Visual Studio and contained within a single solution. This allowed us to leverage the advanced code-refactoring capabilities of Visual Studio to quickly change solution structure and/or API's without fear of missing required changes in other projects/languages.
.NET Standard 2.0 Libraries
Due to the incredible efforts of the Mono team, the Uno Platform is able to use pretty much any fully-managed .NET Standard 2.0 library. This not only allowed us to share solution artefacts across projects and platforms but also to use "off-the-shelf" nuget packages on platforms they had almost certainly not been designed for. (For an example of this, see my post on "Cross-Platform Real-Time Communication with Uno & SignalR" where I use the "Microsoft.AspNetCore.SignalR.Client" nuget package from Android, iOS and WebAssembly).
When we did need to leverage platform specific capabilities, Uno Platform allowed us to directly reference and call Xamarin libraries without needing any form of marshalling. For example, Zenue uses the
ZXing.Net.Mobile library - ostensibly designed for Xamarin.Forms - to implement QR Code scanning (which is likely to be the subject of a future blog post).
Advanced "Common" Controls and Visual States
Using Uno Platform, "write-once" controls really can "run-anywhere". Furthermore, by leveraging the incredible capabilities of XAML ("look-less" controls, visual states, storyboarded animations, etc) these controls can be templated, styled and reused across a broad range of projects and platforms.
Integrated debugging & Hot Reload
Regardless of platform (UWP, Android, iOS, Web, etc) or deployment target (physical device, simulator, browser, etc), Uno Platform has strong support for integrated debugging and hot reloading of changes. This is a real game changer for the rapid development of cross-platform apps and once you get used to it, going back to a development environment/platform that doesn't allow you to break at arbitrary points in your (non-minified/transpiled) code or to visualize a change without restarting your app, simply feels like a return to the dark ages.
End-to-end QA & automated testing
As all projects in the solution could be started and debugged from within a single IDE, we were easily able to spin-up and run the solution off-line. This allowed us to run end-to-end QA testing and quickly resolve issues in the integration of system components. We then augmented these QA tests via automated UI tests which covered every component of the solution (and which we found to be particularly good for creating the myriad application screenshots required by the various app stores).
Conclusion & Future
As I hope is evident from the above, we found employing a "One Stack" approach for the Zenue project to be a huge win. Reducing our development tech-stack to just a single language and two frameworks resulted in productivity gains that we're still enjoying as we continue to iterate on the app and it's capabilities.
At Cogenity we believe the Uno Platform has a very exciting future. While already an incredibly capable and mature framework for delivering cross-platform apps, the Uno team will shortly be releasing v3.0 (perhaps later at UnoConf 2020) which promises many new capabilities and myriad improvements.
If you're interested in using the Uno Platform in your next project, Cogenity is able to offer consulting/development services which can ensure your project not only gets off to a flying start but also reaches a successful conclusion! Just drop us an email or use our contact form here and we'll get back to you asap.
We're currently engaged with a number of local businesses interested in using Zenue but would welcome the opportunity to partner with businesses across the UK. While helping assuage the fallout from the current pandemic is very much Zenue's raison d'être, we're already looking to expand it's reach beyond visitor tracking. Our aim is to help small businesses leverage the innumerable use-cases modern technologies could provide but which have, so far, remained out of reach for all but large chains.
If your business needs help meeting current government guidance for visitor tracking or you have an idea for a killer feature you feel Zenue might be able to provide, please feel free to contact us via Twitter, Facebook or email.