Implementação da Lógica de Projeto - Tecnologia
Pular para o conteúdo

Implementação da Lógica de Projeto

  • por

Anúncios

Filosofias de Abordagem de Implementação

Abordagem Cachoeira

A abordagem em cascata para implementar um aplicativo requer que um designer consulte um ou mais representantes da organização do usuário final e anote todas as especificações do aplicativo. Normalmente, as especificações vêm em um conjunto de documentos funcionais ou casos de uso, escritos de forma que o usuário final possa ler e entender facilmente os documentos.

O usuário final assina esses documentos e os documentos são então recolhidos pela equipe de design técnico que projeta o aplicativo, criando vários artefatos, como diagramas de modelo de classe, diagramas de estado, diagramas de atividade e modelos de dados. O objetivo desta fase é escrever tudo com tantos detalhes que um desenvolvedor não terá problemas para criar o código necessário. Há uma transferência formal do design para a equipe de desenvolvimento e para a equipe de teste. Após a entrega, a equipe de desenvolvimento começa a codificar e a equipe de teste usa o design técnico em combinação com os casos de uso para criar casos de teste e cenários de teste.

Depois que a equipe de desenvolvimento termina de codificar, o código é entregue à equipe de teste. A equipe de teste realiza os testes que projetou com base nos requisitos e no projeto detalhado. Qualquer problema será corrigido pela equipe de desenvolvimento. Uma vez concluído o processo de teste e correção, o aplicativo é entregue ao usuário final para um teste de aceitação. O usuário final realiza uma verificação final para ver se o aplicativo está em conformidade com os requisitos iniciais. Se aprovado, ele aprova o produto acabado e o projeto é concluído. Depois que a equipe de desenvolvimento termina de codificar, o código é entregue à equipe de teste.

A equipe de teste realiza os testes que projetou com base nos requisitos e no projeto detalhado. Qualquer problema será corrigido pela equipe de desenvolvimento. Uma vez concluído o processo de teste e correção, o aplicativo é entregue ao usuário final para um teste de aceitação. O usuário final realiza uma verificação final para ver se o aplicativo está em conformidade com os requisitos iniciais. Se aprovado, ele aprova o produto acabado e o projeto é concluído. Depois que a equipe de desenvolvimento termina de codificar, o código é entregue à equipe de teste. A equipe de teste realiza os testes que projetou com base nos requisitos e no projeto detalhado.

 Qualquer problema será corrigido pela equipe de desenvolvimento. Uma vez concluído o processo de teste e correção, o aplicativo é entregue ao usuário final para um teste de aceitação. O usuário final realiza uma verificação final para ver se o aplicativo está em conformidade com os requisitos iniciais. Se aprovado, ele aprova o produto acabado e o projeto é concluído.

O usuário final realiza uma verificação final para ver se o aplicativo está em conformidade com os requisitos iniciais. Se aprovado, ele aprova o produto acabado e o projeto é concluído. O usuário final realiza uma verificação final para ver se o aplicativo está em conformidade com os requisitos iniciais. Se aprovado, ele aprova o produto acabado e o projeto é concluído.

Um projeto pode ter mais ou menos fases ao usar a abordagem em cascata, mas a principal característica é um início e um fim muito formais de cada fase, com entregas muito formais.

A vantagem da abordagem em cascata é que a responsabilidade da equipe responsável por cada fase é maior. Fica claro o que eles precisam entregar, quando precisam entregar e para quem devem entregar. Muitas vezes, a equipe de desenvolvimento não precisará interagir com o usuário. Isso pode ser muito útil ao terceirizar o desenvolvimento para um país diferente.

A principal desvantagem da abordagem em cascata é que, em um ambiente em que tudo é organizado de maneira bastante formal, a flexibilidade para responder às mudanças diminui. Mesmo a mudança precisa ser organizada. Muito poucas empresas parecem fazer isso de forma eficaz, muitas vezes resultando em um aumento significativo nos custos indiretos. Para gerenciar os custos de um projeto, algumas empresas chegam a adiar qualquer alteração nos requisitos até a entrega inicial do aplicativo, entregando efetivamente um aplicativo que não atende às necessidades do usuário final.

Desenvolvimento ágil

Muitos projetos de desenvolvimento de software de longa duração ultrapassaram seus orçamentos e não entregaram o produto no prazo. A premissa da filosofia ágil de desenvolvimento de software é minimizar o risco desenvolvendo software em caixas de tempo curtas, chamadas de iterações, que normalmente duram de uma a quatro semanas. Cada iteração é como um projeto de software em miniatura próprio e inclui todas as tarefas necessárias para liberar o incremento da nova funcionalidade: planejamento, análise de requisitos, design, codificação, teste e documentação. Embora uma iteração possa não adicionar funcionalidade suficiente para garantir o lançamento do produto, um projeto de software ágil pretende ser capaz de liberar um novo software ao final de cada iteração. Ao final de cada iteração, a equipe reavalia as prioridades do projeto.

O objetivo do desenvolvimento ágil de software é atingir a satisfação do cliente por meio da entrega rápida e contínua de software útil; visando sempre construir o que o cliente precisa; acolher, em vez de se opor, mudanças tardias nos requisitos; adaptar-se regularmente a circunstâncias em mudança; ter uma cooperação próxima e diária entre empresários e desenvolvedores, na qual a conversa face a face é a melhor forma de comunicação.

A principal vantagem do desenvolvimento ágil de software é a flexibilidade em lidar com mudanças, sempre visando entregar de acordo com as necessidades do negócio. A desvantagem, é claro, é um aumento na complexidade do gerenciamento de escopo, planejamento e orçamento. Outro risco comum é a atenção limitada à documentação (técnica).

Desenvolvimento Incremental

O desenvolvimento incremental de software é uma mistura de desenvolvimento ágil e em cascata. Um aplicativo é projetado, implementado e testado de forma incremental para que cada incremento possa ser entregue ao usuário final. O projeto não é concluído até que o último incremento seja concluído. Ele visa encurtar a cascata definindo incrementos intermediários e usando algumas das vantagens do desenvolvimento ágil. Com base no feedback recebido em um incremento anterior, os ajustes podem ser feitos ao entregar o próximo incremento. O próximo incremento pode consistir em um novo código, bem como em modificações do código fornecido anteriormente.

A vantagem é que as formalidades permanecem em vigor, mas o gerenciamento de mudanças se torna mais fácil. O custo de testar e implantar um aplicativo várias vezes será maior do que fazer isso apenas uma vez.

Controle de Fluxo do Programa

Escolher uma abordagem para o controle de fluxo do programa é uma tarefa bastante arquitetônica. O objetivo é criar um projeto de seu aplicativo no qual, uma vez que você comece a adicionar funcionalidade e código, tudo pareça ter seu próprio lugar. Se você já revisou ou escreveu um código de alta qualidade, você entende este princípio

Código Organizador

A primeira etapa ao projetar o fluxo do programa é organizar o código, estabelecendo um conjunto de regras para ajudar a criar um plano, ou esboço, do aplicativo. Manutenção, depuração e correção de erros ocorrerão com mais facilidade porque o código está localizado em um local lógico. Depois de fazer o trabalho de base, você pode escolher uma abordagem para implementar a lógica de seu aplicativo.

Os padrões de projeto devem desempenhar um papel importante no projeto do controle de fluxo do programa. Ao longo dos anos, muito código foi escrito e muitas soluções foram projetadas para problemas recorrentes. Essas soluções são estabelecidas em padrões de projeto. A aplicação de um padrão de design a um problema comum de design de software ajudará você a criar soluções facilmente reconhecíveis e que podem ser implementadas por seus colegas. Problemas exclusivos ainda exigirão soluções exclusivas, mas você pode usar padrões de projeto para orientá-lo na solução deles.

Criando o Projeto

Camadas

O primeiro passo é considerar as camadas lógicas. Observe que as camadas não são iguais às camadas, muitas vezes confundidas ou até mesmo consideradas iguais.

Camadas versus camadas

As camadas dizem respeito à criação de limites em seu código. A camada superior pode ter referências ao código nas camadas inferiores, mas uma camada nunca pode ter uma referência ao código em uma camada superior. As camadas dizem respeito à distribuição física de camadas em vários computadores. Por exemplo, em um aplicativo de três camadas, a interface do usuário é projetada para ser executada em um computador desktop, a lógica do aplicativo é projetada para ser executada em um servidor de aplicativos e o banco de dados é executado em um servidor de banco de dados dedicado e o código em cada camada pode consistir em várias camadas.

Figura 8-1: Organização básica de três camadas

Camadas refere-se a níveis de abstração. As camadas mostradas na Figura 8-1 são verdadeiras para a maioria das aplicações. Esses níveis também são referidos como as três camadas principais e podem ter vários outros nomes. Como regra, o código na camada de apresentação pode chamar serviços na camada lógica do aplicativo, mas a camada lógica do aplicativo não deve chamar o método na camada de apresentação. A camada de apresentação nunca deve chamar diretamente a camada de acesso a dados, pois isso ignoraria as responsabilidades implementadas pela camada de lógica do aplicativo. A camada de acesso a dados nunca deve chamar a camada de lógica do aplicativo.

As camadas são apenas uma abstração e provavelmente a maneira mais fácil de implementar as camadas é criar pastas em seu projeto e adicionar código à pasta apropriada. Uma abordagem mais útil seria colocar cada camada em um projeto separado, criando assim montagens separadas. A vantagem de colocar a lógica do aplicativo em um assembly de biblioteca é que isso permitirá que você crie testes de unidade, usando o Microsoft Visual Studio ou o NUnit, para testar a lógica. Também cria flexibilidade na escolha de onde implantar cada camada.

Camadas Físicas

Em um aplicativo corporativo, você deve esperar ter vários clientes para a mesma lógica. Na verdade, o que torna um aplicativo um aplicativo corporativo é que ele será implantado em três camadas: cliente, servidor de aplicativos e servidor de banco de dados. O aplicativo Microsoft Office Access criado pelo departamento de vendas de sua empresa, embora muito importante para o departamento de vendas, não constitui um aplicativo corporativo.

Observe que a lógica do aplicativo e as camadas de acesso a dados geralmente são implantadas juntas no servidor de aplicativos. Parte da elaboração do projeto é escolher se deseja acessar o servidor de aplicativos usando serviços remotos .NET ou da Web. Independentemente da escolha, você adicionará algum código para acessar facilmente os serviços remotos na camada de apresentação. Se você estiver usando serviços da Web para acessar os serviços em seu servidor de aplicativos, o Visual Studio .NET fará o trabalho para você e gerará o código de proxy, fornecendo automaticamente uma implementação do padrão de proxy remoto.

Adicionando Padrões a Camadas

As três camadas básicas fornecem uma visão geral de alto nível. Vamos adicionar alguns padrões estruturais para criar uma arquitetura corporativa robusta. O resultado é mostrado na Figura 8-2 .

Concentre-se na camada de lógica do aplicativo. A Figura 8-2 mostra que o acesso à lógica do aplicativo está usando o padrão de fachada. Uma fachada é um objeto que fornece uma interface simplificada para um corpo maior de código, como uma biblioteca de classes. Uma fachada pode reduzir as dependências do código externo no funcionamento interno de uma biblioteca porque a maioria dos códigos usa a fachada, permitindo assim mais flexibilidade no desenvolvimento do sistema. Para fazer isso, a fachada fornecerá uma interface de granulação grossa para uma coleção de objetos de granulação fina.

Fluxo de decisão

O controle de fluxo do programa, também conhecido como fluxo de decisão, diz respeito a como você projeta os serviços em sua camada lógica de aplicativo ou, como você viu no parágrafo anterior, como você projeta os métodos em sua fachada.

Existem duas abordagens para organizar seus serviços:

  • Orientado para a ação
  • Orientado pelo estado

Abordagem orientada para a ação

Ao organizar os serviços com base nas ações do usuário, você estará implementando a lógica do aplicativo oferecendo serviços, cada um dos quais lida com uma solicitação específica da camada de apresentação. Isso também é conhecido como padrão de script de transação. Essa abordagem é popular porque é simples e parece muito natural. Exemplos de métodos que seguem essa abordagem são BookStoreService.AddNewOrder(Order order) e BookStoreService.CancelOrder(int orderId).

A lógica necessária para executar a ação é implementada de forma bastante sequencial dentro do método, tornando-a muito legível, mas também mais difícil de reutilizar o código. O uso de padrões de design adicionais, como o padrão de módulo de tabela, pode ajudar a aumentar a capacidade de reutilização.

Abordagem orientada pelo estado

Também é possível implementar o fluxo de decisão do aplicativo de uma maneira muito mais orientada ao estado. Os serviços oferecidos pelo servidor de aplicativos são de natureza mais genérica, por exemplo, BookStoreService.SaveOrder(Order order). Este método examinará o estado do pedido e decidirá se deseja adicionar um novo pedido ou cancelar um pedido existente.

Projetos de estrutura de dados

Você deve fazer várias escolhas ao projetar suas estruturas de dados. A primeira escolha é o mecanismo de armazenamento de dados, a segunda é o uso pretendido dos dados e a terceira são os requisitos de versão. Existem três maneiras de olhar para projetos de estrutura de dados:

  • Os serviços oferecem dados; data é um reflexo do banco de dados relacional.
  • Os dados devem ser mapeados para objetos e os serviços oferecem acesso a objetos.
  • Os dados oferecidos pelos serviços devem ser baseados em esquema.

A escolha de um dos três como base para sua estrutura de fluxo de dados deve ser feita em um estágio inicial do processo de design. Muitas empresas têm uma diretriz da empresa que impõe uma das três opções em todos os projetos, mas, quando possível, você deve reavaliar as opções para cada projeto, escolhendo a abordagem ideal para o projeto em questão.

Escolhendo um mecanismo de armazenamento de dados

Ao projetar seu aplicativo, sem dúvida, você terá que projetar algum tipo de armazenamento de dados. Os seguintes armazenamentos e formas de armazenamento de dados estão disponíveis:

  • Registro
  • arquivo app.config
  • arquivos XML
  • arquivos de texto simples
  • Base de dados
  • Enfileiramento de mensagens

Cada loja tem suas próprias características únicas e pode ser adequada a requisitos específicos.

Projetando o fluxo de dados

Fluxo de dados usando ADO.NET

Ao implementar serviços centrados em dados na camada de lógica do aplicativo, você projetará seu fluxo de dados usando ADO.NET. A biblioteca de classes .NET Framework oferece uma extensa interface de programação de aplicativos (API) para manipulação de dados em código gerenciado. Referida como ADO.NET, a API pode ser encontrada no namespace System.Data. A separação completa de suportes de dados e armazenamentos de dados é um importante recurso de design do ADO.NET. Classes como DataSet, DataTable e DataRow são projetadas para armazenar dados, mas não retêm nenhum conhecimento de onde os dados vieram. Eles são considerados agnósticos quanto à fonte de dados. Um conjunto separado de classes, como SqlConnection, SqlDataAdapter e SqlCommand, cuida da conexão com uma fonte de dados, da recuperação de dados e do preenchimento de DataSet, DataTable e DataRow. Essas classes estão localizadas em sub-namespaces como System.Data.Sql, System.Data.OleDB, System.Data.Oracle e assim por diante. Dependendo de qual fonte de dados você deseja se conectar, você pode usar as classes no namespace correto e, dependendo da abrangência do produto que está usando, você descobrirá que essas classes oferecem mais ou menos funcionalidade.

Como o DataSet não está conectado à fonte de dados, ele pode ser usado com bastante sucesso para gerenciar o fluxo de dados em um aplicativo. A Figura 8-5 mostra o fluxo de dados ao fazer isso.

Vamos dar uma olhada neste projeto e imaginar que alguém se conectou à sua livraria e encomendou três livros. A camada de apresentação gerenciou o estado do carrinho de compras. O cliente está pronto para fazer o pedido e forneceu todos os dados necessários. Ele escolhe enviar ordem. A página da Web transforma todos os dados em um DataSet contendo duas DataTables, uma para a ordem e outra para ordem; insere um DataRow para o pedido; e insere três DataRows para as linhas do pedido. A página da Web então exibe esses dados de volta para o usuário mais uma vez, controles de vinculação de dados em relação ao DataSet e pergunta Tem certeza? O usuário confirma o pedido e o mesmo é submetido à camada lógica da aplicação. A camada de lógica do aplicativo verifica o DataSet para ver se todos os campos obrigatórios têm um valor e executa uma verificação para ver se o usuário tem mais de US$ 1.000. 00 em contas pendentes. Se tudo estiver certo, o DataSet é repassado para a camada de acesso a dados, que se conecta ao banco de dados e gera instruções de inserção a partir das informações do DataSet.

Usar o DataSet dessa maneira é uma maneira rápida e eficiente de criar um aplicativo e usar o poder da Framework Class Library e a capacidade do ASP.NET de vincular dados a vários controles, como o GridView em relação a um DataSet. Em vez de usar objetos DataSet simples, você pode usar objetos Typed DataSet e melhorar a experiência de codificação ao implementar o código na camada de apresentação, bem como na camada de lógica do aplicativo. A vantagem desta abordagem é também a desvantagem da abordagem. Pequenas mudanças no modelo de dados não necessariamente levam a que muitos métodos tenham que mudar suas assinaturas. Então, em termos de manutenção, isso funciona muito bem. Se você lembrar que a camada de apresentação não é necessariamente uma interface de usuário, ela também pode ser um serviço da Web. E se você modificar a definição do DataSet, talvez porque você esteja renomeando um campo no banco de dados, então você está modificando o contrato que subscreve o serviço da Web. Como você pode imaginar, isso pode levar a alguns problemas significativos. Este cenário funciona bem se a camada de apresentação for apenas uma interface de usuário, mas para interfaces para sistemas ou componentes externos, você desejará ocultar o funcionamento interno de seu aplicativo e transformar dados em algo diferente de um clone direto de seu modelo de dados e você desejará criar Objetos de Transferência de Dados (DTOs).

Fluxo de dados usando mapeamento relacional de objeto

O fluxo de dados usando ADO.NET é uma abordagem muito centrada em dados para gerenciar o fluxo de dados. Dados e lógica são discretos. O outro lado do espectro é adotar uma abordagem mais orientada a objetos. Aqui, as classes são criadas para agrupar dados e comportamento. O objetivo é definir classes que imitem os dados e o comportamento encontrados no domínio de negócios para o qual o aplicativo foi criado. O resultado geralmente é referido como um objeto de negócios. A coleção de objetos de negócios que compõem o aplicativo é chamada de modelo de domínio. Alguns desenvolvedores afirmam que um modelo de domínio rico é melhor para projetar uma lógica mais complexa. É difícil provar ou refutar tal afirmação. Apenas saiba que você tem uma escolha e cabe a você fazê-la.

A Figura 8-6 mostra um fluxo de dados semelhante à Figura 8-5 , exceto que agora você adicionou a camada de mapeamento relacional de objeto e substituiu os objetos DataSet por diferentes suportes de dados.

Agora faça o mesmo passo a passo de antes; imagine que alguém se conectou à sua livraria e encomendou três livros. A camada de apresentação gerenciou o estado do carrinho de compras. O cliente está pronto para fazer o pedido e forneceu todos os dados necessários. Ele escolhe enviar ordem. A página da Web transforma todos os dados em um DTO, mantendo dados para um pedido e com três linhas de pedido, criando os objetos conforme necessário. A página da Web exibe esses dados de volta ao usuário mais uma vez, controles de vinculação de dados em relação ao DTO usando o ObjectDataSource no ASP.NET 2.0 e pergunta Tem certeza? O usuário confirma a escolha e o DTO é submetido à camada lógica da aplicação. A camada de lógica do aplicativo transforma o DTO em um objeto de negócios do tipo Order com uma propriedade para conter três objetos OrderLine. O método Ordem. Validate() é chamado para validar o pedido e verificar se todos os campos obrigatórios possuem um valor, e é feita uma verificação para identificar se o usuário possui mais de R$ 1.000,00 em boletos pendentes. Para fazer isso, o pedido chamará Order.Customer.GetOutstandingBills(). Se tudo estiver bem, o método Order.Save() é chamado. O pedido se submeterá à camada de mapeamento relacional do objeto, onde o pedido e as linhas do pedido são mapeados para um DataTable em um DataSet, e o DataSet é passado para a camada de acesso a dados, que se conecta ao banco de dados e gera instruções de inserção a partir das informações no DataSet. Há, é claro, muitas maneiras pelas quais o mapeamento relacional de objeto pode ocorrer, mas nem todas incluirão a transformação em um DataSet. Alguns criarão as instruções de inserção diretamente, mas ainda usarão a camada de acesso a dados para executar essa instrução.

Como você pode ver, algumas transformações ocorrem. O uso de DTOs é necessário porque um objeto de negócios implementa o comportamento e o comportamento está sujeito a mudanças. Para minimizar o impacto dessas alterações na camada de apresentação, você precisa transformar os dados, retirá-los do objeto de negócios e colocá-los em um objeto de transferência de dados. Em Java, o objeto de transferência de dados é normalmente chamado de objeto de valor.

Uma grande vantagem de trabalhar com objetos de negócios é que isso realmente ajuda a organizar seu código. Se você olhar para trás em um pedaço de lógica complexa, geralmente é muito legível porque há muito pouco código de encanamento. A desvantagem é que a maioria dos armazenamentos de dados ainda é relacional e o mapeamento de objetos de negócios para dados relacionais pode se tornar bastante complexo.

Serviços baseados em esquema

Você acabou de ver dois opostos quando se trata de gerenciar o fluxo de dados. Muitas variações são possíveis. Um comum é a variante na qual um conjunto de dados é usado como suporte básico de dados da interface do usuário para o armazenamento de dados, mas esquemas separados (DTOs) são usados ​​para serviços da Web chamados de outros sistemas. A camada de aplicação transforma os dados relacionais em um esquema predefinido. A principal vantagem disso é que qualquer aplicação que referencia o serviço não depende de nenhum tipo de implementação interna do componente. Isso permite mais flexibilidade no controle de versão, compatibilidade com versões anteriores de interfaces e a capacidade de alterar a implementação do componente sem alterar a interface do serviço.

Obviamente, você pode usar objetos de negócios no aplicativo da Web e ignorar a transformação DTO, mas isso geralmente funciona bem apenas se a lógica do aplicativo for implementada junto com o aplicativo da Web. Lembre-se que para chamar Order.Save(), você precisará de uma conexão com o banco de dados. Se isso é desejável, depende de você e, provavelmente, de seu diretor de segurança.