Na época de volta às aulas nas faculdades percebe-se uma grande invasão de alunos desesperados em foruns de informática para resolverem os seus execícios. É facil reconhecer um aluno em pânico com o seu primeiro while ou algum exercício sobre Fibonacci: eles não tentam, simplesmente colam o enunciado do problema esperando a resposta pronta.
Entretanto tão bizarro quanto são os exercícios propostos: um programa que leia pergunte 2 numeros e retorne a soma, ou um programa para calcular alguma coisa que pergunte ao usuário… perai, pergunte? Um programa perguntando? Como?
Este é o típico programa ‘interativo’ com o usuário. Quando não usa a entrada padrão (algo completamente misterioso para boa parte dos alunos), usam algum recurso SWING. Mas sera que ninguem pensa o quão PREJUDICIAL são estes exercícios?
Normalmente o aluno se preocupa com a apresentação do mesmo, fazendo frescuras de menuzinhos, asteriscos pra lá e pra cá… e o algoritmo que é bom nada. Sinceramente: dane-se os menuzinhos. Sabem quantos programas com menuzinhos e que vão perguntar alguma coisa pro usuario vcs vão fazer na vida profissional de vcs? 0! Zero! Nenhum!
Existem muitas formas de interação com o usuario, hoje em dia vc pode ter interfaces web, por exemplo. Eu acho que, num primeiro momento, a única interação com o usuario deveria ser escrever na tela. Nada mais que isso se o camarada não sabe o que significa um NullPointerException.
Exemplo pratico:
- Prepare um diretório para trabalhar (suponho que vc vai usar linux, senão deve ser facil portar este exemplo para outros sistemas operacionais).
- Crie um diretorio lib e copie o junit-4.4.jar pra lá (use o google pra baixar esse arquivo, se vc não conseguir saia do curso de informática).
- Crie a estrutura abaixo, ainda no diretório de trabalho:
src/java
src/test
- Instale o aplicativo ant (de novo o google te ajuda, alias vc tem algum JDK instalado, certo??).
- Crie um arquivo chamado build.xml no diretorio de trabalho.
- Baixe o arquivo ant-junit.jar daqui [ http://www.java2s.com/Code/Jar/ANT/Downloadantjunitjar.htm ] e copie o .JAR para ~/.ant/lib (se não existe, crie).
Agora vem a proposta: baseado nessa interface:
Vais criar uma classe chamada, digamos, SuaClasse que implementa esta interface (percebeu que tudo deve ficar em src/java não é?). Não pense na implementação dessa classe ainda.
No diretorio src/test vc vai salvar esta classe:
Uma ideia sobre o JUnit pode ser encontrada aqui: [ http://guj.com.br/java.tutorial.artigo.40.1.guj ], alias o guj, na sessão de tutoriais, explica varias coisas, é ótimo material de referência!
Ok, vc tem a interface que vc deve respeitar e um arquivo de teste. Vamos falar do arquivo de build do ant.
A utilização desse arquivo é muito simples, não se amedronte pelo tamanho do arquivo, o formato xml do ant é bizarro e verboso, sou muito mais um Makefile, porém uma vez com ele feito basta ir adicionando coisas “com cuidado”. Sem falar que tudo tem documentação oficial cheia de exemplos, só não aprende quem não quer.
$ ant
isso deve compilar a sua classe e gerar um jar (pode ser util no futuro).
$ ant clean
limpa os diretorios que vc acabou de criar com as suas paradas compiladas.
$ ant test
compila e executa os testes unítarios.
É claro que vc vai dizer, e agora??? Bom, veja isso:
Olha que legal! Uma classe que tem o minimo pra compilar! Agora vamos testar…
Agora basta escrever codigo de verdade na SuaClasse e testar, estara pronto quando TUDO estiver passando. São 4 métodos básicos, sabendo lidar com variaveis locais, if e for, vc consegue muita coisa.
Se eu fosse professor eu daria exercícios assim: o projeto deveria compilar e todos os testes deveriam passar senão o aluno leva 0. A nota viria de acordo com o que eu espero, posso usar um EMMA e ver a cobertura de código, posso avaliar a presença de um Javadoc que preste, etc.
Enfim, eu seria um professor muito malvado }-)
Não perca a parte 2 aqui, e uma introdução ao TDD aqui.
Entretanto tão bizarro quanto são os exercícios propostos: um programa que leia pergunte 2 numeros e retorne a soma, ou um programa para calcular alguma coisa que pergunte ao usuário… perai, pergunte? Um programa perguntando? Como?
Este é o típico programa ‘interativo’ com o usuário. Quando não usa a entrada padrão (algo completamente misterioso para boa parte dos alunos), usam algum recurso SWING. Mas sera que ninguem pensa o quão PREJUDICIAL são estes exercícios?
Normalmente o aluno se preocupa com a apresentação do mesmo, fazendo frescuras de menuzinhos, asteriscos pra lá e pra cá… e o algoritmo que é bom nada. Sinceramente: dane-se os menuzinhos. Sabem quantos programas com menuzinhos e que vão perguntar alguma coisa pro usuario vcs vão fazer na vida profissional de vcs? 0! Zero! Nenhum!
Existem muitas formas de interação com o usuario, hoje em dia vc pode ter interfaces web, por exemplo. Eu acho que, num primeiro momento, a única interação com o usuario deveria ser escrever na tela. Nada mais que isso se o camarada não sabe o que significa um NullPointerException.
Exemplo pratico:
- Prepare um diretório para trabalhar (suponho que vc vai usar linux, senão deve ser facil portar este exemplo para outros sistemas operacionais).
- Crie um diretorio lib e copie o junit-4.4.jar pra lá (use o google pra baixar esse arquivo, se vc não conseguir saia do curso de informática).
- Crie a estrutura abaixo, ainda no diretório de trabalho:
src/java
src/test
- Instale o aplicativo ant (de novo o google te ajuda, alias vc tem algum JDK instalado, certo??).
- Crie um arquivo chamado build.xml no diretorio de trabalho.
- Baixe o arquivo ant-junit.jar daqui [ http://www.java2s.com/Code/Jar/ANT/Downloadantjunitjar.htm ] e copie o .JAR para ~/.ant/lib (se não existe, crie).
Agora vem a proposta: baseado nessa interface:
public interface Algoritmo{
/* dado um numero, retorna true se for par */
boolean ehPar(int numero);
/* calcula o valor absoluto ou modulo de um numero, ex: -1 vira 1, 1 vira 1 */
int calculaModulo(int numero);
/* calcula algum termo da série de fibonacci: se 0, mostra o primeiro, se 1 mostra o segundo...*/
int calculaFibonacci(int elemento);
/* calcula o fatorial do numero indicado */
long calculaFatorial(int numero);
}
Vais criar uma classe chamada, digamos, SuaClasse que implementa esta interface (percebeu que tudo deve ficar em src/java não é?). Não pense na implementação dessa classe ainda.
No diretorio src/test vc vai salvar esta classe:
import junit.framework.TestCase;
public class AlgoritmoTeste extends TestCase{
Algoritmo algoritmo;
public void setUp(){
algoritmo = new SuaClasse();
}
public void tearDown(){
algoritmo = null;
}
public void testEhPar() throws Exception{
assertTrue("2 deve ser par",algoritmo.ehPar(2));
assertTrue("4 deve ser par",algoritmo.ehPar(4));
assertTrue("6 deve ser par",algoritmo.ehPar(6));
assertTrue("1 NAO deve ser par",!algoritmo.ehPar(1));
assertTrue("3 NAO deve ser par",!algoritmo.ehPar(3));
assertTrue("5 NAO deve ser par",!algoritmo.ehPar(5));
}
public void testCalculaModulo() throws Exception{
assertTrue("modulo de 3 deve ser 3",algoritmo.calculaModulo(3) == 3);
assertTrue("modulo de -3 deve ser 3",algoritmo.calculaModulo(-3) == 3);
assertTrue("modulo de 5 deve ser 5",algoritmo.calculaModulo(5) == 5);
assertTrue("modulo de -5 deve ser 5",algoritmo.calculaModulo(-5) == 5);
}
public void testCalculaFibonacci() throws Exception{
assertTrue("elemento 0 da serie fibonacci deve ser 0",algoritmo.calculaFibonacci(0) == 0);
assertTrue("elemento 1 da serie fibonacci deve ser 1",algoritmo.calculaFibonacci(1) == 1);
assertTrue("elemento 2 da serie fibonacci deve ser 1",algoritmo.calculaFibonacci(2) == 1);
assertTrue("elemento 3 da serie fibonacci deve ser 2",algoritmo.calculaFibonacci(3) == 2);
assertTrue("elemento 4 da serie fibonacci deve ser 3",algoritmo.calculaFibonacci(4) == 3);
assertTrue("elemento 5 da serie fibonacci deve ser 5",algoritmo.calculaFibonacci(5) == 5);
assertTrue("elemento 6 da serie fibonacci deve ser 8",algoritmo.calculaFibonacci(6) == 8);
assertTrue("elemento 7 da serie fibonacci deve ser 13",algoritmo.calculaFibonacci(7) == 13);
assertTrue("elemento 11 da serie fibonacci deve ser 89",algoritmo.calculaFibonacci(11) == 89);
assertTrue("elemento 13 da serie fibonacci deve ser 223",algoritmo.calculaFibonacci(13) == 233);
}
public void testCalculaFatorial() throws Exception{
assertTrue("Fatorial de 1 deve ser 1",algoritmo.calculaFatorial(1) == 1);
assertTrue("Fatorial de 2 deve ser 2",algoritmo.calculaFatorial(2) == 2);
assertTrue("Fatorial de 3 deve ser 6",algoritmo.calculaFatorial(3) == 6);
assertTrue("Fatorial de 4 deve ser 24",algoritmo.calculaFatorial(4) == 24);
assertTrue("Fatorial de 5 deve ser 120",algoritmo.calculaFatorial(5) == 120);
assertTrue("Fatorial de 6 deve ser 720",algoritmo.calculaFatorial(6) == 720);
assertTrue("Fatorial de 10 deve ser 3628800L",algoritmo.calculaFatorial(10) == 3628800L);
}
}
Uma ideia sobre o JUnit pode ser encontrada aqui: [ http://guj.com.br/java.tutorial.artigo.40.1.guj ], alias o guj, na sessão de tutoriais, explica varias coisas, é ótimo material de referência!
Ok, vc tem a interface que vc deve respeitar e um arquivo de teste. Vamos falar do arquivo de build do ant.
<project name="Meu Projeto" basedir="." default="dist">
<description>
Aprendendo a fazer um build.xml para o ant
</description>
<property name="lib" location="lib"/>
<property name="src" location="src/java"/>
<property name="test" location="src/test"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<path id="classpath.test">
<pathelement location="${test}" />
<pathelement location="${build}" />
<pathelement location="${lib}/junit-4.4.jar" />
</path>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init" description="compile the source " >
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile" description="generate the distribution" >
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<jar jarfile="${dist}/lib/Algortimo-${DSTAMP}.jar" basedir="${build}"/>
</target>
<target name="clean" description="clean up" >
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
<target name="test" depends="compile">
<javac srcdir="${test}">
<classpath refid="classpath.test"/>
</javac>
<junit>
<classpath refid="classpath.test" />
<formatter type="brief" usefile="false" />
<test name="AlgoritmoTeste"/>
</junit>
</target>
</project>
A utilização desse arquivo é muito simples, não se amedronte pelo tamanho do arquivo, o formato xml do ant é bizarro e verboso, sou muito mais um Makefile, porém uma vez com ele feito basta ir adicionando coisas “com cuidado”. Sem falar que tudo tem documentação oficial cheia de exemplos, só não aprende quem não quer.
$ ant
isso deve compilar a sua classe e gerar um jar (pode ser util no futuro).
$ ant clean
limpa os diretorios que vc acabou de criar com as suas paradas compiladas.
$ ant test
compila e executa os testes unítarios.
É claro que vc vai dizer, e agora??? Bom, veja isso:
public class SuaClasse implements Algoritmo{
public boolean ehPar(int numero){return false;}
public int calculaModulo(int numero){ return -1;}
public int calculaFibonacci(int elemento){return -1;}
public long calculaFatorial(int numero){return -1;}
}
Olha que legal! Uma classe que tem o minimo pra compilar! Agora vamos testar…
$ ant test
Buildfile: build.xml
init:
[mkdir] Created dir: /home/GLOBO.COM/peczenyj/test/junit/build
compile:
[javac] Compiling 2 source files to /home/GLOBO.COM/peczenyj/test/junit/build
test:
[javac] Compiling 1 source file
[junit] Testsuite: AlgoritmoTeste
[junit] Tests run: 4, Failures: 4, Errors: 0, Time elapsed: 0.005 sec
[junit]
[junit] Testcase: testEhPar(AlgoritmoTeste): FAILED
[junit] 2 deve ser par
[junit] junit.framework.AssertionFailedError: 2 deve ser par
[junit] at AlgoritmoTeste.testEhPar(Unknown Source)
[junit]
[junit]
[junit] Testcase: testCalculaModulo(AlgoritmoTeste): FAILED
[junit] modulo de 3 deve ser 3
[junit] junit.framework.AssertionFailedError: modulo de 3 deve ser 3
[junit] at AlgoritmoTeste.testCalculaModulo(Unknown Source)
[junit]
[junit]
[junit] Testcase: testCalculaFibonacci(AlgoritmoTeste): FAILED
[junit] elemento 0 da serie fibonacci deve ser 0
[junit] junit.framework.AssertionFailedError: elemento 0 da serie fibonacci deve ser 0
[junit] at AlgoritmoTeste.testCalculaFibonacci(Unknown Source)
[junit]
[junit]
[junit] Testcase: testCalculaFatorial(AlgoritmoTeste): FAILED
[junit] Fatorial de 1 deve ser 1
[junit] junit.framework.AssertionFailedError: Fatorial de 1 deve ser 1
[junit] at AlgoritmoTeste.testCalculaFatorial(Unknown Source)
[junit]
[junit]
[junit] Test AlgoritmoTeste FAILED
BUILD SUCCESSFUL
Total time: 1 second
Agora basta escrever codigo de verdade na SuaClasse e testar, estara pronto quando TUDO estiver passando. São 4 métodos básicos, sabendo lidar com variaveis locais, if e for, vc consegue muita coisa.
Se eu fosse professor eu daria exercícios assim: o projeto deveria compilar e todos os testes deveriam passar senão o aluno leva 0. A nota viria de acordo com o que eu espero, posso usar um EMMA e ver a cobertura de código, posso avaliar a presença de um Javadoc que preste, etc.
Enfim, eu seria um professor muito malvado }-)
Não perca a parte 2 aqui, e uma introdução ao TDD aqui.
Infelizmente muitos professores se preocupam mais com telinhas e “firulas” do que o que é importante na disciplina, pior é que muitos destes professores nunca nem ouviram falar sobre TDD ou mesmo testes unitários!
Terminam as matérias que envolvem programação sabendo como fazer sobrecarga de operadores, mas implementando toda a lógica de um programa dentro de uma única classe com métodos static. Sabem fazer janelas com botões bonitinhos, mas se matam para implementar a lógica do programa.
Ficaria feliz se minha primeira aula de programação fosse no esquema do seu post. Sempre gostei de brincar com os exercícios propostos em sala, mas o cara era tão inflexível que certo dia veio me pedir para trocar de editor de texto, porque o que eu estava utilizando era complicado demais (vim) e me confundiria (wtf?). Tive aulas bastante boas depois, com um cara que valorizava o que é realmente essencial, mas alguns de meus colegas não tiveram a mesma sorte e continuaram tendo aulas desse tipo durante vários semestres.
Triste é ver o camarada que me pediu para trocar de editor de texto sendo citado como “excelente professor para quem está começando”. :-|
Mas tem quem cague pra isso. Paciência, depois vai pegar um estágio onde vai ter que fazer algo muito pior e sem internet pra poder postar as dúvidas!
Interessante notar que alguns professores que fazem os alunos pensarem mas ensino coisas inúteis não tem fama tão ruim…
Agora, Tiago, vc deveria dar aulas para alguns professores sobre como ensinar de verdade… hehe
Muito bom.
Pelo menos foi isso que eu vi acontecer. :(
De qualquer maneira, concordo com o seu post, e se um dia eu der aula, vou seguir a dica !
Onde já se viu utilizar Junit, ant e essas bizarrices em sala de aula?
Cadê o bom e velho pascal? [engraçado que tem aluno do 5º semestre ainda chamando de pascoal]
Cadê os System.out.println que todo sistema de vergonha tem?
:)
Tirando a brincadeira, muito bom seu artigo!