Multiplataforma

Crie aplicativos multiplataforma para o desktop, o Prism e o Windows Phone 7

Bill Kratochvil

A Microsoft oferece uma estrutura poderosa para desenvolvimento de aplicativos extensíveis e escaláveis. Alguns projetos recentes — o Prism, o Managed Extensibility Framework (MEF) e o Unity — oferecem recursos multiplataforma. A multiplataforma permite ter uma única base de código que pode ser compartilhada com as plataformas de desktop, do Silverlight e do Windows Phone 7. Essas ferramentas gratuitas têm ampla documentação com inícios rápidos, laboratórios e muitos códigos de exemplo para ajudar você a começar. Para maximizar seu retorno sobre o investimento (ROI) — horas/homem aplicadas em pesquisa e aprendizado — é importante compreender que você deve abordar essas ferramentas e documentação com uma nova maneira de pensar.

O Prism, o MEF e o Unity usam padrões avançados de desenvolvimento de software que podem tornar a curva de aprendizado difícil para a maioria dos desenvolvedores — tão difícil que pode parecer falta de ROI. Eles exigem não apenas uma nova maneira de pensar, mas a compreensão das ferramentas e dos padrões envolvidos. A falha em qualquer área será custosa em termos da curva de aprendizado e da estabilidade do aplicativo. Felizmente, se você dominar alguns conceitos básicos, não apenas compreenderá as ferramentas e a documentação, mas também será capaz de abrir qualquer aplicativo do Prism, do MEF ou do Unity e navegar rapidamente por ele de modo a aprender ou reutilizar o melhor do que estiver disponível para criar seus aplicativos multiplataforma. Esses conceitos incluem o vinculador do projeto, injeção de dependência (DI), compartilhamento de código e padrões de arquitetura.

O vinculador de projeto

É importante compreender que os projetos não podem ser compartilhados entre plataformas. Os projetos de desktop não fazem referências a projetos do Silverlight e estes não fazem referências a projetos de desktop. Da mesma forma, um projeto do Windows Phone 7 não faz referência a projetos do Silverlight ou de desktop. Se você não estiver compartilhando projetos, estará compartilhando código. Isso exige criar um projeto para cada plataforma e “vincular” os arquivos.

Arquivos vinculados no Visual Studio são identificados com um símbolo de atalho no ícone do arquivo e não existem fisicamente em seu disco rígido.

Observe na Figura 1 que apenas o projeto Phone (fonte) possui código; os projetos destinados a desktop e Silverlight possuem arquivos vinculados, portanto, suas pastas estão vazias.

Only Source Projects Have Code

Figura 1 Apenas os projetos-fonte têm código

O projeto Prism (compositewpf.codeplex.com) inclui um aplicativo vinculador de projeto; sem essa ferramenta, o gerenciamento de aplicativos multiplataforma se tornaria uma tarefa assustadora. Isso permite definir um projeto-fonte e vinculá-lo a projetos de destino de modo que qualquer ação executada na fonte — por exemplo, adicionar, renomear e excluir pastas e arquivos — será duplicada nos projetos de destino.  

As convenções de nomenclatura tornam-se mais importantes em aplicativos multiplataforma. Os projetos vinculados devem compartilhar todos o mesmo nome, com exceção do sufixo, que representa a plataforma. Para fins de estrutura de pasta, é melhor criar o projeto com o sufixo — por exemplo, Gwn.Infrastucture.Desktop — e depois remover o sufixo do namespace padrão da configuração do projeto, conforme mostrado na Figura 2.

Remove the Suffix from the Default Namespace After Creating the Project

Figura 2 Remova o sufixo do namespace padrão após criar o projeto

Isso garante que suas estruturas de pasta não serão ambíguas nem causarão problemas na criação de novos projetos (com o mesmo nome) para outras plataformas. Remover o sufixo do namespace padrão é uma etapa importante; como você está compartilhando código em diversas plataformas, o código não deve ter namespaces específicos da plataforma ou as outras plataformas acusarão erro no momento da compilação.

A orientação anterior também ajuda a manter sua sanidade durante o desenvolvimento. Se você adicionar inadvertidamente uma referência de assembly a uma plataforma diferente — por exemplo, na Figura 2, meu aplicativo de desktop tem uma referência a um assembly do Silverlight — você obterá uma mensagem de erro complicada (porque ela existe de fato no namespace).Uma rápida olhada nas referências do projeto revelará o culpado se você tiver usado um sufixo de plataforma.

A Microsoft oferece uma excelente documentação para o vinculador do projeto em msdn.microsoft.com/library/dd458870. Além disso, você pode usar o mecanismo de pesquisa Bing para pesquisar “vinculador do projeto” e obter outros recursos valiosos, incluindo um link de minha autoria (BillKrat), com um webcast que o orienta pelo processo de vinculação de projetos. (Observação: O processo de instalação será muito mais fácil do que o observado na documentação, se você estiver usando o Visual Studio 2010. Nas opções de menu, você pode acessar Tools | Extension Manager, pesquisar “Project Linker” e instalá-lo a partir daí.)

Injeção de dependência

Para compreender o Prism, o MEF e o Unity, você precisará compreender a injeção de dependência. Sem isso, a documentação e os exemplos parecerão estranhos a você e sua curva de aprendizado será mais difícil do que deve. Limitaremos o tópico da injeção de dependência ao contêiner do Unity (unity.codeplex.com); depois de compreender a injeção de dependência, você compreenderá melhor o MEF (mef.codeplex.com).

O que é um contêiner de injeção de dependência A grosso modo, você pode ver o contêiner de injeção de dependência como uma classe de dicionário superestimada com o poder de criar classes. Nesse dicionário, você pode registrar interfaces e suas implementações (ou instâncias) — dictionary.add(IFoo,Foo), por exemplo. Quando você diz a seu contêiner para criar IFoo — uma interface — ele pesquisará o dicionário, descobrirá se há um tipo (Foo) e criará uma instância dele. Após criar uma instância de Foo, você verá se Foo tem qualquer interface que precisa ser resolvida e a cadeia continuará recursivamente até que todos os filhos tenham sido criados com êxito. Depois de concluído, o contêiner retornará uma instância de Foo.

Injeção de construtor e injeção de setter Geralmente, as declarações de código criarão uma instância de uma classe de modo a usar seus recursos (Figura 3, linha 18).

Constructor and Setter Injection

Figura 3 Injeção de construtor e injeção de setter

Com a injeção de dependência, as classes são resolvidas (instanciadas) externamente e as instâncias são injetadas na classe pelo contêiner de injeção de dependência. O Unity suporta dois tipos de injeção: injeção de construtor e injeção de setter. Com a injeção de construtor (Figura 3, linha 25) o contêiner criará dinamicamente a classe MyTaskConstructorInjection, resolverá o IFoo e o passará ao parâmetro de construtor. Após o contêiner Unity construir a classe e injetar os parâmetros, ele pesquisará a classe quanto aos atributos de dependência (Figura 3, linha 33) e resolverá as propriedades. Devido à injeção de setter não ocorrer até a conclusão da injeção do construtor, você não pode fazer referência a objetos com o atributo de dependência em seu construtor.

Registrando tipos Para que o contêiner resolva os tipos de interface, como IFoo, a implementação deve ser registrada primeiro no contêiner (consulte a Figura 4, linhas 49 e 50).

Registering the Implementation with the Container

Figura 4 Registrando a implementação no contêiner

Geralmente, o registro será feito no bootstrapper, módulo ou apresentador/controlador do aplicativo, pois essas são geralmente as classes de inicialização. Como as interfaces são registradas, o contêiner saberá como resolver uma interface quando ela for encontrada na cadeia de dependência.

Aplicativos extensíveis e escaláveis Para fins explicativos, digamos que a classe Foo seja uma camada de acesso a dados (DAL) que sua empresa usa para acessar seu banco de dados do SQL Server. Ela é usada por centenas de módulos e vários aplicativos. A gerência acabou de concluir um contrato de licenciamento com a Microsoft — para serviços de nuvem — e você foi notificado de que deve atualizar seus aplicativos para utilizar a nuvem. Durante a migração, Foo continuará a ser usado por alguns aplicativos (para o banco de dados do SQL Server), enquanto outros serão movidos para a nuvem. Para os aplicativos que estão migrando para a nuvem, você precisa ser capaz de alternar para o antigo banco de dados rapidamente no caso da migração falhar por qualquer motivo. Quanto tempo isso exigiria de você?

Usando a injeção de dependência, apenas algumas poucas linhas de código! O pseudocódigo é o seguinte:

var  isCloud =  GetCloudConfigurationFromConfigFile();
if(isCloud)
  container.RegisterType<IFoo, FooCloud>();
else
  container.RegisterType<IFoo, Foo>();

Como os aplicativos de sua empresa passaram por testes de integração, você pode executar um desenvolvimento orientado a testes (TDD) no novo DAL FooCloud. Após a conclusão do TDD, você estará pronto para atualizar o bootstrapper de cada aplicativo com o código anterior e implantá-lo “SEM” necessidade de teste de regressão para os aplicativos que continuam a usar o banco de dados do SQL Server (classe Foo), pois o código não mudou.

A camada de lógica de negócios (BLL) a seguir pode ser usada potencialmente por centenas de apresentadores/controladores. Como ela lida estritamente com objetos do domínio, não precisamos tocar nesse código — ou qualquer código que consuma essa BLL — pois estamos codificando em relação à interface DAL (IFoo):

public class FinancialDataBll  : IFinancialDataBll
   {
     [Dependency]
       public  IFoo Dal {get;set;}

       public  IEnumerable<FinancialEntity> 
         GetFinanicalData(object sender, EventArgs e)
       {
         // Validate event arguments prior to calling data layer
         var returnResults = Dal.GetFinancialData(sender,e);
         // Handle errors with friendly messages as applicable
         return returnResults;
       }
   }

Se você tiver acoplado precisamente seu código à classe Foo na Figura 3, linha 18, então seus aplicativos não serão tão extensíveis e o processo de migração será consideravelmente mais custoso em termos de codificação e testes.

Camadas A utilização eficiente da injeção de dependência requer que você estruture apropriadamente suas BLLs e seus DALs. A BLL não deve ter conhecimento dos componentes do DAL — por exemplo, as cadeias de caracteres de conexão, declarações SQL, manipulações de arquivo como arquivos XML, etc. Da mesma maneira, sua camada de apresentação (componentes da interface do usuário) não deve ter conhecimento algum do DAL; ela reconhece apenas a BLL. (Observação: seus BLLs devem ser trocadas tão facilmente quanto o DAL se sua apresentação usar injeção de dependência para resolver as BLLs; isso é ótimo se você tiver que executar uma realocação, mas quiser afetar apenas um aplicativo.)

Agregação de eventos A comunicação entre os componentes desacoplados pode apresentar desafios. No exemplo mostrado na Figura 5, o objeto D contém uma lista suspensa que o usuário utilizará para alterar o tipo de moeda — por exemplo, de Dólar norte-americano para Euro. 

Communication Between Decoupled Objects

Figura 5 Comunicação entre objetos desacoplados

Os objetos B e F estão atrelados à moeda selecionada no momento e devem ser recalculados quando a moeda mudar. Uma solução possível seria aplicar uma bolha ao evento para A (onde A assina B, B assina C e C assina D) e, então, encapsular as informações de A para E que, por sua vez, as encapsulará para F. À medida que o aplicativo cresce, esse processo se torna mais complicado. Essa complexidade se estende aos testes, na medida em que todas as áreas afetadas têm que ser testadas quanto à regressão se declarações condicionais forem adicionadas em qualquer lugar no caminho.

Para evitar vazamentos de memória para essa solução, devemos nos assegurar de que implementamos IDIsposable em todos os objetos afetados e descartamos todas as assinaturas de eventos; isso adiciona outra camada de complexidade a ser gerenciada.

Prism A agregação de eventos é uma das muitas áreas nas quais o Prism se destaca. Com o Prism, você pode simplesmente publicar um evento em D usando uma sintaxe comparável à seguinte:

aggregator.GetEvent<MyEvent>().Publish(MyPayload)...

Os objetos B e F assinariam esse evento; portanto, após escrever apenas algumas linhas de código, você estaria concentrado na lógica de negócios e não mergulhado na infraestrutura. Um exemplo de assinatura de B e F é mostrado aqui:

[Dependency]
public ILoggerFacade Logger {get;set;}

private  IEventAggregator _eventAggregator;
[Dependency]
public  IEventAggregator EventAggregator 
{
  get { return _eventAggregator; }
  set { 
    _eventAggregator=value;
    OnEventAggregatorSet();  // Subscribe to events in this method
  }
}

E eis outro exemplo:

public  MyConstructor(IEventAggregator aggregator){
  aggregator.GetEvent<MyEvent>().Subscribe(HandleMyEvent);  
}
public void HandleMyEvent(MyEventArgs e){
  Logger.Log("HandleMyEvent is handling event in Foo", Category.Debug, Priority.None);
 // Do something useful
}

Compartilhando código e XAML

Antes dos requisitos da certificação Electronic Health Record (EHR) serem estabelecidos (tornando o custo de desenvolvimento da EHR proibitivo para pequenos escritórios), escrevi um aplicativo EHR para um pequeno grupo médico. Ele começou com um PDA com Windows Mobile e um site para gerenciar com precisão o atendimento e as cobranças de pacientes. O PDA continha toda a lógica de negócios, e o site oferecia uma interface para a equipe de cobrança. Lentamente, os recursos do PDA foram migrados para o site e a expectativa era a de que todas as regras de negócios e comportamentos seriam migrados também. Para complicar as coisas, foi pedido posteriormente que eu criasse um aplicativo de desktop para tablets e laptops e, em um ano, o escopo do projeto mudou de um PDA para todas as três plataformas. Acabei tendo que gerenciar três bases de código separadas; cada uma tinha variações específicas de plataforma, o que impedia o compartilhamento direto da lógica de negócios.

Quando o vinculador de projeto surgiu no projeto Prism e a equipe de projeto de padrões e práticas se preparou para oferecer suporte a um ambiente multiplataforma (usando os mesmos namespaces entre plataformas), embarquei imediatamente, pois fiquei muito satisfeito com as ramificações da direção que estava sendo seguida. Usando multiplataforma, o projeto EHR poderia ser feito em uma fração do tempo e a um custo mínimo para meu cliente quanto ao desenvolvimento, às atualizações e à manutenção.

Código Há muito sobre o que pensar em relação às plataformas às quais você oferecerá suporte. É importante que sua única base de código esteja na plataforma com menos suporte. Por exemplo, se você vai programar apenas nos ambientes Silverlight e de desktop, então defina seus projetos do Silverlight como fonte, e os projetos do desktop serão vinculados a eles. Se você vai oferecer suporte ao Windows Phone 7, ao Silverlight e ao desktop, então o Windows Phone 7 precisa ser a fonte.

Isso é importante, pois você não quer desperdiçar tempo escrevendo código que não será compilado em outras plataformas. Se, por exemplo, você fez o desenvolvimento na plataforma Window Phone 7, é possível ver, por meio do IntelliSense, quais recursos da estrutura estão disponíveis. Você pode escrever seu código com a certeza de que ele será compilado em outras plataformas.

Também recomendamos que você defina um padrão para a configuração “Símbolos condicionais do compilador” de seu projeto (consulte a Figura 6; observe que as áreas destacadas mostram configurações padrão).

Set Compiler Symbols for Each Platform

Figura 6 Defina símbolos do compilador para cada plataforma

Eu descobri que isso pode ser um problema, pois "SILVERLIGHT" é compartilhado com os projetos Windows Phone 7 e Silverlight; para codificar especificamente para o Silverlight 4, eu tive que fazer o seguinte:

#if SILVERLIGHT
#if !WINDOWS_PHONE
  // My Silverlight 4-specific code here 
#endif
#endif

XAML O XAML foi surpreendentemente fácil de reutilizar, particularmente entre os aplicativos de desktop e Silverlight; o truque é não ter nenhuma referência de assembly em seu XAML. Eu consegui isso criando uma classe wrapper (consulte a Figura 7, painel esquerdo superior) dentro do projeto local que torna a classe atual uma subclasse no assembly externo.

Create a Wrapper Class for the Current Project

Figura 7 Crie uma classe wrapper para o projeto atual

Observe que minha classe UserControlBase carrega programaticamente o arquivo de recurso específico de plataforma, que contém os conversores, estilos e modelos que me permitem ter o mínimo de declarações XAML que possam afetar minha habilidade de compartilhá-la.

Padrões de arquitetura

Se você colocar 10 programadores em uma sala e atribuir-lhes a mesma tarefa de desenvolvimento, provavelmente verá 10 maneiras diferentes de concluir a tarefa com sucesso. Como desenvolvedores, temos níveis variados de experiência com arquitetura e codificação que podem se refletir facilmente no código que escrevemos (tornando nossos aplicativos empresariais difíceis de seguir e manter). Os padrões de arquitetura nos fornecem uma experiência fundamental comum, o que pode fazer com que os 10 desenvolvedores saiam da sala com códigos parecidos.

O Windows Presentation Foundation (WPF), o Prism, o MEF e o Unity apresentam um ambiente de desenvolvimento diferente de qualquer outro. A adição de multiplataforma traz mais um nível de complexidade — especialmente se você usá-la bastante, minimizando o código específico de plataforma. Com a tecnologia em evolução em um mundo ágil, os padrões precisam ser constantemente atualizados para utilizar eficientemente a nova tecnologia oferecida; é inevitável que você encontre uma infinidade de combinações de padrões à medida que analisa os exemplos que essas poderosas ferramentas oferecem.

Se você não reconhecer os padrões, terá dificuldade em compreender as ferramentas, a documentação e os exemplos; pior ainda, você poderá usar essas poderosas ferramentas de uma maneira que viole o design pretendido, o que se tornará um risco ao sucesso de seu projeto. O Apêndice B na documentação do Prism oferece informações abrangentes em padrões aplicáveis. Resumirei a evolução dos padrões de apresentação na próxima seção.

Model-View-Controller (MVC) Application Model Este modelo surgiu como a solução para os problemas encontrados no MVC, mais especificamente a poluição dos objetos do domínio pela lógica de negócios e pelo estado da UI, como cor do texto, um item selecionado em uma lista, visibilidade do controle, etc. Ele também trouxe a possibilidade de atualizar a visualização diretamente (algo não permitido no MVC).

O Application Model foi inserido entre o View e o Model e continha lógica de negócios para gerenciar o comportamento, o estado e a sincronização no Model. O View seria associado ao Application Model (em vez de ao Model).

MVC Presentation Model A principal distinção entre o Presentation Model e o Application Model é sua habilidade de atualizar o View. O Presentation Model segue as diretrizes do MVC e não permite a atualização do View diretamente.

Model-View-ViewModel (MVVM) John Gossman, criador do MVVM, diz o seguinte:

“Quanto a nomes, minha opinião é a de que o padrão [MVVM] é uma versão específica do WPF do padrão Presentation Model. O modelo de apresentação (Presentation Model) é muito mais fácil de dizer e de escrever, é mais conhecido... mas, por enquanto, estou atento à terminologia do MVVM para captar a essência do WPF e evitar quaisquer conflitos de interpretação."

Model-View-Presenter (MVP) O MVP foi a solução para as limitações dos padrões MVC, Application Model e Presentation Model. Com o MVP, o desenvolvedor pode controlar o View e o ViewModel. Os desenvolvedores da plataforma Windows sempre podem usar controles inteligentes em seu trabalho, portanto, a diferença entre MVC e MVP pode não ser clara para a maioria de nós. Com um pouco de pesquisa, você descobrirá que o Windows tornou obsoleto o controlador MVC, pois o SO e os controles incluem a maior parte da funcionalidade de controle.

A necessidade de evolução a partir do MVC não se limitava ao controlador obsoleto; outros fatores foram limitações no Application Model e no Presentation Model, como já explicado.

Eis um resumo dos componentes do MVP:

Model O Model contém os dados aos quais o View será associado.

View O View mostra o conteúdo do Model por meio da associação de dados. Essa separação é importante devido ao View poder ser compartilhado com vários Presenters. (Observação: em 2006, Martin Fowler dividiu o padrão MVP em dois padrões distintos: Supervising Controller e Passive View. A principal diferença entre os dois está na associação de dados; se a associação de dados for usada, então estamos falando de Supervising Controller [seguindo as responsabilidades resumidas anteriormente]. Se não houver associação de dados, estamos falando de Passive View e as responsabilidades mudam; torna-se responsabilidade unicamente do Presenter manter o View sincronizado com o Model.)

Presenter O Presenter tem conhecimento tanto do View quanto do Model, com a responsabilidade de manipular a lógica de negócios e preencher o Model.

Model-View-Presenter, ViewModel (MVPVM) Este padrão (sem nome) foi encontrado em um trecho anterior do projeto Prism; ele combina o poder do MVP e do MVVM:

// Load the view into the MainRegion 
  // after the presenter resolves it
  RegionViewRegistry.RegisterViewWithRegion("MainRegion", () => 
    presenter.View);

Esta simples linha de código, juntamente com lições aprendidas com a equipe de padrões e práticas ao usar seus projetos Prism, Unity, Smart Client Software Factory (SCSF) e Web Client Software Factory (WCSF), seria usada para criar o padrão que chamei apropriadamente de MVPVM. Com esse padrão, o Presenter é responsável por resolver (criar uma instância) o ViewModel, o View e os componentes de BLL necessários. O Presenter, então, faz as chamadas necessárias aos métodos BLL aplicáveis (consulte a Figura 8) para preencher o ViewModel com dados do View a ser exibido.

Model-View-Presenter, ViewModel  (MVPVM) and Associated Components

Figura 8 Model-View-Presenter, ViewModel (MVPVM) e componentes associados

Como a lógica de negócios reside no Presenter, o ViewModel pode ser facilmente reutilizado por outros Presenters. Além disso, o Presenter pode atualizar o View diretamente para eliminar lógica de associação complexa (se aplicável), especialmente quando uma referência de controle é necessária. Sendo assim, o MVPVM resolve (sem trocadilhos) todas as limitações do Application Model, do Presentation Model e do MVVM (conforme resumido por nossos renomados arquitetos) para nosso ambiente do Prism e de injeção de dependência multiplataforma.

Você encontrará a linha de código anterior no SecurityModel de nosso projeto de código aberto Password Manager, em PasswordMgr.CodePlex.com. Esse projeto multiplataforma apresenta aplicativos de desktop, do Silverlight e do Windows Phone 7 compartilhando uma única base de código, com aplicativos de desktop e do Silverlight compartilhando o mesmo XAML.

(Observação: No momento em que este artigo foi escrito, não havia suporte oficial para o contêiner de injeção de dependência na plataforma Windows Phone 7. Para este projeto, baixei o ContainerModel do projeto do Windows Mobile 6.5 [mobile.codeplex.com], implementei a interface IUnityContainer[do projeto para Unity emunity.codeplex.com], fiz vários testes de unidade do Unity e executei TDD até passar em todos os testes. Com o contêiner de injeção de dependência recém-criado, que se parecia com o Unity, consegui portar o projeto do Prism — esse projeto do Password Manager tinha mais de 800 testes de unidade e era compilado sem erros, avisos e mensagens.)

Model O DAL terá total responsabilidade pelos objetos Model persistentes. Além disso, ele tem a responsabilidade de transferir os objetos Model persistentes aos objetos do domínio (entidades que representam o modelo dentro do escopo de todas as camadas do aplicativo empresarial). (Observação: A BLL não tem conhecimento da camada de apresentação ou do Model; ela apenas se comunica com o DAL por meio de uma interface.)

View O View observa o ViewModel (associação de dados) e mostra os dados no ViewModel conforme aplicável. Um View tem apenas um ViewModel; entretanto, o ViewModel pode ser compartilhado com diversos Views.

Presenter O Presenter é responsável por criar uma instância do View e do ViewModel, definir o contexto de dados do View, ligar eventos e manipular a lógica de negócios de quaisquer eventos e comportamentos (cliques do mouse e de botões, seleções de menu, etc.).

O Presenter usará BLLs (compartilhadas) para manipular a lógica de negócios e executar a criação, leitura, atualização e exclusão (CRUD) de operações nos dados do modelo persistente. (Observação: as BLLs passam facilmente pelo teste de unidade e podem substituídas sem dificuldade por meio da injeção de dependência.)

O Presenter compartilha a habilidade do MVP de modificar diretamente o View, seus controles e o ViewModel.

ViewModel O ViewModel pode ser reutilizado por vários Views, de modo que pode ser sempre projetado visando o compartilhamento.

O ViewModel pode se comunicar com o Presenter usando a agregação de eventos (preferencialmente) ou por meio de interfaces (para funcionalidade genérica). Geralmente, isso pode ser manipulado por uma classe base do ViewModel (comunicando-se com a classe base do Presenter). Essa comunicação é necessária porque o Presenter manipula toda a lógica de negócios, mas o View terá seus comandos e eventos associados ao ViewModel; esses eventos precisam ser propagados para o Presenter de uma maneira levemente acoplada para processamento.

Poder e versatilidade

Com esses fundamentos básicos compreendidos, o segmento de código mostrado na Figura 9 não deve parecer tão estranho para você agora.

Module Registrations

Figura 9 Registros de módulo

O poder e a versatilidade das ferramentas que a equipe de padrões e práticas oferece devem ser evidentes, revelando um ROI significativo. Eles eliminam a complexidade da infraestrutura, permitindo que você crie aplicativos levemente acoplados, escaláveis e extensíveis — aplicativos que podem compartilhar a mesma base de código, de modo que você possa realizar mais trabalho com menos recursos de uma maneira confiável e estável.

A utilização eficiente de camadas (camadas de apresentação, BLLs e DALs) oferece uma clara separação das preocupações, permitindo reutilizar seus componentes entre diversos módulos e aplicativos. Isso reduz os custos de testes e a necessidade de novo desenvolvimento, atualizações e manutenção.

E, o mais importante, você poderá criar equipes ágeis e de alta velocidade que podem se adaptar a um mundo em constante transformação, utilizando a experiência e o conhecimento do domínio para que concentrem seus talentos na lógica de negócios (não na infraestrutura) em uma única base de código, permitindo que construam aplicativos que funcionarão nas plataformas Windows Phone 7, da Web, do tablet ou de desktops.

Bill Kratochvil, um prestador de serviços independente, é tecnólogo e arquiteto renomado de uma equipe de desenvolvedores de elite trabalhando em um projeto confidencial para uma empresa líder no setor médico. Sua própria empresa, a Global Webnet LLC, está sediada em Amarillo, Texas.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Christina Helton e David Kean