Ate um simples Hello World pode ser complicado

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

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
[?]

Literate Programs

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
[?]