Object Calisthenics | Boas práticas de programação

Object Calisthenics é basicamente um conjunto de boas práticas e regras de programação para aumentar a qualidade do seu código, ele foi introduzido por Jeff Bay e publicado no seu livro chamado Thought Works Anthology, sua principal motivação para o Object Calisthenics é aplicar alguns princípios do Solid.

As regras do Object Calisthenics são focadas em manutenibilidade, legibilidade, testabilidade e compreensão de seu código. Se você já consegue escrever um código utilizando essas boas práticas como manutenção, legível, testável e compreensível essas regras o ajudarão a escrever um código ainda mais sustentável, mais legível e mais compreensível.

 

São 9 regras do Object Calisthenics:

 

  1.  Apenas um nível de indentação por método.

A principal ideia é que cada método faça apenas uma coisa, dessa forma facilita a leitura e a manutenção do código. Você pode extrair comportamentos para outros métodos garantindo um único nível de indentação, assim, você está fazendo a aplicação do Extract Method Pattern.

Antes

<? php
show de função pública ($ slug)
{
    $ lição = $ this-> repository-> findBySlug ($ slug);
    if ($ lição) {
        if (! vazio ($ lição-> polegar_url)) {
            $ this-> seo () -> addImages ($ lição-> polegar_url);
        }
        if ($ lesson-> track) {
            $ this-> seo () -> setTitle ($ lição-> título. '['. $ lição-> faixa-> título. ']');
        } outro {
            $ this-> seo () -> setTitle ($ lição-> título);
        }
        $ this-> seo () -> setDescription ($ lição-> descrição);
        return $ this-> view ('aulas :: show') -> com (compacto ('lição'));
    }
    retornar redirecionamento (rota ('lição.index'));
}

Depois

<? php
show de função pública ($ slug)
{
    $ lição = $ this-> repository-> findBySlug ($ slug);
    if ($ lição) {
        $ this-> addThumbToImages ($ lição-> polegar_url);
        $ trackTitle =! $ lição-> acompanhar? '': '['. $ lição-> faixa-> título. ']';
        $ this-> seo () -> setTitle ($ lição-> título. $ trackTitle);
        $ this-> seo () -> setDescription ($ lição-> descrição);
        return $ this-> view ('aulas :: show') -> com (compacto ('lição'));
    }
    retornar redirecionamento (rota ('lição.index'));
}
função protegida addThumbToImages ($ thumbURL)
{
    if (vazio ($ thumbURL)) {
        retorna falso;
    }
    retornar $ this-> seo () -> addImages ($ thumbURL);
}

Segunda Regra: Não use else

A ideia principal dessa regra é evitar o máximo possível o uso do “else” e assumindo que temos um fluxo de execução.

Antes

<? php
função protegida indexAction ()
{
    if ($ this-> security-> isGranted ('ADMIN')) {
        $ view = 'admin / index.html.twig';
    } outro {
        $ view = 'home / access_denied.html.twig';
    }
    retornar $ this-> render ($ view);
}
Depois
<? php
função protegida indexAction ()
{
    if ($ this-> security-> isGranted ('ADMIN')) {
        retorne $ this-> render ('admin / index.html.twig');
    }
    retorne $ this-> render ('home / access_denied.html.twig');
}

Terceira regra: Envolva seus tipos primitivos

Essa regra é simples, pois ela diz que você deve encapsular todos os tipos primitivos dentro dos objetos, prevenindo assim Primitive Obsession Anyi-Pattern.

Antes

<? php
ordem da classe
{
    função pública notifyBuyer ($ email)
    {
        if (filter_var ($ email, FILTER_VALIDATE_EMAIL) === false) {
            lançar novo InvalidEmailException;
        }
        
        retornar $ this-> repository-> sendEmail ($ email);
    }
}

Depois

<? php
classe Email {
    público $ email;
    função pública __construct ($ email)
    {
        if (filter_var ($ email, FILTER_VALIDATE_EMAIL) === false) {
            lançar novo InvalidEmailException;
        }

        retornar $ this-> email = $ email;
    }
}
ordem da classe
{
    função pública notifyBuyer ($ email)
    {
        retornar $ this-> repository-> sendEmail (novo email ($ email));
    }
}

Quarta regra: Envolva sua collections em classes
Essa regra diz que se você tiver um conjunto de elementos e quiser manipula-los, é necessário criar uma classe dedica apenas para este conjunto, sendo assim, ao atualizar aquele valor, com certeza será em sua collection.
Seguindo o comportamento dessa regra, você deixa os comportamento relacionados. A regra tem como objetivo Aderir o Single Responsibility Principle e High Cohersion.

Quinta regra: Use apenas um ponto por linha
O “ponto” é o que você usa para chamar métodos em Java ou C#; no PHP seria uma seta. Esta regra é o exemplo da Lei de Deméter: você nunca deve usar mais de um operador de objeto, explicando com outras palavras, você não deve encadear chamadas de métodos.

Sexta Regra: Não Abrevie
Por mais tentador que seja abreviarmos nomes de variáveis, classes ou métodos, não façam isso, pois as abreviações podem ser confusas e tendem a esconder problemas maiores.
Sempre tente manter nome de suas classes, métodos ou variáveis, com apenas duas palavras, e que essas palavras não sejam repetitivas.

Sétima regra: Mantenha todas as classes pequenas
É recomendável que uma classe tenha no máximo 50 linhas, e os pacotes não tenham mais do que 10 arquivos, pois geralmente quando criamos uma classe com mais de 50 linhas, atribuímos a ela mais responsabilidades, tornando-a mais difícil de se entender e reutilizar.
As classes e os pacotes devem ser coesos e ter um propósito, e esse proposito deve ser fácil de se entender.

Oitava regra: Não tenha mais que duas variáveis de instância em sua classe
A regra pode ser muito simples, mas ao mesmo tempo é uma das mais difíceis a serem implementadas, já que ela depende de um mindset totalmente diferente do habitual. Quando temos no máximo duas variáveis de instância, desta forma estamos garantindo o respeito novamente ao Single Responsibility Principle e High Cohesion. Se sua classe tem mais que duas variáveis de instância, é provável que ela esteja fazendo mais de uma responsabilidade

Nona regra: Não use Getters ou Setters

É uma ideia básica, onde você retira os getters e setters para poder adicionar decisões no próprio objeto, qualquer decisão baseada inteiramente no estado de um objeto deve ser feita diretamente nele. Com isso melhoramos nosso código reduzindo a duplicação de regras e damos uma melhor compreensão àquele objeto.