Tuesday, 18 June 2024
Kyle Hawkes
8 minute read
Thankfully, this is now easier than ever due to new technologies being developed and more cross-platform libraries popping up every day, but with the advent of more and more options becoming available, it creates a new hurdle to cross: Which path do you take? Is there a "correct" choice?
Right off the bat I'm going to answer that question with a definitive 'No'. There is no catch-all correct choice when porting a product from one platform to another. Every project is different, and one of the most important skills to develop is being able to critically evaluate which option may best suit your project and team.
The first steps in this process are to identify your project's specific needs, your available resources, your team’s skillsets, your timeframe, and then to draw up a pros & cons list of each potential approach. In this article, we will go through this process using a recent project of ours as an example.
The project we will be using as an example for this article is a Windows desktop application we developed several years prior for a client. This application was written in C# using .NET Framework 4, and the client expressed a desire to port it to macOS. The application has a core dependency on OS-specific code and requires a very fast response at all times. Both were things we had to take into special consideration when planning our port.
So, now that we know the project and the task, we should evaluate the resources and skill sets at hand.
For resources, two developers were available, with a senior developer overseeing the project. One junior developer has several years of C# experience and had previously been a developer on the Windows version of this application, meaning they have a strong understanding of the codebase and domain; They also have some minor experience with Objective-C.
The second junior developer has some moderate experience in macOS development and a good understanding of Swift and Xcode's Interface Builder . From this we can gather that there is a good spread of knowledge on potential languages we could use, and knowledge of native development. This gives us quite a few options and minimises potential unknowns.
Now that we have evaluated our resources and skill sets, we can start looking at potential approaches to port this application. A good way to do this is with a simple 'Pros & Cons' list.
When developing a pros & cons list, the metric for what could be considered a pro or con can vary for each project and environment, but here are some common 'pros' to look for to get you started:
Code reuse is a massive 'pro' to look out for. With a high amount of code reuse, you immediately have a sizable chunk of code that already works, is tested, and you are familiar with. It can cut down on development times greatly, and if you are working for a client this can give them some peace of mind knowing that a portion of the code is already up to production standard.
While it is certainly not a popularity contest, and the most popular solution isn't always the best, if a language or a framework is popular and has a large community around it the chances are there is a lot of community support available to your team if they have any questions, and more tutorials and open-source code to refer to. This often lends to more productive development.
This might be an obvious one, but it is certainly an advantage if members of your development team have prior experience with a piece of tech, as the fewer unknowns you have going into a project, the better.
Saying that, you should always be looking for opportunities to grow and improve. If the situation allows it, deciding to use something new can often be a very good idea too, provided you are well prepared.
With the basics of the pros & cons list described, let's look at the pros & cons (how many more times can I say that in this article?) list we put together when evaluating the available options for our project.
Once we had identified our options and made a pros and cons list of each of them, we discussed which we felt most comfortable with and why.
As developers and as a company, we had decent experience of using Xamarin in various projects before. This would allow us to stick with C#, so we decided to initially go with Xamarin. From that point our first step was to create a quick, light prototype.
Before diving headfirst into any project, it can often be very beneficial to whip up a small prototype that covers the core features and explores as many identified unknowns as possible. This allows you to better understand how you may tackle the full project, identify any hurdles you may have previously missed, demonstrate an early example to your client (if appropriate), and give much more accurate estimates for your work.
In our case, taking the time (approximately one work week) to create a small prototype in Xamarin proved incredibly valuable for us, as we concluded that it wasn't right for this project for several reasons:
With that in mind, we decided to take another week and explore an alternative: Creating a native front-end and connecting that with our existing C# code.
For this next prototype, we decided to go with IPC between two applications. One application providing the UI using Swift, and a second one providing the back-end services written in C# running on .NET Core. The two processes are connection using gRPC, an IPC technology.
This prototype had slightly different goals than the previous, as it was as much an exploration of a new technology as seeing if it was also the right fit for our needs.
With the ability to have the gRPC client be a native UI application and the server be our existing C# code, allowing vast amounts of code reuse, it seemed like a very solid option on paper.
For this prototype, our goals were to:
After some initial teething pains, we managed to get a basic prototype working and found that not only did it meet our requirements, but it also far exceeded them. The framework was exceptionally fast, very lightweight. It was a fantastic fit for our development team as it allowed both developers to work to their strengths, while keeping a common element that required strong communication.
We won't go into too much detail regarding gRPC in this article, but I will give a quick overview to explain its core concepts and why we felt that it was the right choice for our project.
If you would like to learn more about gRPC, their website provides a good introduction, available here.
At its most basic level, gRPC (and Remote Procedure Calls in general) is based around the idea of client-server interaction, with one server and x clients. The server and client(s) do not have to be individual machines; in our case, they are not - our server and client are both on the same machine, running as two separate applications.
This allows us to keep much of our original Windows codebase as a server application (with some minor changes, including migrating from .NET Framework to .NET Core to allow it to run on macOS), as well as writing a Swift application that gives us OS-level access where needed, and a nice UI, acting as a client application.
This client-server interaction is achieved by defining a service shared by all parties that specifies the available methods that can be called, as well as their parameters and return types. The clients only need to be aware of this as a stub method, whereas the server implements the specifics.
With gRPC at the helm we were able to successfully port our existing Windows application to macOS with a native Swift front-end, a C# back-end, and a massive amount of code reuse.
Overall, thanks to a structured pre-production phase, the outcome of this project was very positive.
Because we took the time initially to understand the project's unique needs, the resources we had available, and what options we had available to us based on that information, we could make informed decisions about what would result in the best end product.
In addition, because we took the time to take our chosen development plan and develop a small prototype before committing to a whole project, we gained valuable information that allowed us to re-evaluate our plan and pivot to a more fitting set of technologies for the project. A minor amount of additional time spent early on saved us a lot of trouble later down the line.
Last updated: Tuesday, 20 August 2024
Software Developer
"He/Him"
We're proud to be a Certified B Corporation, meeting the highest standards of social and environmental impact.
+44 333 939 8119