Dojo PHP no #guma10anos

Dia 4 de abril de 2014 ocorreu mais um evento do GUMA, sendo este especial pelo fato do mesmo estar completando 10 anos de existência, então o evento todo foi em ritmo de festa e comemorações.

Eu e o Guilherme Lacerda conduzimos um Dojo de PHP para a galera treinar um pouco de TDD, OO, comunicação e trabalho em equipe.

Abaixo seguem algumas fotos, bem como link para os slides e repositório com código fonte da solução para o problema proposto (Cifra de César).

Slides Repositório

 

 

 

Advertisement

Valeu CBSoft 2013!

Está acontecendo, de 29 de setembro a 04 de outubro, a 4a edição do CBSoft 2013, Conferência Brasileira de Software: Teoria e Prática, em Brasília.

O evento, que conta com vários cursos, workshops, tutoriais e simpósios em paralelo é o grande evento de Engenharia de Software no Brasil. Neste ano, eu e o Daniel representamos o CbE, ministrando um tutorial que leva o nome do nosso blog. Neste tutorial, discutimos a postura de um desenvolvedor profissional e o que é necessário para chegar lá, em termos de aprendizado.

No tutorial, é proposto um exercício prático de programação, onde o objetivo é treinar refatoração, baby steps, TDD e conhecer algumas ferramentas que fazem a diferença, como PMD, Checkstyle, Findbugs, JaCoCo, JUnit, Jenkins e Sonar.

Abaixo, colocamos uma foto para registrar o final do tutorial. Nosso muito obrigado a todos os participantes e a organização, em especial ao Prof. Ségio Soares, da UFPE.

Participantes do Coding By Example

Ah… e como prometido, disponibilizamos os slides no slideshare (apresentação e exercício proposto) e o código no github. Bom treino a todos!! 🙂

Database Refactoring

Contextualização

Refatoração de código (Code Refactoring) é uma disciplina/processo que consiste em melhorar a estrutura interna de um software sem modificar seu comportamento externo, e uma Refatoração de Banco de Dados (Database Refactoring) parte do mesmo princípio, porém além de manter o comportamento externo também deve manter a semântica da informação que ele mantém/armazena, e por esse motivo é considerada mais difícil.

Um outro conceito que posso destacar a respeito de Database Refactoring é:
“Mudança disciplinada na estrutura de uma base de dados que não altera sua semântica, porém melhora seu projeto e minimiza a introdução de dados inconsistentes”
O ponto interessante deste último é o texto “minimiza a introdução de dados inconsistentes“, pois esse é o grande objetivo de realizarmos um refactoring na estrutura de um banco de dados, ou seja, melhorar o desing atual para melhorar a consistência dos dados e também a qualidade dos novos dados que serão adicionados ao seu banco de dados.

E esta tarefa não é das mais simples, pois existe um fator preponderante no que diz respeito a dificuldade de execução deste tipo de refactoring, que é o acoplamento.

Acoplamento

dataRefactoringBestCase

Figura 1. Baixo Acoplamento

É a medida de dependência entre dois elementos. Quanto mais acoplados dois elementos estiverem, maior a chance que a mudança em um implique na mudança em outro.

Simples assim, quanto mais o seu banco de dados estiver acoplado, ou seja, dependente de diversas aplicações externas, mais difícil será a aplicação de um refactoring.

dataRefactoringWorstCase

Figura 2. Alto Acoplamento

A figura 1 demonstra um cenário “Single-Database Application” que é bem simplificado, onde a aplicação de um refactoring será mais tranquilo. 

Com certeza o cenário da Figura 2, o “Multi-Database Application” é o pior caso, pois exige muito cuidado e planejamento para execução do refactoring, então veremos a seguir uma sugestão de processo para execução.

Processo de refatoração

databaseRefactoringProcess

Figura 3. Processo de Database Refactoring

Um processo é um conjunto organizado de atividades com um objetivo em comum. Executar um database refactoring em um cenário “Single-Database Application” ou “Multi-Application Database” requer um processo, por mais simples que seja. A grande diferença na execução em ambos cenários é que no caso do “Multi-Application Database” o período de transição (mais abaixo falaremos) geralmente será mais longo.

É bom sempre ter em mente que um database refactoring, como já vimos, não é uma atividade simples então caso seja identificada a real necessidade de refatorar um banco de dados então podemos usar o seguinte roteiro (processo) para se guiar:

  • Escolher o refactoring mais apropriado;
  • Depreciar o esquema original;
  • Testar antes, durante e após;
  • Modificar esquema;
  • Migrar os dados;
  • Modificar código externo;
  • Executar testes de regressão;
  • Versionar seu trabalho;
  • Anunciar o refactoring.

Na Figura 4 é demonstrado um pequeno processo descrevendo um fluxo básico para aplicação de um refactoring.

process-refactoring-regra-geral

Figura 4. Regra Geral Processo Refatoração

Atente bem para o “Período de Transição”, que é a fase mais importante, principalmente para cenários “Multi-Database Application” (Figura 2), onde você precisa ter em mente que não conseguirá realizar o refactoring e fazer o deploy em produção de todas as aplicações ao mesmo tempo. A grande verdade é que muito provavelmente você nem consiga alterar todas as aplicações ao mesmo tempo, principalmente se você tiver dependência de terceiros, então você precisará suportar o esquema original e o esquema resultante ao mesmo tempo, para somente quando todas aplicações estiverem suportando apenas o esquema resultante, ou novo esquema, você poderá aposentar de vez o antigo esquema e assim finalizar este período.

Estratégias de Database Refactorings

Existem alguns pontos a considerar com estratégias para adoção de um database refactoring:

  • Pequenas mudanças são mais fáceis de aplicar;
  • Identifique unicamente cada refactoring;
  • Implemente uma grande mudança realizando várias pequenas mudanças;
  • Tenha uma tabela de configuração/versionamento do seu banco de dados;
  • Priorize triggers ao invés de views ou sincronizações em lote;
  • Escolha um período de transição suficiente para realizar as mudanças;
  • Simplifique sua estratégia de controle de versão de banco de dados;
  • Simplifique negociações com outros times;
  • Encapsule acesso ao banco de dados;
  • Habilite-se a montar facilmente um ambiente de banco de dados;
  • Não duplique SQL;
  • Coloque os ativos de banco de dados sobre controle de mudanças;
  • Seja cuidadoso com políticas.

Os items acima mostram apenas algumas sugestões, em forma de “lições aprendidas”, de algumas estratégias que você pode considerar quando tiver a necessidade de realizar um refactoring.

Para apoiar essas estratégias existe um catálogo que descrevem diversos tipos de refactorings em bancos de dados e exemplos de uso, que veremos a seguir.

Catálogo de Database Refactorings

Este catálogo é dividido em algumas categorias:

  • Structural: são mudanças na estrutura do banco de dados (tabelas, colunas, visões, etc).
  • Data Quality: são mudanças que melhoram a qualidade das informações contidas em um banco de dados.
  • Referential Integrity: são mudanças que asseguram que uma linha referenciada exista em outra relação e/ou assegura que uma linha que não é mais necessária seja removida apropriadamente.
  • Architectural: são mudanças que melhoram a maneira que programas externos interagem com a base de dados.
  • Method: são mudanças que melhoram a qualidade de uma Procedure um Função.
  • Transformations: mudanças que alteram a semântica do esquema do banco pela adição de novas funcionalidades.

No meu github é possível encontrar exemplos práticos de aplicação passo-a-passo de um refactoring em um modelo inicial, passando por um período de transição e chegando ao modelo final.

Considerações Finais

Devemos levar em consideração que apesar destas técnicas serem direcionadas para refatoração, ou seja, mudar estrutura sem mudar sua semântica, as mesmas podem e devem ser utilizadas para evolução da sua aplicação, ou seja, se você precisa construir uma nova feature em sua aplicação que está em produção, você poderá recorrer das práticas aqui apresentadas para evoluir seu esquema de forma mais consistente e segura.

Baseado no exposto podemos facilmente responder a pergunta “Por quê Refatorar?”:

  • aceitar mudança de escopo;
  • fornecer feedback rápido;
  • melhoria contínua;
  • aumentar simplicidade para facilitar entendimento;
  • tornar os modelos mais próximos do mundo real;
  • termos modelos simples para facilitar:
    • manutenção e
    • evolução da aplicação

E para refatorarmos precisamos ter conhecimento, disciplina, simplicidade, bom senso e persistência, sem contar no ponto fundamental que é organização.

Referências

Reduzindo o Tamanho de Listas de Parâmetros de um Método

a) Smell a ser reduzido/eliminado: Long Parameter List

b) Ingredientes

Ferramentas

Métrica(s) associada(s): número de parâmetros por método (Number of Parameters in Method – PAR)

Técnicas

Mecânica

  1. Identificar pontos onde o smell ocorre (PMD com Maven)
  2. Garantir que todas as ocorrências de código duplicado tenham um nível satisfatório de cobertura de testes (uso do JaCoCo)
  3. Caso a cobertura não esteja satisfatória, escrever testes unitários que garantam o comportamento (introduzir mais testes com JUnit, acompanhando sua cobertura com JaCoCo)
  4. Aplicar as técnicas de refactoring
  5. Rodar métricas novamente para verificar a melhoria
  6. Repita o passo 1

c) Aplicando a Receita no Projeto ArgoUML

Base de código: ArgoUML (http://argouml.tigris.org/)

Repositório utilizado: https://github.com/carlosaml/argouml

Configuração de ferramentas

  • Maven utilizado para o build
  • PMD configurado para detectar métodos com mais de 6 parâmetros
  • Testes JUnit rodando atráves do Maven
  • JaCoCo plugado no Maven para geração de relatórios de cobertura de testes

Aplicação da Receita

Executando o build do Maven, o relatório do PMD acusa que o seguinte método recebe muitos parâmetros:

private String toString(Object modelElement, boolean useGuillemets, 

            boolean showVisibility, boolean showMultiplicity, boolean showTypes,

            boolean showInitialValues, boolean showProperties)

Portanto, utilizaremos ele como base para a aplicação desta receita.

Primeiramente verificamos a cobertura de testes dos chamadores deste método (pelo fato do mesmo ser privado), que é apenas um:

public String toString(Object modelElement, NotationSettings settings)

O relatório de cobertura de testes existente não passa a confiança necessária para que o método possa ser refatorado. Para melhorar este cenário, escreve-se mais testes para o método público.

Para isso, a classe TestAttributeNotationUml, contendo cinco testes unitários, é adicionada.

Com isso eleva-se a cobertura de testes e consequentemente consegue-se autorização para refatorar o método toString que conta com muitos parâmetros.

Procurando pelos usos do método em questão, vemos que existe apenas um e que este apenas extrai os valores de algumas propriedades do objeto NotationSettings recebido e os passa adiante. Isso define claramente um ótimo candidato para Preserve Whole Object, já que muitos dos parâmetros do método são fortemente relacionados.

Para isso, substituímos todos estes parâmetros:

  • boolean useGuillemets
  • boolean showVisibility
  • boolean showMultiplicity
  • boolean showTypes
  • boolean showInitialValues
  • boolean showProperties

Por apenas um:

  • NotationSettings settings

E mudamos a única chamada do método para que passe diretamente a instância de NotationSettings.

Com isso o PMD já não acusa mais o método em seu relatório.

Porém, o método recém refatorado conta com somente um uso, o que não faz sentido devido ao fato do mesmo ser privado. Para tanto, podemos aplicar Inline Method e eliminar o método privado em questão.

Reduzindo o Tamanho de Métodos

a) Smell a ser reduzido/eliminado: Long method

b) Ingredientes

Ferramentas

Métrica(s) associada(s) número de linhas por método (Method Lines of Code – MLOC)

 Técnicas

Mecânica

  1. Identificar pontos onde o smell ocorre (PMD com Maven)
  2. Garantir que todas as ocorrências de código duplicado tenham um nível satisfatório de cobertura de testes (uso do JaCoCo)
  3. Caso a cobertura não esteja satisfatória, escrever testes unitários que garantam o comportamento (introduzir mais testes com JUnit, acompanhando sua cobertura com JaCoCo)
  4. Aplicar as técnicas de refactoring
  5. Rodar métricas novamente para verificar a melhoria
  6. Repita o passo 1

c) Aplicando a Receita no Projeto Spark

Base de código: Spark (http://www.sparkjava.com/)

Repositório utilizado: https://github.com/carlosaml/spark

Configuração de ferramentas

  • Maven utilizado para o build
  • PMD configurado para detectar métodos com mais de 50 linhas
  • Testes JUnit rodando atráves do Maven
  • JaCoCo plugado no Maven para geração de relatórios de cobertura de testes

Aplicação da Receita

Executando o build do Maven, o relatório do PMD acusa que o método boolean matchPath(String path) da classe spark.route.SimpleRouteMatcher é muito longo. Utilizaremos ele como base para a aplicação desta receita.

O método em questão é privado e chamado apenas por outro método privado, boolean matches(HttpMethod httpMethod, String path). Este, por sua vez, é utilizado por dois métodos públicos: RouteMatch findTargetForRequestedRoute(HttpMethod httpMethod, String path) e List<RouteMatch> findTargetsForRequestedRoute(HttpMethod httpMethod, String path).

Olhando o relatório de cobertura do JaCoCo, podemos notar que ambos métodos possuem 100% de cobertura de teste, o que nos dá plena segurança em realizar mudanças nessa classe.

Grande parte do comprimento do método se dá devido a existência de bastante código dentro do condicional if (thisPathSize == pathSize) {} else {}. Neste caso o refactoring que melhor se adapta é o Decompose Conditional.

Ao analisar o código mais profundamente, percebe-se que o condicional existe para tratar paths específicos de maneira diferente de “wildcards”. Com isso, podemos extrair dois diferentes métodos, um para cada situação: matchesSpecificPaths para o primeiro caso e matchesWildCards para o segundo. Com isso, todos os métodos da classe se tornam menores e consequentemente mais manuteníveis. Abaixo, temos o resultado do relatório do PMD, executado novamente, garantindo a remoção do smell.

Apresentação disponível: Trunk Based Development Explored (AgileBrazil 2011)

Já está disponível os slides da palestra realizada em Fortaleza, no AgileBrazil 2011. Em breve, disponibilizaremos também os exemplos de Feature Toggle. O mais legal é que, no mesmo dia de nossa palestra, Martin Fowler e Mike Mason gravaram um vídeo abordando o mesmo problema.

 

Atualização em 04/07:  Já estão disponíveis os exemplos de feature toggle.

PHP Brazilian Conference (2008) – Lecture Descriptions

Short Descriptions of Presentations – PHP Conference Brazil 2008

Christopher Jones, from Oracle, asked me to put a brief description of lectures in English on the blog.  Below follows a summary of both presentations. See the original post here.

Presentation 1 – Coding Standards and Refactoring with PHP

In this presentation held in PHP Conference Brazil 2008, I showed it is possible to develop PHP code with quality, focusing on best practices standards and refactoring techniques of code.  For this, equivalent tools which have existed for some time in technologies like Java and .NET can be also used for PHP.  These tools are:

PHP Tool                           Java Equivalent

PHPUnit                                  JUnit
PHP Code Sniffer                  CheckStyle
PHPUnit PMD/CPD               PMD/CPD
PHPUnit Code Coverage     Cobertura
IDE Eclipse PDT                    IDE Eclipse
PHPDocumentor                    JavaDoc
Apache ANT                           Apache ANT
phpUnderControl                    CruiseControl

In addition to the techniques demonstrated, I discussed values and practices of Agile Software Methodologies, with a focus on LeanSCRUM and XP. It’s been very interesting to see the public receptivity for Agile Methodologies and PHP.

Presentation 2 – Applying Patterns of Enterprise Architecture with PHP

PHP is a language known for developing programs more focused on the WEB.  People are used to hearing about in PHP for development of WEB sites. Soon development of enterprise applications using PHP comes. In this presentation, I gave concepts of Software Architectures, Design Patterns, SOA, Web Services and Enterprise Applications. In addition to these concepts, I also showed the types of Enterprise Patterns used in most applications (also involving other technologies like Java and .NET). After this introduction, the content was directed to patterns of architecture and enterprise applications addressed by Martin Fowler. In the end, I showed a case study of a corporate application developed in PHP, using a set of patterns of architecture.