10 coisas que todo o programador deveria saber

15 de março de 2009

Listas de x coisas só servem para lembrar de tudo o que ficou de fora, portanto, IMHO, as 10 coisas que todo o programador deveria saber são:

0 – usar o google
1 – fazer um hello world em pelo menos 5 linguagens de programação diferentes (sendo uma funcional e uma script)
2 – instalar o wordpress e tudo o que é necessario para que o mesmo execute.
3 – instalar e configurar o Ubuntu, ou outro *nix, incluindo configuração de rede e impressão
4 – entender o que é CLASSPATH
5 – saber a diferença entre HTTP e FTP, entre TCP e UDP e qual camada OSI eles atuam. bonus: saber como funciona um GET ou POST (é possivel ver usando o live http headers do firefox).
6 – conhecer o comando grep e algumas opções como -c, -v, -A
7 – SQL: entender o que é select,update,insert, delete, commit, rollback
8 – como ler e gerar XML
9 – entender o que é NULL, \0, **qqcoisa do C e quais os seus usos (principalmente em strings)
10 – a diferença entre licença BSD e GPL veja aqui.

Alem disso é bom seguir alguns blogs, frequentar foruns, listas de discussão e ler muito. Mesmo um texto “chato” como A Catedral e o Bazar traz informações relevantes e outras referencias.

Boa sorte e que começe a flame-war :)

Rating 3.80 out of 5
[?]

JMock – trabalhando com mock objets em java

15 de março de 2009

Lendo sobre testes unitarios, imagine o caso onde o seu teste é complexo: um objeto que chama outro e, então, realiza as suas tarefas. Um bom caso é um DAO que acessa o banco de dados para fazer alguma coisa: se vc pensa em testar esse codigo de forma unitaria teria que subir um banco de testes e, se encontrasse um problema, poderia ser dificil dizer se é problema do DAO ou dos objetos que ele depende (como a conexão com o banco, ou o banco em si).

A solução para estes casos pode ser trabalhar com mocks: objetos “burros” que podem não ter nenhuma função alem de responder ao que vc especificou. A abordagem mais utilizada é vc programar estes objetos para responder a um ou mais metodos com argumentos especificos, assim como as respostas esperadas. No caso do DAO eu posso esperar um determinado SQL e especificar uma determinada resposta, tudo de acordo com o meu cenario de teste.

É claro que Mock Objects em excesso podem atrapalhar, mas é tudo uma questão de bom senso: costumo dizer para quem esta começando a focar os testes nas partes mais importantes do sistema, o core do modelo e regras de negocio e, então, incrementar estas praticas caso veja necessidade. Sem falar que volta e meia surge algo novo.

Para java existe o excelente framework JMock. Logo de cara o site oficial traz um exemplo de como utilizar um mock bem simples (incluindo a integração do mesmo com JUnit 4)

http://www.jmock.org/getting-started.html

Para entender, imagine esta interface

interface Subscriber {
    void receive(String message);
}

Imagine que eu tenho um objeto do tipo Publisher que, ao invocar o metodo publish(message), ele envie esta mensagem para um Subscriber (que recebe com o metodo acima). Para testar o publish eu teria que me certificar que o metodo receive deste objeto Subscriber foi invocado com a mensagem especificada, mais ou menos assim:

import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.Expectations;
 
@RunWith(JMock.class)
class PublisherTest {
    Mockery context = new JUnit4Mockery();
 
    @Test
    public void oneSubscriberReceivesAMessage() {
        // set up
        final Subscriber subscriber = context.mock(Subscriber.class);
 
        Publisher publisher = new Publisher(); // objeto que vou testar
        publisher.add(subscriber); // tenho que adicionar o mock!
 
        final String message = "message";
 
        // aqui eu programo o que eu espero do teste
        context.checking(new Expectations() {{
            oneOf (subscriber).receive(message);
        }});
 
        // aqui eu executo!
        publisher.publish(message);
    }
}

Facil?

Rating 4.00 out of 5
[?]

XStream – Simplicidade ao lidar com XML em Java

15 de março de 2009

Quem nunca passou por isso: ter que gerar e/ou ler arquivos xml e teve que escolher dentre diversas tecnologias e frameworks diferentes. Seja carregar tudo pra memoria ou ler aos poucos, se é um parser push ou pull, etc, é possivel dizer que para cada situação existe uma boa escolha.

Se o seu caso é trabalhar com arquivos cujos elementos podem ser mapeados em objetos java, uma boa escolha é o XStream

XStream xstream = new XStream(new DomDriver());
Person pac = new Person("Tiago", "Pac Man");
String xml = xstream.toXML(pac);

/* Simples. É, para fazer o contrario, basta */

Person newPac = (Person)xstream.fromXML(xml);

Este e outros exemplos podem ser conferidos aqui:
http://xstream.codehaus.org/tutorial.html

É claro que o xml gerado assim, cru, nem sempre serve. Para isso vamos usar algumas linhas a mais para trabalhar com os recursos de alias, annotations e os Converters.


xtream.alias("pessoa",Person.class);

Dessa forma, para se livrar do nome.do.pacode.Person e trabalhar com algo mais expressivo como pessoa, basta adicionar este alias antes de converter de/para xml. Para trabalhar com aliasing de atributos (e coleções implicitas) o ponto de partida é este:

http://xstream.codehaus.org/alias-tutorial.html

É possivel trabalhar com annotations no seu modelo de classes, evitando toda essa configuração manual

http://xstream.codehaus.org/annotations-tutorial.html

Para trabalhar com o maximo de flexibilidade do XStream, entretanto, vc precisa trabalhar com Converters – Veja o exemplo da classe Birthday

http://xstream.codehaus.org/converter-tutorial.html

XStream trabalha muito bem com classes imutaveis, pois não recria os objetos usando o construtor e sim de maneira semelhante ao mecanismo de serialização de objetos, fazendo um bypass do construtor. Sem falar que traz um pensamento menos voltado a “tags” e mais OO.

Rating 2.00 out of 5
[?]

Ate um simples Hello World pode ser complicado

27 de fevereiro de 2009

Para ilustrar a sintaxe de uma linguagem, é comum o primeiro exemplo ser o hello world, no qual o programa realiza um aceno breve e fugaz (valeu zED9h) para o mundo exterior. Vejamos em C:


#include <stdio.h>
int main (int argc, const char* argv[]){
printf("hello world!\n");
return 0;
}

Aparentemente é um codigo simples, vamos olhar a execução

peczenyj@XXX:~$ gcc -Wall hello.c -o hello.exe
peczenyj@XXX:~$ ./hello.exe && echo "ok" || echo "nok"
hello world!
ok

Testar um hello world sob condições normais não é dificil: ele vai escrever uma mensagem fixa na stdout e vai retornar 0 para o bash (que pode ser recuperado via $? ou então encadear && e || como eu fiz no exemplo acima.

Agora vejamos o strace:

peczenyj@XXX:~$ strace ./hello.exe
execve("./hello.exe", ["./hello.exe"], [/* 35 vars */]) = 0
brk(0) = 0x804a000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f9c000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=81298, ...}) = 0
mmap2(NULL, 81298, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f88000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\260a\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=1339816, ...}) = 0
mmap2(NULL, 1349136, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e3e000
mmap2(0xb7f82000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x143) = 0xb7f82000
mmap2(0xb7f85000, 9744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f85000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e3d000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7e3d6b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb7f82000, 4096, PROT_READ) = 0
munmap(0xb7f88000, 81298) = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f9b000
write(1, "hello world!\n", 13hello world!
) = 13
exit_group(0) = ?
Process 6344 detached

Vejamos só: uma grande preparação para, no final, mostrar um hello world e sair (com sucesso). Isso mostra que qualquer coisa, mesmo a mais simples, esta envolta em muitas camadas de abstração até ser corretamente executada. Aqui estamos ignorando o sistema de arquivos, sistema operacional, memoria, cpu, etc. Com linguagens interpretadas ou que rodam sob uma JVM a coisa é mais complexa ainda.

Rating 4.60 out of 5
[?]

Adicionando Funcionalidades a um Sistema em Produção

20 de fevereiro de 2009

Por mais de uma vez eu tive que adicionar certas funcionalidades em sistemas que ja estavam em produção. É uma tarefa arriscada pois o serviço não pode parar por algum erro que vc esta introduzindo, ainda mais se este mesmo sistema estiver funcionando sem problemas nos ultimos meses ou anos.

Aprendi um truque bem interessante que, pensando bem, é um tanto obvio: ao adicionar uma funcionalidade onde boa parte do codigo ficou inalterada, pode fazer sentido desabilitar esta nova funcionalidade na configuração. Dessa forma se a porção nova de codigo produzir algum problema é possivel – teoricamente – minimizar os problemas desabilitando temporariamente esta feature.

Nem sempre isto faz sentido, porém não se trata de esconder a sujeita para debaixo do tapete: é de se esperar uma intensa bateria de testes de regressão alem de testes sobre o codigo novo. Conseguimos ter certeza da situação ao olhar os relatorios de cobertura de código, por exemplo. Esta é mais uma tecnica para evitar problemas em algo ja estabelecido.

Imagine que, no ambiente de produção, a nova feature desenvolve um memory leak, ou a escalabilidade dela não é a esperada? Desabilitar na configuração é menos traumatico do que um rollback na aplicação, mas ainda assim é traumatico. Agora, se vc desabilita e o problema continua isso ja dá pistas de que existe um problema em outro lugar – por exemplo na propria porção de código legado.

E vc, como adiciona funcionalidade a um sistema em produção?

Rating 3.33 out of 5
[?]

How Many HTML Elements Can You Name in 5 Minutes?

11 de fevereiro de 2009







50

Created by OnePlusYou

Rating 4.33 out of 5
[?]

Literate Programs

2 de fevereiro de 2009

Descobri uma wiki muito interessante sobre algoritmos, programação e linguagens: Literate Programs

Eles estão abertos a contribuições (em inglês) e utilizam um formato bem interessante para descrever os problemas e soluções: infelizmente não é tão completo quando poderia ser por isso precisa da contribuição de pessoas bem intencionadas como nós. Não é um repositorio de códigos e sim artigos elaborados explicando alguns detalhes interessantes.

Um bom exemplo são as 9 versões de 99 Bottles of Beer, porém vc encontra calculo de numeros primos, fibonacci, quicksort, o interessante exponentiation by squaring e muito mais. Vc encontra implementações em muitas linguagens como C, Java, AWK, Erlang entre outras.

Quem procura coisas mais basicas em linguagens mais populares (Java, C#, ActionScript) como “gravar em arquivo”, “ler xml”, etc, pode procurar no java2s.

Rating 4.00 out of 5
[?]

Fibonacci: alguns algoritmos efetivos em AWK

30 de janeiro de 2009

Estava apreciando hoje de manhã um post do Felipe Tonello: Analisando Número de Fibonacci e Recursividade. É um bom artigo sobre aquelas coisas que alguns podem ter visto na faculdade e são sempre uteis: matemática, analise de algoritmos e um pouco de mente aberta.

Imediatamente tratei de testar a velocidade dos dois algoritmos propostos usando AWK (que, por ser interpretado, pode revelar melhor as nuances entre as abordagens). Algoritmos recursivos são interessantes, principalmente quando trabalhamos com linguagens funcionais, porém algumas formas tem um custo computacional muito alto e o calculo de Fibonacci é um exemplo perfeito: para cada termo eu preciso calcular os dois termos anteriores e, então, soma-los, e isso cresce geométricamente, consumindo memória e processamento, sem falar que tenho muita repetição de código desnecessária.

A tecnica de programação dinâmica apresentada cria um cache de resultados, dessa forma evito boa parte do trabalho extra, veja o resultado:

Fibonacci(36) pelo algoritmo recursao simples:14930352 usando 48315633 iteracoes

real    0m51.961s
user    0m23.881s
sys     0m0.012s
Fibonacci(36) pelo algoritmo programacao dinamica:14930352 usando 71 iteracoes

real    0m0.002s
user    0m0.000s
sys     0m0.000s

Usando programação dinâmica eu uso muito menos de 1% do processamento necessário pela forma recursiva tradicional. Parece ótimo, não? Depende, pois eu apenas afastei o problema: ao calcular termos de alta ordem eu terei o mesmo problema, afinal o algoritmo é O[n].

Lembrei de um post do Ronaldo Melo Ferraz, Conceitos de Programação: Tail Recursion enquando estava testando os algoritmos em Erlang e encontrei esta implementação. A adaptação para awk é tranquila e o teste mostrou este resultado:

Fibonacci(36) pelo algoritmo programacao dinamica:14930352 usando 71 iteracoes

real    0m0.002s
user    0m0.000s
sys     0m0.000s
Fibonacci(36) pelo algoritmo tail recursion:14930352 usando 38 iteracoes

real    0m0.001s
user    0m0.000s
sys     0m0.004s

Um resultado ainda mais interessante, pois eu consigo obter o valor do termo com um pouco mais da metade das iterações do que usando programação dinâmica (sem onerar a memória com o cache dos resultados).

Esta analise é muito superficial, a ideia é apenas despertar a curiosidade sobre estes tópicos.

O codigo fonte utilizado nesse benchmark:
function Fib_normal(N) {
return (N > 1)? Fib_normal(N-1) + Fib_normal(N-2) : N
}
function Fib_dinamic(N) {
if (!m[N]) m[N] = (N > 1)? Fib_dinamic(N-1) + Fib_dinamic(N-2) : N
return m[N]
}

function Fib(N) { return Fib_tr(N,0,1); }
function Fib_tr(I,R,N){
return (I==0)? R : Fib_tr(I-1,N,R+N)
}

Rating 4.00 out of 5
[?]

Pesquisa: o que te desmotiva no trabalho?

29 de janeiro de 2009

Nem sempre estamos satisfeito no ambiente de trabalho, seja pelo transito, paredes que dão choques ou projetos malucos que fazem a gente varar a noite.

Pensando no que os meus colegas e eu ja passamos, quero fazer uma pesquisa: alguem ja passou por estas situações e quais são as piores, no sentido de arrebentar com a nossa incrivel motivação no trabalho?
- Falta de equipamentos adequados (quem nunca pensou em comprar um pente de memória com o dinheiro do bolso pra levar pro trabalho);
- Falta de café, chá ou ar condicionado (ou quando tem é ruim);
- Colegas doidos que te levam a loucura;
- Internet bloqueada (incluindo o google);
- Ter que trabalhar depois do horario (as vezes sem receber por isso);
- Codigos que parecem ter saido de um conto de H.P. Lovecraft;
- Projetos que parecem não ter sentido ou importância;
- Chefes que parecem ter saido de uma tirinha do Dilbert;
- Chefes truculentos, desses que da medo falar o nome;
- Resistência a mudanças (riem de Ruby on Rails e desenvolvem em Java como se fosse Cobol);
- Buzzwords são mais importantes do que atender aos clientes;

Os profissionais de informática, especialmente os desenvolvedores, possuem formas de encarar o trabalho que, de acordo com o ambiente, a vontade de fazer algo bom some restando cinismo, péssimo humor e curriculos atualizados prontos para zarpar para outras oportunidades. Algumas vezes é inevitavel, afinal somos humanos, mas o que nos leva a aguentar, enfrentar ou desistir desses problemas?

Uma caracteristica é bem clara: gostamos de fazer coisas especiais. É ironicamente engraçado ver as reações de alguns profissionais quando estão fazendo algo ordináriol, comum ou que julguem sem importância pois muitos odeiam isso, porém estão fazendo por algum motivo: geralmente existe alguma extratégia da empresa que deveria ser respeitada. Creio que este tipo de “soberba” afeta o nosso rendimento pois é muito facil ver reações emocionais e não tanto racionais.

No aguardo da flame-war

Rating 4.00 out of 5
[?]

RPG em Ruby com apenas 15 linhas

28 de janeiro de 2009

Achei este link bem interessante: MUD in 15 Lines of Ruby. Para quem não sabe MUD é uma familia de jogos textuais inspirados em RPGs conhecidos: normalmente vc escolhe uma raça e uma classe e, dentro do jogo, evolui através da morte de criaturas controladas pelo jogo e através de missões varias como recuperar itens ou decifrar enigmas, são os avós dos MMORPGs modernos.

O codigo foi um tanto obsfuscado, na verdade são umas 77 linhas, mas não deixa de ser interessante o poder das linguagens scripts :)

Rating 4.00 out of 5
[?]