Desenvolvendo aplicativos Cross-Platform com Xamarin

Hoje vamos começar a entender o desenvolvimento cross-platform com Xamarin…

O que é Xamarin?

Xamarin é uma plataforma que tem como objetivo disponibilizar para empresas e desenvolvedores a possibilidade de desenvolver NATIVAMENTE aplicativos Cross-Platform.

Usando Xamarin, os desenvolvedores podem direcionar a plataforma de destino do aplicativo, seja ela Android (Mobile, Wear, etc), iOS (iPhone, IPad, etc) e Windows (10, Mobile, Universal Windows Platform, etc), utilizando uma linguagem única em uma “biblioteca” (Projeto) núcleo e compartilhar este código com cada uma das plataformas usando a linguagem C#.

É EVIDENTE QUE CERTOS “aspectos” da implementação do aplicativo deverão ser desenvolvidos ESPECIFICAMENTE para cada uma das plataformas “target” desejadas, mas grande parte do aplicativo (em alguns cenários 95% dele) será compartilhado entre as plataformas e portanto não precisará ser replicado.

Xamarin e Microsoft

Recentemente, a Microsoft adquiriu a Xamarin e as coisas começaram a melhorar muito no que diz-se respeito a melhorias nas ferramentas e estabilidade geral da plataforma.

A Xamarin, é hoje parte essencial na estratégia cross-platform da Microsoft para seus desenvolvedores.

Com .NET (C#) e Xamarin o código desenvolvido pode ser aplicado a ~99% dos devices existentes no mercado.

Xamarin Nativo

É a abordagem mais tradicional para criar aplicativos usando Xamarin, desta forma boa parte do código implementado (mais especificamente implementações na camada de regras de negócio, acesso a dados, clientes de API, etc) será compartilhado entre as plataformas.

Visualmente representamos a plataforma conforme segue:

Diagrama da plataforma Xamarin, abordagem nativa.
Diagrama da plataforma Xamarin, abordagem nativa.

O código compartilhado refere-se a camada de acesso a dados “local” (SQLite por exemplo), serviços (WebAPI, serviços em nuvem, etc), camada de regras de negócios e seus modelos. Enfim, muita coisa é compartilhada!

Outro aspecto relevante a observar é que o código específico a ser implementado restringe-se a camada de aplicação, interface e acesso aos recursos do device, através das SDK’s específicas de cada plataforma.

Xamarin Forms

Em 2014 a Xamarin anunciou a criação do Xamarin Forms. O Xamarin Forms acrescenta uma “camada de abstração” permitindo que os desenvolvedores criem interfaces através do código (C#) ou então usando XAML (Extensible Application Markup Language).

Nesta abordagem, o reaproveitamento do código é maior, tornando a proposta atraente com ótima relação custo x benefício.

Visualmente, a arquitetura pode ser representada da seguinte forma:

Diagrama da plataforma Xamarin, abordagem Xamarin Forms.
Diagrama da plataforma Xamarin, abordagem Xamarin Forms.

Como pode-se observar apenas uma “mísera” (não tão mísera se seu aplicativo for extremamente complexo) parte precisa ser implementada no projeto de destino, o aplicativo será NATIVO, no fim das contas, mas poderá ser “compilado” para várias plataformas.

A parte específica a ser implementada corresponde a customizações de renderização, acesso a recursos do device, etc.

Para o usuário, é imperceptível a diferença, pois a camada de abstração será “traduzida” para sua respectiva implementação nativa, como pode ser visto na imagem abaixo.

Interface criada em Xamarin Forms renderizada em diferentes dispositivos.
Interface criada em Xamarin Forms renderizada em diferentes dispositivos.

O suporte a linguagem XAML torna o desenvolvimento das interfaces extremamente prático, quando comparado ao desenvolvimento através do código, mas não é um pré-requisito, nem obrigatório. Alguns desenvolvedores já estão habituados a esta linguagem, utilizada em tecnologias como Silverligth, WPF, Windows Phone e Windows Store. Lógico que as particularidades deverão ser aprendidas, mas se você já está familiarizado com a “lógica” da coisa, você se sentirá em casa.

Compartilhando código

Observando atentamente a representação da arquitetura nativa o quadro “Shared Code” possui uma marcação “*” atentando para um texto descritivo que diz “Portable Class Library or Shared Asset Project”. Mas o que isso quer dizer?

Você pode compartilhar o código entre as plataformas utilizando um recurso chamado Portable Class Library OU Shared Project, vamos entender cada uma delas.

Shared Projects

Essa abordagem faz o compartilhamento direto dos ARQUIVOS do código entre todos os projetos que fazer referência ao projeto “Shared Project”. Graficamente podemos representar a arquitetura da seguinte forma:

Arquitetura usando Shared Projects
Arquitetura usando Shared Projects

Neste caso, para que o compilador saiba qual código é válido para cada uma das plataformas, são usadas “marcações” no arquivo chamadas DIRETIVAS DE COMPILAÇÃO, exemplo:

Exemplo de código com diretivas de compilação
Exemplo de código com diretivas de compilação

Prós

  • Permite o compartilhamento de código entre multiplas plataformas.
  • O código compartilhado é dividido e compilado usando diretivas de compilação e somente o código referente a plataforma de destino é “embarcada” no aplicativo resultante.
  • Os aplicativos podem incluir referencias de terceiros (DLLs) específicas de cada plataforma e as diretivas de compilação podem ser utilizadas desde as declarações das mesmas (no “using”).

Contras

  • Shared Projects não geram uma DLL durante sua compilação, eles não possuem “output”, os arquivos dentro de um Shared Project são tratados COMO PARTE dos projetos que fazem referência ao projeto compartilhado.
  • Alterações que afetam um segmento de código “inativo”, fora de uma diretiva de compilação válida para a plataforma “target”, não sofrem alterações até a plataforma destino seja compatível com a diretiva e o código seja compilado novamente.

Portable Class Libraries

Nesta arquitetura, pode-se desenvolver um código ÚNICO cujo suporte a outras plataformas é feito referenciando o projeto do tipo PCL nos projetos de destino.

O conjunto de recursos disponíveis ao desenvolvedor no projeto PCL irá depender do “profile” desejado pelo desenvolvedor. O “profile” depende do conjunto de plataformas que deve ser atendidas pelo código desenvolvido e o .NET disponibiliza automaticamente o conjunto de recursos (classes, etc) que atende ao “profile” selecionado.

Graficamente, fica assim:

Arquitetura usando Portable Class Libraries
Arquitetura usando Portable Class Libraries

Prós

  • Permite o compartilhamento de código entre múltiplas plataformas.
  • Alterações no código dentro da Portable Class Library SEMPRE são refletidos em suas referências.
  • Possuem “output”, ou seja, geram uma DLL que pode ser compartilhada de forma simples e segura, pois o código é compilado e encapsulado na DLL.

Contras

  • Somente um “subset” (subconjunto) do .NET Framework estará disponível para utilização, isso é necessário para que todas as funcionalidades em uso atendam a todas as plataformas (mais detalhes podem ser encontrados AQUI).
  • Não oferece suporte a diretivas de compilação.

Resumindo (Shared Projects x Portable Class Libraries)

Na prática, ambos produzem o mesmo resultado e o aplicativo não sofre “penalidades” em tempo de execução.

Shared Projects são uma boa solução para desenvolvimento de aplicativos cujo código será compartilhado somente entre desenvolvedores INTERNOS, caso seja necessário compartilhar recursos com equipes EXTERNAS, optar por Portable Class Library é melhor recomendado, uma vez que ele faz o encapsulamento do código em uma DLL.

NA MINHA OPINIÃO, Shared Projects produzem um código mais “chato” de ser lido e entendido, e nunca se sabe se SOMENTE a sua equipe terá acesso ao código, nunca se sabe o futuro de um aplicativo, pode ser que não dê em nada, mas também pode ser que “bombe” do dia para a noite e você precise de mais “pares de mãos” para atender a demanda.

EU SEMPRE USO Portable Class Library, e os recursos específicos de cada plataforma são implementados usando Injeção de Dependência, mas cada um tem uma opinião, meu intuito não é (e nunca será) ser o dono da verdade absoluta.

Xamarin x (Java e Obj-C)

A grande vantagem do desenvolvimento Xamarin sobre o desenvolvimento nativo é ter a possibilidade de compartilhar código entre plataformas distintas sem sofrimento e retrabalho.

Utilizar de todo o “poder” dos recursos do C# como Async-Await, LINQ e muitos outros frameworks.

Uma desvantagem pode ser o acréscimo de uma camada de abstração, que pode conter erros e suas correções vão “entrar na fila” de correções de uma empresa terceira e podem ser disponibilizados com certo atraso para os desenvolvedores.

Quanto a limitações de recursos, não há! Pois todos os recursos disponíveis no desenvolvimento nativo são mapeados pela Xamarin, portanto os mesmos recursos disponíveis ao desenvolvedor nativo serão encontrados pelo desenvolvedor Xamarin.

Xamarin Tradicional x Xamarin Forms

Como dito anteriormente a Xamarin mapeia 100% das APIs do iOS e do Android. Portanto você terá as mesmas funcionalidades que você teria no desenvolvimento nativo sem nenhuma penalidade em performance.

Com Xamarin Forms, uma NOVA camada de abstração será adicionada para a interface (além da camada de abstração que faz a ponte entre o código C# e o device), isso irá fazer com que você não tenha o controle “pixel-a-pixel” da sua interface e TALVEZ sofra alguma perda de performance, que muitas vezes é imperceptível para o usuário “civil”.

E ambas as abordagens de compartilhamento de código (Shared Projects ou Portable Class Library) são possíveis entre Xamarin Nativo e Xamarin Forms.

Conclusão…

Escolher entre desenvolvimento “tradicional” e “Xamarin Forms” não é uma tarefa fácil.

Xamarin Forms sai na frente quando avaliamos o TEMPO para entregar uma solução capaz de atender a todas as plataformas.

Xamarin “Nativo” sai na frente quando avaliamos a EXPERIÊNCIA DO USUÁRIO pois desenvolver as interfaces e a lógica da aplicação de forma nativa possibilita total controle sobre os recursos de cada plataforma.

As performances são muito similares e atualmente a equipe da Xamarin tem trabalhado incansavelmente para eliminar qualquer limitação que possa causar problemas de performance, na maioria dos casos a performance chega a ser superior ao desenvolvimento Java e Obj-C.

EM LINHAS GERAIS, eu considero a IMPLEMENTAÇÃO da UX (User Experience) o aspecto mais relevante para decidir entre uma ou outra plataforma:

  • Os componentes “padrão” do Xamarin.Forms atendem quantos % da demanda total de componentes necessários para atender a usabilidade pretendida?
  • Os componentes “padrão” das abordagens tradicionais atendem quantos % da demanda total de componentes necessários para atender a usabilidade pretendida?

Pesar as respostas para essas perguntas irão definir a melhor abordagem para utilizar em seu aplicativo. Não é porque um aplicativo será implementado usando a abordagem tradicional, que 100% dos componentes disponíveis não irão precisar de customização a ponto de compensar aumentar a complexidade da aplicação (em termos de arquitetura, por exemplo) e, muitas vezes o ganho de tempo com componentes “padrão” no Xamarin.Forms justificam a utilização de Custom Renderers para atender um componente específico, enfim, sem um mapeamento detalhado da aplicação como um todo e também avaliarmos a evolução do aplicativo e enquadramos na abordagem que melhor irá nos atender.

Recentemente desenvolvi um aplicativo cujo design seguia as linhas gerais do Instagram, e os recursos de hardware necessários para implementação requeridos eram apenas a câmera e GPS, a abordagem escolhida foi Xamarin Forms! Motivo?! O design seria implementado “na mão” independente da plataforma escolhida, pois o menu inferior “similar” ao Instagram pode ser facilmente implementado sem controles nativos de cada plataforma (customização ZERO na renderização do Xamarin Forms, cenário perfeito), outro fator foi a evolução, projetando a evolução do aplicativo para os próximos 5~10 anos, não foram detectadas necessidades de recursos nativos (tanto hardware, como componentes visuais) para atender os requisitos do usuário.

Mais importante do que avaliar todos os aspectos acima mencionados, é entender como O USUÁRIO DO SEU APLICATIVO irá utilizá-lo! Isso não é só fator determinante para a escolha da abordagem correta, mas também é fator CRUCIAL para o sucesso de qualquer software!

Enfim…

Vou ficando por aqui, no próximo artigo iremos ver como tudo isso acontece na prática, criando aplicativos em cada uma das abordagens do Xamarin e prosseguirmos aprendendo juntos!

Espero ter esclarecido um pouco sobre o assunto e até a próxima!

Abraço, Jefferson.

Um agradecimento especial aos feedbacks do Willian Barbosa, que ajudaram bastante para melhorar a clareza do artigo.