Meu objetivo com este post é ouvir o feedback de outros arquitetos a respeito do tema: Sistemas Empresariais (ERP) que permitem mobilidade offline para realizar vendas e cadastros no campo, geralmente em locais onde não há sinal de internet. Já tive a oportunidade de trabalhar em um sistema desse porte no setor de Agronegócios, era necessário sincronizar um grande volume de dados offline, uma tarefa realmente desafiadora e talvez até incomum para a maioria dos sistemas. Caso nunca tenha ouvido falar desse tipo de solução, dá uma olhada neste vídeo.
Pretendo comentar sobre a arquitetura generalista, que está em alta no mercado, e depois irei comentar sobre uma arquitetura especialista, mostrando as vantagens e desvantagens de cada uma neste cenário.
Requisitos
-
O aplicativo deve sincronizar informações com o servidor para que as mesmas regras e fluxos de negócio que são executados no servidor também seja executado no aplicativo offline, dessa forma o representante da empresa pode receber os dados de clientes no início do expediente e ir a campo para efetuar operações in-off como: cadastro de clientes, cadastro de pedido de venda, agendamento de visitas em propriedades, verificação do status financeiro do cliente, relatórios de contas à receber/pagar, dentre muitas outras rotinas de negócio. No final do expediente, assim que o representante chegar na empresa ou em casa, ele terá acesso a internet, então deverá sincronizar esses cadastros com o ERP.
-
Para receber os dados atualizados do servidor, deve ser desenvolvido uma tela de sincronização que solicita a geração de um banco de dados SQLite com todas as informações vindas do SGBD relacional.
-
Para enviar os dados para o servidor é mais simples, apenas uma requisição que enviará os dados cadastrados para o ERP. O banco SQLite que contêm os dados gerenciais para uso offline sempre será gerado no servidor, enquanto que o outro banco de dados local será utilizado para persistir os dados cadastrados.
-
Quanto a plataforma Mobile, muito provavelmente o Android será mais utilizado, principalmente se o smartphone do representante é da empresa, dificilmente seria um iPhone por exemplo, a não ser que o representante utilizar o seu iOS para trabalho.
Estrutura
-
Backend: Aplicação REST desenvolvida em Java, pode ser qualquer plataforma ou framework desse ecossistema (Jakarta EE, Spring, Quarkus, Micronaut).
-
Frontend: Solução client-side (frameworks JavaScript) ou server-side (JSP/JSF).
-
Banco de dados: Um banco de dados relacional como Oracle, Postgres, MySQL etc.
-
Banco de dados offline: Acredito que o SQLite é a solução com mais maturidade para lidar com dados offline, pois é um banco relacional arquitetado para rodar localmente.
Arquitetura Generalista
- Aplicativo offline: Solução híbrida como Flutter, React Native, dentre outras.
Arquitetura Especialista
- Aplicativo offline: Solução nativa para ambas plataformas, Android (Java/Kotlin) e iOS (Swift).
Tradeoffs: Aplicativo híbrido
-
Provavelmente a decisão mais comum seria desenvolver um app híbrido para ter a grande vantagem do suporte para Android e iOS mantendo apenas uma base de código. Esta abordagem geralmente é adotada em um MVP, mas apresenta vários problemas a nível de manutenção e performance.
-
O primeiro problema seria lidar com uma linguagem que não é interoperável com o backend, no caso do Flutter seria o Dart, isso significa que boa parte do código de negócio que é executado no ERP online em Java também teria que ser executado no aplicativo, causando duplicidade na camada de negócio, pois não seria possível realizar uma requisição para o backend lidar com o fluxo de negócio, o requisito é funcionar boa parte do tempo in-off.
-
Outro problema é que os testes unitários seriam duplicados também, tanto em Java quanto Flutter, dessa forma o tempo de desenvolvimento pode aumentar e para entregar as features mais rapidamente, o time poderia acabar deixando de lado o teste automatizado em uma das duas pontas.
-
Como se trata de um app offline, a manutenção de código de negócio duplicado pode realmente dificultar as coisas.
Tradeoffs: Aplicativo nativo
-
A decisão mais segura no longo prazo é desenvolver o mesmo aplicativo em ambas plataformas, além disso possibilita a contratação de desenvolvedores especializados caso seja necessário lidar com recursos mais avançados da plataforma, além de ter mais performance se necessário.
-
Antes de comentar sobre os tradeoffs, vamos analisar o cenário antigo e atual de desenvolvimento mobile nativo: Antigamente a duplicidade do código de negócio era inevitável, fazendo com que esse tipo de solução ficasse limitada ao Android pois seria mais caro desenvolver para iOS, já os apps online optavam por desenvolver nas 2 plataformas, duplicando assim o código que realizava a comunicação com o backend. Uma forma de tentar resolver este problema de duplicidade era usando a JNI como uma camada entre as duas plataformas, porém não era trivial pois o código de negócio seria escrito em C/C++ e ficaria preso nesse contexto. Para tornar o desenvolvimento mobile mais acessível foi criado o Flutter na tentativa de resolver definitivamente esse e outros problemas.
-
No entanto, muitas empresas não tiveram escolhas e continuaram desenvolvendo nativo pois nem sempre é possível utilizar uma solução híbrida, podem existir limitações nessas soluções. Nesse contexto, a Jetbrains já tinha criado a linguagem Kotlin, uma linguagem interoperável com Java e que fornece uma experiência de desenvolvimento melhor para o Android, inclusive a Google teve que estabelecer uma posição quanto a arquitetura dos apps, recomendando o MVVM, pois boa parte do mercado usava outras arquiteturas como MVP ou não seguiam nenhum padrão ainda, dessa forma o Kotlin se tornou a linguagem oficial nesse contexto. Por último, a Jetbrains criou o KMM, uma solução multiplataforma que promete resolver os problemas de duplicidade do código de negócio entre as plataformas nativas: “Write the business logic for your iOS and Android apps just once, in pure Kotlin”.
-
Logo, uma solução para o problema de duplicidade do ERP móvel pode ser o módulo Kotlin compartilhado entre os projetos Java, ajudando não só o desenvolvimento mobile mas também a nível de back-end, já que é possível compartilhar o código comum entre os projetos, porém não significa que é uma tarefa fácil, ainda mais lidando com código já existente, mas é uma ótima opção tanto para desenvolvimento exclusivo Android e Web quanto para desenvolvimento iOS nativo, pois o código KMM compartilhado, é compilado para bytecode (JVM) para Android e também é compliado em binários nativos para iOS. Isso torna a integração com o KMM perfeita em ambas as plataformas, desde que o seu código seja compatível.
-
Então, a grande vantagem seria esta camada de negócio escrita em Kotlin com testes unitários, ela atuaria como uma ponte entre o Android, iOS e até mesmo no backend (tratando-se apenas de código unitário). Não seria mais necessário duplicar este código e nem os testes.
-
Existem mais detalhes técnicos como as consultas SQL que serão compartilhadas entre as plataformas, para isso existe uma lib compatível com o KMM, o SQL Delight que internamente utiliza o driver do JDBC do SQLite através de chamadas JNI. Para fazer requisições HTTP por exemplo, tem o Ktor Client, sendo mais útil ainda para apps online mas mesmo um app offline terá que fazer as chamadas para sincronizar com o servidor.
-
No entanto, a desvantagem dessa abordagem é que o KMM não é híbrido, sendo necessário desenvolver as Views nativamente para ambas plataformas.
Tudo vai depender do contexto, nesse caso específico de aplicativo offline, acredito que seria muito interessante construir a arquitetura considerando o módulo Kotlin compartilhado e usando o KMM se for necessário desenvolver o app para iOS. No caso do KMM, não vejo a duplicidade das telas como um problema visto que a View e outros detalhes de UX são menos críticos do que o código de negócio que será alterado com muito mais frequência nesse tipo de sistema.
O que acham dessa ideia?