Muitas vezes, ao desenvolver algum programa, sentimos falta de uma funo, parmetro, ferramenta ou rotina que facilitaria muito o desenvolvimento.
As vezes, acabamos tendo de criar um mtodo de desenvolver aquela rotina.
Muitos acabam repetindo o mesmo cdigo algumas vezes quando percebemos que poderamos escrever somente uma vez. E ento criada uma rotina, e todas as vezes que precisamos daquele mtodo fazemos a chamada a rotina que criamos.
Ainda, h casos onde a mesma rotina usada em diversas sources diferentes.

Esse artigo, escrito com foco em Perl, vale para qualquer linguagem, orientada ou no a objeto, em seu todo ser mais focadas nas linguagens com suporte a OO. Vamos entender como organizar um cdigo sintetizando rotinas.

Comearemos com um simples programa para desenhar quadrados feitos de pontos


Cdigo PHP:
#!/usr/bin/env perl

use common::sense;

# Desenhar um retangulo ou quadrado feito de pontos

my $altura $ARGV[0];
my $largura $ARGV[1];
for (
my $i 1$i <= $altura$i++){
    print (
". " x $largura) if ($largura != 0) or die "Largura no pode ser 0";
    print 
"\n";


Agora vamos criar uma subrotina


Cdigo PHP:
#!/usr/bin/env perl

use common::sense;

# Desenhar um retangulo ou quadrado feito de pontos

sub retangulo{
    
my $altura $_[0];
    
my $largura $_[1];
    
my $desenho;
    for (
my $i 1$i <= $altura$i++){
        
$desenho .= (". " x $largura) if ($largura != 0) or die "Largura no pode ser 0";
        
$desenho .= "\n";
    }
    return 
$desenho;
}

my $retangulo retangulo(@ARGV);
print 
$retangulo

Mas aqui no faz sentido termos uma subrotina, na verdade o exemplo abaixo ira mostrar porque ter uma.


Cdigo PHP:
#!/usr/bin/env perl

use common::sense;

# Desenhar um retangulo ou quadrado feito de pontos
sub retangulo{
    
my $altura $_[0];
    
my $largura $_[1];
    
my $desenho;

    for (
my $i 1$i <= $altura$i++){
        
$desenho .= (". " x $largura) if ($largura != 0) or die "Largura no pode ser 0";
        
$desenho .= "\n";
    }
    return 
$desenho;
}

print 
"Desenhe um retangulo \nAltura: ";chomp (my $a1 = <STDIN>);
print 
"Largura: ";
chomp (my $l1 = <STDIN>);
my $retangulo retangulo($a1$l1);
print 
$retangulo;

print 
"Desenhe um quadrado \nAresta: ";
chomp (my $a2 = <STDIN>);
my $quadrado retangulo($a2$a2);
print 
$quadrado

Veja que foi possvel usar a mesma rotina de desenhar em pontos diferentes do programa sem repetir todo o cdigo.


Mas as vezes no so um mesmo programa que usa uma determinada rotina.
Na bioinformtica por exemplo, varios programas diferentes usam a mesma rotina.
Ou ate mesmo em casa, voc sempre usa uma mesma rotina em varios dos seus scripts.
Ou quer compartilhar uma rotina ou algo parecido.


Para isso, podemos fazer um mdulo, isso ir facilitar muito.


Exemplo:


Cdigo PHP:
use common::sense;

package retangulo;

#criando o construtor

sub new{
    
my $self shift;
    
bless{@_}, $self;
}

#Nosso gerador de retangulo

sub desenhar{
    
my $self shift;
    
my $altura $self->{altura};
    
my $largura $self->{largura};
    
my $desenho;

    for (
my $i 1$i <= $altura$i++){
        
$desenho .= (". " x $largura) if ($largura != 0) or die "Largura no pode ser 0";
        
$desenho .= "\n";
    }
    return 
$desenho;
}

1

*A classe acima tem vrias formas de serem feitas. Como criar objetos manualmente dentro de uma classe fica para outro post.


Crie o script abaixo e teste.
Cdigo PHP:
#!/usr/bin/env perl

use common::sense;
use 
retangulo;

my $s retangulo->new(altura => 3largura => 5);
print 
$s->desenhar

Salvando o projeto acima como "retangulo.pm", agora voc tem um modulo para desenhar retngulos.
*Lembrando que todo quadrado um retngulo de altura == largura


Agora vamos para a festa.


No exemplo acima tivemos que criar um construtor e ter muito trabalho para acessar os objetos.
Podemos facilitar? Logico que sim. Perl move montanhas.


Para comear a facilitar as coisas, apresento um Modulo muito bom que facilita a criao dos objetos e
da de presente um construtor.


Class::Accessor


No precisarei explicar muito, so lendo a verso atualizada do nosso mdulo abaixo vocs entendero.


Cdigo PHP:
package retangulo;

use 
common::sense;
use 
base 'Class::Accessor';

Class::
Accessor->mk_accessors (qw(altura largura));

sub desenhar{
    
my $self shift;
    
my $altura $self->altura;
    
my $largura $self->largura;
    
my $desenho;

    for (
my $i 1$i <= $altura$i++){
        
$desenho .= (". " x $largura) if ($largura != 0) or die "Largura no pode ser 0";
        
$desenho .= "\n";
    }
    return 
$desenho;
}

1

Recomento o estudo desse mdulo (o que no objetivo dessa postagem).
Recomendo tambm, como opo, o Moose minimalista (Moo).


Agora um detalhe. Teremos que fazer uma alterao no nosso script teste. No deveramos, mas infelizmente o
Class::Accessor exige isso. Ento onde temos my '$s = retangulo->new(altura => 3, largura => 5);' colocaremos
'my $s = retangulo->new({altura => 3, largura => 5});'. Sim, eu sei, minha critica a esse mdulo.
Mas pelo lado positivo, ele melhora o desempenho, acessando os objetos da classe mais rpido do que feito
da forma manual que ensinei na primeira verso do mdulo ou do que na forma a seguir usando o Moose completo.

Nesse artigo mostra um proof entre o Moose, o manual e o Moo. Entre Moo ou Class::Accessor, no conheo, mas deve ser
bem parecido.


#Finalmente o Moose


Vo me perguntar: "Mas voc no disse que os mdulos acima tero desempenho melhor que o Moose?"
Sim! Mas no disse que so melhores.


Eles so verses minimalistas do Moose. Facilitam a criao dos objetos e criam o construtor automaticamente.
Mas isso no o suficiente para alguns casos.
O Moose tem muito mais features (lazy, delegators, roles) e plugins ( procure por MooseX:: ),
fora os hooks after / before / around.


Basicamente, nosso modulo com as mesmas funcionalidades nos exemplos acima ficariam assim com o Moose:


Cdigo PHP:
package retangulo;

use 
common::sense;
use 
Moose;

has 'altura' => (is => 'rw'isa => 'Int', default => '4');
has 'largura' => (is => 'rw'isa => 'Int', default => '4');
#observe que inclui um default

sub desenhar{
    
my $self shift;
    
my $altura $self->altura;
    
my $largura $self->largura;
    
my $desenho;

    for (
my $i 1$i <= $altura$i++){
        
$desenho .= (". " x $largura) if ($largura != 0) or die "Largura no pode ser 0";
        
$desenho .= "\n";
    }
    return 
$desenho;
}

1
* nesse caso o programa fica com aquela linha norma 'my $s = retangulo->new(altura => 3, largura => 5);'.


Podemos usar nosso script normal ou mesmo dessa forma:
Cdigo PHP:
#!/usr/bin/env perl

use common::sense;
use 
retangulo;

my $s retangulo->new;
print 
$s->desenhar
Agora se no definirmos uma aresta, ela vir pr-definida.


uma ferramenta muito mais robusta, com mais funcionalidades. Analisar somente pelo que fiz muito pouco.
O default pode ser feito de outra forma se preciso.
Caberia um estudo minucioso.

Outra opo ao defaut colocar como 'required'.

Cdigo PHP:
package retangulo;

use 
common::sense;
use 
Moose;

has 'altura' => (is => 'rw'isa => 'Int'required => 1);
has 'largura' => (is => 'rw'isa => 'Int'required => 1);
#observe que inclui um default

sub desenhar{
    
my $self shift;
    
my $altura $self->altura;
    
my $largura $self->largura;
    
my $desenho;

    for (
my $i 1$i <= $altura$i++){
        
$desenho .= (". " x $largura) if ($largura != 0) or die "Largura no pode ser 0";
        
$desenho .= "\n";
    }
    return 
$desenho;
}

1
Agora obrigatrio definir as arestas.

Fica a dica pelo estudo do Moose.


Espero que no tenha falado muitas besteiras e que tenha valido de ajuda.