Clean Code não é tudo!

Mas é 100%

Alessandro Feitoza

PHP Evangelist

FullStack Developer

PHP com Rapadura

Professor de Desenvolvimento Web

Código Limpo!

  • Apenas algumas dicas de como deixar o código manutenivel.
  • Tentar fazer códigos profissionais que garantem uma boa legibilidade.
  • Não entenda a talk como lei, mas como uma visão pessoal do autor que traz argumentos válidos.

Uncle Bob

17 capitulos

1 - Código Limpo

2 - Nomes Significativos

3 - Funções

4 - Comentários

5 - Formatação

7 - Tratamento de Erros

9 - Testes de Unidade

10 - Classes

Vamos aos problemas!

  • Falta de dominio na linguagem
  • Prazo apertado
  • Código escrito "nas côxas"
  • Falta de refatoração
  • GoHorse
  • "Não sou pago pra isso"

Tudo isso cria um alojamento para bugs

Heróizão!

"Chefe" dos prazos

Dev: "chefe, vou ter q atrasar a entrega"

Chefe: "Rapaz, te vira. Lá em cima daquele armário tem uma caixa, aí tem uma roupa verde, de sapo, pega ela, veste e dá teus pulo."

"Chefe" com pitada de motivação

Dev: "chefe, vou ter q atrasar a entrega"

Chefe: "Rapaz, confio na sua capacidade."

#FAZTEUNOME

Isso tudo cria código ruim.

E código ruim sai muito caro, impede melhorias e dificulta a liberdade.

Então simbora aprender a fazer código limpo.

Mas o que é Código Limpo pra você?

"nomes de variáveis limpas, nomes de funções limpas, nomes de classes limpas. Estruturas do código de facil entendimento, códigos explícitos."

Uncle Bob

"código elegante e eficiente com lógica direta que dificulte um alojamento para bugs"

Bjarn Stroustrup

Somos todos Autores

  • Um autor escreve um capitulo que vai ser lido de cima pra baixo.
  • Você lê, e dificilmente volta pra ver o que leu pra entender.
  • Uma escrita romantica é diferente de uma escrita técnica. Quanto mais romantica mais facil do leitor entender.

2 - Nomes Significativos

<?php
$a = 'Alessandro';
$b = 'eu@alessandrofeitoza.eu';
$c = 22;
$d = 'tesudo';
<?php
$name = 'Alessandro';
$email = 'eu@email.eu';
$idade = 22;
$nickname = 'ale_tesudo';

Use nomes que revelem o propósito.

2 - Nomes Significativos

<?php

o = 1;

if (o == 1) {
    a = 0l;
} else {
    a = o1;
}

Não crie problemas para si mesmo

2 - Nomes Significativos

public function dtaRcd102();
public function svUsGroup();

Crie nomes pronunciaveis

public function dataRecord();
public function saveUserInGroup();

3 - Funções

 

  • Crie funções pequenas e Objetivas.
  • Uma função tem a função de fazer apenas uma coisa.
  • Ler o código de cima pra baixo.
  • Poucos Parametros (se precisar crie um objeto)
  • Prefira exceções a retorno de erros em forma de código

3 - Funções

 

  • Poucos Parametros (se precisar crie um objeto)
<?php 

function saveUser(
  string $name, 
  string $email, 
  string $password, 
  bool $status, 
  string $phone, 
  string $type
) {
	...
}
<?php 

function saveUser(User $user) 
{
	...
}

3 - Funções

 

  • Prefira gerar Exception do que validar erros
<?php 

if (saveUser() === 1) {
	...
}

if (saveUser() === false) {
	...
}

if (saveUser() !== false) {
	...
}
<?php 

function saveUser() 
{
  if ($password === '123') {
    return false;
  }
    
  execute();
    
  if (error()) {
    return "error 01";
  }
}

3 - Funções

 

  • Prefira gerar Exception do que validar erros
<?php 

try {
  saveUser();
} catch (PasswordInvalidException $e) {
  ...
} catch (LogicException $e) {
  ...
}
<?php 

function saveUser() 
{
  if ($password === '123') {
    throw new PasswordInvalidException();
  }
    
  execute();
    
  if (error()) {
    throw new LogicException('message here');
  }
}

Aí sim viu, minha vida é o try/catch agora!!!

3 - Funções

  • Tratamento de Erro é uma coisa
<?php

try {
    if ( x() ) {
        $this->facaIsso();
    }

    $this->comandoGeral();
} catch (\Exception $exception) {
    try {
        comando1();
        comando2();
        comando3();
    } catch (\Exception $exception) {
    
    	try ...
        return false;
    }
}

4 - Comentários

  • Evite comentários, isso lhe obriga a criar código auto explicativos;
  • Não faça um diário de bordo (meu querido código)
  • Evite explicar o óbvio
  • Comentários podem se voltar contra você.

4 - Comentários

  • Evite explicar o óbvio
<?php 

// função pra buscar todos os usuários
public function findAllUsers(): array
{
  //abrindo conexão com o banco
  $connection = $this->openConnection();
  
  //retornando um array com todos os usuários
  return $connection->findAll(User::class);
}

4 - Comentários

  • Os comentários podem se voltar contra você.
<?php 

/* função pra adicionar um novo usuário.
 * a função validára se já existe um usuário com o email
 * e gerará uma Exception caso o email já exista.
 */
public function addProduct(Product $product): void
{
  $this->entityManager->persist($product);
}

5 - Formatação

  • Cuidado com o comprimento horizontal;
  • Cuidado com o comprimento vertical;
  • Cuidado com o comprimento;
  • Dê espaço entre os comandos que não fazem sentido próximo;
  • Agrupe códigos que façam uma coisa dependente da outra;
  • Faça uma boa identação!

5 - Formatação

<?php 

public function updateUser(User $user, Request $request): void
{
$user->setName($request->get('name'));
$user->setEmail($request->get('email'));
if ($request->get('password')) {
$user->setPassword(
$this->passwordSecurity->encrypt(
$request->get('password')
)
);
}
$this->entityManager->persist($user);
$this->entityManager->flush();
}

5 - Formatação

<?php 

public function updateUser(User $user, Request $request): void
{
  $user->setName($request->get('name'));
  $user->setEmail($request->get('email'));
  if ($request->get('password')) {
    $user->setPassword(
      $this->passwordSecurity->encrypt(
        $request->get('password')
      )
    );
  }
  $this->entityManager->persist($user);
  $this->entityManager->flush();
}

5 - Formatação

<?php 

public function updateUser(User $user, Request $request): void
{
  $user->setName($request->get('name'));
  $user->setEmail($request->get('email'));
  
  if ($request->get('password')) {
    $user->setPassword(
      $this->passwordSecurity->encrypt(
        $request->get('password')
      )
    );
  }
  
  $this->entityManager->persist($user);
  $this->entityManager->flush();
}

7 - Tratamento de Erro

  • Trate os erros como gostaria de ser tratado (com atenção)
  • Gere Exceções ao invés de códigos de erro;
  • Crie o try - catch antes do restante do código
  • Defina suas exceções de acordo com sua necessidade;
  • Não retorne Null
  • Não passe null como parametro

7 - Tratamento de Erro

class InvalidNumberException extends \InvalidException
{

}

class EmailServiceException extends \Exception
{

}

9 - Teste de Unidade

  • Faça TDD
  • Refatore
  • Faça mais TDD
  • Teste limpos;
  • Testes de acordo com o dominio da Aplicação;

10 - Classes

  • Classes Pequenas e Objetivas (Veja Object Calisthenics)
  • Agrupe as Classes de acordo com o módulo do dominio
  • Responsabilidade Única
  • Cuidado com o alto acomplamento
  • Estude SOLID

Ah, mas PHP é feio e sujo!

PHP 7 / 8

PHP 7.4

class User
{
    /** @var string $name */
    private $name;

    /** @var string $email */
    private $email;

    /** @var int $age */
    private $age;

    /** @var bool $status */
    private $status;

    /** @var Address $address */
    private $address;
}
class User
{
    private string $name;

    private string $email;

    private int $age;

    private bool $status;

    private Address $address;
}

Typed Properties

Tem muito mais coisa.

#FazTeuNome!

#FazTeuCódigo!

Dúvidas

Qualquer programador consegue fazer códigos pra computadores entenderem, mas apenas Bons Programadores fazem código que humanos entendem.

Martin Fowler

Recomendo ler também.

Dica de Dicas

facebook.com/hashtag/PHPnaMarra

twitter.com/hashtag/PHPnaMarra

Valeu o Boi!

Alessandro Feitoza

eu@alessandrofeitoza.eu

@alessandro_feitoza

@feitozaAle

phpcomrapadura.org

[DMT-2020] - Clean Code não é tudo!

By Alessandro Feitoza

[DMT-2020] - Clean Code não é tudo!

Slide sobre Clean Code na Palestra de PHPeste.

  • 712