Integração Contínua

27.fevereiro.2009
Instalei em minha máquina de trabalho um servidor de integração contínua.

Quando se trabalha sozinho, num projeto pequeno, isso realmente não faz muito sentido. Porém, trabalhando com um recurso a 500km de distância, e mais dois recursos remotos cuidando de um projeto relacionado, cuja alteração indevida pode quebrar o funcionamento da parte em que trabalho, esse tipo de ferramenta começa a fazer sentido.

O modo correto, antes de mais nada, é instalar esse servidor numa máquina que possa ser facilmente acessada por qualquer parte interessada. Minha máquina de trabalho, obviamente, só fica disponível quando estou conectado na rede da empresa, para quem estiver na mesma condição.

Instalei o Apache Continuum rodando como um NT Service (sim, eu uso Windows no trabalho), acessível como uma aplicação web a partir da porta 8080.

Para quem se interessou, recomendo a leitura do artigo do Martin Fowler sobre Integração Contínua. Estou organizando uma documentação para compartilhar com a equipe e pretendo divulgá-la aqui.

P.S.: Sim, eu sei que tem Bamboo, mas comunicação ainda é um ponto crítico a ser desenvolvido.

Anúncios

Hail for Grails

19.janeiro.2009
Infelizmente não estou tendo o tempo que gostaria para investir no Clojure. Porém, por uma coincidência, surgiu uma oportunidade para trabalhar com Grails (Groovy on Rails), uma versão Groovy do consagrado framework para Ruby.

Minha primeira impressão foi muito boa. Para montar um CRUD, são necessários menos de cinco minutos, caso você nunca tenha mexido antes com o framework.

“Ah, mas o Rails também tem isso”. Claro que tem, afinal de contas, o Grails é um ‘clone’ que roda com Groovy. É possível gerar um arquivo .war e publicar a aplicação num servidor Tomcat, como uma aplicação Java normal. Por trás dos panos, o que acontece é exatamente compilar o código Groovy para Java, e o Java para o bytecode da JVM. Caso você tenha uma aplicação Rails, pode também utilizar o JRuby para o mesmo fim.

Outro ponto que me chamou a atenção no Grails (ou no Groovy, se preferir) são as contraints. São checagens que você codifica na própria entidade, que funcionam como validações automáticas dos dados inseridos. Numa tela de login, por exemplo, você pode ter uma entidade User e informar que login é único, não pode estar em branco e deve ter entre 5 e 20 caracteres, por exemplo. Tudo isso em uma ou duas linhas de código facilmente legível.

Como o trabalho deve ser entregue rapidamente, não vou ter muito tempo de fuçar e experimentar funcionalidades não usuais, mas com certeza o framework já entra para a minha lista de ferramentas preferidas.

Aos mais puristas, deixo meu compromisso de estudar Ruby e olhar o Rails com mais atenção, já que, ao que me parece, esses frameworks atendem plenamente às minhas necessidades.


Tipo byte em Java

15.janeiro.2009
O tipo byte, na linguagem Java, tem comprimento de oito bits e armazena valores inteiros entre -127 e 128.

No post anterior eu citei o caso do método que recebia 255 e retornava -1. Isso acontece por que qualquer valor acima de 128 e menor que 256 (o máximo passa a ser representado usando oito bits) passa a ser representado como um valor negativo.

Exemplo:

byte exemplo1 = 127; // por ser menor que 128, não precisa de cast
byte exemplo2 = (byte) 255; // por ser maior que 128, o cast é necessário
byte exemplo3 = (byte) 254; // idem acima

println(exemplo1); // mostra 127
println(exemplo2); // mostra -1
println(exemplo3); // mostra -2

Qualquer valor menor que -127 e maior que 128 exise um cast (ou typecast, ou ‘coerção de dados’) para ser atribuído.

Cast é quando você força um valor de um tipo a ser de outro tipo. No caso ilustrado acima, valores menores que -127 e maiores que 128 são considerados como sendo do tipo int, exigindo a conversão antes da atribuição.


O caso do byte perdido

14.janeiro.2009
Encontre o erro:

public class AnyInputStream extends InputStream {
  private byte getTheNextByteFromSomewhereElse(){
    // do something useful
  }

  public int read() {
    byte result = -1;
    if(!(hasAnyKindOfError() || wasTheLastByte())) {
      result = getTheNextByteFromSomewhereElse();
    }
    return result;
  }
}

A propósito, os nomes estranhos de métodos e da classe são meramente ilustrativos, para auxiliar na compreensão.

Qual o problema do fonte?

Quando você tem algum erro de leitura, ou chega ao final do conteúdo, recebe um -1 como resposta. Caso contrário, recebe o próximo byte e assim por diante. O problema ocorre quando você lê um byte de valor 255.

Se você jogar o valor 255 numa variável de typo byte, no Java, ele passa a ser -1, por questões de overflow e tamanho de variável. Ou seja: um byte válido passa a ser compreendido como final de arquivo ou erro de leitura.

Um simples teste teria pego esse erro ainda na mesa do programador e ele não teria chegado ao ambiente de produção.

Então eu pergunto:
– qual o problema em testar a droga da funcionalidade antes de entregar?
– qual o problema em gastar alguns segundos pensando antes de escrever?
– qual o problema em prestar atenção na merda que você, supondo que seja um desenvolvedor, está fazendo?

São essas coisas que me fazem achar que estou me preocupando em limpar os pés para entrar numa sala cheia de lama.


O diabo mora nos detalhes

08.janeiro.2009
Dez minutos olhando para dois métodos pequenos (cinco linhas cada), à procura da causa de um ConnectionTimeout.

Ao invés de escrever dataOutputStream.writeInt(integer), escrevi dataOutputStream.write(integer).

Good grief, Charlie Brown.


Sem comentários

11.dezembro.2008
Antes de mais nada: o que vou escrever aqui não se aplica a linguagens de ‘baixo nível’, como Assembly, por exemplo. Se você utiliza Java, Delphi, C#, Ruby ou qualquer outra que possa ser chamada de ‘alto nível’, pode continuar lendo.

Comecemos com uma ordem: não comente seu código.

Plaft. O impacto da ordem e os trolls agitam os dedos para começar a criticar.

Para que servem os comentários no código? Ensinaram na escola que é para informar suas intenções aos outros programadores. Teoricamente, quando o próximo coitado abrir o seu código, ele vai entender perfeitamente todas aquelas amarrações e voltas lógicas que você deu no código, apenas se guiando pelos comentários. Genial, não?

Agora, me mostre um só código legado, daqueles sem testes e que passaram na mão de pelo menos vinte estagiários, que tem os comentários perfeitamente atualizados e consistentes com a abordagem utilizada no código. Pois é, esse é o segundo problema que encontramos ao usar comentários. O primeiro, se você ainda não percebeu, é o retrabalho de ter que escrever código e em seguida escrever comentários para explicar o que o código faz.

Claro que ainda não te convenci. Anos de vício não se perdem em uma leitura. “Tudo bem, é só apagar aquele comentário que não faz sentido”. Vou usar um exemplo que encontrei aqui mesmo, no projeto em que trabalho.

O que a linha abaixo quer dizer?

int t = 0;

Nem mais, nem menos. Para mim, está sendo declarada e inicializada uma variável t. Para que serve, eu não faço idéia.

Vamos então comentar o código. Claro, assim o próximo sujeito que der manutenção nesse código vai entender perfeitamente o que estou tentando fazer aqui.

// tentativas de login
int t = 0;

Opa, bem melhor agora, não concorda? É óbvio que t é exatamente a mesma coisa que tentativas de login. Claro. Como não pensei nisso antes? Assim, no meio do código, basta você encontrar a variável, voltar ao local onde ela foi declarada e ler o porquê dela existir. Ou então, você pode ser uma pessoa bem legal e comentar cada linha onde a variável é utilizada. Se você for mais legal ainda, logo você terá um código de 300 linhas, sendo que 160 delas são só comentários. Legal mesmo.

Só que eu não sou um cara legal. Eu tenho preguiça de escrever comentários. Eu acho que um código de 300 linhas com 160 linhas de comentário é uma nojeira difícil de ler. Eu acho uma perda de tempo ter que reescrever comentários para cada linha que eu altero do código. É demorado, pouco produtivo e sujeito a erros. “E então, espertão. Como você faria?”

int tentativasDeLogin = 0;

Que tal assim? Sem comentários, sem nenhuma explicação adicional. Apenas código, puro e simples. O código se torna uma forma clara e concisa de documentação.

Ferramentas como NetBeans, Eclipse e Visual Studio, automatizam o ato de renomear um membro da classe dentro do escopo correto, o que honestamente, me faz desacreditar em qualquer argumento a favor do uso de comentários em detrimento da legibilidade do código.

Por falar em legibilidade, vou começar a inserir linhas entre os parágrafos. Pelo menos para mim isso ajuda muito na hora de ler textos maiores. Espero que te ajude também.

😉


One more achieved goal

24.novembro.2008

Na metade do ano estabeleci como meta conseguir duas certificações.
Hoje consegui a segunda.

Certified ScrumMaster

Sun Java Certified Programmer

Que venha 2009. 😉