.:: Jorge Pereira ::.

- Depuração: Parte 1

Seja Elegante

Talvez possa ser algo que passe despercebido por vários desenvolvedores, porém dúvido quem nunca tenha se deparado com mensagens de “log” vagas ou sem nenhum nexo ou bem pior, como mensagens idênticas replicadas por várias partes do código! :shock:
A algum tempo atrás estava trabalhando em um projeto em que um respectivo desenvolvedor da equipe possuia o costume de espalhar ou replicar centenas de printf() pelo código com mensagens tipo!

printf(“!!! FULANO – Aqui!!!”);

ou

printf(“!!! FULANO – Arquivo.cpp:  Aqui!!!\n”);

Precisa falar que isto e pessímo? Certo que e preciso um bom senso com o uso de mensagens de depuração pois dependendo ao invés de ajudar podem só atrapalhar. principalmente quando você necessita ter controle sobre tais mensagens, como por exemplo obter a localização da mensagem através do nome da função, arquivo e linha.

Lembrando que dependendo da situação e contexto eu sou a favor de utilizar o pragma no compilador ativando o “poison” desativando dentre várias funções o printf (), evitando de ter espalhada pelo sistema! Futuramente um post sobre o poison.

O pré-processador do GCC oferece (*) várias macros, as que irei utilizar em questão são:

  • __FILE__ : Substituída pelo nome do arquivo.
  • __PRETTY_FUNCTION__ : Substituídas pelo nome nome da função.
  • __LINE__ : Substituída pelo número da linha de código.

(*) Mais detalhes sobre as macros do GCC.

A utilização dessas macros irá facilitar a localização das mensagens de depuração, Abaixo um simples exemplo demonstrado em debug1.c.

/**
 * By Jorge Pereira <jpereiran@gmail.com>
 * Date: Tue Jun 29 02:51:44 BRT 2010
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

// Macro condicional
#ifdef DEBUG
#	warning "Debug is enabled"
#	define TRACE_DEBUG(fmt, ...) \
	fprintf(stderr, " ** DEBUG: %s:%d %s(): "fmt"\n", \
	__FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__)
#else
#	warning "Debug is disabled"
#	define TRACE_DEBUG(fmt, ...)
#endif

#define MAX_STRING 5 /* tamanho maximo de uma string */

// Função simples de exemplo...
void
show_name (const char* name,
		   size_t len)
{
	size_t offset = len;

	// Verificação qualquer...
	if (len > MAX_STRING)
	{
		// Abaixo mensagem de depuração, perceba que ela será ativada apenas
                // quando em tempo de compilação você ativar a macro "DEBUG"
		TRACE_DEBUG ("Ooops! Tamanho da string(%d) e excedeu o limite(%d)...",
			len, MAX_STRING);
		offset = MAX_STRING;
	}

	// Manipulação qualquer...
	write (STDOUT_FILENO, name, offset);
	write (STDOUT_FILENO, "\n", 1);
}

int
main (int argc, char* argv[])
{
	if (argc < 2)
	{
		printf ("Usage: %s <string>\n", argv[0]);
		exit (1);
	}

	show_name (argv[1], strlen (argv[1]));

	return 0;
}

Com este exemplo básico em mãos, vamos compilar e executar.

[jpereira@miracleworld Codes]$ gcc -Wall -o debug1 debug1.c
debug1.c:18:3: warning: #warning "Debug is disabled"
[jpereira@miracleworld Codes]$ ./debug1 "Jorge"
Jorge
[jpereira@miracleworld Codes]$ ./debug1 "Jorge Pereira"
Jorge
[jpereira@miracleworld Codes]$

Imagine que seu sistema possui inúmeros arquivos e você precisa em determinados pontos obter o máximo de informação sobre as mensagens de depuração, talvez seja interessante ter além de uma mensagem objetiva obter juntamente o nome da função, arquivo e linha de onde foi invocada tal mensagem.

[jpereira@miracleworld Codes]$ gcc -Wall -DDEBUG -o debug1 debug1.c
debug1.c:13:3: warning: #warning "Debug is enabled"
[jpereira@miracleworld Codes]$ ./debug1 "Jorge"
Jorge
[jpereira@miracleworld Codes]$ ./debug1 "Jorge Pereira"
 ** DEBUG: debug1.c:36 show_name(): Ooops! Tamanho da string(13) e excedeu o limite(5)...
Jorge
[jpereira@miracleworld Codes]$

Agora veja situação que você está trabalhando em um sistema com várias checagens complexas de cenários “nada convencionais” em que você não tem certeza se vai acontecer sempre ou não.
Sem falar que torna-se um atrativo a possibilidade de você poder ativar/desativar o simples mecanismo, como por exemplo poder criar macros para depuração de componentes específicos (ex.: relacionadas a sockets, I/O, sgdb, …), isto poderá facilitar a identificação e remoção de bugs.

Lembrando que este e o primeiro post entre vários que pretendo publicar relacionados a sugestões e técnicas de depuração. Fique de olho na segunda parte desta saga em que irei explicar uma mais dinâmica do mesmo assunto abordado neste post associando ao uso de variáveis de ambiente.
Dúvidas e Sugestões, são sempre bem vindas! ;)

Autor: Jorge Pereira

- Adicionado ao Kernel o suporte nativo as teclas especiais do notebook “Sony Vaio VPC-EB15FB”

Sempre tive preferência pelos produtos produzidos pela Sony, em especial os notebooks. O meu antigo VGN-FS750 começou a apresentar alguns problemas após eu ter dado um tombo nele, desde então nunca mais foi o mesmo. :roll:

Porém no mês passado resolvi comprar um novo notebook que fosse preferencialmente da Sony, e após várias buscas cheguei ao modelo VPC-EB15FB. Então fui ao shopping e comprei diretamente na loja da SonyStyle o brinquedinho abaixo.

Assim que cheguei em casa fiz o download do Ubuntu 9.10 e instalei, após o primeiro boot que iniciei a configuração e recuperação dos meus backups do notebook antigo percebi que algumas teclas de atalhos não funcionaram, estranho né? Abaixo imagem das teclas na qual estou me referindo.

Obviamente que não fiquei de braços cruzados, fiz checkout diretamente pelo GIT do Kernel o modulo “platform-drivers-x86” e após alguns ajustes já estava adicionado o suporte das novas teclas da série EB de notebooks da Sony ao Kernel do Linux.

Resumindo, suporte adicionado seguido de patch gerado e submetido ao Kernel. Agora e aguardar a próxima versão do Kernel para termos por padrão o suporte a tais teclas! ;)

Patch gerado a partir do Kernel 2.6.35-rc3

- Introdução aos Linux Device Drivers (ILDD)

Olá,

Caso você tenha necessidade ou curiosidade em relação a Device Drivers no Linux, este com certeza será um bom material para iniciar-se na “brincadeira”.

Introdução aos Linux Device Drivers (ILDD) é um curso que tem por objectivo apresentar os princípios básicos do desenvolvimento de device drivers no Linux kernel. Pretende-se com este curso, que o leitor tenha contacto com várias ferramentas e sub-sistemas existentes no kernel, adquirindo assim as bases que lhe irão permitir desenvolver o suporte para a grande maioria dos dispositivos. Alguns dos temas introduzidos são: estrutura básica de um device driver, comunicação com o userspace, memória dinâmica, eventos assíncronos, primitivas de sincronização e comunicação com o hardware.

Este curso aborda o tema de uma perspectiva pedagógica, através da sistematização dos conceitos em conjunto com uma forte componente prática, na qual se convida o leitor à implementação gradual de um device driver que dará suporte a um dispositivo especificamente concebido para o efeito. O leitor poderá ainda consultar a literatura de referência, de onde se destacam os excelentes títulos: Linux Device Drivers, Understanding the Linux Kernel e Linux Kernel in a Nutshell.

O autor, com a ajuda dos seus revisores, investiu mais de um ano de trabalho na elaboração e preparação deste curso, no sentido de oferecer à comunidade, não só um manual de aprendizagem abrangente, mas também uma importante referência futura. Caso encontre alguns erros ou tenha sugestões que visam melhorar ou complementar este trabalho, não hesite em contactar o autor.

Download aqui

- Imagens talvez jamais vistas?

Para descontrair, abaixo segue algumas imagens que registrei durante o passar do tempo.

(*) Go Horse Process

- Por que as empresas teimam em contratar programadores mercenários?

Recentemente li The Python Paradox, de Paul Graham, e sua tradução O Paradoxo Python no #!SouNerd.

O texto faz todo sentido: quem aprende a fazer qualquer coisa por gosto tende a fazer melhor do que quem aprende a fazer por dinheiro. É uma verdade.

Assim, quem aprende a programar porque gosta de programar tende a programar melhor do que quem aprende para ganhar dinheiro e a grande maioria de quem aprende a programar Java só o faz por dinheiro (claro que há lá suas exceções), enquanto quem aprende linguagens mais esóticas o faz por prazer.

Então por que as empresas teimam em contratar programadores mercenários?

Pensando sobre nisso e observando a comunidade, pensei em uma resposta…

Eu vejo três tipos de programadores, como três vértices de um triângulo cromático, e cada um está em uma região dessa área, mais próximo ou distante de cada vértice.

Esses três tipos são: amador, mercenário e empolgado (por falta de palavra melhor).

Mercenário

O mercenário é aquele que quer dinheiro e lucro é tudo o que o impulsiona. Geralmente não tem escrúpulos e faz tudo o que lhe mandam. Seu mantra é: «Pagando bem, que mal tem?»

Quem é 100% mercenário geralmente acaba largando a profissão por algo que dê mais dinheiro, mas basta estar um pentelésimo mais para o centro do triângulo que permanece na profissão.

Normalmente aprende uma linguagem que dê muitas opções de emprego – e que, por consequência, tenha de competir com muita gente –, como Java, C# ou PHP, e rejeita todas as demais. Quando as trata como inferiores, é apenas para tentar justificar a própria incompetência, resultante da falta de gosto pelo que faz.

Amador

O amador é aquele que gosta de verdade do que está fazendo, ele ama programar, daí amador.

Quem é 100% amador quase sempre se perde aprendendo coisas inúteis e não consegue ganhar dinheiro porque muitas vezes perde o foco do que precisa fazer, distraindo-se com besteiras.

Normalmente aprende linguagens bem diferentes, que poucos sabem, como Lisp, Smalltalk ou Fortran – talvez LOLCODE –, e não é incomum que aprenda uma penca de linguagens, nesse caso, também os hypes, como Python e Ruby.

Empolgado

O empolgado é aquele que vai atrás de algum hype, linguagem da moda. Há uns anos eram de Java, mas os empolgados da atualidade querem Python e/ou Ruby.

Quem é 100% empolgado sabe tudo que acontece na comunidade, mas quase nada de programação. Conhece todas as metodologias em alta, sabe todos os macetes e design patterns de sua linguagem que precisa para impressionar os iniciantes, mas não é lá muito eficiente. É tão preocupado com a auto-imagem e o que acontece na comunidade que se esquece que há todo um background a ser aprendido por trás da Computação.

**

Felizmente (quase) ninguém é 100% alguma coisa.

Depois de toda esta dissertação, por que diabos as empresas mais engessadas preferem os mercenários?

Por causa de seu mantra! Basta pagar o que o mercenário acha muito – o que muitas vezes é quase nada pra empresa – e ele faz qualquer coisa que mandarem, torna-se um cão bem adestrado. Essas empresas não querem eficiência, querem obediência.

O que as empresas não veem é que esses cães não são tão ágeis quanto os gatos que pulam pelos telhados: aqueles que, apesar de em nenhum extremo, se encontram mais próximos do vértice do amador.

Na verdade as metodologias ágeis não são práticas de trabalho, mas técnias sociais para atrair programadores que, apesar de ainda um pouco mercenários, sejam muito mais amadores – ser um pouco empolgado também ajuda, já que as linguagens hype facilitam pela grande mobilidade da comunidade. As empresas mais espertas e as start-up viram isso e usam as metodologias ágeis para criar equipes enxutas e mais eficientes do que qualquer equipe de mercenários jamais conseguirá ser.

Fonte