Object Calisthenics
Dorian Neto
- Desenvolvedor desde 2011
- Fundador do DojoCE
- CTO na Prombox
- ZCPE ID: ZEND030288


Sumário
- Questionamento e Motivações
- Conceito
- Estudo das regras
Você está satisfeito com a qualidade do seu código?
Motivações
- Legibilidade
- Manutenabilidade
- Testabilidade
- Reusabilidade

Calisthenics é um termo grego = Exercício
Apenas um nível de indentação por método
protected function destroyFile(Model $record)
{
    if (method_exists($record, 'getFileField')) {
        $field = $record->getFileField();
        $field = $record->$field;
        if (!empty($field)) {
            list($file, $extension) = explode('.', $field);
            $extension = '.' . $extension;
            $size = [
                '',
                '_150x150'
            ];
            foreach ($size as $item) {
                $file = $this->uploadPath . $file . $item . $extension;
                
                if (File::exists($file)) {
                    File::delete($file);
                }
            }
        }
    }
}
1
2
3
0
protected function destroyFile(Model $record)
{
    if (!method_exists($record, 'getFileField')) {
        return null;
    }
    $field = $record->getFileField();
    $field = $record->$field;
    if (!empty($field)) {
        list($file, $extension) = explode('.', $field);
        $extension = '.' . $extension;
        $size = [
            '',
            '_150x150'
        ];
        foreach ($size as $item) {
            $file = $this->uploadPath . $file . $item . $extension;
            
            if (File::exists($file)) {
                File::delete($file);
            }
        }
    }
}1
2
0
protected function destroyFile(Model $record)
{
    if (!method_exists($record, 'getFileField')) {
        return null;
    }
    $field = $record->getFileField();
    $field = $record->$field;
    if (empty($field)) {
        return null;
    }
    list($file, $extension) = explode('.', $field);
    $extension = '.' . $extension;
    $size = [
        '',
        '_150x150'
    ];
    foreach ($size as $item) {
        $file = $this->uploadPath . $file . $item . $extension;
        
        if (File::exists($file)) {
            File::delete($file);
        }
    }
}1
0
Não use o ELSE
public function authenticate(Request $request)
{
    $credentials = array(
        'email'    => $request->email,
        'password' => $request->senha
    );
    if (Auth::attempt($credentials)) {
        $notice = [
            'alert'   => 'success',
            'message' => trans('auth.success')
        ];
        return Redirect::intended(route('dashboard'))
            ->with('notice', $notice);
    } else {
        $notice = [
            'alert'   => 'danger',
            'message' => trans('auth.failed')
        ];
        return Redirect::route('login.index')
            ->with('notice', $notice);
    }
}
public function authenticate(Request $request)
{
    $credentials = array(
        'email'    => $request->email,
        'password' => $request->senha
    );
    $notice = [
        'alert'   => 'danger',
        'message' => trans('auth.failed')
    ];
    if (Auth::attempt($credentials)) {
        $notice['alert']   = 'success';
        $notice['message'] = trans('auth.success');
        return Redirect::intended(route('dashboard'))
            ->with('notice', $notice);
    }
    
    return Redirect::route('login.index')
        ->with('notice', $notice);
}
Um único operador de objeto (->) por linha
$this->group->member->setName("Fulano")->getConfig()->invite();
$this->group->member->setName("Fulano")->getConfig()->invite();
$this->group
    ->addFilter(new Foo())
    ->addFilter(new Bar());Exceto para Interface fluente e Query Builder
$this->group->member->setName("Fulano")->getConfig()->invite();
$this->group
    ->addFilter(new Foo())
    ->addFilter(new Bar());
$this->group
    ->where('id', 34)
    ->select(['name'])
    ->get();Exceto para Interface fluente e Query Builder
Não abrevie!
public function calcNum(Group $group) {...}public function calcNum(Group $group) {...}
public function totalMembers(Group $group) {...}public function addMemberAndInviteToGroup(Member $member) {...}
public function addMemberAndInviteToGroup(Member $member) {...}
public function addMember(Member $member) {...}if ($rjx === true) {...}???
if ($rjx === true) {...}
if ($request_ajax === true) {...}Mantenha suas classes pequenas
- Máximo de 200 linhas por classe (incluindo documentação)
- 10 métodos por classe
- Até 20 linhas por método
- 15 Classes por Namespaces (pasta)
Limite o número de atributos de instância numa classe (2 a 5)
class Group
{
    protected $provider;
    protected $member;
    protected $school;
    protected $helper;
    protected $view;
    protected $request;
}class Group
{
    protected $provider;
    protected $member;
    protected $school;
}Não use getters e setters
define('KILL_THE_ENEMY', 1);
define('KILL_THE_BOSS', 5);
class Game
{
    private $score = 0;
    public function setScore($score)
    {
        $this->score = $score;
    }
    public function getScore()
    {
        return $this->score;
    }
}
$player = new Game();
$player->setScore($player->getScore()+KILL_THE_BOSS);Decisão está sendo tomada fora da classe
<?php
define('KILL_THE_ENEMY', 1);
define('KILL_THE_BOSS', 5);
class Game
{
    private $score = 0;
    public function addScore($score)
    {
        $this->score += $score;
    }
}
$player = new Game();
$player->addScore(KILL_THE_BOSS);<?php
define('KILL_THE_ENEMY', 1);
define('KILL_THE_BOSS', 5);
class Game
{
    protected $score = 0;
    public function addScore($score)
    {
        $this->score += $score;
    }
    public function getScore()
    {
        return $this->score;
    }
}
$player = new Game();
$player->addScore(KILL_THE_ENEMY);
$player->addScore(KILL_THE_ENEMY);
$player->addScore(KILL_THE_BOSS);
var_dump($player->getScore());
// int(7)Referências
- http://pt.slideshare.net/guilhermeblanco/php-para-adultos-clean-code-e-object-calisthenics
- http://williamdurand.fr/2013/06/03/object-calisthenics/
- http://www.maawko.com/blog/carreira/object-calisthenics-regras-pra-um-codigo-melhor/
- https://github.com/object-calisthenics/phpcs-calisthenics-rules
- https://www.youtube.com/watch?v=u-w4eULRrr0
Seu código reflete o profissional que você é, então, zele para que ele, assim como você, cresça e se desenvolva.
Obrigado!
@doriansneto
dorianneto.com.br