Moo - Orientação de objeto minimalista
Tags: perl, opensource, braziliandevs, oop
Published: 2022-04-26 15:55:16


---

Como começar a programar em ***Perl*** da maneira correta. ~~(Diferente de mim)~~


[Perl Orientado a Objeto Part I]
(https://dev.to/victoriabispo/perl-orientado-a-objeto-1bd1/)

[Perl Orientado a Objeto Part II](https://dev.to/victoriabispo/perl-orientado-a-objeto-part-ii-2o54)

[Perl Orientado a Objeto Part III](https://dev.to/victoriabispo/perl-orientado-a-objeto-part-iii-4fe2)

[Moo - Orientação de objeto minimalista](https://dev.to/victoriabispo/moo-orientacao-de-objeto-minimalista-6el)
## O que é o *Moo*

Diferente do *[Moose](https://dev.to/victoriabispo/perl-orientado-a-objeto-part-iii-4fe2)*, que vimos anteriormente, o *Moo* é um sistema de orientação a objetos extremamente leve. Permitindo definições de objetos e funções de maneira bem simples. Tem um sub-conjunto do *Moose o Moo* evita depender de qualquer módulo XS para permitir implantações simples. Fornece quase dois terços do *Moose.*

## Quando usar o *Moo*

Como dito a cima, o *Moo* deve ser utilizado quando a aplicação preza por rapidez ao carregar pacotes e não tem necessidade de utilização de todos os metaprotocolos do *Moose.* A seguir exemplifico alguns casos que o podemos escolher o *Moo:*

- Quando uma linha de comando ou script CGI onde a inicialização rápida é essencial;
- Código projetado para ser implantado como um único arquivo via [App::FatPacker](https://metacpan.org/pod/App::FatPacker);
- Um módulo CPAN que pode ser usado por outros nas situações acima;

## Incompatibilidades do *Moo* para o *Moose*

Se o *Moo* detectar que o *Moose* está sendo carregado, ele registrará automaticamente metaclasses para seus pacotes *Moo* , então você poderá usá-los no código do *Moose* sem modificação.

  O *Moo* não dará suporte para *initializer, super, override, inner e augment* pelos seus criadores considerarem más idéias ou práticas de programação no *Perl.*

## Usando o Moo nos exemplos dos artigos anteriores

```perl
package Performances;
use strict;
use warnings;
use Moo;

# Declare the attributes
has 'name' => (is  => 'rw', # Declare read and write at runtime
	default =>'No name', # Attribute default value
);

has 'audience' => (isa =>'Int', # Declare as integer
  is => 'rw',
  default => sub { 
      my $self = shift; 
      my $qtd = shift;
      return $qtd if defined $qtd and $qtd > 0;
      return 'No audience or invalid value';
  } # Attribute default value
); # Declare read and write at runtime
```

## Sub-rotinas importadas

### Extends

Declara uma classe base. A classe será carregada, mas nenhum erro será acionado se a classe não puder ser encontrada e já houver subs na classe.

Chamar *extends* mais de uma vez irá SUBSTITUIR suas superclasses, não adicionar a elas como '*use base'* ou *‘use parent’* faria.

```perl
extends 'Performances';
```

### With

```perl
with 'Performances::Tragedy', 'Performances::Comedy';
```

Indica que a classe atual compõe uma ou mais funções da *Performances* [](https://metacpan.org/pod/Moo::Role). Um erro será gerado se essas funções não puderem ser compostas porque possuem definições de método conflitantes. As funções serão carregadas usando o mesmo mecanismo que os *extends*.

### Has

Declara um atributo para a Classe.

**is**

Obrigatório para a declaração , pode ser *ro, lazy, rwp* ou *rw.*

- *ro* - significa "somente leitura" e gera um acessador que morre se você tentar escrever nele - ou seja, apenas um *getter* - padronizando *reader* o nome do atributo.
- *lazy* - gera um leitor como *ro*, mas também define *lazy*  como 1 e *builder* como *_build_${attribute_name*} permitir atributos gerados sob demanda.
- *rwp* -significa "ler-escrever protegido" e gera um leitor como *ro*, mas também define *writer* para *_set_${attribute_name}* atributos que são projetados para serem escritos de dentro da classe, mas somente leitura de fora.
- *rw* - significa "ler-escrever" e gera um *getter/setter* normal padronizando o *accessor* o nome do atributo especificado.

**isa**

Recebe um *coderef* que é usado para validar o atributo. Ao contrário do *Moose*, o *Moo* não inclui um sistema de tipo básico, então ao invés de fazer *isa ⇒ ‘str’*, deve-se fazer:

```perl
package Performances;
...
# Declare the attributes
has 'name' => (is  => 'rw', # Declare read and write at runtime
	default =>'No name',
	isa => sub {
			die "$_[0] is not a name!" unless looks_like_name $_[0]
		} # Attribute type
);
```

**coerce**

Recebe um coderef que se destina a coagir o atributo. A ideia básica é fazer algo como o seguinte:

```perl
package Performances;
...
# Declare the attributes
has 'audience' => (
	isa => sub {
		die "$_[0] is not a number!" unless looks_like_number $_[0]
		},
	coerce => sub {
			$_[0] % 2 ? $_[0] : $_[0] + 1
		} # Attribute type for audience always ever 
);
```

Observe que o *Moo* sempre executará sua coerção: isso é para permitir que *as* entradas de *isa* sejam usadas puramente para captura de bugs, enquanto as coerções são sempre estruturais para seu código. No entanto, aplicamos a verificação de isa após a execução da coerção para garantir que ela retornou um valor válido.

**trigger**

Recebe um coderef que será chamado sempre que o atributo for definido. Isso inclui o construtor, mas não os valores padrão ou construídos. O coderef será invocado no objeto com o novo valor como argumento.

**default**

Recebe um *coderef* que será chamado com *$self* como seu único argumento para preencher um atributo se nenhum valor para esse atributo for fornecido ao construtor. Como alternativa, se o atributo for *lazy*, será *default* executado quando o atributo for recuperado pela primeira vez se nenhum valor ainda tiver sido fornecido.

**predicate**

Recebe um nome de método que retornará true se um atributo tiver um valor. Se você definir  como apenas 1, o *predicate* será nomeado automaticamente *has_${attr_name}* se o nome do seu atributo não começar com um sublinhado ou *has_${attr_name_without_underscore}* se começar.

**clear**

Recebe um nome de método que limpará o atributo. Se você definir  como apenas 1, o *clear* será nomeado automaticamente *clear_${attr_name*} se o nome do seu atributo não começar com um sublinhado ou  *_clear_${attr_name_without_the_underscore}* se começar. 
**NOTA:** Se o atributo for *laze*, ele será gerado novamente *default ou*  *buider* na próxima vez que for acessado. Se não for, será *undef*.

**lazy**

Recebe um booleano. Definir se desejar que os valores do atributo sejam capturados lentamente. Isso geralmente é uma boa ideia se você tiver um ["construtor"](https://metacpan.org/pod/Moo#builder) que requer que outro atributo seja definido.

**required**

Recebe um booleano . Definir se o atributo deve ser passado na instanciação do objeto.

**reader**

O valor deste atributo será p nome do método que retorna o valor do atributo. 

**writer**

O valor deste atributo será o nome do método para definir o valor do atributo. 

**weak_ref**

Recebe um booleano . Definir se desejar que a referência que o atributo contém seja enfraquecida. Use isso quando referências circulares, que causam vazamentos de memória, são possíveis.

**init_arg**

Recebe o nome da chave a ser procurada no momento da instanciação do objeto. Um uso comum disso é fazer com que um atributo sublinhado tenha um nome de inicialização não sublinhado. *undef* significa que passar o valor na instanciação é ignorado.

**moosify**

Recebe um *coderef* ou uma matriz de *coderefs* que se destina a transformar as especificações de atributos fornecidas, se necessário, ao atualizar para uma função ou classe *Moose*. Você não deve precisar disso por padrão, mas é fornecido como um meio de extensibilidade possível.

### before, around e after

**before** chamado antes do método que está modificando. 

**around** chamado em vez do método que está modificando. O método que você está substituindo é passado como o primeiro argumento (chamado $orig por convenção). Cuidado com os valores de retorno contextuais de $orig.

**after** é chamado após o método que está modificando. 

<aside>
👋🏻 Então pessoal, hoje definimos o *Moo,* mostramos onde ele pode ser usado e quais suas incompatibilidades com o *Moose*. Qualquer dúvida, ou sugestão para os próximos artigos, podem deixar nos comentários. Até a próxima.

</aside>