Programação (I) - Planejamento e Otimização

Este é o primeiro de uma série de artigos sobre programação. Não se trata de um manual e nem de conhecimento sobre uma linguagem específica. São tópicos que podem contribuir para uma melhor qualidade dos programas, de uma forma geral. Espero que a série venha a ajudar de alguma forma, em especial aos novatos na área.

[ Hits: 28.170 ]

Por: Edvaldo Silva de Almeida Júnior em 11/04/2008 | Blog: http://emeraldframework.net


Pesquise sempre a melhor forma de fazer



Bem, estamos chegando ao final e aqui entra o nosso bate-papo sobre otimização.

Não basta fazer um programa funcionar. Tem de fazer ele funcionar bem, ter uma boa performance e ser estável.

Isso exige de analistas e programadores uma constante pesquisa, buscando metodologias alternativas, novas tecnologias e novos conhecimentos.

Para dar um exemplo de como pequenos detalhes podem influenciar grandemente o resultado dos seus programas, escrevi três pequenos exemplos em Perl. São três versões distintas do mesmo programa, que tem como objetivo mostrar na tela uma tabela com todos os números primos menores que 10000.

Sei que esse exemplo pode parecer artificial, mas escolhi-o por razões didáticas. Fui também tendencioso, já que sou matemático por formação acadêmica.

De qualquer forma, o objetivo é mostrar como é que pequenas coisas podem afetar grandemente um programa.

Um pequeno esclarecimento para os menos afeitos à bela ciência da Matemática: número primo é aquele que só é divisível por si mesmo e por um.

Para avaliar a performance do programa eu o executei usando um pequeno shell script que me dá no final a hora de início e de término da execução, permitindo que eu calcule o tempo total de execução. O shell script para executar o programa é bem simples:

teste.sh

#!/bin/bash

INICIO=`date`
perl primos1.pl
FINAL=`date

echo $INICIO
echo $FINAL

INICIO=`date
perl primos2.pl
FINAL=`date`

echo $INICIO
echo $FINAL

INICIO=`date
perl primos3.pl
FINAL=`date`

echo $INICIO
echo $FINAL

exit 0

Na minha primeira versão eu escolhi verificar se um número N era primo testando o resto de sua divisão por todos os números de 2 até (N-1). A variável $l (linha 7) controla o limite do teste. Essa será a única linha alterada nas três versões.

Veja a primeira versão:

primos1.pl

#!/usr/bin/perl

use strict;

sub primo {
    my $n = shift;
    my $l = $n - 1;
    my $d;
    for $d ( 2 .. $l ) {
if ( ( $n % $d ) == 0 ) { return 0; }
    }
    return 1;
}

my $n;
my $cp = 0;
for $n ( 2 .. 10000 ) {
    if ( primo( $n ) ) {
   $cp++;
   printf( "%05d  ", $n);
   if ( ( $cp % 14 ) == 0 ) { print "\n" };
    }
}

print "\n\n Quantidade de primos: ", $cp, "\n\n";

Lembrei então de um resultado matemático que diz que o maior divisor de um número não pode exceder a sua metade, ou seja, o maior divisor de N não pode ser maior do que N/2.

Reescrevi o programa, então, alterando apenas a linha 7, como você pode ver.

primos2.pl

#!/usr/bin/perl use strict; sub primo {     my $n = shift;     my $l = int( $n / 2 ) + 1;     my $d;     for $d ( 2 .. $l ) { if ( ( $n % $d ) == 0 ) { return 0; }     }     return 1; } my $n; my $cp = 0; for $n ( 2 .. 10000 ) {     if ( primo( $n ) ) {    $cp++;    printf( "%05d  ", $n);    if ( ( $cp % 14 ) == 0 ) { print "\n" };     } } print "\n\n Quantidade de primos: ", $cp, "\n\n";

Não fico satisfeito facilmente, portanto continuei buscando em minha já velha e cansada mente uma forma de melhorar o programa. Lembrei então de um outro teorema que afirma que o maior divisor inteiro de um número N não pode ser maior que a raiz quadrada de N. Com essa informação eu fiz a terceira versão, novamente alterando apenas a linha 7.

primos3.pl

#!/usr/bin/perl

use strict;

sub primo {
    my $n = shift;
    my $l = int( sqrt( $n ) ) + 1;
    my $d;
    for $d ( 2 .. $l ) {
if ( ( $n % $d ) == 0 ) { return 0; }
    }
    return 1;
}

my $n;
my $cp = 0;
for $n ( 2 .. 10000 ) {
    if ( primo( $n ) ) {
      $cp++;
      printf( "%05d  ", $n);
      if ( ( $cp % 14 ) == 0 ) { print "\n" };
    }
}

print "\n\n Quantidade de primos: ", $cp, "\n\n";

Você podem pensar que para uma mudança tão pequena não haveria uma alteração tão radical assim no tempo de execução, não é mesmo?

Se pensou assim, enganou-se!

Olha os tempos que obtive para as três versões:

Versão 1 (primos1.pl)
---------------------
Seg Mar 24 23:39:13 BRT 2008
Seg Mar 24 23:39:54 BRT 2008

Tempo total: 41 segundos

Versão 2 (primos2.pl)
---------------------
Seg Mar 24 23:39:54 BRT 2008
Seg Mar 24 23:40:16 BRT 2008

Tempo total: 22 segundos


Versão 3 (primos3.pl)
---------------------
Seg Mar 24 23:40:16 BRT 2008
Seg Mar 24 23:40:17 BRT 2008

Tempo total: 1 segundo

Como você pode ver, uma pequena alteração pode impactar drasticamente a performance de um programa!

É por isso que vale a pena planejar e otimizar.

Programadores precisam ter um conhecimento amplo. Devem procurar estudar bastante os assuntos que estão envolvidos nos programas que estão fazendo. Só assim poderão descobrir a melhor forma de fazer as coisas acontecerem.

OBS: Estes tempos foram obtidos em um K6 380 Mhertz com 128 Mbytes de RAM. Uma supermáquina, não é mesmo?

Conclusão

Espero que o artigo tenha sido instrutivo. Críticas e sugestões são bem vindas. Quem quiser pode escrever diretamente para mim (edlonewolf@gmail.com).

No próximo artigo vou tratar sobre a Modularização de um sistema e sobre as características dos bons módulos.

Até lá!

Página anterior    

Páginas do artigo
   1. O porquê desta série de artigos
   2. A importância do planejamento
   3. Saiba onde quer chegar
   4. Faça uma especificação do seu programa
   5. Planeje seu programa pensando em várias coisas
   6. Pesquise sempre a melhor forma de fazer
Outros artigos deste autor

KDE em um PC "primitivo"

Programação (III) - Programação Orientada a Objetos (POO)

Instalando o Fedora Core 5 via NFS

Software Livre... e um passo além

Programação (II) - Modularização

Leitura recomendada

I Encontro da Comunidade Viva o Linux

obshutdown, Shutdown Menu para OpenBox

A arte do tetra-boot

Obtendo Gnome 2.10 de modo prático!

Babytrans, o Babylon for Linux

  
Comentários
[1] Comentário enviado por eversonamancio em 11/04/2008 - 10:36h

Edvaldo,

Seu artigo está ótimo.

Pretendo ingressar nessa área, e essas informações me foram preciosas.

[2] Comentário enviado por kabalido em 11/04/2008 - 11:20h

Muito bom cara. Parabéns;

[3] Comentário enviado por foguinho.peruca em 11/04/2008 - 14:24h

Olá!

Mto bom artigo. aborda aspectos importantissimos na área de engª de sw...

[4] Comentário enviado por ssdeassis em 11/04/2008 - 17:05h

muito bom artigo, vou ler todos os outros da continuação

[5] Comentário enviado por elionw3 em 11/04/2008 - 17:58h

Otimo, em 15 minutos de leitura conseguiste resumir o q os professores tentam nos ensinar por 5 anos na facul, heehauhuh

principalmente em "Engenharia de Software", o problema é q pelo fato de ser uma materia muito teorica o pessoal não da credito, e depois acaba "se quebrando" pra consertar os furos, q poderiam ser evitados no Planejamento :)

Cumprimentos,
e...
quando sai "Programacao (II)" ?

[]'s

[6] Comentário enviado por removido em 14/04/2008 - 00:28h

Muito bom o artigo e aliás muito bem estruturado.
Só queria deixar registrado, que por causa de vários problemas citados no artigo é que surgiram outras metodologias de desenvolvimento, como XP e SCRUM por exemplo, conhecidas como metodologias ágeis.
Um contato direto com o cliente, mostrando os resultados gradativos, torna a resolução de problemas muito mais rápida e menos "dolorosa".
Como no primeiro caso que você citou, onde após 2 meses apresentaram o projeto e estava tudo errado, se na primeira semana fosse apresentado algum material para o cliente, este poderia detectar diferenças de pensamento no ato, poupando muito tempo (e tempo = dinheiro).
O modelo abordado no artigo, que é conhecido como waterfall (em cascata) tem suas vantagens, mas fazer todo o planejamento antes de iniciar com a mão na massa também acarreta vários problemas, afinal quase todos (para não dizer todos) os projetos estão sujeitos a mudança de escopo no decorrer da implementação ou em um tempo muito curto após ela.

Bom, finalizando gostaria de salientar que não é uma crítica, apenas queria mostrar que existem outras possibilidades nas metodologias de desenvolvimento.

Abraços,

Marcos Antonio Campos Jordão''

[7] Comentário enviado por agk em 14/04/2008 - 16:41h

Muito bom, gostei das explicações, parabéns pelo artigo.

Meu byte de contribuição: no teu shell script pode utilizar o time, fica mais fácil para saber os tempos de execução de cada script.

man time

[ ]'s.

[8] Comentário enviado por EdDeAlmeida em 15/04/2008 - 14:33h

Obrigado pelos comentários! Programação II sai em breve, estou dando meus últimos retoques. Valeu pela dica, agk. Eu já usei o time, mas não sei porque resolvi usar esse método do script. Com certeza o time é mais eficiente.

[9] Comentário enviado por marcio_paim em 14/02/2012 - 20:49h

Muito bom! Acho que a maioria do pessoal que está começando não nota a importância das dicas por que ainda não se deparou com o desenvolvimento de um software cujo tamanho mostre que elas são realmente úteis.

[10] Comentário enviado por MrCrawl3r em 02/05/2016 - 20:26h

Excelente!

Parabéns pelo artigo que já tem um bom tempo e mesmo assim continua ajudando iniciantes como eu rs.

--------------------------------------------------
Att,
Mr Crawler.

O mundo depende dos computadores. Tenha total domínio sobre os computadores e domine o mundo!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts