Onionizing Xamarin Part 2

For those who just want code: https://github.com/SuavePirate/Xamarin.Onion 

Don’t forget part 1 on the general project structure: Onionizing Xamarin Part 1

A strong and scale-able architecture is important in applications, especially in Mobile Apps. APIs and SDKs are constantly changing, new technology is constantly released, and team sizes are always changing. A solid Onion Architecture can save a development team a lot of time by making it simple to change service implementations, restrict access to certain areas, making logic flow easy to follow, and making testing isolated blocks of code easier.

Some of the important topics this will cover:

  • Separation of Concerns
  • Inversion of Control
  • Dependency Injection
  • Model-View-ViewModel
  • Testability
  • Why all these things are important

Part 2

In this section, we’ll start to dive into the code for our definition layers (or at least what is important).

Let’s get into the Domain and Application layers:

Domain.Models

As said before, this is where our core models are, so let’s take one as an example:

User.cs

 public class User
 {
     public int Id { get; set; }
     public string Email { get; set; }
     public string FullName { get; set; }
     public string PasswordHash { get; set; }
 }

We’ll focus on our one model, but you could grow your entities out here.

Domain.Interfaces

This is where we define our data access layer for consuming our Domain.Models; Stores, DataProviders, and Repositories. These are good places to set up generic definitions so that multiple implementations can be made more easily. Here are examples of each:

IGenericStore.cs and IUserStore.cs

 public interface IGenericStore<T>
 {
     List<T> Data { get; set; }
 }

 public interface IUserStore : IGenericStore<User>
 {
 }

If you were to need to define custom methods for the user, you can do that in your IUserStore

Another common practice is to add a manager wrapper for your stores, to make it easier to inject the use of multiple stores in our business layer in the future. In this example, it would look something like this:
IStoreManager.cs

public interface IStoreManager
{
    IUserStore UserStore { get; }
    IGenericStore<T> Set<T>();
}

IGenericRepository.cs and IUserRepository.cs


 public interface IGenericRepository<T>
 {
     void Add(T entity);
     void AddRange(IEnumerable&lt;T&gt; entities);
     void Remove(T entity);
     void RemoveRange(T entities);
     Task<T> FindAsync(Func<T, bool> predicate);
     Task<IEnumerable<T>> GetAsync(Func<T, bool> predicate);
     Task CommitAsync();
 }
 public interface IUserRepository : IGenericRepository<User>
 {
 }

Just as with the Stores, you can define entity specific methods / queries in your specific repository (IUserRepository).

Application.Models

Now that we are through our data definition layers, let’s take a look at the application definition layers, starting with Application.Models. This is where our business models live – our Data Transfer Object Models, Input Models, Output Models, etc. So here is how our Domain.Models.User maps to each of these types:

UserTransferObject.cs


 public class UserTransferObject
 {
     public int Id { get; set; }
     public string Email { get; set; }
     public string FullName { get; set; }
     public UserTransferObject()
     {
     }
     public UserTransferObject(User entity)
     {
         Id = entity.Id;
         Email = entity.Email;
         FullName = entity.FullName;
     }
 }

Note that we have added a constructor that also consumes a Domain.Models.User type. This is completely optional. Many people do not want the Application.Models layer to reference any other layer. Another common way to handle the mapping is via an extension class in the Infrastructure.Business layer, like so:


public static class UserExtensions
{
     public static UserTransferObject ToDTO(this User entity)
     {
         return new UserTransferObject
         {
            Id = entity.Id;
            Email = entity.Email;
            FullName = entity.FullName;
         }
     }
}

The important thing to note in all of this, is that the DTO has properties mapped from the entity that are relevant and SAFE to the application. Notice the PasswordHash field was omitted.

NewUser.cs


 public class NewUser
 {
     public string Email { get; set; }
     public string FullName { get; set; }
     public string NewPassword { get; set; }
 }

This is one of our input models for creating a new User. Notice that it only has the properties required for creating one.

Last but not least, our output. This example uses a generic output Result that holds data from a DTO, errors, and the type of result. The output models you use will depend on the services you’re using, so this is not a catch-all.

Result.cs and ResultType.cs


 public class Result<T>
 {
     public ResultType Type { get; set; }
     public IEnumerable<string> Errors { get; set; }
     public T Data { get; set; }

     public Result(T data)
     {
         Data = data;
         Type = ResultType.Ok;
         Errors = new List<string>();
     }

     public Result(ResultType type, IEnumerable<string> errors)
     {
         Type = type;
         Errors = errors;
     }

     public Result(ResultType type, string error)
     {
         Type = type;
         Errors = new List<string> { error };
     }
 }

 public enum ResultType
 {
     Ok,
     BadRequest,
     Failed,
     Unauthorized,
     Forbidden,
     Invalid
 }

Now we have our models, let’s define our business layer.

Application.Interfaces

These are the definitions of our business logic that use our Application.Model layer. We’ll use services here, and like our data definitions, will utilize generic definitions where possible.

IBaseService.cs and IUserService.cs


 public interface IBaseService
 {
     IEnumerable<string> Validate(object model);
 }

 public interface IUserService : IBaseService
 {
    Task<Result<UserTransferObject>> CreateUserAsync(NewUser model);
    Task<Result<UserTransferObject>> FindByIdAsync(int userId);
    Task<Result<UserTransferObject>> RemoveByIdAsync(int userId);
    Task<Result<IEnumerable<UserTransferObject>>> GetValidUsers();
 }

Notice that each of our consumes either a primitive type, or an input model from our Application.Models and outputs one of our output models.

What’s Next

That’s all there is for the different definition layers. In the next post, we’ll look at implementing these two layers in our Infrastructure.Data and Infrastructure.Business layers. From there, we can look at our actual Xamarin code for consuming these layers and mapping them all together.

Once we’ve gone over all our layers, we will look into replacing different pieces, building tests, and areas where you can add your own flare.

Check out Part 3 to look at those Infrastructure layers.

Advertisement

Onionizing Xamarin Part 1

For those who just want code: https://github.com/SuavePirate/Xamarin.Onion 

A strong and scale-able architecture is important in applications, especially in Mobile Apps. APIs and SDKs are constantly changing, new technology is constantly released, and team sizes are always changing. A solid Onion Architecture can save a development team a lot of time by making it simple to change service implementations, restrict access to certain areas, making logic flow easy to follow, and making testing isolated blocks of code easier.

Some of the important topics this will cover:

  • Separation of Concerns
  • Inversion of Control
  • Dependency Injection
  • Model-View-ViewModel
  • Testability
  • Why all these things are important

Part 1

This first post will talk about the general project structure and high level role of each layer in the solution. Later posts will touch on the individual projects’ code, why things are where they are, using the structure to build out tests, and ways to bend or change the structure to work for you.

Project Structure

For this example we will be talking about Xamarin.Forms, but the same patterns can be applied in the exact same way without it.
Lets just take a look at the high level structure and layers of the solution:

xamarinonionsolution

Domain

This is the lowest level. Projects within Domain should not reference any projects outside of this layer and should also avoid referencing any external libraries.

Domain.Models

These are our base data models. This project shouldn’t reference any other projects, even within Domain.

Domain.Interfaces

These are the definitions for our data access layer. Repositories, Stores, etc. There should be no implementation in this project and should only reference the Model project.

Application

This layer is what defines our Services and Business logic without implementing any of it. Projects in this layer can only reference Model layers of Domain.

Application.Models

These are our application models such as input models, data transfer objects, as well as any helpers for mapping Domain models to these. This project will only reference the Domain.Models to help map them to DTOs or other models. This, however, is also optional. You could opt to handle mapping externally when the models are needed in business logic rather than in the Application layer.

Application.Interfaces

These are the definitions for our business logic layer. Services, Managers, etc. There should be no implementation in this project and it should only reference the Application.Models project

Infrastructure

This is where we implement our data and business logic.

Infrastructure.Data

This is the implementation of our Data access layer. Communicate with 3rd party data providers, local storage, databases, etc. Domain.Interfaces should be implemented here.

Infrastructure.Business

This is the implementation of our Business logic layer. Communicate with the data layer through contracts from the Domain.Interfaces. This project should NOT reference the Data project. Application.Interfaces should be implemented here

Clients

This is where we implement client logic, set up IoC, create ViewModels, and controls. If we are using Xamarin.Forms, this is where the PCL or Shared Library with Xamarin.Forms is. This Layer can reference any of the above layers in order to wire up IoC. If you have multiple Xamarin.Forms projects in one solution, they can both be here.

Clients.Controls

This is where reusable controls within Xamarin.Forms exist. Pretty straightforward.

Platforms

This is the section where the Native Projects live. If you have too many native projects for things like wearables, or the different TV OS’s, then it might make sense to break this section into smaller sections for things like “Apple”, “Google”, “Windows”, or something similar. But for the sake of this demo, we are only working with one project for each platform, so they live together.

This layer should only reference the Client layer and Binding Layer

Droid

This is the Xamarin.Android project. If any native services need to be called from one of the shared layers, the IoC set up can be extended into this project and one of the interfaces could be implemented here and registered.

iOS

This is the Xamarin.iOS project. As stated above, native services can be set up and injected from here as well.

UWP

This is the UWP project. As stated above, native services can be set up and injected from here as well.

Binding

This is where Xamarin Binding projects should be if there is a need for binding to any native libraries. As with the Platforms layer, if there are many different binding projects, this layer could be split into different sections for each OS. This layer should be exclusive and not reference any other layer.

Tests

This is where UI and Unit tests are. This layer can reference any other level in order to test them. This layer can wire up a completely different IoC container, contain mock projects for simulating any other layer, or any other external reference.

 

Continue on:

Onionizing Xamarin Part 2

Xamarin Component Review: ModernHttpClient

These reviews consist of a Pros/Cons, some things developers might need to be aware of before using or during the use of a given component, and a quick code sample that might help people get started.

Links:
Component https://components.xamarin.com/view/modernhttpclient
Nuget – https://www.nuget.org/packages/modernhttpclient/
Github – https://github.com/paulcbetts/ModernHttpClient

Pros:

  • Increase HTTP request speeds.
    This really does make a noticeable difference from using the base
    HttpWebRequest,HttpClient, or WebClient. By using native libraries, it can skip through the Mono runtime bottleneck.
  • Ease of Use.
    Probably the easiest to use component you’re going to find, especially if you are already using HttpClient for your requests. It’s a simple one line drop on each instantiation of HttpClient.
new HttpClient(new NativeMessageHandler());
  • Lightweight.
    A common issue with components is that they increase the overall size of your app. Bigger apps get uninstalled quicker if they don’t do anything important for the user.

Cons:

  • Component conflict.
    Most people won’t run into this issue, and it is most prevalent on Android (at least it is the only place I’ve run into it). The problem arises because of ModernHttpClient’s use of OkHttp from SquareThe way they include this library is different from some others that are dependent on it. You’ll find components such as Picasso or Rounded Image View that also use OkHttp handle it differently, so that at build time, you’ll get a very deceiving error message.

Things to know:

The only things that I have been made aware of so far in my use of ModernHttpClient are a few out of place errors or bugs I’ve run across. Note that these are only found on Android.
1. The component conflict issue (as stated above): You can see an example from a thread here on this type of issue.
2. Android “crash” while debugging. This is an issue apparent with OkHttp that seems to cause crashes while debugging an Android app, while still maintaining the debugger. It is important to note that this does NOT cause this type of crash if the debugger is not attached. Also, after a crash, upon re-opening the app, the debugger remains attached and usable. Something along the lines of

F/libc( 1044): Fatal signal 5 (SIGTRAP), code -6 in tid 1131 (OkHttp Dispatch)

I haven’t tried the pro version, since the free license does exactly what I need, but if anyone has any insight into the pro license, let me know.

Sample:

...
using ModernHttpClient;
...

public class WebRequestUtils
{
    public async Task<string> GetResponseString(url)
    {
// Instantiate HttpClient with ModernHttpClient handler
using(var client = new HttpClient(new NativeMessageHandler())
        {
            var result = await client.GetAsync(url);
            return await result.Content.ReadAsStringAsync();
        }
    }
}

Make sure to keep an eye out for more component reviews as I get around to playing with more in real life situations.

Creating a Circular Image in Xamarin.Android

If you’re working with mobile applications, sometimes something as simple as creating a circular image can be a bit more time consuming than it should be. Here is the snippet I use to create Circular Images in Xamarin.Android to follow up with my post about Creating Circular Images in XAML.

CircleDrawable:


public class CircleDrawable : Drawable
 {

     Bitmap bmp;
     BitmapShader bmpShader;
     Paint paint;
     RectF oval;

    public CircleDrawable(Bitmap bmp)
     {
         this.bmp = bmp;
         this.bmpShader = new BitmapShader (bmp, Shader.TileMode.Clamp, Shader.TileMode.Clamp);
         this.paint = new Paint () { AntiAlias = true };
         this.paint.SetShader (bmpShader);
         this.oval = new RectF ();
     }

    public override void Draw (Canvas canvas)
     {
         canvas.DrawOval (oval, paint);
     }

    protected override void OnBoundsChange (Rect bounds)
     {
         base.OnBoundsChange (bounds);
         oval.Set (0, 0, bounds.Width (), bounds.Height ());
     }

    public override int IntrinsicWidth
    {
         get
         {
             return bmp.Width;
         }
     }

    public override int IntrinsicHeight {
         get {
             return bmp.Height;
         }
     }

     public override void SetAlpha (int alpha)
     {

     }

    public override int Opacity {
         get {
             return (int)Format.Opaque;
         }
     }

    public override void SetColorFilter (ColorFilter cf)
    {

    }
 }

And here is an example of how to use it:

var bitmap = new Bitmap(); //do something else here to create your bitmap
var circleImage = new CircleDrawable(bitmap);