Parte 2 – Arquitetura

Um princípio fundamental da criação de aplicativos multiplataforma é criar uma arquitetura que se presta a uma maximização do compartilhamento de código entre plataformas. Aderir aos seguintes princípios de Programação Orientada a Objetos ajuda a criar um aplicativo bem arquitetizado:

  • Encapsulamento – garantir que classes e até mesmo camadas arquitetônicas exponham apenas uma API mínima que execute suas funções necessárias e oculte os detalhes da implementação. Em um nível de classe, isso significa que os objetos se comportam como "caixas pretas" e que o código de consumo não precisa saber como eles realizam suas tarefas. Em um nível arquitetônico, isso significa implementar padrões como Fachada que incentivam uma API simplificada que orquestra interações mais complexas em nome do código em camadas mais abstratas. Isso significa que o código da interface do usuário (por exemplo) só deve ser responsável por exibir telas e aceitar a entrada do usuário; e nunca interagir diretamente com o banco de dados. Da mesma forma, o código de acesso a dados só deve ler e gravar no banco de dados, mas nunca interagir diretamente com botões ou rótulos.
  • Separação de responsabilidades – verifique se cada componente (tanto no nível de arquitetura quanto de classe) tem uma finalidade clara e bem definida. Cada componente deve executar apenas suas tarefas definidas e expor essa funcionalidade por meio de uma API acessível às outras classes que precisam usá-la.
  • Polimorfismo – a programação para uma interface (ou classe abstrata) que dá suporte a várias implementações significa que o código principal pode ser escrito e compartilhado entre plataformas, enquanto ainda interage com recursos específicos da plataforma.

O resultado natural é um aplicativo modelado após entidades do mundo real ou abstratas com camadas lógicas separadas. A separação de código em camadas facilita a compreensão, o teste e a manutenção dos aplicativos. É recomendável que o código em cada camada seja fisicamente separado (em diretórios ou até mesmo projetos separados para aplicativos muito grandes), bem como logicamente separado (usando namespaces).

Camadas de aplicativo típicas

Ao longo deste documento e dos estudos de caso, nos referimos às seis seguintes camadas de aplicativo:

  • Camada de Dados – persistência de dados não volátil, provavelmente um banco de dados SQLite, mas pode ser implementada com arquivos XML ou qualquer outro mecanismo adequado.
  • Camada de Acesso a Dados – Wrapper ao redor da Camada de Dados que fornece acesso CRUD (Criar, Ler, Atualizar, Excluir) aos dados sem expor detalhes de implementação ao chamador. Por exemplo, o DAL pode conter instruções SQL para consultar ou atualizar os dados, mas o código de referência não precisaria saber disso.
  • Camada de Negócios – (às vezes chamada de Camada lógica de negócios ou BLL) contém definições de entidade de negócios (o Modelo) e lógica de negócios. Padrão de Fachada do Candidato para Empresas.
  • Camada de Acesso ao Serviço – usada para acessar serviços na nuvem: desde serviços Web complexos (REST, JSON, WCF) até recuperação simples de dados e imagens de servidores remotos. Encapsula o comportamento de rede e fornece uma API simples a ser consumida pelas camadas de aplicativo e interface do usuário.
  • Camada de Aplicativo – código que normalmente é específico da plataforma (geralmente não compartilhado entre plataformas) ou código específico do aplicativo (geralmente não reutilizável). Um bom teste de se o código deve ser colocado na Camada de Aplicativo versus na Camada de Interface do Usuário é (a) para determinar se a classe tem controles de exibição reais ou (b) se ela pode ser compartilhada entre várias telas ou dispositivos (por exemplo, iPhone e iPad).
  • Camada interface do usuário ( interface do usuário) – a camada voltada para o usuário, contém telas, widgets e os controladores que os gerenciam.

Um aplicativo pode não conter necessariamente todas as camadas – por exemplo, a Camada de Acesso ao Serviço não existiria em um aplicativo que não acessa recursos de rede. Um aplicativo muito simples pode mesclar a Camada de Dados e a Camada de Acesso a Dados porque as operações são extremamente básicas.

Padrões comuns de software móvel

Os padrões são uma maneira estabelecida de capturar soluções recorrentes para problemas comuns. Há alguns padrões-chave que são úteis para entender na criação de aplicativos móveis manteníveis/compreensíveis.

  • Modelo, Exibição, ViewModel (MVVM) – o padrão Model-View-ViewModel é popular entre estruturas que dão suporte à associação de dados, como O Xamarin.Forms. Ele foi popularizado por SDKs habilitados para XAML, como Windows Presentation Foundation (WPF) e Silverlight, em que o ViewModel atua como um intermediário entre os dados (Modelo) e a interface do usuário (Exibição) por meio de associação de dados e comandos.
  • Modelo, Exibição, Controlador (MVC) – um padrão comum e muitas vezes incompreendido, o MVC é usado com mais frequência ao criar Interfaces de Usuário e fornece uma separação entre a definição real de uma tela de interface do usuário (Exibição), o mecanismo por trás dele que manipula a interação (Controlador) e os dados que o preenchem (Modelo). O modelo é, na verdade, uma peça completamente opcional e, portanto, o núcleo de compreensão desse padrão está na exibição e no controlador. O MVC é uma abordagem popular para aplicativos iOS.
  • Fachada de negócios – também conhecido como Padrão do Gerente, fornece um ponto de entrada simplificado para trabalhos complexos. Por exemplo, em um aplicativo de Acompanhamento de Tarefas, você pode ter uma TaskManager classe com métodos como GetAllTasks() , GetTask(taskID) , SaveTask (task) etc. A TaskManager classe fornece uma Fachada para o funcionamento interno de realmente salvar/recuperar objetos de tarefas.
  • Singleton – o padrão Singleton fornece uma maneira em que apenas uma única instância de um objeto específico possa existir. Por exemplo, ao usar SQLite em aplicativos móveis, você só deseja uma instância do banco de dados. Usar o padrão Singleton é uma maneira simples de garantir isso.
  • Provedor – um padrão cunhado pela Microsoft (indiscutivelmente semelhante à Estratégia ou injeção básica de dependência) para incentivar o reutilização de código em aplicativos Silverlight, WPF e WinForms. O código compartilhado pode ser escrito em uma interface ou classe abstrata, e implementações concretas específicas da plataforma são escritas e passadas quando o código é usado.
  • Assíncrono – para não ser confundido com o palavra-chave Assíncrono, o padrão assíncrono é usado quando o trabalho de execução longa precisa ser executado sem manter a interface do usuário ou o processamento atual. Em sua forma mais simples, o padrão assíncrono simplesmente descreve que tarefas de execução longa devem ser iniciadas em outro thread (ou abstração de thread semelhante, como uma Tarefa), enquanto o thread atual continua a processar e escuta uma resposta do processo em segundo plano e, em seguida, atualiza a interface do usuário quando dados e ou estado são retornados.

Cada um dos padrões será examinado com mais detalhes à medida que seu uso prático for ilustrado nos estudos de caso. A Wikipédia tem descrições mais detalhadas dos padrões MVVM, MVC, Facade, Singleton, Estratégia e Provedor (e de Padrões de Design em geral).