Object Calisthenics: relaxe e escreva códigos simples

Preview:

Citation preview

Object Calisthenics:relaxe e escreva

códigos simples

Goiânia, 23 de Março de 2013

Otávio Calaça Xavier

otaviocx@gmail.com

Criado em dezembro de 2007; Lista de Discussão:

− Mais de 650 membros.

Projetos:− Encontros mensais;− Softwares Livres em PHP;− Networking.

Eventos:• FLISOL, FGSL, Latinoware, Conisli, CONSOFT, PHP

Conference Brasil, FISL, Join Community …

Precisamos de Colaboradores!!!

Grupo de Desenvolvedores PHP de Goiás

www.gophp.org.br

3

Object Calisthenics: relaxe e escreva códigos simples

Roteiro

• Motivação;

• Orientações;

• Aplicação.

4

Object Calisthenics: relaxe e escreva códigos simples

Por que meu código é ruim?

• Ele é legível?• Ele é testável?• Ele é de fácil manutenção?• Ele é reusável?

5

Object Calisthenics: relaxe e escreva códigos simples

Object Calisthenics

• Calistenia = exercício de relaxamento; ginástica rítimica;

• Uma variedade de exercícios simples e rítimicos para alcançar melhor qualidade de código e OO.

6

Object Calisthenics: relaxe e escreva códigos simples

Object Calisthenics

• Jeff Bay em The ThoughtWorks Anthology definiu o termo Object Calisthenics para a computação, como o conjunto de exercícios para a programação Orientada a Objetos.

7

Object Calisthenics: relaxe e escreva códigos simples

Object Calisthenics

• Orientações:– Nove (9) orientações simples e que

podem ser utilizadas em qualquer linguagem orientada a objetos.

8

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I

somente um nível de identação/recuo por método.

9

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); $valido = true; foreach($produtos as $produto) { $campos = array_keys($produto); foreach ($camposRequeridos as $campoRequerido) { if(!in_array($campoRequerido, $campos)) { $valido = false; } } } return $valido; }

10

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); $valido = true; foreach($produtos as $produto) { $campos = array_keys($produto); foreach ($camposRequeridos as $campoRequerido) { if(!in_array($campoRequerido, $campos)) { $valido = false; } } } return $valido; }

11

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); $valido = true; foreach($produtos as $produto) { $campos = array_keys($produto); foreach ($camposRequeridos as $campoRequerido) { if(!in_array($campoRequerido, $campos)) { $valido = false; } } } return $valido; }

0

12

3

12

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); $valido = true; foreach($produtos as $produto) { $validacao = $this->validarProdutoIndividual($produto, $camposRequeridos); if( ! $validacao) { $valido = false; } } return $valido; } public function validarProdutoIndividual($produto, $camposRequeridos) { $valido = true; $campos = array_keys($produto); foreach ($camposRequeridos as $campoRequerido) { if( ! in_array($campoRequerido, $campos)) { $valido = false; } } }

13

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); $valido = true; foreach($produtos as $produto) { $validacao = $this->validarProdutoIndividual($produto, $camposRequeridos); if( ! $validacao) { $valido = false; } } return $valido; } public function validarProdutoIndividual($produto, $camposRequeridos) { $valido = true; $campos = array_keys($produto); foreach ($camposRequeridos as $campoRequerido) { if( ! in_array($campoRequerido, $campos)) { $valido = false; } } }

14

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); $valido = true; foreach($produtos as $produto) { $validacao = $this->validarProdutoIndividual($produto, $camposRequeridos); if( ! $validacao) { $valido = false; } } return $valido; } public function validarProdutoIndividual($produto, $camposRequeridos) { $valido = true; $campos = array_keys($produto); foreach ($camposRequeridos as $campoRequerido) { if( ! in_array($campoRequerido, $campos)) { $valido = false; } } }

01

2

01

2

15

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); foreach($produtos as $produto) { if( ! $this->validarProdutoIndividual($produto, $camposRequeridos)) { return false; } } return true; } public function validarProdutoIndividual($produto, $camposRequeridos) { $campos = array_keys($produto); $camposEsquecidos = array_diff($camposRequeridos, $campos); return (count($camposEsquecidos) == 0); }

16

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); foreach($produtos as $produto) { if( ! $this->validarProdutoIndividual($produto, $camposRequeridos)) { return false; } } return true; } public function validarProdutoIndividual($produto, $camposRequeridos) { $campos = array_keys($produto); $camposEsquecidos = array_diff($camposRequeridos, $campos); return (count($camposEsquecidos) == 0); }

01

2

17

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

public function validarProdutos($produtos) { $produtosInvalidos = array_filter($produtos, 'verificaProdutoInvalido'); return (count($produtosInvalidos) === 0); } public function verificaProdutoInvalido($produto) { $camposRequeridos = array( 'nome', 'preco', 'descricao', 'tipo' ); $campos = array_keys($produto); $camposEsquecidos = array_diff($camposRequeridos, $campos); return (count($camposEsquecidos) > 0); }

18

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

class Board { ... String board() { StringBuffer buf = new StringBuffer(); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { buf.append(data[i][j]); } buf.append(“\n”); } return buf.toString(); }}

19

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

class Board { ... String board() { StringBuffer buf = new StringBuffer(); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { buf.append(data[i][j]); } buf.append(“\n”); } return buf.toString(); }}

01

2

20

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

class Board { ... String board() { StringBuffer buf = new StringBuffer(); collectRows(buf); return buf.toString(); } void collectRows(StringBuffer buf) { for (int i = 0; i < 10; i++) { collectRow(buf, i); } } void collectRow(StringBuffer buf, int row) { for (int i = 0; i < 10; i++) { Buf.append(data[row][i]); } buf.append(“\n”); }}

21

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO I somente um nível de identação/recuo por método

• Benefícios:

– Maior coesão;

– Reduz a complexidade ciclomática;

– Métodos acabam fazendo apenas uma coisa, como deve ser;

– Aumenta a reusabilidade.

22

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO II

não utilize a palavra-chave else.

23

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO II não utilize a palavra-chave else

public function login() { $usuario = $this->input()->post('usuario'); $senha = $this->input()->post('senha'); $referencia = $this->input()->post('referencia'); if($this->usuariosModel->verificaPermissao($usuario, $senha)) { redirect($referencia); } else { $this->session->setFlashData('erro', 'Usuário ou senha inválidos.'); $this->session->setFlashData('referencia', $referencia); redirect('login'); } }

24

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO II não utilize a palavra-chave else

public function login() { $usuario = $this->input()->post('usuario'); $senha = $this->input()->post('senha'); $referencia = $this->input()->post('referencia'); if($this->usuariosModel->verificaPermissao($usuario, $senha)) { redirect($referencia); } else { $this->session->setFlashData('erro', 'Usuário ou senha inválidos.'); $this->session->setFlashData('referencia', $referencia); redirect('login'); } }

25

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO II não utilize a palavra-chave else

public function login() { $usuario = $this->input()->post('usuario'); $senha = $this->input()->post('senha'); $referencia = $this->input()->post('referencia'); if( ! $this->usuariosModel->verificaPermissao($usuario, $senha)) { $this->session->setFlashData('erro', 'Usuário ou senha inválidos.'); $this->session->setFlashData('referencia', $referencia); $referencia = 'login'; }

redirect($referencia); }

26

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO II não utilize a palavra-chave else

• Benefícios:

– Ajuda a prevenir duplicação de código;

– Reduz a complexidade ciclomática;

– Faz o código ficar mais limpo, passando por um único caminho.

27

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO III

encapsule todos os tipos primitivos e strings.

28

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO III encapsule todos os tipos primitivos e strings

class Aluno { private int matricula; private boolean ativo; private long cpf; //... }

29

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO III encapsule todos os tipos primitivos e strings

class Aluno { private Integer matricula; private Boolean ativo; private Long cpf; //... }

30

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO III (ajuste)

encapsule todos os tipos primitivos e strings, se eles possuírem comportamento.

31

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO III encapsule os tipos primitivos e strings, se eles possuírem

comportamento

class UIComponent { //... public function repaint($animate = true) { //... }}//...$component->repaint(false);

32

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO III encapsule os tipos primitivos e strings, se eles possuírem

comportamento

class UIComponent { //... public function repaint(Animate $animate) { //... }}

class Animate { private $animate; public function __construct($animate = true) { $this->animate = true; }}//...$component->repaint( new Animate(false) );

33

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO III encapsule os tipos primitivos e strings, se eles possuírem

comportamento

• Benefícios:

– Indução de Tipo;

– Encapsulamento de operações.

34

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO IV

somente um ponto (“arrow” para o PHP) por linha.

35

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO IV(ajuste)

somente um ponto (“arrow” para o PHP) por linha, se não for

fluente.

36

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO IV somente um ponto por linha, se não for fluente

$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());

listeners->addListener(new TimeListener()) ->addListener(new RestfulListener());

Não utilize:

$user->getLocation()->getCountry()->getName();

user.getAddress().getPostalConde();

$this->getRestService()->getJson($representations->find($url->getPath()));

this.getUsers().find(userId).getAddress().

37

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO IV somente um ponto por linha, se não for fluente

• Benefícios:

– Legibilidade;

– Construção de testes facilitada (mocks);

– Mais fácil para depurar;

38

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO V

não abrevie.

39

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO Vnão abrevie

• Por que você abrevia?– Preguiça de escrever o mesmo nome várias vezes...

• Talvez isso indique duplicidade de código!

– Preguiça de escrever o nome do método muito longo...• Talvez isso indique que o seu método faz mais de

uma coisa. Isso deve ser separado em vários métodos ou até classes!

40

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO Vnão abrevie

• Benefícios:

– Comunicação mais clara;

– Facilita a busca por problemas ocultos.

41

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VI

mantenha suas entidades pequenas.

42

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VImantenha suas entidades pequenas

• Regra original: – 50 linhas por classe.

• Regra adaptada: – 100 linhas por classe (para incluir os blocos de

documentação);– 15 classes por pacote/namespace/pasta;– De 15 a 20 linhas por método.

43

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VImantenha suas entidades pequenas

• Benefícios:

– Responsabilidade única;

– Métodos objetivos;

– Pacotes/namespaces mais enxutos;

44

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VII

não crie classes com mais de duas variáveis de instância.

45

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VII(ajuste)

não crie classes com mais de cinco variáveis de instância.

46

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VIInão crie classes com mais de cinco variáveis de instância.

• Benefícios:

– Lista reduzida de dependências;

– Mais fácil para fazer Mocking para testes.

47

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VIII

use coleções de primeiro nível.

48

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VIIIuse coleções de primeiro nível.

• Qualquer classe que contenha uma coleção (ou tenha esse propósito), não deve conter outras propriedades;

• Encapsulamento de coleções primitivas (arrays);

• Utilização de Interfaces Orientadas a Objetos:– Collections do Java;– SPL do PHP.

49

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO VIIIuse coleções de primeiro nível.

• Benefícios:

– É possível implementar operações em coleções;

– Utilizar métodos já existentes em interfaces pré-definidas;

50

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO IX

não crie métodos getter/setter para propriedades.

51

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO IX(removida)

não crie métodos getter/setter para propriedades.

52

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO IXcrie métodos getter/setter para propriedades

• Muitos frameworks utilizam os métodos getters e setters para inicializar variáveis, reduzindo código e evitando erros desnecessários.

• Não coloque nenhum tipo de regra de negócio nos getters e setters.

53

Object Calisthenics: relaxe e escreva códigos simples

ORIENTAÇÃO X (bônus)

documente seu código.

54

Object Calisthenics: relaxe e escreva códigos simples

Referências

• Object Calisthenics aplicado ao PHP– Guilherme Blanco

• You code sucks, let's fix it– Rafael Dohms

• The ThoughtWorks Anthology– Martin Fower

55

Object Calisthenics: relaxe e escreva códigos simples

FIM

Perguntas?

Obrigado!

Otávio Calaça Xavier

otaviocx@gmail.com

@otaviocx