Fevereiro de 2016

Volume 31 – Número 2

Cutting Edge – Resultados da arquitetura do UXDD

Por Dino Esposito | Fevereiro de 2016

Dino EspositoOs anos passam e eu fico contente se conhecer e puder recomendar pelo menos uma ou duas maneiras eficazes de trabalhar com a maioria dos recursos de software. Não deixe que a importância do marketing de software engane você. A qualidade de software vem melhorando constantemente, mas isso não é o negócio principal da maioria das empresas por aí. Isso significa que, para as empresas, é mais do que aceitável continuar usando o mesmo software por muitos anos. De acordo com o índice Tiobe.com, no verão de 2014, o Visual Basic 6 ainda estava no ranking das 10 linguagens de programação mais usadas. No entanto, um ano e meio mais tarde, ele caiu algumas posições. Isso parece confirmar a tendência de que a maioria silenciosa das empresas costuma adiar reescrever o software o máximo possível. Na verdade, a maioria silenciosa das empresas tem, pelo menos, uma lista de pendências de cinco anos em tecnologia de software que ainda é usada em seus negócios. Mas quando chega a hora das empresas atualizarem esses sistemas da lista de pendências, os arquitetos procuram software de última geração.

Arquitetura de software nos dias de hoje

No que diz respeito à arquitetura, duas palavras-chave têm causado agitação nestes últimos dias. Uma é “CQRS,” acrônimo para Command and Query Responsibility Segregation (Comando e Segregação de Responsabilidade de Consulta), e a outra é “persistência poliglota”. Falei recentemente sobre CQRS em uma série de artigos do Cutting Edge. Para começar, seria interessante ler “CQRS para o aplicativo comum” (https://msdn.microsoft.com/pt-br/magazine/Mt147237.aspx) na edição de junho de 2015 da MSDN Magazine. CQRS é uma diretriz de arquitetura que simplesmente recomenda que você mantenha o código que altera o estado do sistema separado do código que lê e relata o estado. De modo geral, a persistência poliglota se refere à prática emergente de usar várias tecnologias de persistência no contexto da mesma camada de acesso a dados. A expressão “persistência poliglota” resume em duas palavras as soluções técnicas complexas adotadas pelas redes sociais para lidar com a quantidade gigantesca de dados que elas têm de gerenciar diariamente. A essência da persistência poliglota é apenas usar a tecnologia de persistência que parece ser ideal para o tipo e a quantidade de dados que você possui.

Enquanto o CQRS e a persistência poliglota têm méritos visíveis e benefícios em potencial, às vezes é difícil ver sua importância quando um aplicativo empresarial complexo tem que ressuscitar das cinzas com uma base de código grande do Visual Basic 6, do Windows Forms ou do Web Forms. Ainda assim, a importância existe e perder a oportunidade pode ser prejudicial a longo prazo, tanto para o projeto quanto para a empresa. Ao mesmo tempo, a arquitetura de software não é um ato de fé. CQRS pode parecer uma coisa ótima, mas você deve encontrar a perspectiva certa para ajustá-la ao seu cenário.

Bem, se você observar a arquitetura de software sob o ponto de vista do UXDD, poderá encontrar um ajuste facilmente tanto para CQRS quanto para persistência poliglota.

Design baseado em tarefa

Os formulários de fluxo de trabalho UXDD já estão sendo usados em empresas de todos os tamanhos e, pessoalmente, já vi tipos diferentes deles tanto em equipes pequenas, de 10 pessoas ou menos, quanto em empresas multimilionárias. Quando isso acontece, existe uma equipe de UX que elabora telas em colaboração com clientes finais, sejam eles internos ou externos. A equipe de UX produz alguns artefatos coloridos em forma de arquivos PDF ou HTML e fornece-os à equipe de desenvolvimento. O problema é que, na maioria das vezes, a equipe de desenvolvimento ignora tais artefatos até que toda a pilha de back-end esteja projetada e criada. Muitas vezes, o back-end é projetado considerando pouco ou nem considerando as tarefas reais executadas no nível de apresentação. Como arquitetos, tomamos muito cuidado com as tarefas de lógica de negócios e pensamos em maneiras de otimizar e generalizar a implementação. Normalmente, nós não nos preocupamos o suficiente com afunilamentos ou com a apresentação e a navegação de dados abaixo do ideal. Quando acabamos descobrindo que a experiência real dos usuários enquanto trabalham com o aplicativo está abaixo do ideal, normalmente já é tarde demais para implementar mudanças de forma econômica, como mostrado na Figura 1.

Design de um sistema de software de baixo para cima versus de cima para baixo
Figura 1 Design de um sistema de software de baixo para cima versus de cima para baixo

Vamos encarar os fatos: Muito além de sua eficácia indiscutível para armazenamento de dados, o modelo relacional pode induzir a arquitetura de software em erro. Ou, pelo menos, começou a induzir em erro seriamente depois de suas primeiras duas décadas de vida. Já em meados dos anos 90, a incompatibilidade no espaço Java entre os modelos de dados conceituais e relacionais foi o que realmente levou à experimentação de ferramentas O/RM. Gerações de arquitetos de software (agora gerentes) cresceram com a ideia de que tudo o que interessa é ter um banco de dados com uma base sólida. Sem dúvida que um banco de dados sólido é a base de qualquer software sólido. O problema é a complexidade e a quantidade de lógica de domínio e de aplicativo. Aliás, enquanto ainda era viável adicionar partes desta lógica em procedimentos armazenados, isso não era problemático. Os arquitetos de software evoluíram para além desse limite em direção à arquitetura clássica de três camadas (apresentação, negócios, dados) e, mais tarde, na arquitetura em camadas do design orientado para domínio (DDD): apresentação, uso, domínio e infraestrutura Independentemente do número de camadas, o design foi essencialmente de baixo para cima.

O design de baixo para cima funciona muito bem se, pelo menos, uma das duas condições seguintes é constatada:

  1. A interface de usuário ideal é muito próxima do modelo relacional.
  2. Seus usuários são burros e não agem.

O design de software parece uma ciência exata quando você olha para tutoriais já prontos para promover alguma tecnologia ou estrutura nova legal. Quando você sai do laboratório asséptico e vai para o mundo real, o design de software se torna um reino de medo, dúvida e incerteza – aquela terra de ninguém onde só existe uma regra: Depende.

O UXDD sugere simplesmente que você não comece nenhum desenvolvimento sério até que tenha uma evidência clara (leia-se: wireframe) da arquitetura ideal da informação e a interação ideal entre os usuários e o sistema. O design de cima para baixo começando a partir do wireframe da camada de apresentação garante que você se aproxime bastante da demanda dos usuários. O risco de ouvir as palavras abomináveis “isso não é o que eu pedi” é dramaticamente reduzido. Lembre-se de que se um wireframe é rotulado como errado, nunca é uma questão de preferência; é muito mais uma questão de negócios. Ignorar o resultado dos wireframes é como criar bugs no sistema resultante de propósito.

A Figura 2 resume a incompatibilidade de impedância da arquitetura nos dias de hoje. Nós temos wireframes que descrevem a camada de apresentação ideal e temos o código que implementa a lógica de negócios tal como foi entendida. Infelizmente, com muita frequência, eles não coincidem. Se os projetos de software raramente correspondem às expectativas, especialmente do ponto de vista financeiro, tem certeza de que a razão não é a incompatibilidade de impedância de arquitetura?

Incompatibilidade de impedância de arquitetura
Figura 2 Incompatibilidade de impedância de arquitetura

Solucionando incompatibilidades de impedância de arquitetura

Acontece que um modelo de domínio completo que cubra todo o espectro de lógica de domínio não faz sentido, para dizer o mínimo. A ideia de modelos de domínio, e de toda a abordagem DDD, surgiu para enfrentar a complexidade na parte central do software, mas isso já foi há mais de uma década. Muita coisa mudou desde então e, embora alguns elementos centrais do DDD, especificamente os conceitos e ferramentas de design estratégico, sejam hoje mais valiosos do que nunca, um modelo de domínio orientado a objeto que cubra completamente todos os aspectos de ler e escrever dos contextos distintos delimitados é complicado de criar e pouco realista.

Ao mesmo tempo, a ideia de um modelo de domínio completo está alinhada com uma visão de baixo para cima do software, na qual você entende o que os usuários querem, elabora um modelo, codifica o modelo e coloca alguma interface do usuário nele. Por mais engraçado que pareça, um software bem-sucedido é uma UX legal e eficaz, além de uma caixa preta mágica (MBB).

Se você começar qualquer trabalho de engenharia a partir dos wireframes, saberá exatamente ao que a MBB deve dar suporte efetivamente. E você também sabe que enquanto a MBB faz seu trabalho, o sistema está realmente próximo daquilo que o usuário oficialmente pediu. O desenvolvedor praticamente não tem espaço nenhum para suposições e a maioria das iterações com os clientes são agrupadas na fase inicial do projeto. É barato realizar qualquer mudança e, quando os testes de UX são aprovados, a maioria do que resta tem a importância de um detalhe de implementação.

O UXDD enfatiza tarefas e eventos. Em um design de cima para baixo, o ponto de partida é uma ação do usuário, como um clique ou uma seleção. Cada ação do usuário está vinculada a um ponto de entrada na camada de aplicativo. Por exemplo, no ASP.NET MVC, isso significa que todos os métodos do controlador (camada de apresentação) estão vinculados a um ponto de entrada em uma classe de camada de aplicativo, como mostrado na Figura 3.

Figura 3 Controlador CQRS

public class SomeController
{  
  public ActionResult SomeQueryTask(InputModel input)
  {
    var service = new QueryStack.SomeService();
    var model = service.GetActionViewModel(input);
    return View(model);
  }
  public ActionResult SomeCommandTask(InputModel input)
  {
    var service = new CommandStack.SomeService();
    service.GetActionViewModel(input);
    RedirectToAction(...);
  }
}

As duas classes SomeService correspondem à seção da camada de aplicativo que é visível da parte da camada de apresentação representada pela classe SomeController. As duas classes SomeService podem fazer parte do mesmo projeto físico e assembly, como a apresentação, ou serem assemblies e projetos distintos. Considere que, do ponto de vista arquitetural, a camada de aplicativo anda de mãos dadas com a camada de apresentação. Isso significa que quando as camadas de apresentação são necessárias (ou seja, para Web, Web móvel e aplicativos móveis), é aceitável haver várias camadas de aplicativo com a capacidade de uso limitada da lógica como resultado.

Você terá um método de ponto de entrada na camada de aplicativo para cada tarefa possível que o usuário possa disparar a partir da interface do usuário aprovada. Se você reproduzir fielmente os wireframes recebidos, saberá exatamente o que entra e sai de cada tela. É impossível errar. Esse método pode ser ineficiente ou lento, mas nunca é errado.

A camada de aplicativo substitui objetos de transferência de dados pela apresentação e organiza todos os fluxos de trabalho necessários para a tarefa. Ao fazer isso, a camada de aplicativo normalmente precisar ler e escrever os dados de um repositório persistente, acessar serviços Web externos e realizar cálculos. Isso é apenas lógica de domínio, o que é invariável nos casos de uso. A tarefa de domínio de negócio executa tanto uma apresentação Web quanto móvel e é totalmente reutilizável. Resumindo, a ideia de lógica de negócios é dividida em mais dois segmentos específicos: lógica de aplicativo, como a lógica necessária para implementar casos de uso de apresentação específicos, e lógica de domínio, que é invariável na apresentação e nos casos de uso.

A lógica de domínio pode ser projetada de acordo com uma variedade de padrões, incluindo script de transação e módulo de tabela. Nesses casos, as regras de negócios são um corpo estranho injetado nas classes usadas por você. Normalmente, as regras de negócios são uma calculadora que você invoca para obter uma resposta sobre a viabilidade de uma ação. O padrão de modelo de domínio, normalmente desvirtuado como a verdadeira essência do DDD, é simplesmente um padrão que sugere que você crie classes que se comportam como entidades reais e, subsequentemente, incorporam as regras do negócios e escondem seu aplicativo nos métodos que eles oferecem. Não existe uma maneira certa ou errada de projetar uma lógica de domínio; é puramente uma questão de atitude e eficácia.

Em um design baseado em tarefa, você vê imediatamente se a ação altera o estado do sistema ou se o relata. Usando o design CQRS, você divide naturalmente os comandos das consultas e, colocando-os em pilhas separadas, obtém as vantagens óbvias de escrevê-los e otimizá-los separadamente sem risco de regressão, mesmo com o potencial de escalabilidade simplificada. O CQRS é uma escolha natural em um contexto de UXDD.

Finalmente vamos falar de persistência!

Quando se trabalha de cima para baixo, inevitavelmente a persistência é a última coisa com que você deve se preocupar. Mas não se engane: todas os aplicativos precisam ter dados de persistência eficazes e dados que possam ser consultados com eficácia. A última de suas preocupações não significa que você deva negligenciar a persistência; apenas significa que em um sistema interativo e orientado ao usuário, o design da persistência se torna crítico apenas depois de alguns aspectos, especificamente UX e lógica de domínio, serem resolvidos. Só por causa disso, você não tem nenhuma restrição quanto ao uso de qualquer tecnologia de banco de dados. Além disso, se você tem um design CQRS, pode ter facilmente várias camadas de persistência, uma para comandos e uma para consultas, gerenciadas de forma independente e até mesmo, se isso ajudar, baseadas em diferentes tecnologias e paradigmas de armazenamento. Por exemplo, se você souber que, em certa altura, a análise deve ser relatada à interface do usuário, talvez queira adotar uma estrutura de fonte de eventos e rastrear cada atualização e ações relevantes como um evento. Isso lhe dará os registros completos de tudo o que aconteceu no sistema, o que pode ser usado como o ponto de partida de uma autoanálise de business inteligence. Ao mesmo tempo, se você precisar de dados já prontos para servir rapidamente o usuário, bastará manter o repositório de eventos sincronizado com uma projeção dos dados que se adapte às suas necessidades de apresentação. Nesse contexto, uma projeção de dados é o estado gerado após uma lista de ações. Isso é o mesmo que desejar saber o saldo da conta bancária (a projeção) resultante de uma lista de transações (eventos). A pilha de consultas é frequentemente feita com exibições simples do SQL Server, em que a pilha de comando pode ser baseada em tabelas relacionais, NoSQL ou repositório de eventos, inclusive uma combinação destes.

Isso é o que alguns chamam de persistência poliglota.

Conclusão

Quer queira, quer não, os usuários julgam o sistema principalmente pela primeira impressão depois de experimentá-lo. Atualmente, o fator principal para economizar dinheiro em projetos de software é ter a certeza de que você está criando, logo de cara, o que os usuários desejam. Não se trata apenas de fazer a coisa certa, mas também de fazê-la o mais rapidamente possível. Com o UXDD, você sabe o mais cedo possível para qual saída vai criar o sistema, o que diminui as correções a serem aplicadas ao implantar o sistema e os usuários na verdade não gostarem. Além disso, com um design de cima para baixo, sua experiência de design é naturalmente levada rumo a padrões modernos, como o CQRS e a persistência poliglota que, para além da tendência, são práticas comprovadas de criação de software eficazes.


Dino Espositoé o coautor do “Microsoft .NET: Architecting Applications for the Enterprise” (Microsoft Press, 2014) e “Modern Web Applications” (Microsoft Press, 2016). Um evangelista técnico para as plataformas Microsoft .NET Framework e Android na JetBrains e palestrante frequente em eventos do setor no mundo inteiro, Esposito compartilha sua visão do software em software2cents.wordpress.com e no Twitter em @despos.

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Jon Arne Saeteras