No matter how hard you try to hide something in your app’s code, at the end of the day when you publish them the result is a compressed format (IPA or APK) with all the necessary DLLs to run your Xamarin apps, and if you know about tools like ILSpy for browsing and decompile .NET assemblies is so easy to take those DLLs and look at your typical Constants.cs class.
Moving the data to the cloud: Let’s make our backend with Azure Functions and CosmosDB and consume it from the app (this post).
Implementing continuous integration and continuous delivery to the stores with App Center.
Moving the data to the cloud: Let’s make our backend with Azure Functions and CosmosDB and consume it from the app.
I decided to make another post for the backend, if your are focused just in the app development you can continue reading this post without worry about the API, we will be using the one that is already deployed.
For consuming the service we will use Refit, an automatic type-safe REST library for .NET Core, Xamarin and .NET, so, let’s install the NuGet package for the library in the shared project (App/CabanasRD), once installed, the first thing we need is an interface for defining the RestService methods, for this add a folder called APIs in App/CabanasRD/Framework, in the new folder add an interface named ICabanasAPI with the following definition:
As you can see, we dont have defined the MotelResponse class yet, let’s add this new class to a folder called “Models” inside App/CabanasRD/Framework/APIs, and fill it with:
This model was generated using the JSON response from the service, with the help of https://quicktype.io/ we got the classes with the fields mapped.
Before using the ICabanasAPI, we will need to register it as a RestService in the App.xaml.cs file located in App/CabanasRD, and add the following code in the RegisterTypes method:
We are ready to consume the service by using the ICabanasAPI!
🤔 But… We don’t want to manually convert the service response to our domain model, that’s why we are going to introduce something called AutoMapper, a simple little library built to solve a deceptively complex problem – getting rid of code that mapped one object to another.
Install the AutoMapper NuGet package in the shared project App/CabanasRD, then add the following code to init and configure it in the App/CabanasRD/App.xaml.cs:
Now we are able to convert easily from the service response to our domain model.
As we are following Interface Segregation principle, changing the way we obtain our data is as simple as create another class that implements IMotelsSource, let’s create the MotelsSource.cs class in App/CabanasRD/Framework/DataSources with the following content:
One last thing for switching the InMemoryMotelsSource for the MotelSource, go to the App/CabanasRD/App.xaml.cs and change this:
That’s all, run the app, wait a few seconds in the map and voilà!
🤔🤔🤔 Hey, this introduces new security and UX problems:
If we push this code to our repository the ApiKey will be exposed.
We don’t have a “Loading” indicator anywhere.
If any error occurred during the request the app will crash, there is a need for handling the exceptions.
There are some motels without phones or services or images, we need some empty states.
Let’s make a deal 🤝, I will resolve the first issue and you are going to help me by resolving the rest of problems on GitHub by creating a PR with the changes.
For manage the ApiKey as a secret we will use this wonderful tool made by Dan Siegel called Mobile.BuildTools.
Install the Mobile.BuildTools NuGet package in the shared project App/CabanasRD, once installed we need to create a file in the root of App/CabanasRD called secrets.json and add it to the .gitignore, now that the file is ignored open it and put this:
If you build the app it should be a new file in App/CabanasRD/Helpers called Secrets.cs, it contains static references to the secrets we put in the secrets.json, this autogenerated file should be ignored too, for ignore both files add this to the .gitignore file:
PD: If the build does not generate the Secrets.cs file, add it and the Helpers folder manually and build again.
Nice, now our secrets are out of the source control!
Remove the ApiKey property from App/CabanasRD/Configs/AppSettingsConstants.cs and replace any reference of this removed prop with Helpers.Secrets.ApiKey rebuild and run the app.
When we are in the process of planning the development of a new application as developers we usually don’t think about the architecture and just go coding guided by some mockups or a list of generic requirements, let’s be clear, this practice is more common than we think, also we are mentally blocked by the idea of being agile (ignoring that it doesn’t mean fast) and we skip the step of architecting our systems.
If we don’t make an statement that architecture matters from the beginning, the cost of maintenance is going to increase and we eventually will spend more hours developing a new feature or even worst a simple task of changing a part of our system could be a mess to develop.
In this article we are going to see how Clean Architecture could help us to organize and structure our Xamarin projects, using some references from the famous book Clean Architecture A Craftsman’s Guide to Software Structure and Design by Robert C. Martin (also known as Uncle Bob) in which he says:
“The architecture of a software system is the shape given to that system by those who build it. The form of that shape is in the division of that system into components, the arrangement of those components, and the ways in which those components communicate with each other.
The purpose of that shape is to facilitate the development, deployment, operation, and maintenance of the software system contained within it.”
Clean Architecture has a main objective, which is the separation of concerns, this separation is done by dividing the software into layers. In the simplest form our architecture should have at least one layer for business rules, and another layer for user and system interfaces.
This kind of architecture produces systems with the following characteristics (extracted from the Uncle Bob’s book):
– Independent of frameworks. The architecture does not depend on the existence of some library. This allows you to use such frameworks as tools, rather than forcing you to cram your system into their limited constraints.
– Testable. The business rules (through use cases) can be tested without the UI, database, web server, or any other external element.
– Independent of the UI. The UI can change easily, without changing the rest of the system. A Xamarin UI could be replaced with a Console UI, for example, without changing the business rules.
– Independent of the data source. You can swap out SQLite or Realm for CosmosDB or something else. Your business rules are not bound to the database.
– Independent of any external agency. In fact, your business rules don’t know anything at all about the interfaces to the outside world.
Presentation: layer that contains the UI.
Framework: implements the interactions with platform specific SDKs and external libraries, also provides the concrete implementations of the data layer.
Use cases: contains application-specific business rules. It encapsulates and implements all of the use cases of the system.
Domain: contains the entities that represent business objects, these objects can have
methods (Critical Business Rules), or it can be a set of data structures and functions.
Data Interfaces: interfaces with the definition of all data sources, they are implemented in the Framework layer.
Repositories: contains the repositories, they use the the Data Interfaces for retrieving external information.
Tests: Unit tests pointing to the use cases.
The golden rule that makes this architecture work is the Dependency Rule:
“Source code dependencies must point only inward, toward higher-level policies.”
With that being said, nothing in an inner circle can know anything about something in an outer circle.
In order to maintain a simple approach, we are going to group the layers into App (yellow circles), Core (gray circles) and Tests (red circles).
Let’s break this down with an app with only one use case: get orders for current user.
This is how it looks in a Xamarin Project:
As you can see, all begins in the UI, when the end user opens the app it shows the Order’s MainPage.xaml, this view has a Binding Context connected to the MainPageViewModel which calls the corresponding use case for get the list of orders and show them to the user.
The connection between the use case and all the dependencies needed it’s done by Unity (using Prism) at the App layer, following the Dependency Rule, is something like this:
The final result of the flow is this screen:
If you want to examine all the code, you can check out the project from GitHub:
In conclusion (yes, another reference from Uncle Bob):
Your architecture should tell readers about the system, not about the frameworks you used in your system. If you are building a health care system, then when new programmers look at the source repository, their first impression should be, “Oh, this is a health care system.” Those new programmers should be able to learn all the use cases of the system, yet still not know how the system is delivered.
Have you ever wonder how to make a reusable boilerplate that includes all the features and architecture that you use for almost every new app?, for example in VS for Mac we don’t have a project template for Prism and we end up setting up the same configuration manually, let’s solve this problem making a template with a Clean Architecture structure and Prism (soon I will be posting about this architecture in Xamarin).