.Net Coders

Olá!

No dia 7 de Fevereiro de 2013 tive a honra de participar de um evento no grupo .Net Coders.

O .Net Coders é uma comunidade muito bacana que existe aqui em São Paulo e que a (cerca de) um ano tem agitado a comunidade paulista com diferentes eventos, abordando assuntos gerais da área de tecnologia e mais especificamente, diferentes segmentações da plataforma .Net.

536033_497508880295712_1611018659_n

Leia mais »

Publicidade

Um modelo arquitetural…

Nos últimos tempos tenho recebido algumas perguntas de como modelo meus projetos, quais design patterns utilizo e como divido minha aplicação em camadas. Estas perguntas possuem apenas uma resposta: depende do caso.

Cada aplicação merece um modelo arquitetural diferente do outro. Cada aplicação exige diferentes design patterns. Cada aplicação funciona de um jeito. Nenhuma aplicação é igual a outra, assim como os dedos das mãos não são iguais.

Mas, como esta pergunta não possui uma resposta certa ou errada, gostaria de demonstrar um modelo arquitetural que me agrada bastante. Este modelo mescla alguns design patterns e alguns princípios de projetos orientados a objetos. A arquitetura da aplicação é a demonstrada abaixo.

architecture

Leia mais »

Padrão Bom Cidadão (Good Citizen Pattern)

Olá,

Faz algum tempo que não escrevo e o motivo disto é uma questão de tempo. Devo apresentar meu mestrado no próximo mês de Dezembro e a correria é grande para terminar tudo…

Hoje gostaria de escrever sobre um design pattern que sempre apliquei, mas que não sabia que era um design pattern. Esse tipo de situação é mais comum de acontecer do que parece… Geralmente os design patterns são soluções que as pessoas aplicam no seu dia-a-dia e que após serem consideradas viáveis e reutilizáveis são documentadas em algum catálogo de padrões.

51M-zRDNMJL._SL500_PIsitb-sticker-arrow-big,TopRight,35,-73_OU01_SS500_

Leia mais »

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.

Princípios de Projetos Orientados a Objetos

Nossas aplicações orientadas a objetos devem seguir princípios básicos de desenvolvimento, tais princípios são comumente intitulados como “Princípios de Projetos Orientados a Objetos”. Tais princípios são conceitos básicos que devemos nos guiar para desenvolvermos aplicações reutilizáveis, desconectadas, bem modeladas e “inteligentes”. Tais princípios foram à base para a construção de diversos catálogos de padrões  (Design Patterns), tais como: GoF e GRASP.

Os Princípios de Projetos Orientados a Objetos são:

Programe para interfaces, não para implementações: Programar para uma interface significa, na verdade, programar para um supertipo, uma classe abstrata ou uma interface de construção. A vantagem desse princípio é explorar o polimorfismo de modo que o objeto fique vinculado à abstração e diminua a quantidade de interdependências.

Utilize designs levemente ligados entre objetos que interagem: Projetos levemente acoplados são mais fáceis de serem modificados e muito mais flexíveis, pois minimizam a interdependência entre os objetos. Este é um dos princípios mais importantes na construção de Projetos Orientados a Objetos.

Dependa de abstrações. Não dependa de classes concretas: Também conhecido como Princípio da Inversão de Dependência, afirma que nenhuma variável ou atributo deve conter uma referência a uma classe concreta e, que nenhuma classe deve derivar de uma classe concreta. Dessa forma, conseguimos diminuir a interdependência de classes concretas e favorecer o desacoplamento entre as mesmas.

Encapsule o que varia: Este princípio possui um conceito simples que forma a base de quase todos os padrões de projeto. Ele defende a idéia de separar as partes que variam e encapsulá-las para que seja possível alterar ou estender essas partes sem afetar as que não variam. Assim é possível que uma parte de um sistema varie independentemente de todas as outras. Isso acarreta um número menor de alterações de código e mais flexibilidade nos sistemas.

Dê prioridade à composição em relação à herança: A utilização de composições proporciona interdependência entre os objetos e muito mais flexibilidade, pois permite a alteração do comportamento durante o tempo de execução, desde que o objeto que estivermos compondo, utilize a interface de comportamento correta.

As classes devem estar abertas para a extensão, mas fechadas para modificações: “Permitir que as classes sejam facilmente estendidas para incorporar um novo comportamento sem modificar o código existente. Assim, tornamos os projetos resistentes a mudanças e suficientemente flexíveis para assumir novos recursos para atender aos requisitos que mudam.” (Freeman, 2005, p. 86)

Mínimo Conhecimento: Também conhecido como Lei de Demétrio. O Princípio do Mínimo Conhecimento nos orienta a reduzir as interações entre os objetos, aconselhando-nos ao encapsulamento de funções, rotinas, lógicas internas e sistemas. Um sistema com muitas dependências entre múltiplas classes é um sistema frágil, de difícil manutenção e complexo demais para ser compreendido por todos.

“Isso significa que, ao projetarmos um sistema, devemos tomar cuidado com o número de classes com que qualquer objeto interage e também com a forma como essa interação ocorre (…) Este princípio nos impede de criar projetos com um grande número de classes interconectadas, o que faz com que qualquer alteração numa parte do sistema exerça um efeito em cascata sobre outras partes.” (Freeman, 2005, p. 221)

O princípio nos fornece algumas dicas: pegamos um objeto qualquer e, a partir de qualquer método para esse objeto, só podemos invocar métodos que pertençam ao próprio objeto, a objetos que tenham sido passados como parâmetros para o método, a qualquer objeto que seja criado ou instanciado pelo método e, finalmente, a quaisquer componentes do objeto.

Princípio de Hollywood – Não nos telefone, nós telefonaremos para você: “O princípio de Hollywood nos proporciona uma maneira de evitar o colapso das dependências (…). Colapso das dependências é o que acontece quando você tem componentes de alto nível dependendo de componentes de baixo nível que dependem de componente de alto nível que dependem de componentes laterais que dependem de componentes de baixo nível, e assim por diante.” (Freeman, 2005, p. 244)

Com este princípio, determinamos que componentes de baixo nível conectem-se ao sistema, mas são os componentes de alto nível que determinam quando e como eles serão solicitados.

“Em outras palavras, os componentes de alto nível dizem aos componentes de baixo nível: Não nos telefone, nós telefonaremos para você.” (Freeman, 2005, p. 244)

Uma classe só deve ter uma única razão para mudar: Uma classe que possua diversas responsabilidades não relacionadas ou executa muitas tarefas que deveriam ter sido delegadas a outras classes é indesejável e acarreta quatro problemas:
– Dificuldade de compreensão;
– Dificuldade de reutilização;
– Dificuldade de manutenção;
– Extremamente frágeis, sendo afetadas constantemente pelas mudanças.

Cada responsabilidade é uma área de mudança em potencial. Mais de uma área de responsabilidade equivale a mais de uma área de mudança. Este princípio nos ensina a limitar cada classe a uma única responsabilidade.

Referências:

FREEMAN, Eric, FREEMAN, Elisabeth; Head First – Design Patterns; O’Reilly Media;  Editora Alta Books Ltda; 2ª Edição Revisada; 2005.

GoF – HELM, Richard; VLISSIDES, John; JOHNSON , Ralph; GAMMA , Erich; Design Pattern – elements of reusable object-oriented software; BookMan; 1995.

LARMAN, Craig; Applying UML and patterns: an introduction to object-oriented analysis and design and the unified process; BookMan; 2004.