Páginas

Mostrando postagens com marcador programming. Mostrar todas as postagens
Mostrando postagens com marcador programming. Mostrar todas as postagens

21 janeiro 2008

Modifique o layout do Trac



Você já ouviu falar no Trac? Ferramenta muito interessante! Aparentemente um simples sistema de tickets para helpdesk, com os plugins certos você pode facilmente organizar uma equipe Ágil... até mesmo o Jeff Shuterlandreferenciou a ferramenta em seu blog. Estamos usando o trac desde outubro na Audaces, e estou cade vez mais impressionado. Além do sistema de tickets existe ainda integração com subversion, subsistema de codeReview....

Mas estamos aki para falar de como modificar o tema padrão do trac...

Passos simples(supondo que vc jah tenha um projeto trac funcionando):

Primeiro Passo:No arquivo /templates/site_css.cs:

##################################################################
# Site CSS - Place custom CSS, including overriding styles here.
?>

@import url(/site/cascadeTracMeuTemplate.css);



Segundo Passo: No diretório htdocs crie o arquivo cascadeTracMeuTemplate.css com o seguinte conteúdo(Sim, copie e cole):


body {
background: #FFFFFF url(background.png) 0 0 repeat-x;
color: #000;
margin: 10px;
padding: 0;
}

form.addnew { clear: right; float: right; margin: -2em 0 4em; }

.nav {
position: relative;
}
.wikipage { padding-left: 18px; position: relative; left: 2%; width:94% }

/* BARRA MENU */
#mainnav {
background: #66CCFF url(nav_fundo.png) 0 0 repeat-x;
border: 1px solid #000;
font: normal 10px verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif;
margin: .66em 0 .33em;
padding: .2em 0;
}
#mainnav li { border-right: none; padding: .25em 0 }
#mainnav :link, #mainnav :visited {
background: url(dots.gif) 0 0 no-repeat;
border-right: 1px solid #000;
border-bottom: none;
border-left: 1px solid #555;
color: #000;
padding: .2em 20px;
}
* html #mainnav :link, * html #mainnav :visited { background-position: 1px 0 }
#mainnav :link:hover, #mainnav :visited:hover {
background-color: #66CCFF;
border-right: 1px solid #000000;
}
#mainnav .active :link, #mainnav .active :visited {
background: #333 url(../topbar_gradient2.png) 0 0 repeat-x;
border-top: none;
border-right: 1px solid #000;
color: #eee;
font-weight: bold;
}
#mainnav .active :link:hover, #mainnav .active :visited:hover {
border-right: 1px solid #000;
}

/* LINKS */
:link, :visited {
text-decoration: none;
color: #3333CC;
border-bottom: 1px dotted #3333CC;
}

/* TIMELINE*/
dt :link:hover, dt :visited:hover { background-color: #eed; color: #3333CC }

dt em {
border-bottom: 1px dotted #bbb;
color: #3333CC;
font-style: normal;
text-decoration: none;
}

/* ROADMAP */
.milestone .info h2 em { color: #3333CC; font-style: normal }


/* FOOTER */
#footer {
clear: both;
color: #bbb;
font-size: 10px;
border-top: 1px solid;
height: 31px;
padding: .25em 0;
}

Terceiro Passo: Edite os arquivos site_header.cs e site_footer.cs no diretório templates:

SITE_HEADER.CS
####################################################################
# Site header - Contents are automatically inserted above Trac HTML
?>





--

#########################################################################
# Site footer - Contents are automatically inserted after main Trac HTML
?>




Quarto e último passo: Crie um degrade bacana para o background com o nome referenciado acima.

Resultado(obviamente com o logo ficou tosco...mas experimente trocá-lo por algo mais aceitável):

12 dezembro 2007

Tem certeza que isso ai é um framework?



Saudações a todos... post melancólico... =)
Acredito que seja talvez nossa ânsia por resolver todos os problemas de uma vez só. Ou ainda nossa pretensão em acreditar que possamos realmente resolver todos os problemas de uma vez só...
Engraçado, mas tenho visto muito disso no mundo de desenvolvimento Java. Basta procurar em sites como Sourceforge ou Javaforge pelas palavras "framework"(1 e 2) e você terá a com extatidão o tamanho do problema.

Deve ser pela interpretação errada que alguns líderes técnicos fazem do tema, mas todos os frameworks que presenciei a implementação causaram sempre mais problemas do que soluções. Sempre fui e sempre serei averso à criação de frameworks, ou um pseudo-genérico-subsistema que "deixe as coisas mais fáceis" sem que seja estritamente necessário... como infelizmente nunca estive na posição de tomar este tipo de decisão, apenas paguei pelo erro dos outros, utilizando implementações que não foram feitas para serem utilizadas, mas apenas para servirem de vitrine: "olha, como nosso framework é maravilhoso! implementamos todos os desigs patterns existentes! não funciona para o seu caso de uso, mas mesmo assim ele é maravilhoso!".

Bom saber que exitem pessoas preocupadas com isso além de mim (vide 37signals com o Getting Real)... a apresentação deste post é do cara que ajudou a implementar a API de coleções do Java, Joshua Bloch... até que ele programa um pouco... conhece um pouco do assunto...

Bem, todos deveriam ver este vídeo... sinceramente...
Principalmente akeles que acreditam que sabem implementar frameworks e APIsp. São apresentados conceitos simples (muito simples), mas que muitas vezes são esquecidos: como tentar SEMPRE implementar um sistema que utilize a API ou framework (sempre é pouco, que tal 3 sistemas até realmente afirmar que o framework está pronto??), ou ainda tentar obter o máximo de feedback e tentar deixar tudo o mais simples possivel? ( do one thing, and do it well!) ou ainda documentar o necessário para que outras pessoas possam utilizar o seu framework/API.... entre muitas outras coisas. Confira por si próprio...

Com vcs, o cara:

ABSTRACT

Every day around the world, software developers spend much of their time working with a ... all » variety of Application Programming Interfaces (APIs). Some are integral to the core platform, some provide access to widely distributed frameworks, and some are written in-house for use by a few developers. Nearly all programmers occasionally function as API designers, whether they know it or not. A well-designed API can be a great asset to the organization that wrote it and to all who use it. Good APIs increase the pleasure and productivity of the developers who use them, the quality of the software they produce, and ultimately, the corporate bottom line. Conversely, poorly written APIs are a constant thorn in the developer's side, and have been known to harm the bottom line to the point of bankruptcy. Given the importance of good API design, surprisingly little has been written on the subject. In this talk, I'll attempt to help you recognize good and bad APIs and I'll offer specific suggestions for writing good ones.

09 dezembro 2007

Triste Realidade



Saudações!
Infelizmente é comum encontrarmos projetos em que não houve a menor preocupação com qualidade... seja qualidade na resolução do problema que um código se propõe, seja na qualidade do código produzido.
Lendo um texto clássico, How to Write Unmaintainable Code, percebe-se o quanto é importante a preocupação com a forma que produzimos software.
"Any fool can write a code that a machine understands. Good programmers can write code that a human can understand"

Pense nisso... em desenvolvimento de software, código legal está entre os principais motivos para atrasos no desenvolvimento.


Continue a leitura do artigo, e caso encontre similaridades na forma com que seu código fonte está organizado repense sua forma de trabalho. Coloquei apenas a introdução do texto, mas vale a pena checar o artigo completo.


Introduction

Never ascribe to malice, that which can be explained by incompetence.

Napoleon

Because of the Slashdot plug, hits peaked at 250 a second on this page, and the hit counters stopped kicking over. I received a slew of email with suggestions for ever more subtle techniques of writing unmaintainable code. It took me quite while for me to incorporate all your suggestions. The essay has been like rock candy, seed the string with sugar, soak in sugar water, soon it grew out of control.

In the interests of creating employment opportunities in the Java programming field, I am passing on these tips from the masters on how to write code that is so difficult to maintain, that the people who come after you will take years to make even the simplest changes. Further, if you follow all these rules religiously, you will even guarantee yourself a lifetime of employment, since no one but you has a hope in hell of maintaining the code. Then again, if you followed all these rules religiously, even you wouldn't be able to maintain the code!
General Principles

Quidquid latine dictum sit, altum viditur.
Whatever is said in Latin sounds profound.

To foil the maintenance programmer, you have to understand how he thinks. He has your giant program. He has no time to read it all, much less understand it. He wants to rapidly find the place to make his change, make it and get out and have no unexpected side effects from the change.

He views your code through a tube taken from the centre of a roll of toilet paper. He can only see a tiny piece of your program at a time. You want to make sure he can never get at the big picture from doing that. You want to make it as hard as possible for him to find the code he is looking for. But even more important, you want to make it as awkward as possible for him to safely ignore anything.

Programmers are lulled into complacency by conventions. By every once in a while subtly violating convention you force him to read every line of your code with a magnifying glass.

You might get the idea that every language feature makes code unmaintainable -- not so, only if properly misused.

15 outubro 2007

Integração Contínua



Termo muito importante no mundo Ágil... eu disse muito? Eu quis dizer MUITO!
Sua intenção é ser a panacéia para os males relacionados a builds e gerações de versão para software, além de pode se tornar uma ferramenta bastante importante para tomada de decisão por parte da área gerencial da equipe... a idéia é simples:
um único botão é responsável por disparar uma série de ações que culminam com a contrução do seu sistema... assim, simples... que tal?
A este mesmo procedimento de construção podem ser adicionadas rotinas como:
  • Execução de testes automatizados
  • Geração de versões internacionalizadas de seu software
  • Disponibilizar a versão atual em desenvolvimento para o cliente
  • Criação de relatórios de código como:
  • Cobertura de testes
  • Inspeção de padrões de codificação
  • Estatísticas de acoplamento

Todo o processo segue a arquitetura descrita na imagem abaixo:


O cenário acima pode ser descrito como: (Fonte: Continuous Integration)
  1. O desenvolvedor envia o código para o controle de versão (SVN, CVS, etc). Enquanto isso a máquina de integração (servidor de Integração Contínua) está verificando o repositório buscando por modificações
  2. Logo após um commit ser efetuado, o servidor ao verificar que alguma mudança ocorreu no repositório inicia o processo de build baixando os arquivos do Servidor de Controle de Versão. Assim, o script de build é executado, testes são realizados, relatórios gerados, e todo o projeto é integrado.
  3. O Servidor de Integração envia por e-mail ou outros dispositivos o feedback sobre build para usuários específicos do projeto
  4. O servidor volta ao estado de Poll buscando por mudanças no repositório
Um comportamento importantíssimo: Esta arquitetura força a equipe a manter sempre em funcionamento o código fonte que existir no repositório, adicionando mais controle a possíveis problemas de implementação ou integração.

Encontrei um site comparativo sobre ferramentas de build contínuo: Continuous Integration Matrix. Vale muito a pena dar uma lida. Autalmente utilizando o luntbuild, sem grandes problemas... bastante eficiente a ferramenta.
No livro, algumas outras ferramentas são citadas:
  • Doxygen: Gera diagramas de classes e relacionamento automaticamente para uma infinidade de linguagem. Ferramenta muito poderosa!!
  • X10: Utilizado para controlar qualquer mecanismo que utilize radio frequencia. Ideal para colocar um sirene ao lado com servidor de build para que todos saibam que algo de errado foi enviado ao repositório
  • Sourcemonitor: Geração de métricas sobre desenvolvimento
  • Selenium: Automatize testes de aceitação. Ferramenta show demais!
  • Checkstyle: Ferramenta de inspeção de código para Java

Um exemplo prático pode ser encontrado no site da Improveit

É isso... =)

25 setembro 2007

Entenda o Behavior Driven Development



Saudações a todos!

O rapaz simpático do video abaixo é David Astels, que lançou o livro TDD:A pratical Guide, extremamente recomendado se você deseja aprender alguma coisa sobre desenvolvimento orientado a testes.

Entretando, testes não atendem às reais necessidade de se criar um sistema de forma a ter uma especificação executável de comportamento. Ou melhor, "Test Driven Development" não é a melhor maneira de descrever o que se pretende com o TDD. Assim, David Astels discorre sobre o modelo Behavior Driven Development, segundo ele mais próximo do intuíto que ele imagina como sendo o válido.

A idéia é simples, e toda a apresentação pode ser expressa da seguinte forma:

A criação e utilização de Testes automatizados não é o real intuíto do TDD, e uma nomenclatura mais efetiva é necessária.
A criação de testes antes de escrever o código é uma forma de especificar um comportamento que o sistema deverá atingir, sem preocupar-se com a implementação do método. E devem existir frameworks que correspondam a essa expectativa. =)


Com vocês, o vídeo:







Aprenda mais sobre TDD no CodingDojoFloripa



13 setembro 2007

Desenvolvimento de software igual Jardinagem, não engenharia!



Essa vai doer fundo na alma de alguma pessoas...
Gostei muito da entrevista de Dave Thomas, ou melhor, Pragmatic Dave como foi dito na Agile2007, feita para a Artima Developers por Bill Venners , acredito que todos deveriam ler na íntegra o artigo.
Mas uma coisa me chamou a atenção durante a leitura do texto (bastante longo por sinal): A tentativa de definição do desenvolvimento de software como sendo Jardinagem, não engenharia... simples não é mesmo? E pra mim acabou fazendo sentido.
Nas próprias palavras de Dave Thomas:
There is a persistent notion in a lot of literature that software development should be like engineering. First, an architect draws up some great plans. Then you get a flood of warm bodies to come in and fill the chairs, bang out all the code, and you're done. A lot of people still feel that way. I saw an interview in the last six months of a big outsourcing house in India where this was how they felt. They paint a picture of constructing software like buildings. The high talent architects do the design. The coders do the constructing. The tenants move in, and everyone lives happily ever after. We don't think that's very realistic. It doesn't work that way with software.

We paint a different picture. Instead of that very neat and orderly procession, which doesn't happen even in the real world with buildings, software is much more like gardening. You do plan. You plan you're going to make a plot this big. You're going to prepare the soil. You bring in a landscape person who says to put the big plants in the back and short ones in the front. You've got a great plan, a whole design.

But when you plant the bulbs and the seeds, what happens? The garden doesn't quite come up the way you drew the picture. This plant gets a lot bigger than you thought it would. You've got to prune it. You've got to split it. You've got to move it around the garden. This big plant in the back died. You've got to dig it up and throw it into the compost pile. These colors ended up not looking like they did on the package. They don't look good next to each other. You've got to transplant this one over to the other side of the garden.


Que tal?

12 setembro 2007

Métricas em Desenvolvimento Ágil



Saudações!
Estive atrás de informações sobre métricas aliadas ao desenvolvimento Ágil, já que é necessário mensurar o desempenho e validar o estado atual de um projeto.
A pesquisa foi muito melhor do que eu imaginava. Além de regras e fórmulas, encontrei um material bastante pertinente a respeito, inclusive uma edição inteira do Agil Journal falando sobre o tema
Farei uma pequena contextualização antes de continuar:

Deviado ao custo elevado em se manter um departamento de TI (profissionais caros e equipamentos mais caros), são necessários métodos de mensurar o desempenho e garantir que o dinheiro investido não está indo para o ralo. Infelizmente à medida que nos aprofundamos no assunto, seguindo modelos tradicionais de desenvolvimento e desempenho, verificamos que falta clareza na utilização de ferramentas de mensuração, e que estamos a todo momento medindo aquilo que não é importante, deixando de lado o que realmente justifica a utilização da TI: a agregação de valor ao negócio. Ao invés disso, o foco das medidas está em atributos de software e quantidade de dinheiro dispendido. Entre essas medidas podemos citar: pontos de função criados, horas trabalhadas, número de linhas de código por desenvolvedor ou ainda orçamento gasto. Aliado à falta de estrutura para receber tais dados esse relatórios fazem que os itens tenham seu valor superestimado, criando uma visão míope do projeto.

Medidas como linhas de código por desenvolvedor ou horas trabalhadas sempre levam a problemas muito maiores para o projeto. Um programador, quando cobrado em linhas de código, evitará qualquer tipo de reutilização ou refactoring que aumente a qualidade do código para que possa parecer produtivo. Ou ainda ele poderá degradar-se completamente ao trabalhar a mais do que o necessário, criando dificuldades de relacionamento e de participação no projeto (lembrem da prática: Semana de 40 horas). Perceba a complexidade que é criar e fomentar tais medidas.

Tradicionalmente atribuimos uma medida de produtividade aos indivíduos do projeto. É pior ainda! Uma equipe deve possuir uma identidade única, que é projetada ao mundo externo como reflexo de seu comprometimento com o projeto, e não como uma série de indivíduos que trabalham por si em detrimento do grupo. Pois é isso que acontece ao medir produtividade individual das pessoas da equipe. Uma equipe deve competir para ser a melhor dentro de toda a organização. Não acredito que gerentes queiram uma equipe que disputa para ver quem é o melhor dentro dela mesma.
Mike Griffths apresenta sua visão sobre isso de forma bastante interessante em seu artigo. Baseado no Efeito Hawthorne, que demonstrou a mudança de produtividade de trabalhadores através do simples fato deles terem conhecimento da medição de produtividade, Mike apresenta a idéia de que uma medição efetiva não deve em nenhum momento atrapalhar a qualidade do projeto (medir linhas de código não é o caso), e deve estar direcionado a elementos chave para o desenvolvimento. Ele cita também um modelo de seleção de métricas definido por Donald Reinertsen:
Primeiro, deve ser simples, métricas ideais são geradas automaticamente no sentido de que não é necessário esforço extra para serem produzidas. Segundo, elas deve ser relevantes. Isto é, o controle deve ser feito pelas mesmas pessoas que estão sendo medidas. Psicólogos já descobriram que quando as pessoas acreditam que podem controlar alguma coisa, elas estarão mais motivadas para controlá-la. Mensurar uma equipe por algo que ela não tem controle apenas causará estresse, insatisfação e alienação. Terceiro, deve ser focado em indicadores de condução. Meça olhando para o futuro, e utilizando tais dados para relatar o passado. É mais fácil medir o tamando de uma fila de testes do que é medir o tempo de processamento dos testes individuais pelo fato de que o tamanho da fila é um indicador de condução para futuros atrasos no processamento do teste.


Modelos ágeis em sua concepção já promovem um jogo completo de métricas que podem ser coletadas de forma trasparente. Testes unitários, análise da qualidade de código e outras medidas técnicas podem ser automatizadas no processo de Integração Contínua. A unidade comum de trabalho - o história - é o fundamento para medidas de gerenciamento de projetos e qualidade de alinhamento de negócio. É importante lembrar que todo o ferramental existe para dar suporte a isso, e que se deve encarar este modelo de métricas com uma visão global.

Ross Pettit, em seu artigo, propõe a seguinte categorização:

  • Excelência em desenvolvimento: Consolidando objetivos para medição de código. Não deve ser analizado em separado, pois causará distorções graves.

  • Qualidade: medidas de defeitos que possam escapar ao desenvolvimento bem como o alinhamento entre desenvolvimento e especificações funcionais.

  • Sensibilidade ao negócio: para os modelos ágeis, requisitos são assumidos como user stories, tornando-se a real expressão do valor de negócio. Podem ser medidas como o grau de valor objetivado e o grau entregue.



Exemplos reais de métricas e relatórios

CFD - Cumulative Flow Diagrams
Bastante Interessante! Ele seria o complementar ao BurnDown Chart do Scrum, trazendo a relação de requisitos completos, requisitos restantes e requisitos em desenvolvimento.

No exemplo acima, o progresso é indicado pela completude da faixa verde no decorrer do projeto. Importante notar a mudança de proporção relacionada à faixa superior, indicando aumento de user stories no decorrer do projeto. Esta mudança pode indicar um problema relacionado à comunicação entre produto e desenvolvedores.

Parking-Lot Chart
Ouvi falar a primeira vez desse gráfico com Mike Cohn no livro Agile Estimating and Planning, e achei extremamente interessante! A ideia é utilizar agrupadores para reunir requisitos com o mesmo domínio e montar um grafico contendo Dominio, Numero de historias em cada dominio, numero de pontos de historia e a completude. A coisa fica mais ou menos assim:


Retirado do site Feature Driver Development

Pode-se ter uma visão bastante real do estado atual do projeto.

Ambiente Informativo
Apresentado na xpRio, na discussão a respeito de um Ambiente Informativo, Alisson Vale mostrou um modelo muito claro para trabalhar com a equipe:

Acredito que a imagem seja suficientemente auto explicativa.

RTF: Running, Tested Features
Representa a quantidade de requistos estão passando em todos os testes de aceitação. É facilmente gerado utilizando ferramentas automatizadas de teste e Teste de aceitação. Idealmente deve parecer com a imagem abaixo:

Também conhecido como Burn-Up chart. Qualquer anomalia no comportamente desta imagem deve ser encarada como um problema, já que, teoricamente, os requisitos implementados devem passar em todos os testes sempre.
Uma ótima referência para este tipo de teste pode ser encontrado aqui.


Outras medidas

Satisfação do Cliente: Determinada nos encontros entre de definição das iterações, podendo ser feita com um questionário simples de satisfação e representada através de imagens/cores. Medida interessante de ser trabalhada, pois deixa a equipe com o real estado de aceitação que o cliente se encontra.

Code coverage (quantidade de código coberto por testes)

Builds feitos com sucesso (por sprint, por semana, por dia)

Builds não realizados (por sprint, por semana, por dia)




É isso senhores... espero que tenha sido proveitoso.

10 setembro 2007

Entre Padrões de Código e a Programação Literária



Dentro da programação, uma coisa é certa: padrões são muito bem vindos. Uma vez que normalmente não estamos sozinhos num projeto, é importante que todos os desenvolvedores possam entender completamente o código produzido por qualquer um da equipe, evitando criar a idéia de propriedade de código para um único programador.
No processo de definição de padrões de desenvolvimento, deve-se levar em consideração os aspectos: Consistência, Estilo e ferramentas de suporte aos padrões.
Não me entendam mal, mas acreditar que sua equipe possue um padrão de código apenas por utilizar convenções de linguagem (ex: Java Code ConventionsM) é ingenuidade pura! (isso mesmo, ingenuidade). Code Conventions definem apenas a forma em que o código será escrito. Entretando devemos ir além, muito além disso.

Consistência
O código produzido utilizando padrões deve ser a marca da equipe e não o código produzido pelo Joãozinho ou a Mariazinha. Deve-se ter o entendimento de que qualquer um dentro da equipe pode ter desenvolvido aquele código, sem que se faça distinção de quem o escreveu.
Uncle Bob escreve muito bem essa definição ao afirmar que "Esta não é a fantasia de igualdade para que se possa sobrepujar a individualidade em detrimento do grupo, é uma necessidade básica". Como todo indivíduo possui seus próprios vícios e fetiches relacionados ao desenvolvimento, imagine 10 programadores trabalhando num mesmo código ao longo do projeto. Conforme o tempo passa, a mistura de padrões e estilos diferentes dentro do código tornará impossível sua leitura.

Estilo
Sim, uma parte importante do processo de desenvolvimento. Muitos podem se perguntar: "Qual a utilidade de definir o número de espaços que o tab representa? Por que determinar a identação correta para todos da equipe??". Falo aqui apenas da forma, não do conteúdo.
E neste ponto é importante diferenciar estilo de consistência pois eles existem para diferentes motivos. E graças a Deus nós temos o Eclipse e a capacidade de exportar um padrão determinado para arquivos xml que serão importados pelos outros desenvolvedores.

Para trasmitir o conhecimento sobre padrões é necessário um ambiente em que a comunicação possa fluir livremente, ferramentas automatizadas são importantes, mas esse conhecimento deve estar na cabeça dos desenvolvedores. Assim, práticas de Pair Programming e Code review podem ser de grande valia. Durante uma sessão de PP, para um programador mais novo, é importante que ele seja apresentado aos padrões existentes para o projeto. De forma oral, e imediata ao que ele estiver produzindo. Esqueça documentação escrita sobre padrões de código, nomes de métodos, etc... Seu código é a documentação! Um exemplo vivo dos padrões determinados em sua aplicação. Explore-o!

Acredito realmente que times devem ousar em adotar os próprios padrões de desenvolvimento, e que devam encorajar outras equipes a fazerem o mesmo. É também uma questão de identidade do grupo.

E a programação literátia?? Pois bem, falemos dela agora.

Bem, definida há quase 30 anos, a Programação Literária diz respeito à promessa de tornar o código fonte de um sistema tão fácil de compreender quanto um livro. Parece impossível? Mas não é...
Talvez seja uma herança dos tempos do Cobol, em que reduzir o nome de um método ao máximo era sinônimo de performance e economia de bytes do programa. Mas já superamos essa fase. Entretanto os problema continuam, e tentamos reduzir o nome dos métodos apenas por preguiça de escrever. Assim, um método simples com o nome: validaSenhaUsuaria() pode tornar-se algo mais complicado de se entender: valPwd(), expressando pouco sobre o significado do método.

Métodos e variáveis devem expressar seu real significado, facilitando e muito a leitura do código. Existem pessoas bastante adiantadas nesse processo, entre elas Martin Fowler, que já trata da questão com o nome: Language-oriented Programming (vale a pena ver a palestra promovida por ele)

Parece besteira, certo? Mas nem tanto. Imagine-se como um programador que, 6 meses depois, é designado a fazer manutenção de um código escrito apenas com abreviações... lhe desejo sorte para compreender o que foi produzido.
Devemos pensar no desenvolvimento como um processo contínuo de garantir a manutenção sadia para os futuros programadores, garantindo que qualquer um possa compreender e trabalhar dentro do sistema, idenpendentemente de quanto tempo atrás ele tenha sido escrito.


É isso...

06 setembro 2007

CppUnit e Borland C++ Builder 6


Bem, como vocês já sabem, estou em uma nova empresa, a Audaces. Em princípio trabalharei com integração contínua, e estou no momento fazendo testes com o ambiente da Borland. É um mundo completamente novo para mim, e estou bastante animado com os resultados! C++!! Segue abaixo um pequeno(e simples) tutorial sobre como iniciar seus testes utilizando Borland C++ Builder 6.

Configuracao de ambiente para testes utilizando o CPPUnit e Borland C++ Builder 6 (BCB6)

Referências:
Requisitos:
Instalação
Será apresentada a utilização do cppUnit para o C Builder através da criação de uma aplicação simples. Seguem os passos para tal:

1. Descompactar CPPUnitBCB6 (Ex: C:\CPPUnitBCB6)

2. Iniciar um projeto novo no BCB (File> New >Application)

2.1 Vincular ao projeto os Headers relativos ao CppUnit.
Faça isso adicionando os diretórios ao projeto em "Project> Options> Directories/Conditionals >Include path"
Selecione os diretórios:

%cppunit_dir%\borland\TestRunner
%cppunit_dir%\test\textui
%cppunit_dir%\test\framework
%cppunit_dir%\test\framework\extensions


2.2 Remover o formulário inicial (Form1) em "Project> Remove from Project...> Unit1.cpp"

3. Adicione ao projeto as bibliotecas do CppUnit (podem ser copiados para o diretório raiz do projeto de exemplo):

%cppunit_dir%\bin\culib.lib
%cppunit_dir%\bin\TestRunnerDlg.lib
%cppunit_dir%\bin\TestRunnerDlg.dll


4. Crie uma classe de testes Simples:

A primeira classe a ser criada será chamada de FirstTest. Iniciaremos por seu Header, que deve extender a classe TestCase. É necessário declarar os métodos setUp() e tearDown() para que o funcionamento ocorra normalmente.

#ifndef FIRST_TEST_H
#define FIRST_TEST_H

#include "TestCase.h"
#include "TestCaller.h"

class FirstTest: public TestCase
{
public:
FirstTest(std::string name);
void setUp();
void tearDown();
static Test *suite();
protected:
void testAssertTrue();
void testAssertFalse();
void testFalhara();
void testAssertMaisUmExemplo();


};

typedef TestCaller FirstTestCaller;
#endif


Abaixo segue a implementação dessa classe. FirstTest.cpp
#include "FirstTest.h"
#include "TestSuite.h"

FirstTest::FirstTest(std::string name): TestCase(name) {
}

void FirstTest::setUp() { }

void FirstTest::tearDown() { }
Test* FirstTest::suite() {
// All tests have to be explicity added to TestSuite to be executed
TestSuite *suite ;
suite = new TestSuite("nameFirstTest");
suite->addTest(new FirstTestCaller("assert True", &FirstTest::testAssertTrue));
suite->addTest(new FirstTestCaller("assert False", &FirstTest::testAssertFalse));
suite->addTest(new FirstTestCaller("teste que falha", &FirstTest::testFalhara));
suite->addTest(new FirstTestCaller("teste equals", &FirstTest::testAssertMaisUmExemplo));
return (suite);
}



void FirstTest::testAssertTrue()
{
assert( true );
}

void FirstTest::testAssertFalse()
{
assert( !false );
}

void FirstTest::testFalhara()
{
assert( false );
}

void FirstTest::testAssertMaisUmExemplo()
{
assertDoublesEqual(0, 0, 0);
}



6. Testando o funcionamento do CppUnit:

O método suite() serve para que se possa adicionar todos os métodos de testes que a classe possui e que devem ser executados. Caso um método nao seja adicionado ao TestSuite neste método, ele não serpa executado.
Edite o código inicial do projeto ("Project> View Source"), adicionando a chamativa ao CppUnit após a compilar a aplicação. Exemplo exemplo.cpp:
#include 
#pragma hdrstop

#include "ITestRunner.h"
#include "FirstTest.h"
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
ITestRunner runner;

runner.addTest(FirstTest::suite());

runner.run();

}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}



Pressione F9. Uma ferramenta gráfica aparecerá e você terá como visualizar todos os testes escritos na classe FirstTest. Clique em run e divirta-se.
Obs: propositalmente neste tutorial eu inseri um teste que falhará, para que você possa ver o funcionamento da ferramenta...

=)

27 agosto 2007

Coding Dojo Floripa dia 30/08



Saudações!
O Próximo DojoFloripa será dia 30/08 na Fundação Certi.
Necessário confirmar presença: (gaa@certi.org.br)

Mais informações: CodingDojoFloripa

26 agosto 2007

You think you know (JavaScript) but you have no idea


Seguindo a iniciativa do Rafael Mueller, que por sinal foi muito bem sucedida, vou tentar apresentar um pouco sobre JavaScript, tentando desmistificar essa história de JS como uma Ciência Oculta, destinada apenas às famosas gambiarras do mundo do desenvolvimento de software.

Concordo com o Douglas Crockford quando ele diz que JavaScript é a Lingaguem de Programação mais não-compreendida do mundo. E digo mais, isso é culpa nossa!
Somos nós, programadores, que normalmente não buscamos a melhoria de nosso código fonte devido a uma série de fatores: falta de ferramentas de apoio, desinteresse ou preguiça. Acreditar que no desenvolvimento web a camada de apresentação não precisa da mesma atenção e cuidados que as camadas de persistência e negócio, é fadar o sistema ao limbo da manutenção.

Vou passar alguns conceitos, visando a melhoria do código produzido em javascript:

Você pode não gostar da idéia, mas a grande maioria dos computadores do mundo possuem ao menos um interpretador JS instalado.

Orientação a objetos

Sim! Orientado a objetos! De uma maneira diferente de algumas linguagens, mas javascript e totalmente orientado a objetos. E infelizmente como toda linguagem (ak. Java, Cpp, C#) também existe uma enorme possibilidade de produzir código ruim, escrevendo um programa sem a menor compreensão de OO.

JS possui objetos que podem conter dados ou métodos para tratar dados. Objetos podem conter outros objetos. Mesmo não possuindo a definição de classes, existe o conceito de constructor que possui o mesmo princípio. Ainda possui um sistema de objetos com herança (é-um) e agregação (possui-um).

Metodos e atributos privados? Claro que possue....

Vamos ao código:

Variáveis e Métodos públicos


Os membros de um objeto são sempre públicos. Podem ser modificados, utilizados ou alterados por qualquer função. Existem duas maneira de colocar novos membros a um objeto:

Utilizando um construtor:
function Container(param) {
this.nome = param;
}

Criando Objeto:
var umContainer = new Container('nomeCont');

Assim, a umCantainer.nome possui o valor 'nomeCont'.

Utilizando o prototype:
Tecnica utilizada para adicionar metodo publicos a um objeto. O mecanismo de prototype é utilizado para herança, ele também conserva memória. Para adicionar um novo metodo a um objeto:

Container.prototype.getNome = function(){
return this.nome;
}

Assim o método pode ser utilizado normalmente:
umContainer.getNome()


Métodos estáticos:
A estratégia de utilizar o prototype é uma grande vantagem para o desenvolvimento, entretanto os métodos criados através desse modelo ficam acessíveis apenas após a instância do objeto. Uma maneira de criar métodos estáticos em JS é através do mesmo princípio que utilizamos acima, com atributos:
function Container(param) {
this.nome = param;

this.metodoEstatico = function() {
return 'Eu sou um método estático';
}
}

Tanto o atribuito Container.nome quanto Container.metodoEstatico() estão disponiveis sem que haja a necessidade de instarciar a classe.


Variáveis e Métodos privados


Variáveis dentro de um objeto são considerados privados:
function Container(param) {
this.nome = param;
var secret = 0;
var that = this;

function diminuirUm() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
}

Acima, o atributo secret é apenas acessível pela própria instância do objeto Container, assim como o metodo diminuirUm. O atributo that, descrito como a solução para um problema de Especificação da Linguagem ECMAScript, serve para tornar o objeto disponível para os métodos privados. Assim, para fazer uso de métodos privados, necessitamos apresentar o conceito de métodos Privilegiados, capazes de acessos metodos públicos e privados de um objeto.

Métodos privilegiados

São métodos destinados a serem acessíveis de forma pública, entretanto possuem acesso aos métodos privados de um objeto. É possível removê-lo ou alterá-lo, mas não é possível através dele ter acesso real (alteração, exclusão) aos métodos e atributos privados.
function Container(param) {
this.nome= param;
var secret = 3;
var that = this;

function diminuirUm() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}

this.service = function () {
if (dec()) {
return that.nome;
} else {
return null;
}
};
}

service é um método privilegiado. Chamando umContainer.service() obteremos o retorno 'nomeCont' apenas por três vezes, e após isso será sempre retornado null. service é disponível para outros objetos, mas seus atributos não.


Será que consegui melhorar seu conceito?? Ainda não?? Logo tem mais!
Fonte

Douglas Crockford fala sobre JavaScript

21 agosto 2007

TDD Anti-Patterns

Aqui está a tradução (e considerações) para o texto de James Carr entitulado TDD Anti-Patterns
Acredito que essa contribuição é válida, pois ainda vejo muitas pessoas buscando materiais em português sobre testes, e encontrando pouca coisa de qualidade. Segue o texto abaixo:


Catálogo de Anti-Padrões em TDD

  • The Liar
    • Todos os metodos de um teste unitário estão passando perfeitamente, aparentando serem validos, entretanto sob uma inspeção mais próxima é descoberto que o teste unitário não testa o real intuíto para que foi criado.
  • Excessive Setup
    • Um teste que necessita muito trabalho para ser configurado antes mesmo de ser executado. Algumas vezes centenas de linhas de código tornam-se necessárias para adaptar o ambiente a um único método de testes, com dezenas de objetos envolvidos. Aqui a maior dificuldade é compreender "o quê" realmente está sendo testado dentro de toda a "sujeira" que um setup pode causar. (tradutor: Lembrem-se sempre do princípio KISS)
  • The Giant
    • Um teste unitário que, mesmo sendo verdadeiro na intenção de validar um objeto, pode possuir centenas de linhas contendo inúmeros casos de teste (inúmeros mesmos). Esta pode ser uma indicação do que chamamos de God Object, objeto que possui responsabilidades demais dentro do sistema. Indício claro de alto acoplamento em seu sistema.
  • The Mockery
    • Muitas vezes um mock pode ser útil e bastante indicado. Mas desenvolvedores podem perder tempo desnecessariamente esforçando-se em mockear o que não está sendo testado. Percebe-se neste caso que a classe possuí tantos mocks, stubs ou fakes que no final das coisas o sistema não está sendo testado, mas o que é retornado da interação entre os mocks. (tradudor: use apenas o que for estritamente necessário!)
  • The Inspector
    • Um teste unitáro que viola o encapsulamente em um esforço de atingir 100% de cobertura de testes, mas está situação nem sempre é favoravél, pois qualquer tentativa de refactor pode quebrar testes desnecessariamente, necessitanto adequações nas classes de teste unitário.
  • Generous Leftovers
    • Uma instância de um teste unitário cria um dado que é persistido em algum lugar, e outro teste utiliza tal dado para seus próprios asserts. Caso algo saia errado, o teste que utiliza o dado cadastrado também falhará. (tradutor: Testes devem ser independentes! )
  • The local Hero
    • Um teste que é dependente de algo específico do ambiente de desenvolvimento em que ele foi escrito. O resultado: o teste passa perfeitamente na células de desenvolvimento, mas falha quando alguém tenta executá-lo fora desse ambiente.
  • The Nitpicker
    • Um teste unitáro que compara toda a saída quando o que lhe deveria interessar é uma pequena parte apenas, assim o teste deve se manter sempre alinhado com detalhes que o teste não deveria tratar. Esta situação é endemica em testes de aplicações web.
  • The Dodger
    • Um teste unitário que possui muitos testes para efeitos pequenos (e presumidamente simples de testar), mas nunca testando o comportamente real desejado. Encontrado em testes relacionados para testes de banco de dados, onde um método é chamado, e então o teste seleciona itens do banco e procede asserts contra os resultados.
  • The Loudmout
    • Um teste unitário (ou suite de testes) que enxe o console com mensagens de diagnóstico, logs e qualquer outro tipo de saídas, mesmo quando os testes estão passando. Algumas vezes durante a criação dos testes existe o desejo de manualmente ver a saída dos metodos, mas mesmo eles deixando de serem necessários, são deixados para trás.
  • The Greedy Catcher
    • Um teste unitário que trata exceções e sobrepões pilhas de execução (stack trace) algumas vezes com mensagens menos informativas, mas algumas vezes ainda apenas logando (Loudmouth) e deixando o teste passar.
  • The Sequencer
    • Um teste unitário dependente de uma lista que sempre é retornada em forma desordenada.
  • Hidden Dependecy
    • Primo de primeiro grau do "The Local Hero", um teste unitário dependente de um dado que deve ser populado em algum lugar par ao teste rodar. Se o dado não estive presente, o teste falhará deixando pouca informação para o desenvolvedor o que é necessário, ou porque o teste falhou... forçando-o a buscar através de uma floresta de código para descobrir de onde vem o dado que o teste deveria utilizar.
  • The Enumerator
    • Um teste unitário em que os nomes de métodos são apenas uma enumeração: teste1, teste2, teste3. Como resultado, a intenção dos testes torna-se pouco clara, e a única maneira de ter certeza é ler o código fonte e rezar para que esteja bem escrito.
  • The Stranger
    • Um método de teste que nem ao menos pertence ao Teste Unitário que ele está inserido. O método está realmente testando um objeto separado e independente, normalmente um objeto utilizado pelo objeto que sofre o teste.
  • The Operating System Evangelist
    • Um teste unitário que está ajustado apenas para um determinado sistema operacional para que possa funcionar. Um bom exemplo seria um caso de teste que utilize o separador de linhas do Windows para um assert, que falha apenas rodando em Linux.
  • Success Against All Odds
    • Um teste escrito para passar antes mesmo de falhar. Como um infeliz efeito colateral, o caso de teste acaba sempre passando mesmo que tenha sido feito para falhar.
  • The Free Ride
    • Ao invés de escrever um novo teste para uma nova funcionalidade ou característica, apenas um novo assert é criado ao final de um teste já existente.
  • The One
    • Uma combinação de alguns outros padrões, particularmente o TheFreeRide e TheGiant. Um teste unitário que contém apenas um único metodo que teste todo tipo de funcionalidade que um objeto pode conter. Um indicador comum é que o teste possui o mesmo nome da classe, e ainda com múltiplas linhas, setups e asserts
  • The Peeping Tom
    • Um teste que, compartilhando recursos, pode ver o resultado de outro test, e pode falhar mesmo que o sistema testado esteja em perfeito funcionamento. Verificado na ferramenta Fitnesse, onde a utilização de variáveis estáticas para abrigar coleções não eram corretamente limpas após a execução do teste, podendo surgir erros durante a execução de qualquer teste. Também conhecido com TheUninvitedGuests.
  • The Slow Poke
    • Um teste unitário que é incrivelmente lento para ser executado. Quando o teste é iniciado, os programadores podem ir ao banheiro, fumar um cigarro ou pior ainda, inicar o teste no final do dia e ir para casa, esperando que o resultado saia no dia seguinte.

Fonte

Treinamento de TDD: Testes! Código! Ação!

Evento que será realizado aqui perto, em Joinville - SC:

Treinamento de TDD na PyCon Brasil 3, em Joinville, SC.

Nível da Palestra: Intermediário

Como desenvolver código limpo, fácil de evoluir e que possa ser mudado sem medo quando necessário? Este treinamento é um exercício prático e interativo de Desenvolvimento Dirigido por Testes (TDD), uma das práticas mais eficazes da Programação eXtrema (XP). Os participantes serão guiados no desenvolvimento "ao vivo" de um jogo simples a partir de testes unitários, enfatizando os valores desta prática e a importância do foco constante no design simples e em código correto, conciso e legível.

Palestrantes

Rodrigo Bernardo Pimentel e Danilo Toshiaki Sato

São Paulo - SP

Rodrigo: Programador por profissão e hobby. Pythonista há alguns anos. Curioso. Escreve em http://isnomore.net.

Danilo: Desenvolvedor de software generalista, consultor da AgilCoop, mestre pela USP e blogger esporádico em http://www.dtsato.com.



Mais informações


Infelizmente não poderei ir... será que alguém do CodingDojo estará por lah?

16 agosto 2007

50 ações para conter o Aquecimento Global

Há pouco tempo assisti a um filme impressionante: Uma Verdade inconveniente, onde Al Gore discursa sobre o aquecimento global. Muito bem fundamentado, o filme trata do aquecimento global, com a seguinte premissa: cabe a nós, cidadãos do mundo, o papel de conter o processo. E ainda há tempo.

Pesquisando sobre o assunto, acessando o Ueba encontrei um texto falando das 50 ações para conter o aquecimento global. Vou listar as mais simples e importantes abaixo:

  • Gere menos lixo!!
    • use canecas ao invés de copos descatáveis
    • garrafinhas de água
    • leve grandes sacolas ou bolsas ao supermercado
    • se o intuíto de algum item é ir direto para o lixo, por quê levá-lo para casa? isso vale para papeizinhos de rua, sacos plásticos e extratos bancários impressos
    • utilize menos CDs e DVDs substituindo-os por penDrivers e emails de grande espaço
  • Troque suas lâmpadas incandescentes por fluorescentes
    • 60% a menos de energia do que as convencionais
  • Escolha eletrodomésticos de baixo consumo energético
    • O imetro criou um selo de consumo de energia para aparelhos - Escolha produtos com este selo (Veja as tabelas de consumo)
  • Não deixe seus aparelhos em standby
    • Economize 15% a 40% da energia que seus aparelhos consomem
  • Use a máquina de lavar roupas/louça só quando estiverem cheias
    • assim, água e energia são economizadas
  • Nunca é demais lembrar: RECICLE
    • Que tal propor o seguinte: separação do lixo em seu condomínio?? Na sua empresa?? simples...
    • Empresas hoje conseguem reduzir muitos custos com um programa simples: reciclagem de papel! Impressoes com problemas saem do lixo e transformam-se diretamente em dinheiro no caixa das empresa!
    • Por que nao fazer o mesmo com o seu condomínio?? Que tal diminuir a taxa de arrecadação (o famoso rateio) mensal de todos os apartamentos com uma proposta de venda de papel para reciclagem e latas de alumínio??? COISA CHIQUE D+!!!!
  • Reduza o uso de embalagens
    • Eu acabo sendo chato... mas tente repetir a seguinte frase para o atendente que insiste em colocar numa sacola a caixa do dvd na locadora: "Não precisa de sacola, muito obrigado. Gera mais lixo". Qual será a reação dele??
    • Vá às compras de mochila ou sacola e evite compras muito grandes: consumismo demais gera lixo demais
  • Lave o carro a seco
  • Vá de escada
    • Hábitos saudáveis também são muito úteis. Pergunte-se: será que preciso realmente ir de elevador?
  • ECONOMIZE ÁGUA
    • Preciso dizer algo mais???

Veja a lista completa