quarta-feira, dezembro 29, 2004

Wiki SPAM + Blacklists

Recentemente, vários wikis tem sido pichados com links. Aparentemente a idéia dos pichadores é aumentar o rank page no Google com isso. A idéia já é estúpida pelo simples fato que vc poderia simplesmente pagar para colocar propaganda no Google, mas vá lá, quem faz isso não costuma fazer propaganda de nenhum site "legal" (no sentido jurídico da bagaça). O site do XisPê é uma das grandes vítimas. Acabei tendo a oportunidade de dar uma mexidinha nele e estou tentando colocar um "blacklist" de sites. O Osvaldo, da Objective, me deu um toque e apontou para um wiki (o MoinMoin) que já faz blacklist. Acho que o próximo passo é consultar o blacklist deles, e talvez de outros sites, e adicioná-los no blacklist do XisPê de tempos em tempos. Achei o desenvolvimento desse tipo de coisa bem simples e interessante. Soluções para evitar spam em wikis não tem implementação muito complicada, mas dá pra gente imaginar um bocado de brincadeiras e métodos pra fazer isso. ---- Sites com blacklists: Del.icio.us - blacklist sites

Pattern para transformação simples?

Faz um tempo que não escrevo nada. Esses dias estava mexendo com transformações entre dois objetos. O problema é que nem sempre as transformações são entre atributos simples, algumas vezes um atributo vira dois, outras vezes dois atributos viram um, outras vezes ainda uma transformação é baseada no resultado de uma outra... Acabei usando o princípio do KISS (Keep It Simple Stupid) e a solução ficou bastante boa. Vou compartilhar aqui pra não esquecer. Basicamente, eu crio vários transformadores, cada um recebe o objeto de origem e o objeto de destino. Dessa forma, o transformador pode acessar o que bem entender dos dois lados. Para transformar o objeto inteiro, eu crio uma coleção de transformadores e rodo eles todos em cima do mesmo objeto origem e objeto destino. O objeto destino funciona como um Collecting Parameter (isso é um pattern, viu!) e ao final de rodar todos os transformadores, ele está totalmente preenchido. Simples né? As vantagens: 1 - Se tiver transformações que dependam do resultado de outra, vc pode simplesmente colocar uma antes da outra. O transformador dependente vai consultar o resultado no objeto destino para decidir o que fazer, uma vez que a transformação anterior já preencheu ela. 2 - Todo transformador pode ser fatorado para trabalhar na base do um-pra-um. Exemplificando: imagine que tenho um transformador que pega o campo "número de registro" na origem e coloca os cinco primeiros dígitos em "número do departamento" e os cinco últimos em "número do funcionário". Posso quebrar ele em dois transformadores, um que usa "número de registro"->5 primeiros dígitos->"número do departamento" e outro que usa "número de registro"->5 últimos dígitos->"número do funcionário", ao invés de usar um transformador só que faz tudo. Da mesma forma, posso compor vários transformadores em um único, e se eu quiser fazer gracinha, posso implementar eles como se fossem um Composite, aí um transformador pode conter vários transformadores. Mas não vi muita vantagem em fazer isso. No geral, a abordagem ficou muito simples e muito extensível. Será que isso já está escrito como pattern em algum lugar?

quarta-feira, dezembro 15, 2004

Carregamento dinâmico de classes em Java

Tá aqui um truque java que vale a pena. Basicamente, tenho o source code vindo do limbo e quero criar uma classe "on the fly". A dureza é que o java não é nada amistoso pra fazer isso, mas dá pra fazer. ;) Peguei do seguinte fórum
package com.sun.tools.javac.v8;
 
import com.sun.tools.javac.v8.JavaCompiler;
import com.sun.tools.javac.v8.util.List;
import com.sun.tools.javac.v8.util.Context;
import com.sun.tools.javac.v8.comp.Gen;
import com.sun.tools.javac.v8.comp.Env;
import com.sun.tools.javac.v8.tree.Tree;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
 
import java.util.Hashtable;
import java.util.ArrayList;
import java.util.Iterator;
 
public class Derik1
{
	static class Compiler
	{
		private ByteArrayOutputStream os;
 
		public byte[] compile(String name, final String source)
			throws Throwable
		{
			os= new ByteArrayOutputStream(1024);
 
			final Context context= new Context();
 
			JavaCompiler compiler= new JavaCompiler(context) {
				public InputStream openSource(String filename) {
					return new ByteArrayInputStream(source.getBytes());
				}
				void genCode(Env env, Tree.ClassDef classdef) 
					throws IOException
				{
					Gen.instance(context).genClass(env, classdef);
					writer.writeClassFile(os, classdef.sym);
				}
			};
	
			List list= new List();
			list= list.append(name +".java");
			compiler.compile(list);
 
			byte[] bytes= os.toByteArray();
			os.close();
			return bytes;
		}
	}
 
	static class Loader
		extends ClassLoader
	{
		private Hashtable mClasses= new Hashtable();
 
		public void add(String name, byte[] bytes) { mClasses.put(name, bytes); }
 
		public Class findClass(String name)
			throws ClassNotFoundException 
		{
			byte[] bytes= (byte[]) mClasses.get(name);
			if (bytes == null) 
				return super.findClass(name);
			return defineClass(name, bytes, 0, bytes.length);
		}
	}
 
	static class Attribute
	{
		public String name;
		public String type;
 
		public Attribute(String name, String type)
		{
			this.name= name.substring(0,1).toUpperCase() +
				name.substring(1).toLowerCase();
			this.type= type;
		}
 
		public String declaration() {
			return "private " +type +" m" +name +";";
		}
 
		public String getter() {
			return "public " +type +" get" +name +"() { return m" +name +"; }";
		}
 
		public String setter() {
			return "public void set" +name +
				"(" +type +" " +name.toLowerCase() +") { m" +
				name +"= " +name.toLowerCase() +"; }";
		}
	}
 
	public static void main(String[] argv)
		throws Throwable
	{
		BufferedReader reader= new BufferedReader(
			new InputStreamReader(System.in));
 
		System.out.print("Class: ");
		String cname= reader.readLine();
 
		ArrayList attributes= new ArrayList();
 
		while (true) {
			System.out.print("Attribute (return to finish): ");
			String name= reader.readLine();
			if (name.length() < 1) 
				break;
			System.out.print("Type for " +name +": ");
			String type= reader.readLine();
			attributes.add(new Attribute(name, type));
		}
 
		String src= "public class " +cname +" {";
 
		Iterator iter= attributes.iterator();
		while (iter.hasNext()) 
			src += "\n\t" + ((Attribute) iter.next()).declaration();
 
		iter= attributes.iterator();
		while (iter.hasNext()) {
			Attribute a= (Attribute) iter.next();
			src += "\n\t" + a.setter();
			src += "\n\t" + a.getter();
		}
 
		src += "\n\tpublic String toString() {";
		src += "\n\t\treturn \"";
		iter= attributes.iterator();
		boolean first= true;
		while (iter.hasNext()) {
			Attribute a= (Attribute) iter.next();
			if (!first) 
				src += "+\",\" +\n\t\t\t\"";
			src += a.name +"=\" +get" +a.name +"()";
			first= false;
		}
		src +=  ";\n\t}\n}";
 
		System.err.println("##### Source Code");
		System.err.println(src);
 
		System.err.println("##### Compiling...");
		byte[] bytes= new Compiler().compile(cname, src);
    
		System.err.println("##### Class Loading...");
		Loader loader= new Loader();
		loader.add(cname, bytes);
		Class clazz= loader.findClass(cname);
 
		System.err.println("##### Class: " +clazz.getName());
    
		Object instance= clazz.newInstance();
		System.err.println("##### Instance: " +instance);
	}
}

segunda-feira, dezembro 06, 2004

Desenvolver software = nova linguagem != construir casas

Recentemente eu estava lendo alguns artigos sobre LOP (Language Oriented Programming) e sobre DSL (Domain Specific Languages), eles acabaram me dando finalmente a metáfora que eu estava procurando para desenvolvimento de software "Desenvolver software é como criar uma linguagem" Normalmente, associamos desenvolvimento de software com construção civil: "Desenvolver software é como construir um prédio, vc primeiro faz o design da planta, blah, blah, blah". Sempre achei esse conceito perigosamente errado, mas ainda não tinha achado um conceito para substituir ele. Bom, talvez eu não tenha achado o conceito certo (será que existe conceito certo?), mas acho que pelo menos é mais adequado pra mim. A metáfora sobre linguagem é que quando criamos um objeto e seus métodos, estamos criando um "conceito", ou seja, uma palavra para ser usada em no programa. Podemos montar conceitos em cima de conceitos para expressar conceitos mais complexos. Isso é mais ou menos o conceito de "camada" mas não tão restrititivo qdo elas. Complicado, né? Bom, acho que o melhor é refletir um pouco mais sobre isso antes de escrever muito. Vou fazer uns protótipos aqui e ver no que dá, aí reporto o que aconteceu no blog. Que vc acha? Essa metáfora vira?

sexta-feira, novembro 26, 2004

Livros para comprar

Estava vendo livros para comprar, achei algumas resenhas sobre esses aqui que me interessaram muito: Pragmatic Project Automation - Amazon (US$ 20,00) - Livraria Cultura (R$ 122,00) The Pragmatic Programmer - Amazon (US$ 31,00) -Livraria Cultura (R$ 102,00) O duro é que pra comprar apenas um livro na Amazon o frete sai mais caro que o próprio livro. E não estou com cacife por enquanto para pagar mais que um. Alguém conhece algum desses livros?

quarta-feira, novembro 24, 2004

Tequila nunca mais

Galera! Exagerei na tequila ontem. Foram 5 a 7 rodadas de tequila, fora 3 caipirinhas que eu já tinha tomado. Um ex-colega de trampo, o Cláudio, veio ontem e a gente saiu pra botar o papo em dia. Sei que pra finalizar a noite, resolvemos fechar com UMA tequila... aí apareceu mais uma, mais uma, mais uma.... aff! O engraçado é que nem dor de cabeça eu estou hoje. Bicho ruim é assim, acho. Mas bebedeira igual essa, de novo, só daqui uns 20 ou 30 anos... :) Olha o link das fotos: Fotos da tequilada

segunda-feira, novembro 22, 2004

Sobre simplicidade e mudança

Não adianta, Ward Cunningham é mestre! Segue o link para o del.icio.us com artigos de primeira linha do tio Ward. Vale a pena ler. Artigos e afins de Ward Cunningham

quarta-feira, novembro 17, 2004

Três tipo de pessoas

Outro dia estava lembrando de um ditado que eu vi em algum lugar. "Pessoas cretinas falam sobre outras pessoas Pessoas inteligentes falam sobre fatos Pessoas sábias falam sobre idéias" Fico imaginando quantas vezes por dia eu sou cretino, inteligente e sábio, uma vez que estamos sempre mudando de assunto. No geral, acho bom tentar ficar no sábio e inteligente a maior parte do tempo :)))

domingo, novembro 14, 2004

Test FIRST - Pra que servem testes?

Simples e rápido: "Pra que servem testes?" ou melhor: "Pra que serve testar uma aplicação depois de pronta?" Resposta: Serve pra melhorar o código!!! Péééé!! Errado! *vaias* Uuuuuuuuuhhhhh! A menos que vc adicione uma fase extra de codificação ("tiração" de bugs), testar um código depois que está pronto só serve pra vc ter a certeza que seu código tem bugs. Então qdo o tempo está curto, a primeira coisa que vai pro brejo são os testes E a qualidade do seu código. Uma vez que se vc nem faz a fase de teste, tb não tem como fazer a fase de "tiração de bugs". Solução: Test-First Design nele. Só não confunda isso com fase de testes, "PELARMOD'DEUS"! O que eu vejo de gente falando que faz UnitTest e na verdade faz testes tradicional "mais ou menos" automatizado, não tá escrito.

segunda-feira, novembro 08, 2004

"Caça às Bruxas"

Já viu chefe louco da vida procurando quem foi que fez aquela cagada? Já viu isso adiantar de algo? Outro dia foi bem engraçado, o chefe perguntou: "Por que foi que vcs não fizeram o que eu pedi?". Era uma coisa muito boba e a única explicação possível era "eu esqueci". Foi o que dissemos pra ele, e me veio na boca um "ok, agora vc sabe que esquecemos, e aí?", mas eu engoli. Pra que criar atrito à toa? De fato, fiquei pensando depois que não adianta nada saber quem foi ou porque foi. Depois de feita a cagada, o que interessa é saber o que se pode fazer pra resolver. Principalmente pq não resolve dar bronca, nessa área de informática, nenhum desenvolvedor que mereça o nome erra por querer, sempre fazemos o melhor possível, mas às vezes não é suficiente. Ou estou errado?

Tempos de "polimento"

Tenho reparado que sempre que um software está para ser liberado, existem um monte de pequenas arestas, ou "pontas soltas", que precisam ser corrigidas. Esse tempo costuma ser de no mínimo dois dias até uma semana, no caso mais genérico. Depois disso, ainda existem os "polimentos" de pequenos bugs que só são percebidos em produção. Esse tempo normalmente é disperso, de acordo com a velocidade em que os bugs são encontrados/reportados, em pequenos "chunks" de quinze minutos até metade de um dia. Isso costuma invadir o tempo de desenvolvimento de outros software e, olha que interessante, não costuma ser contado no tempo de projeto desses outros softwares. Uma vez medimos esse tempo de "polimento de produção" e ele tomou cerca de 10% do tempo total de outro projeto. Próxima vez que eu fizer uma estimativa de projeto, vou incluir uma semana de "polimento" no fim, e já vou alertar para essa "invasão" de projeto. Será que isso seriam "patterns de desenvolvimento de software"?

Precisando de XP

Desde que sai da última empresa, 8 meses atrás, tenho sentido uma falta imensa de XP. A gente fica mal acostumado qdo trabalha direito. Estou sentindo na pele o "retrocesso". Mas sem problemas, a empresa é competente e aos poucos, bem aos poucos, vamos colocando um processo aqui, um processo ali, até termos XP de novo. Se fiz duas vezes, posso fazer uma terceira ;) De resto meu maior problema no momento é colocar Unit Tests. E como sempre, o que mais empaca para colocar Unit Tests é integração com banco. Sinto que vou ter que apelar fortemente para o Connection Mother.

quinta-feira, novembro 04, 2004

Tempo de projeto / Número de desenvolvedores

Tava pensando agora há pouco. Vc já trabalhou em um time em que cada um está fazendo um projeto diferente? Fico pensando se dá efeito. Até onde sei e vi, vale a pena agrupar esforços até um certo limite, acima disso, fica complicado. Exemplo simples e estúpido: 2 projetos, 2 desenvolvedores. Imagine que se cada um trabalhar em um projeto, ambos os projetos ficariam prontos no fim de 2 meses. Se os dois trabalhassem em um único projeto, ele ficaria pronto em apenas um mês? Que vc acha? Provavelmente cada um levaria MENOS de um mês pra ficar pronto. Só que essa regra não é linear, não é "tempo/número de desenvolvedores". Até onde eu vi, 4 a 6 desenvolvedores é o melhor custo benefício por projeto. Acima disso, vc começa a precisar de muita coordenação. Bom, essa é minha experiência, mas acho que cada caso é um caso, que vcs acham? Alguém já teve experiência diferente?

domingo, outubro 31, 2004

"Para inglês ver"

Eu estava lendo essa manhã a revista "Consumidor Moderno" e logo no índice uma reportagem me chamou a atenção: "Recursos Humanos - Motivação é show (por Gilberto Paiva Junior)". Mas o que me chamou a atenção não foi o título, foi a empresa da qual a reportagem falava, a Atento. Por que? Bem... tive vários amigos que trabalharam em call centers da atento (total: 7 dos meus amigos mais chegados), desses, apenas um continua lá. Eu já ouvi muito sobre como funciona a empresa e todas as partes boas e muitas partes podres dela, então, qdo vi a reportagem, fiquei curioso se a percepção do artigo era o mesmo que meus amigos funcionários tinham. Já até imaginam o resultado, não? A reportagem mostra um programa de incentivo ao funcionário na forma de show de talentos. Esses meus amigos comentavam desses shows de talentos e dava para perceber que eles eram realmente motivantes. Mas mesmo assim, as reclamações deles sobre o trabalho eram muito maiores, ia de desde falta de reconhecimento até um regime de "exército" com tempos para atender, para ir ao banheiro, e "punições" (era percebido por eles como punição) por não atingir metas de vendas e coisa e tal. Resumo: péssimo clima de empresa e um medo incrível de ser demitido. Quer ver o efeito disso? Vc sabe que a Atento é quem faz o "call center" para a Telefonica, né? Em outras palavras, aqueles serviços que vc liga 102, 103, 104 (alguns até mudaram de número) etc e tal são responsabilidade da Atento. Vc já tentou ligar pra esses serviços? Ficou satisfeito? Ultimamente, toda vez que vou ligar para lá, já começo a ligação de mau humor. O atendente é um substituto de robô, sempre falando a mesma coisa (fraseologia, né), te atende como se quisesse q vc desligasse no segundo seguinte (o que é verdade, cerca de 30 segundos pra te atender no 102, se não me falha a memória) e frequentemente, se é algo chato pra ele, te derruba da linha, te põe em mudo, espera até vc desligar, etc e tal. Última vez, pra cancelar um daqueles serviços "gratuitos por 1 mês" que puseram no meu telefone (sem que eu tenha pedido, óbvio), tive que ligar 3 vezes e perdi quase uma hora nisso: na primeira, me deram uma desculpa nada a ver, dizendo que ele não poderia desligar o serviço, pedi pra falar com o supervisor, o atendente me "transferiu" e eu aguardei quase 15 minutos até a linha cair. Na segunda vez, outro atendente, outra desculpa (diferente da primeira), pedi novamente o supervisor e fiquei na linha mais 15 minutos. Na terceira vez meu mau humor já estava épico, pedi novamente para cancelarem os serviços, ouvi outra desculpa (diferente das duas primeiras), pedi o supervisor e o R.E. do atendente e já emendei um "se eu ficar esperando na linha e ela cair de novo, passo seu R.E. para o onbundsman reclamando", a atendente quase chorou e disse que ela não poderia ser responsabilizada se isso acontecesse, avisei que se era verdade ela não teria problemas se eu reclamasse ao onbundsman e pedi o supervisor. Ela me transferiu e dois segundos depois o supervisor estava cancelando os serviços "gratuitos" sem perguntar mais nada. Motivação de funcionários é realmente show, mas fazer show de talentos não garante qualidade se as condições de trabalho e o treinamento dos funcionários é medíocre. Aliás, faltou um dado na reportagem, qual o índice de "turn over" (dispensa e contratação) da empresa. Eu nunca vi uma empresa com um turn over tão alto para atendentes. Pois é, programa de incentivo pra inglês ver. Bom pra mostrar para outras empresas, mas nós aqui embaixo que utilizamos os serviços ainda nos debatemos a qualidade extremamente pobre do serviço de atendimento. E vc? Já se estressou com a Telefonica (leia-se "atendente da Atento")? Ou fui só eu?

sábado, outubro 30, 2004

Acordando cedo

Normalmente eu odeio acordar cedo, ainda mais qdo é pra trabalhar. (Como é o caso nesse belo sabadão) Mas é estranho, pq depois da primeira hora de sonolência eu fico bem disposto e o dia rende bastante... Mas ainda assim, não gosto de acordar cedo.

sexta-feira, outubro 29, 2004

ADD EDD SDD = TDD

Continuam as discussões sobre trocar no nome de TDD. Já propuseram Assertion Driven Development, Example Driven Development, Specification Driven Development e meu colega Marlus até comentou um T'n'GDD (Try and Guess Driven Development). Eu ainda acho que ADD é bem comercial e mais "digerível". Muitos preferem que o nome deve continuar como está pq é o que se faz. Sei não. Concordo com o autor original do thread, se trocar o nome para outra coisa, tiramos a necessidade de ficar explicando que TDD não tem nada a ver com testes no sentido mais tradicional da palavra. Sabe que muita discussão esclareceo assunto, mas não leva a conclusão nenhuma. Então, acho que vou experimentar falar de ADD ao invés de TDD por um tempo (principalmente para os gerentes) e vamos ver o que acontece.

Programa de incentivo

Nós aqui trabalhamos com software para programa de incentivos. Pra quem não sabe o que é um programa de incentivo, basicamente são "promoções" e recompensas feitas para vendedores. Qto mais o cara vende, mais prêmios (e outros incentivos) ganha. Hj o Roberto (colega aqui), por acaso descobriu um onde tem um programa de incentivo bem interessante: http://www.huntingwinners.com.br/ Basicamente, fazem uma competição de vendas entre duas equipes. Vale a pena olhar.

Testando w.bloggar

Tou testando o w.bloggar. Já consegui destruir o layout q estava lá em dois cliques (talvez três). Mas parece bom, vou continuar testando. De resto, odeio preencher timesheets. Preciso inventar um jeito de ficar mais fácil e menos chato.

quinta-feira, outubro 28, 2004

ADD = TDD

Está rolando na lista de Extreme Programming uma idéia para trocar o nome "Test Driven Development" para "Assertion Driven Development". O ponto é que qdo vc diz "test" para um gerente, tem que explicar que não está falando de testes do jeito que eles conhecem. Ou seja, o termo "test" já induz a um mal-entendimento da coisa. Talvez mudando o termo vc só tenha que explicar uma coisa nova, e não desfazer um mal-entendido e explicar uma coisa nova. Kent Beck sugeriu "Specification Driven Development", mas eu acho que Kent é péssimo pra colocar nomes nas coisas. Além do que "Assertion Driven Development" fica com a sigla "ADD", o que é bem comercial. E convenhamos, mais comercial é mais fácil de se propagar, eu acho.

quarta-feira, outubro 27, 2004

MecanicaMente

Primeiro post nessa coisa, vamos ver se me adapto a ter um blog. Às vezes acho bom colocar as idéias no ar, até porque, qdo não coloco, logo logo as esqueço. Só não sei se um blog é a melhor maneira pra isso. A partir de hoje, vou dar um mês pra testar isso. Se em um mês a coisa andar bem, eu continuo, caso contrário, desisto, fecho o blog e vou dormir.