Design Patterns

Olá,

Não sei se sabem, mas Design Patterns são realmente um tema do qual eu gosto muito de falar e do qual sou extremamente fascinado. Por isso gostaria de começar uma série de artigos abordando o tema. Espero que aproveitem!

Design Patterns…

“Os Design Patterns não exigem nenhum recurso incomum da linguagem, nem truques de programação surpreendentes para impressionar seus amigos e gerentes.” (GoF, 1995, prefácio vii)

Um Design Pattern (Padrão de Projeto) é uma solução para um problema recorrente de modelagem de um software orientado a objetos. É composto por descrições de objetos e classes comunicantes que precisam ser personalizadas para resolução de um problema geral de projeto dentro de um contexto particular. (GoF, 1995, p. 20) (Freeman, 2005, p. 47/460)clip_image002

Leia mais »

Entity Framework open source, e agora? Como eu faço?

Agora o Entity Framework é open source. E o que podemos esperar disso?

O maior significado desta atitude é que o time de Entity Framework esta realmente interessado e esperando por nossas contribuições. O EF não é o primeiro produto da Microsoft a tornar-se open source. O ASP.Net MVC 4, ASP.Net Web API e Razor são projetos que também tornaram-se open source no último semestre.

O que significa ser open source? Open source é uma ideologia/filosofia que promove a distribuição livre e o acesso ao código fonte de um software/produto/projeto. O modelo open source também prevê a colaboração voluntária, a fim de melhorar o software disponibilizado, por meio do trabalho e do conhecimento de seus colaboradores voluntários.

ado_net_entity_framework

Leia mais »

Microsoft Virtual Academy – Entity Framework

Esta semana saiu a publicação de mais um Microsoft Virtual Academy (MVA), e agora é a nossa vez! Este novo MVA é sobre Entity Framework (http://www.microsoftvirtualacademy.com/tracks/fundamentos-do-entity-framework-4).

Neste MVA discutimos sobre:
– O que é o Entity Framework
– Bancos de dados e ORM
– Leitura de dados do banco de dados
– Inclusão, atualização e exclusão de dados

Neste trabalho, Carlos dos Santos, Renato Haddad e eu gravamos uma sequência de vídeos e escrevemos alguns artigos explicando o funcionamento do Entity Framework.

Leia mais »

Microsoft Virtual Academy

Olá pessoal,

Essa semana a Microsoft lançou o MVA (Microsoft Virtual Academy), esse projeto tem como objetivo ajudar no desenvolvimento da sua carreira Microsoft.
É uma plataforma de aprendizagem na nuvem, que disponibiliza:
•    Formação completamente de graça.
•    Recursos disponíveis on-line, vídeo on demand e artigos de especialistas.
•    Três tipos de conteúdo, cursos , carreiras e especializações.
•    Documentos especializados, laboratórios on-line e Webcasts.
•    Categorias de Reconhecimento: Bronze, Silver, Gold, Platinum.
•    Download de documentos para conclusão de cada conteúdo e uma transcrição com o resumo da atividade de cada usuário no MVA.

As categorias existentes são: Clustering, Hyper-V, IaaS, Office 365, PaaS, Private Cloud, Public Cloud, SaaS Security, SQL Azure, System Center, Virtual Machine,  VDI, Virtualization, VMware, Windows Azure, Windows Client e Windows Phone.Leia mais »

Construindo sua camada de acesso a dados com o Entity Framework 4.1

O Entity Framework 4.1(EF41) Code First veio para ajudar os desenvolvedores no processo de construção da camada de acesso a dados de suas aplicações. Ao contrário dos demais modelos do Entity Framework, o modelo Code First tem por objetivo criar o banco de dados seguindo como base a estrutura de nossas classes – os demais modelos, conhecidos como Table First, baseavam a criação das classes no modelo existente em nosso banco de dados. A vantagem da utilização do Code First é a possibilidade de criar um modelo de classes muito mais próximo a nossa necessidade, ao contrário das abordagens anteriores que produziam um modelo de classe “adaptado” de nossa estrutura de banco de dados.

Neste exemplo vamos discutir os modos de implementação de diferentes modelos de relacionamentos (e.g. um-para-muito, muitos-para-muitos, um-para-um) utilizando o ADO.Net Entity Framework 4.1. Além disso, quero mostrar algumas novas features e dar algumas dicas de como nos adequar ao Entity Framework 4.1.

Vamos começar! Alegre

Obs.: Para fazer download do código-fonte acesse este link: http://code.msdn.microsoft.com/Construindo-sua-camada-de-de659425.

1 – Nosso projeto de teste

Para este teste criaremos um cadastro de Clientes, Fabricantes, Produtos e Ordens de Compra. Neste modelo um cliente pode efetuar diversas ordens de compras, sendo que cada comprar pode conter um ou mais produtos, onde cada produto pode estar atrelado a uma ou mais ordens de compra. Além disso, um produto obrigatoriamente contém um fabricante. Nosso diagrama de classes será o seguinte:

diagrama

2 – Camadas da aplicação

Para este exemplo adotei os design patterns MVC e DAO. Os projetos estão dispostos como a imagem a seguir:

Projects

Commerce.Controler: corresponde a camada de controle de nossa aplicação.

Commerce.Entity: possui todas as entidades lógicas de nossa aplicação, além das interfaces que devem ser implementadas pelas demais camadas.

Commerce.Data: responsável pela funcionalidade de armazenamento das informações, esta camada engloba todo o uso do Entity Framework 4.1, diminuindo a dependência do projeto a um tecnologia. Isso permite a fácil manutenção e alteração da tecnologia, sem gerar impactos globais por toda a aplicação.

Commerce.Console: camada de apresentação e consumo dos recursos.

3 – Estratégia de criação da base de dados

Para definir a estratégia de criação do banco de dados fazemos uso de inicializadores.A estratégia default é a DropCreateDatabaseIfModelChanges, que apaga o banco de dados e o recria, além dessa estratégia ainda existem outras duas, sendo elas: DropCreateDatabaseAlways e CreateDatabaseIfNotExists. O time de produto do ADO.Net trabalha hoje em um projeto chamado Code First Migration, que trata do processo de adequação do modelo do banco de dados com as atualizações de suas entidades, sem que seja necessário apagar e recriar o banco de dados. Para fazer uso dos inicializadores de bancos de dados crie em seu DataContext um construtor que defina a estratégia de criação da base de dados como a seguir:

SetInitializer

4 – Remoção de convenções do Entity Framework 4.1

Para efetuar o mapeamento automático de nossas tabelas, o EF41 adota algumas convenções de nomenclatura, tipos de dados, e outros recursos. Para adicionar ou remover convenções devemos sobrescrever o método OnModelCreating de nosso DataContext. Em nosso exemplo removerei duas convenções: IncludeMetadataConvention, que evita a criação da tabela EdmMetada, que é uma tabela que contém um código uma única linha com um código hash utiliza para verificar se o modelo de nosso código é o mesmo do modelo de nosso banco de dados (mais informações aqui: http://blog.oneunicorn.com/2011/04/08/code-first-what-is-that-edmmetadata-table/); e PluralizingTableNameConvention, que é um atributo que evita que a nome das tabelas seja pluralizado, isto é, se você possui uma entidade chamada Carro, a tabela criada automaticamente no banco de dados se chamará Carro, e não Carros como a convenção do EF41 faz.

Conventions

5 – Tipos complexos

É bastante comum em nossas aplicações a necessidade de utilizarmos atributos que apenas servem como “agrupadores” de dados, e que na verdade não deve ser mapeamos em uma única tabela dedicada a eles. Podemos adotar como exemplo um tipo de dados Endereço. Uma classe chamada Endereço é bastante importante para agrupar informações de localidade, mas não possui características que exijam mapeamento para uma tabela dedicada exclusivamente para isso. Diante deste cenário devemos fazer uso do atributo ComplexType. Este atributo quando utilizado indica que nossa classe é um tipo complexo, que não deverá ser persistido em uma tabela própria, e que estará vinculado a atributo de alguma classe. Podemos indicar que uma classe é um tipo complexo de duas maneiras, sendo elas:

2.1 – No corpo da classe, indicando através do atributo ComplexType:

ComplexType01

2.2 – Indicando o tipo complexo em nosso DataContext, dentro do método OnModelCreating:

ComplexType02

Ultimamente tenho pensado que é mais interessante configurar o mapeamento de nossas classes dentro do DataContext do que em nossas classes através da utilização de atributos. Acredito que essa é a melhor forma, pois nosso projeto de entidades ficará livre de mais dependências, necessitando apenas de recursos nativos do Framework .

6 – Entidade base para persistência de dados em fontes de dados

É interessante, ao implementarmos nossas entidades, a criação de uma entidade base que defina atributos obrigatórios para todas as entidades. Neste exemplo criei uma entidade chamada DataEntity que contém três atributos: Id, atributo do tipo inteiro que servirá como chave primária de nossas entidades na base de dados; GlobalId, atributo do tipo GUID que fornecerá um identificador global a nossos registros dentro da base de dados; e Created, atributo do tipo DateTime que informará a data de criação de nossas entidades.

dataEntity

A utilização dessa classe como entidade base exige duas implementações em nossas entidades:

1 – Herança

Herança

2 – Invoque ao construtor da classe base em nossas entidades

construtor

7 – Interface como contrato para os repositórios

Para implementação dos repositórios criei uma interface com um conjunto de métodos obrigatórios que se espera de um repositório.

IRepository

Nessa interface temos as assinaturas:

void Save(T target): este método deve ser responsável pela inclusão e atualização dos dados na base de dados. Uma vez executado deve garantir que os dados serão inclusos ou atualizados conforme a entidade passada por parâmetro.

void Delete(T target): método de exclusão de registros da base de dados. Quando invocado, deve apagar o registro passado por parâmetro da base de dados.

T GetById(int id): método que deve retornar o registro na base de dados que contiver em sua chave primária o valor passado por parâmetro.

T GetByGlobalId(Guid id): gosto bastante de utilizar um campo UNIQUEIDENTIFIER em meus registros, pois atribuímos ao registro uma chave de identificação única que o torna único em todo o banco de dados, independente de sua localização – assim como propostos em bases de dados orientadas a objetos.

IEnumerable<T> GetAll(): deve retornar todos os registros existentes na base de dados para a entidade consultada.

IEnumerable<T> ExecuteQuery(Func<T, bool> expression): este método faz consultas na base de dados utilizando como filtro a expressão passada por parâmetro.

Esta interface define o que é esperado por cada classe repositório, mas se notarmos ela utiliza um tipo genérico como parâmetro para sua implementação. Para refinarmos o seu uso e tornarmos nosso repositório reutilizável e expansível, acredito que devemos criar para cada classe repositório uma interface que implemente o contrato definido por IRepository<T>, mas que defina qual entidade será persistida ali. Tomemos como exemplo a interface do repositório de clientes, conforme código:

IClientRepository

Seu classe repositório deve implementar ICLientRepository e ser igual a seguinte implementação:

ClientRepository

Observem que nossa classe de repositório implementa a interface IClientRepository utilizando a entidade Client como alvo de nossas ações de persistência no banco de dados, e não um tipo de dados genérico, como utilizado na interface IRepository<T>.

Este uso é indicado ao construirmos nossos testes unitários, pois ao implementarmos nossos repositórios fakes já teremos nossos repositórios bem estruturados e prontos para extensão.

Outra dica para a construção de nossos testes unitários é tornar os repositórios parametrizáveis através de nossas classes controllers. Devemos criar uma assinatura de construtor que permita a parametrização do repositório que utilizaremos em nossa implementação, assim como é importante fornecer um construtor que defina um repositório padrão, caso não seja passado nenhum parâmetro para o repositório, podemos fazer isso desta forma:

clientController

Bom, espero que algumas dicas aqui descritas ajudem a implementação de suas aplicações com o Entity Framework 4.1. Bom estudo e continuem programando… Alegre

[]s!

Por
Fernando Henrique Inocêncio Borba Ferreira

Entity Framework 4.1 + MVC + DAO

Neste exemplo vamos demonstrar o uso dos design patterns MVC e DAO, combinados com a utilização do Entity Framework 4.1 como tecnologia de acesso a dados de nossa aplicação.

O MVC (Model-View-Controller) é um design pattern bastante utilizado no mercado devido a sua capacidade de dividir a aplicação em camadas especialistas em suas funções, favorecendo a alta coesão das mesmas. A camada model é responsável por representar o mundo real através do uso de objetos. A camada view é dedicada exclusivamente a apresentação dos dados, podendo ser uma aplicação web, uma aplicação console, um formulário do Windows, uma page Silverlight, ou qualquer outra tecnologia front-end. A camada controller faz ponte entre a camada view e a camada model, interceptando a comunicação entre as duas e aplicando regras, validações, redirecionamentos ou encapsulando a comunicação com diferentes frameworks e sistemas. Outra vantagem deste modelo é a possibilidade de criar módulos independentes que trabalhem de modo desacoplado, para que se tornem fáceis de serem substituídos e reutilizados.

O design pattern DAO (Data Access Object) tem o objetivo de encapsular todos os acessos as fontes de dados feitas na aplicação. O uso deste design pattern permite que nossa aplicação não fique dependente de uma tecnologia de acesso a dados, pois estaremos agrupando todas as regras e usos de frameworks específicos de acesso a dados em uma única camada que pode ser facilmente substituída. Caso seja necessária a substituição da tecnologia de armazenamento (exemplo: de MS SQL para Oracle, ou de MS SQL para SQL Azure, ou de Oracle para alguma tecnologia NoSQL) o impacto não será tão grande, e a adaptação do sistema será restrita, evitando impactos globais na aplicação.

Mãos a obra

Pare demonstrar o uso destes design patterns e do Entity Framework 4.1 criaremos um cadastro simples de carros e suas respectivas montadoras.

1 – Abra o Microsoft Visual Studio 2010 e crie uma solução em branco.
2 – Adicione um projeto class library, no nosso exemplo este projeto chamará SampleCore.
3 – Apague o arquivo “Class1.cs” que é criado automaticamente pelo Visual Studio. Faça referências ao namespace “System.Data.Entity” e ao Entity Framework 4.1, geralmente esta localizado no caminho C:\Program Files (x86)\Microsoft ADO.NET Entity Framework 4.1\Binaries\EntityFramework.dll, o download do EF 4.1 pode ser feito neste link: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8363
4 – Crie três pastas dentro do projeto, chamadas Model, Controller e Data.
5 – Crie as classes Carro e Montadora dentro de Model conforme os exemplos a seguir:

01

02

Observe que para representar o relacionamento um para muitos (entre a montadora e os carros) utilizamos o tipo de dados ObservableCollection. ObservableCollection representa uma coleção de dados dinâmica que fornece notificações quando os itens são adicionados, removidos ou quando toda a lista é atualizada.

6 – Agora vamos começar a trabalhar com nossa camada de acesso a dados. Antes de qualquer coisa, criaremos duas interfaces para nossos repositórios de montadoras e carros. As interfaces devem ser criadas dentro de Model e devem implementar a seguinte estrutura:

03

04

Crie dentro da pasta Data uma classe chamada ContextoBancoDados e faça-a herdar de DbContext (namespace System.Data.Entity dentro do assembly EntityFramework.dll). E implemente-o conforme o código abaixo:

05

Caso o banco de dados não exista, e nenhuma string conexão tenha sido fornececida, então será criada uma base de dados local, cujo nome será igual a assinatura da classe dbcontext, isto é, o namespace da qual a classe pertence concatenado com o nome da classe dbcontext. Por exemplo, se sua classe dbcontext pertencer ao namespace “NomeDoCliente.NomeDoProjeto.Repositorio” e sua classe datacontext se chamar “ContextoBancoDados” então o nome de seu banco de dados será  “NomeDoCliente.NomeDoProjeto.Repositorio.ContextoBancoDados”… Não parece ser uma boa prática um nome deste tamanho com características de nomenclatura tão específicas, então recomendo que sempre seja informada uma string de conexão, como no exemplo anterior.

Obs.: Para este exemplo deixei a string de conexão fixa (“chumbada”) no código… Esta realmente não é uma boa prática, o melhor neste caso é deixar a string de conexão em um arquivo configurável de sua aplicação. Para este cenário procure utilizar recursos nativos, como os arquivos App.Config e Web.Config.

7 – Para garantir a criação de seu banco de dados no primeiro acesso procure deixar fixo em algum lugar estratégico de sua aplicação a chamada para o método de criação da base. Não é uma boa prática tornar esse bloco de criação do banco de dados algo que será sempre validado e executado, pois isso pode consumir tempo e recursos operacionais. Então, como dica, os dois locais que acredito serem os ideais para este tipo de procedimento:
– Evento Application Start do Global.asax – no caso de aplicações web.
– Método Main() do arquivo Program.cs – no caso de aplicações desktop e console.

Mais para frente, neste mesmo post, irei demonstrar os comandos necessários para criação do banco de dados.

8 – Para implementação do design pattern DAO e utilização do Entity Framework 4.1 implementaremos as classes RepositorioMontadora e RepositorioCarro dentro da pasta Data da seguinte forma:

060

070

Para encapsular os comandos de criação do banco de dados, encapsularemos seu comportamento em uma classe chamada BancoDadosRepositorio implementada por uma interface chamada IFonteDadosRepositorio, conforme o código a seguir:

090

080

9 – Agora que temos criadas nossas entidades e nossos repositórios, poderemos implementar nossa classe controller que irá gerenciar os acessos as nossas fontes de dados, além de fazer ponte com nossa camada de visão. Nesta classe, por conta da simplicidade de nosso exemplo, iremos implementar as regras de persistência das montadoras e dos carros no mesmo controller. Da seguinte maneira:

100

10 – Nesses momentos já temos nossa camada de DAO pronta, além das camadas model e controller (pertencentes ao MVC) também concluídas. O próximo passo agora é implementar a camada de visão. Para este exemplo criaremos uma aplicação console, pois no momento a estrutura de nossa aplicação tem maior relevância do que a interface. Nesta demonstração criamos uma aplicação console chamada SampleConsole, e fizemos referência para o projeto SampleCore, para que conseguíssemos acessar suas classes. Nossa aplicação console deverá se parecer com algo como:

110

A estrutura da aplicação deve ficar como a imagem a seguir:

00000

Para fazer o download acesse este link: http://code.msdn.microsoft.com/Entity-Framework-41-MVC-DAO-4860e78c

Por
Fernando Henrique Inocêncio Borba Ferreira.

Livro – 97 Coisas que todo arquiteto de software deve saber

Nessas últimas semanas comecei a ler o livro “97 Things Every Software Architect Should Know” (“97 Coisas que todo arquiteto de software deve saber”). Achei interessante o título do livro, pois parecia ser o resumo de diversas dicas sobre comportamento, arquitetura, compromisso e análise de sistemas… E realmente este é o conteúdo do livro…

A obra reúne pequenos textos de diversos arquitetos de software de grande expressão no cenário de tecnologia mundial. Alguns dos profissionais que colaboraram com o conteúdo desta obra trabalham em empresas como: Google, ThoughtWorks, Oracle, InfoQ, Blue River Systems Group, Software Engineering Professionals Inc, entre outros.

O livro é bastante interessante para quem procura um resumo de experiências e lições aprendidas. Não necessariamente precisa-se ser arquiteto de software para ler esse conteúdo (mesmo porque eu não sou arquiteto de software =] ), o conteúdo não é voltado para tecnologia, e sim para a troca de experiências.

Seguem algumas dicas que achei interessantes, existem muitas outras, mas gostaria de inicialmente dar destaque a estas:

– Não coloque seus objetivos técnicos a frente dos requisitos do sistema: não utilize uma tecnologia sem que ela seja necessária. Não deixe que suas tendências tecnológicas direcionem os requisitos do software.

– A arquitetura da aplicação determina sua performance: Esta parece ser uma característica óbvia, mas para muitos não é. Muitas empresas investem no tunning de servidores como solução de ganho de performance, mas performance não é apenas isso! A performance esta diretamente atrelada no modo como seu software foi arquitetado e construído. Para obter ganhos de performance, antes de mais nada, reveja sua arquitetura e procure por pontos a serem melhorados.

– Entenda a necessidade dos requisitos: Procure entender a real necessidade pela qual os requisitos são necessários. Nem sempre o requisito desejado pelo cliente será aquele que melhor atenderá a sua necessidade. Questione, pergunte, julgue as escolhas dos usuários e procure entender sua real necessidade.

– Tudo um dia irá falhar: Hardware é falível, então adicionamos redundância. Software é falível, nós adicionamos monitoramento para nos contar quando a aplicação falha, mas este monitoramento é um software, e também é falível. Seres humanos cometem erros, por isso automatizamos processos e ações. Redes são feitas de hardware e software, redes são falíveis. Todo mecanismo que utilizamos para mitigar um tipo de erro adiciona novos modos de falhas. Então o que devemos fazer, se existe a certeza de erro em nossos sistemas? Devemos aceitar que falhas são inevitáveis, e assim construir em nossos sistemas reações para alguns tipos específicos de falhas, que controlem o erro e protejam o restante do sistema.

– Patologia de padrões: Design patterns são uma das mais valiosas ferramentas disponíveis na arquitetura de software. O uso de padrões favorece a criação de soluções fáceis de compartilhar e entender. Design patterns tornam-se um problema quando nós tentamos utilizá-los em todo problema que encaramos. Não podemos deixar que nossa admiração por design patterns torne os problemas de nosso projeto mais complicados do que o necessário. Design patterns não são mágicos, e não necessariamente qualificam sua solução como ótima.

– Se existe apenas uma solução, então peça uma segunda opinião: A arquitetura de software objetiva encontrar a melhor solução para um dado problema, é muito difícil conseguir cobrir todos os requisitos e restrições com a primeira solução que vem a mente. Se você possui apenas uma solução em mente, e não possui experiência sobre o domínio do problema, então é preciso pedir ajuda a alguém mais experiente.

 

Por
Fernando Henrique Inocêncio Borba Ferreira.

USP-EACH – Mestrado em Sistemas de Informação – O primeiro ano se encerra…

main

Ao longo dos anos fazemos planos, determinamos metas, traçamos objetivos… E passamos o resto da vida tentando atingi-los…

Alguns anos atrás, eu tracei como meta a obtenção do título de mestre, a fim de conseguir combinar meu conhecimento com a vontade de desenvolver soluções que pudessem ajudar as pessoas… E para mim, o mestrado é a melhor ponte para atingir esse objetivo, pois o conhecimento que é transmitido nos abre a mente, incentiva a pesquisa, fortalece a curiosidade e a vontade de construir algo notável para a comunidade científica e/ou para um público alvo…

Sempre ouvir dizer que os cursos stricto sensu eram solitários… Mas, depois de 1 ano de estudo no curso de mestrado em Sistemas de Informação da USP-EACH, posso afirmar o contrário! Alegre Posso afirmar, com grande satisfação, que dividi o último ano com um dos maiores grupos com os quais alguém pode um dia conviver. Posso afirmar que este grupo é formado por mentes brilhantes que irão elevar a qualidade científica, profissional e educacional por onde passarem. Mas além de tão brilhantes, todos estes colegas são de extrema simplicidade e companheirismo, sempre ajudando uns aos outros nos momentos de maior exigência e trabalho.

Aos professores, quero deixar minha gratidão pela paciência com minhas idéias e opiniões, e também por abrirem a minha mente para tantas novas possibilidades, conceitos e técnicas que eu jamais imaginara.

Tenho muito orgulho de participar deste grupo e de conhecer pessoas tão brilhantes e humildes, que com certeza nunca serão esquecidas por mim. Sei que posso contar com cada um destes colegas, e também sei que eles sabem que terão meu auxílio quando necessário, além de minha admiração eterna…

Obrigado a todos os companheiros de mestrado da USP-EACH por este ano de muito aprendizado, amizade e conhecimento.

Universidade de São Paulo – Escola de Artes, Ciências e Humanidades
Programa de Pós-Graduação em Sistemas de Informação – Mestrado
http://www.each.usp.br/ppgsi/
ppgsi-each@usp.br

Algumas das pessoas que tanto admiro:

20110630_151942 20110630_152812
20110630_155557 20110630_170619
20110630_170624 20110630_172355
20110630_173648 20110630_173846
20110630_174040 20110630_174107
20110630_155604 20110630_161400
20110630_164530 20110630_164633
20110630_164530 20110630_152827.jpg

Por
Fernando Henrique Inocêncio Borba Ferreira.

Porque o teste de software orientado a objetos é difícil

Ao contrário do software procedimental, o software orientado a objetos nem sempre se comporta da mesma maneira se executarmos o mesmo método com os mesmo valores de entrada. Essa afirmação pode parecer chocante, mas é sensata, e justifica uma das dificuldades de testar software orientado a objetos.
Uma das maiores peculiaridades do software orientado a objetos é o controle de estados. O estado de um objeto caracteriza sua composição em um dado momento de tempo. Dentro da UML temos diversos diagramas (i.e., Diagrama Temporal, Diagrama de Estados) que tratam de representar a troca de estados dos objetos.
E por que é difícil testá-lo? Por que a afirmativa acima é sensata? Vamos discutir isso através de um exemplo…
Vamos supor uma classe que possua a seguinte implementação:

Se criássemos um teste unitário para o teste do método “MultipleRex(int)”, possivelmente ele seria implementado da seguinte forma:

Mas, se observarmos de forma mais detalhada o comportamento do método “MultipleRex(int)”, veremos que existe dependência à um atributo interno. Tal dependência é tão forte, que o valor deste atributo influência quais blocos de código que podem ou não serem executados. Um conjunto de condições aninhadas, que validam o atributo _sault, direciona a execução do método para um bloco de código distinto dos demais. Blocos de código que podem conter lógicas mais complexas, chamadas a outros métodos, construção de outros objetos, comunicação com satélites, enfim… códigos que estão propensos ao erro.

Desta forma, se incluirmos a chamada a um método intermediário entre a execução do nosso método sob teste e a instância do objeto, alteraremos o comportamento do nosso método, mesmo passando os mesmos valores de entrada. Podemos confirmar isso através do exemplo abaixo:

A execução do método “MultipleRex(int)” modifica o valor do atributo privado e altera os blocos de código executados pelo método “MultipleRex(int)”, acarretando em um valor de retorno diferente do esperado.

Se modificarmos nosso teste, e trocarmos o método intermediário, acarretaremos na execução de um terceiro comportamento distinto. A alteração pode ser vista no exemplo a seguir:

Assim, podemos afirmar que, o teste de software orientado a objetos, não apenas por este motivo, mas por um conjunto de peculiaridades próprias do paradigma orientado a objetos, é difícil de ser testado e exige que dediquemos atenção durante a construção dos nossos casos de teste. De forma que seja abrangente o suficiente, a fim de executar todos os possíveis blocos de execução de nossas aplicações.


Por
Fernando Henrique Inocêncio Borba Ferreira.