Oi, Você teria 1 minuto para falar de

Object Calisthenics

"Programe como eu Digo, mas não Como eu Faço"

Alguem Famoso

Alessandro Feitoza

  • Professor de códigos e outras computarias
  • Programador/Desenvolvedor
  • Modelo de Orientação a Objetos

Pusque ter boas práticas?

Pusque ter boas práticas?

Pra não viver perigosamente!

Pra saber o que tá fazendo!

Pra ter um código confiável

Pro código dá "serto"

Não ter um código sobrecarregado

Pra não ter que apagar incêndio

debaixo dágua

Então...

Object Calisthenics

Object Calisthenics

Termo derivado do grego "Exercicio"

Jeff Bay - 2004

  • Dá pra ler

  • Pra testar

  • Dá tesão

8 regras

Regra 1

Somente 1 nível de endentação por método

Regra 1: Somente 1 nível de indentação por método

<?php
    
class Util
{
    public function menu ($role) 
    {
        
        if (isset( $this->options[$role] )) {
            foreach ($this->options[$role] as $key => $item {
                if ( is_array($item) ) {
                    foreach ($item as $sub_item) {
                        ...
                    }  
                } 
            }
        }
    }
}

Regra 1: Somente 1 nível de indentação por método

<?php
    
class Util
{
    public function menu ($role) 
    {
        
        if (isset( $this->options[$role] )) {
            foreach ($this->options[$role] as $key => $item {
                if ( is_array($item) ) {
                    foreach ($item as $sub_item) {
                        ...
                    }  
                }
            }
        }
    }
}

0

1

2

3

Regra 1: Somente 1 nível de indentação por método

<?php
    
class Util
{
    public function menu ($role) 
    {
        if ( !isset( $this->options[$role] )) {
            return false;
        }

        foreach ($this->options[$role] as $key => $item {
            if ( is_array($item) ) {
                foreach ($item as $sub_item) {
                    ...
                }  
            }
        }
    }
}

0

0

1

2

Regra 1: Somente 1 nível de indentação por método

<?php
    
class Util
{
    public function menu ($role) 
    {
        if ( !isset( $this->options[$role] )) {
            return false;
        }

        foreach ($this->options[$role] as $key => $item {
            if ( ! is_array($item) ) {
                ...
                continue;
            }            

            foreach ($item as $sub_item) {
                ...
            }  
        }
    }
}

0

0

1

1

Regra 2

Não use ELSE

Regra 2: Não use ELSE

<?php
    
class Auth
{
    public function login ($email, $password) 
    {
        if ($email === '') {
            return false;
        } else { 
            if ($password === '') {
                return false;
            } else {
                if ($log = $this->searchUserByEmail($email) {
                    if ($log->password === $password) {
                        ...
                    } else {
                        throw new Exception ('Senha Incorreta');
                    }
                } else {
                    throw new Exception ('Usuário não encontrado');
                }
            }
        }
    }
}

Regra 2: Não use ELSE

<?php
    
class Auth
{
    public function login ($email, $password) 
    {
        if ($email === '' && $password === '') {
            return false;
        } else { 
            if ($log = $this->searchUserByEmail($email) {
                if ($log->password === $password) {
                    ...
                } else {
                    throw new Exception ('Senha Incorreta');
                }
            } else {
                throw new Exception ('Usuário não encontrado');
            }
        }
    }
}

Regra 2: Não use ELSE

<?php
    
class Auth
{
    public function login ($email, $password) 
    {
        if ($email === '' && $password === '') {
            return false;
        }

        if ($log = $this->searchUserByEmail($email) {
            if ($log->password === $password) {
                ...
            } else {
                throw new Exception ('Senha Incorreta');
            }
        } else {
            throw new Exception ('Usuário não encontrado');
        }
    }
}

Regra 2: Não use ELSE

<?php
    
class Auth
{
    public function login ($email, $password) 
    {
        if ($email === '' && $password === '') {
            return false;
        }

        $log = $this->searchUserByEmail($email);
        
        if (! $log ) {
            throw new Exception ('Usuário não encontrado');
        }

        if ($log->password === $password) {
            ...
        } else {
            throw new Exception ('Senha Incorreta');
        }
    }
}

Regra 2: Não use ELSE

<?php
    
class Auth
{
    public function login ($email, $password) 
    {
        if ($email === '' && $password === '') {
            return false;
        }

        $log = $this->searchUserByEmail($email);
        
        if (! $log ) {
            throw new Exception ('Usuário não encontrado');
        }

        if ($log->password !== $password) {
            throw new Exception ('Senha Incorreta');
        }
        
        ...
    }
}

Regra 3

Um único '->' por linha

Regra 3: Um único '->' por linha

<?php
    
class UserDAO
{
    public function searchUserByEmail ($email) 
    {
        $this->database->select('tb_user')->from(['email', 'name', 'password'])->where(['email' => $email])->limit(1);
    }
}

Regra 3: Um único '->' por linha

<?php
    
class UserDAO
{
    public function searchUserByEmail ($email) 
    {
        $this->database->select('tb_user')
            ->from(['email', 'name', 'password'])
            ->where(['email' => $email])
            ->limit(1);
    }
}

Regra 3: Um único '->' por linha

<?php
    
class UserDAO
{
    public function searchUserByEmail ($email) 
    {
        $this
            ->database
            ->select('tb_user')
            ->from(['email', 'name', 'password'])
            ->where(['email' => $email])
            ->limit(1);
    }
}

Exemplo com outra linguagem

Regra 3: Um único '->' por linha


    
document.getElementById('name').style.borderColor = 'red';

document
    .getElementById('name')
    .style
    .borderColor = 'red';                            

Regra 3: Um único '->' por linha


    
React.useEffect(() => {
    fetch('/api/customers').then(res => res.json()).then(json => setCustomers(json));
}, []);
                           

                React.useEffect(() => {
                    fetch('/api/customers')
                        .then(res => res.json())
                        .then(json => setCustomers(json));
                }, []);
                                           
                    

Regra 3: Um único . por linha


    
const values = Array.from(document.querySelectorAll('input[type="radio"]')).map(item => item.value.toUpperCase());

Regra 3: Um único . por linha


    
const inputs = document.querySelectorAll('input[type="radio"]');

const values = Array.from(inputs).map(item => item.value.toUpperCase());

Regra 3: Um único . por linha


    
const inputs = Array.from(
    document.querySelectorAll('input[type="radio"]')
);

const values = inputs.map(item => {
    return item.value.toUpperCase();
});

Regra 4

Não use nomes curtos.

Não Abrevie.

Regra 4: Não Abrevie

<?php
    
class User
{
    public function qtd (): int 
    {
        ...
    }

    public function delUs (): void
    {
        ...
    }
}

Regra 4: Não Abrevie

<?php
    
class User
{
    public function totalUsers (): int
    {
        ...
    }

    public function deleteUser (): void
    {
        ...
    }
}

Regra 5

Métodos com apenas 1 responsabilidade

Regra 5: Métodos com apenas 1 responsabilidade

<?php
    
class User
{
    public function createUserAndAddToGroup (User $user): void
    {
        
    }
}

Regra 5: Métodos com apenas 1 responsabilidade

<?php
    
class User
{
    public function createUser (User $user): void 
    {
        ...
    }

    public function addToGroup ($userId): void
    {
        ...
    }
}

Regra 6

Limite o número de atributos de uma classe

Regra 6: Limite o número de atributos de uma classe

<?php
    
class UserLogged
{
    private string $name;
    private string $email;
    private string $password;
    private Config $config;
    private bool $permission;
    private array $menu;
}

Regra 6: Limite o número de atributos de uma classe

<?php
    
class UserLogged
{
    private string $name;
    private string $email;
    private string $password;
}

Regra 7

Classes pequenas e objetivas

Regra 7: Classes pequenas e objetivas

  • Máximo de 200 linhas
  • 10 métodos
  • 20 linhas por método
  • 1 responsabilidade

Regra 8

Use set() concientemente

Regra 8: Use set() concientemente

<?php
    
class EmailSended
{
    private $numberClicks;

    public function setNumberClicks($newClicks)
    {
        $this->numberClicks = $newClicks;
    }

    public function getNumberClicks()
    {
        return $this->numberClicks;
    }
}
<?php
    
class EmailSended
{
    private $numberClicks;

    public function addClick()
    {
        $this->numberClicks++;
    }

    public function getNumberClicks()
    {
        return $this->numberClicks;
    }
}

Regra 8: Use set() concientemente

Referências

  • http://pt.slideshare.net/guilhermeblanco/php-para-adultos-clean-code-e-object-calisthenics
  • http://williamdurand.fr/2013/06/03/object-calisthenics/
  • https://github.com/object-calisthenics/phpcs-calisthenics-rules

Dúvidas?

O que mais estudar?

Padrões de Projeto

E padroes arquiteturais

DRY

Dont Repeat Yourself

KISS

Keep It Simple, Stupid

SOLID

  • Single Responsibility Principle
  • Open Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

Valeu o boi! valeu o vaqueiro!

@alessandro_feitoza

phpcomrapadura.org

alessandrofeitoza.github.io/slides