código legado - php conference brasil - 2014

81
CÓDIGO LEGADO / Michael Granados @dgmike

Upload: michael-castillo-granados

Post on 08-Jul-2015

226 views

Category:

Technology


1 download

DESCRIPTION

Código sujo, código ruim, código feio, código mal-feito, código não orientado a objetos, código rebuscado, espaguete de código. Em duas simples palavras: código legado. Algumas dicas simples de como melhorar o seu dia-a-dia e como ganhar a confiança do seu chefe para tomar decisões nos projetos.

TRANSCRIPT

Page 1: Código legado - PHP Conference Brasil - 2014

CÓDIGO LEGADO / Michael Granados @dgmike

Page 2: Código legado - PHP Conference Brasil - 2014

MICHAEL GRANADOSConversor de sonhos de grandes investidores em realidade

Page 3: Código legado - PHP Conference Brasil - 2014

AGENDAWTF?A vítimaVersionamentoPacotes, pacotes, pacotes...Um grupo, um códigoTestesProgramação Calistênica

Page 4: Código legado - PHP Conference Brasil - 2014

A VÍTIMA

http://github.com/dgmike/phpconference2014-vitima

Page 5: Código legado - PHP Conference Brasil - 2014

WTF?

Page 6: Código legado - PHP Conference Brasil - 2014

WTF?Código sujo

Page 7: Código legado - PHP Conference Brasil - 2014

WTF?Código ruim

Page 8: Código legado - PHP Conference Brasil - 2014

WTF?Código feio

Page 9: Código legado - PHP Conference Brasil - 2014

WTF?Código mal-feito

Page 10: Código legado - PHP Conference Brasil - 2014

WTF?Código não orientado a objetos

Page 11: Código legado - PHP Conference Brasil - 2014

WTF?Código rebuscado

Page 12: Código legado - PHP Conference Brasil - 2014

WTF?Código espaguete

Page 13: Código legado - PHP Conference Brasil - 2014

CÓDIGO LEGADO!To me, legacy code is simply code without tests.

Michael Feathers

Page 14: Código legado - PHP Conference Brasil - 2014

VERSIONAMENTO

Page 15: Código legado - PHP Conference Brasil - 2014

COMECE AGORA!csvsubversion (svn)mercurial (hg)git

Page 16: Código legado - PHP Conference Brasil - 2014

PARE DE TRABALHAR NO SERVIDOR!Tenha uma cópia do projeto em sua máquina

$ cd projeto_que_fiz_download

$ git init

$ git add .

$ git commit -m "Importando projeto para o git"

Page 17: Código legado - PHP Conference Brasil - 2014

AHH.... MAS EU TENHO MEDO DESSA "TELA PRETA"Chega de desculpas: TortoiseGit

Page 18: Código legado - PHP Conference Brasil - 2014

DIA-A-DIA

Page 19: Código legado - PHP Conference Brasil - 2014

LOG DE ATIVIDADES$ git log --oneline -n 10

0b66a73 Adding stepup uptater207d43f Updating phpdocumentor to get last corrections6015990 creating make filed54aafa some doc miscb2a8726 miscc8c3624 Documentor settings70697d4 Adding phpdocumentor to dev239f47d Merge pull request #16 from dgmike/enhancement/#14bf53652 "method" implementationf3653c8 "method" signature

Page 20: Código legado - PHP Conference Brasil - 2014

O QUE MUDOU?$ git diff --name-only b2a8726..HEAD

.stepuprcMakefilecomposer.jsonsrc/Apolo.phpsrc/Route.php

Page 21: Código legado - PHP Conference Brasil - 2014

FUNCIONA SOMENTE NA MINHA MÁQUINA?

No seu servidor linux (git init --bare / gitosis)Na máquina do seu amigo (via ip de rede + ssh)

githubgitlabbitbucket

Page 22: Código legado - PHP Conference Brasil - 2014

NOVO FLUXO DE TRABALHO

Page 23: Código legado - PHP Conference Brasil - 2014

PACOTES, PACOTES, PACOTES...Iremos precisar de ferramentas que irão nos auxiliar ao longo de

nossa jornada.

Fazer download do zip e descompactar é tão anos 90...

Utilize algum gerenciador de pacotes: pear, composer, npm,bower

Page 24: Código legado - PHP Conference Brasil - 2014

UTILIZAREMOS COMPOSERFácil de instalar

$ curl -sS https://getcomposer.org/installer | php

Page 25: Código legado - PHP Conference Brasil - 2014

UTILIZAREMOS COMPOSERFácil de usar

// composer.json{ "require": { "monolog/monolog": "1.2.*" }}

$ php composer.phar install

Page 26: Código legado - PHP Conference Brasil - 2014

UTILIZAREMOS COMPOSERUsar em sua aplicação

require 'vendor/autoload.php';

Page 27: Código legado - PHP Conference Brasil - 2014

UM GRUPO, UM CÓDIGO

Page 28: Código legado - PHP Conference Brasil - 2014

UM GRUPO, UM CÓDIGOfunction dinheiro($valor) { return 'R$ ' . number_format( $valor, 2, '.', '' );}

function precoComDesconto ($produtos, $codigo_promocional = false){ $total = 0;

foreach ( $produtos as $produto ) { $total += $produto['preco_final']; }

$porcentagem = 0;

if ( count($produtos) == 2 ) {

Page 29: Código legado - PHP Conference Brasil - 2014

UM GRUPO, UM CÓDIGOTabs vs Espaços?

2 ou 4 espaços?

Final de linha? mac, linux, windows?

Page 30: Código legado - PHP Conference Brasil - 2014

EDITORCONFIG.ORG

Page 31: Código legado - PHP Conference Brasil - 2014

EDITORCONFIG.ORG# .editorconfig# top-most EditorConfig fileroot = true

# Unix-style newlines with a newline ending every file[*]end_of_line = lfinsert_final_newline = true

# Matches multiple files with brace expansion notation# Set default charset[*.{js,py}]charset = utf-8

# 4 space indentation[*.php]indent_style = spaceindent_size = 4

Page 32: Código legado - PHP Conference Brasil - 2014

CODESNIFFER// composer.json{ "require-dev": { "squizlabs/php_codesniffer": "*" }}

$ composer install

Page 33: Código legado - PHP Conference Brasil - 2014

CODESNIFFER$ ./vendor/bin/phpcs --standard=PSR2 funcoes.php

FILE: ./funcoes.php--------------------------------------------------------------------------------FOUND 16 ERROR(S) AFFECTING 10 LINE(S)-------------------------------------------------------------------------------- 7 | ERROR | Expected "foreach (...) {\n"; found "foreach(...)\n {\n" 7 | ERROR | Space found after opening bracket of FOREACH loop 7 | ERROR | Space found before closing bracket of FOREACH loop 7 | ERROR | Expected 0 spaces after opening bracket; 1 found 7 | ERROR | Expected 0 spaces before closing bracket; 1 found 30 | ERROR | Expected "if (...) {\n"; found "if (...)\n {\n" 34 | ERROR | Opening parenthesis of a multi-line function call must be the | | last content on the line 36 | ERROR | Closing parenthesis of a multi-line function call must be on a | | line by itself 47 | ERROR | Expected "function abc(...)"; found "function abc (...)" 47 | ERROR | Expected 0 spaces between argument "$codigo_promocional" and | | closing bracket; 1 found 47 | ERROR | Opening brace should be on a new line

Page 34: Código legado - PHP Conference Brasil - 2014

CODESNIFFERfunction dinheiro($valor) { return 'R$ ' . number_format( $valor, 2, '.', '' );}

function precoComDesconto ($produtos, $codigo_promocional = false){ $total = 0;

foreach ( $produtos as $produto ) { $total += $produto['preco_final']; }

$porcentagem = 0;

if ( count($produtos) == 2 ) {

Page 35: Código legado - PHP Conference Brasil - 2014

CODESNIFFERfunction dinheiro($valor){ return 'R$ ' . number_format($valor, 2, '.', '');}

function precoComDesconto($produtos, $codigo_promocional = false){ $total = 0;

foreach ($produtos as $produto) { $total += $produto['preco_final']; }

$porcentagem = 0;

if (count($produtos) == 2) { $porcentagem = 5; $total = $total - ($total * 5/100);

Page 36: Código legado - PHP Conference Brasil - 2014

TESTESfunction calculaJuros($produtos, $juros){ echo '<pre>'; print_r($produtos); echo '</pre>'; // teste $total = 0; foreach($produtos as $produto) { $total += $produto['valor_real']; } $total = $total + ($total * $juros / 100); die($total); // teste return $total;}

Page 37: Código legado - PHP Conference Brasil - 2014

TESTESPacotes: PHPUnit, SimpleTest

Tipos: unitários, integração, aceitacao

Page 38: Código legado - PHP Conference Brasil - 2014

SIMPLETEST$ php composer.phar require --dev "lastcraft/simpletest:*"

Page 39: Código legado - PHP Conference Brasil - 2014

SIMPLETESTdefine('SIMPLETEST_DIR', realpath(__DIR__ . '/../../vendor/lastcraft/simpletest'));

require SIMPLETEST_DIR . '/autorun.php';require SIMPLETEST_DIR . '/web_tester.php';

class TestIndex extends WebTestCase{ function testHomePage() { $this->assertTrue($this->get('http://localhost:3001')); $this->assertText('Loja Legado'); }

function testCliqueComprarAdicionaLinkCarrinhoDeCompras() { $this->assertTrue($this->get('http://localhost:3001')); $this->assertNoText('Carrinho de compras');

Page 40: Código legado - PHP Conference Brasil - 2014

SIMPLETEST$ php tests/aceitacao/test_index.php

test_index.phpOKTest cases run: 1/2, Passes: 13, Failures: 0, Exceptions: 0

test_index.php1) Text [texto inexistente] not detected in [String: Loja Legado Loja Legado Loja Legado Carrinho de compras casacos saias vestidos in testCliqueComprarAdicionaLinkCarrinhoDeCompras in TestIndexFAILURES!!!Test cases run: 1/2, Passes: 12, Failures: 1, Exceptions: 0

Page 41: Código legado - PHP Conference Brasil - 2014

PHPUNIT$ php composer.phar require --dev 'phpunit/phpunit:*'

Page 42: Código legado - PHP Conference Brasil - 2014

PHPUNITrequire_once __DIR__ . '/../../funcoes.php';

class FuncoesTest extends PHPUnit_Framework_TestCase{ public function testDinheiro() { $dinheiro = dinheiro(24); $this->assertEquals('R$ 24,00', $dinheiro); }}

Page 43: Código legado - PHP Conference Brasil - 2014

PHPUNIT$ ./vendor/bin/phpunit tests/unitarios/funcoes_test.php

PHPUnit 4.3.5 by Sebastian Bergmann.

..

Time: 33 ms, Memory: 3.00Mb

OK (2 tests, 4 assertions)

Page 44: Código legado - PHP Conference Brasil - 2014

PHPUNIT$ ./vendor/bin/phpunit --testdox tests/unitarios/funcoes_test.php

PHPUnit 4.3.5 by Sebastian Bergmann.

Funcoes [x] Dinheiro [x] Preco com desconto

$ ./vendor/bin/phpunit --tap tests/unitarios/funcoes_test.php

TAP version 13ok 1 - FuncoesTest::testDinheirook 2 - FuncoesTest::testPrecoComDesconto1..2

Page 45: Código legado - PHP Conference Brasil - 2014

PHPUNITO que dá pra fazer?

Mock/StubPre-popular banco de dadosCodeCoverageSelenium

Page 46: Código legado - PHP Conference Brasil - 2014

PROGRAMAÇÃO CALISTÊNICA

Page 47: Código legado - PHP Conference Brasil - 2014

PROGRAMAÇÃO CALISTÊNICA é uma forma de atividade que consiste em uma

variedade de exercícios físicos feitos sem equipamentos oupesos que têm por objetivo aumentar a força e a flexibilidade

usando o peso do próprio corpo como resistência

Calistenia

Jeff Bay escreveu um artigo no livro "The ThoughtWorksAntology" entitulado "Object Calisthenics". Ele propõe um

exercício "calistênico" para melhorar o design de software eajudar a internalizar princípios de bom design de programação

orientada a objetos

Page 48: Código legado - PHP Conference Brasil - 2014

ALGUNS PONTOS RELEVANTES!PHP não é JAVA!!!

Algumas alterações serão feitas!

São apenas dicas e não regras!

Page 49: Código legado - PHP Conference Brasil - 2014

REGRAS DO EXERCÍCIO1. Use apenas um nível de identação por método2. Não use else3. Crie objetos para tipos primitivos e strings4. Use apenas um ponto por linha5. Não abrevie6. Mantenha todas as entidades pequenas7. Não use classes com mais de duas variáveis instanciadas8. Não use coleções de primeira-classe9. Não use Getters/Setters/Properties

Page 50: Código legado - PHP Conference Brasil - 2014

USE APENAS UM NÍVEL DE IDENTAÇÃO POR MÉTODOfunction ganho($registros){ $ganhosTotais = 0; foreach($registros as $registro) { foreach ($registro['produtos'] as $produto) { $ganhosTotais += $produto['valor_real'] - $produto['valor_compra']; } } return $ganhosTotais;}

Page 51: Código legado - PHP Conference Brasil - 2014

USE APENAS UM NÍVEL DE IDENTAÇÃO POR MÉTODOfunction ganho($registros){ $ganhosTotais = 0; foreach($registros as $registro) { $ganhosTotais += ganhosPorRegistro($registro); } return $ganhosTotais;}

function ganhosPorRegistro($registro){ $ganhos = 0; foreach ($registro['produtos'] as $produto) { $ganhos += $produto['valor_real'] - $produto['valor_compra']; } return $ganhos;}

Page 52: Código legado - PHP Conference Brasil - 2014

NUNCA USE ELSEfunction precoFinal($produto){ if ($produto['desconto'] > 0) { $precoFinal = $produto['preco'] - ($produto['preco'] * $produto['desconto'] / 100); } else { $precoFinal = $produto['preco']; } return $precoFinal;}

Page 53: Código legado - PHP Conference Brasil - 2014

NUNCA USE ELSEfunction precoFinal($produto){ if ($produto['desconto'] > 0) { return $produto['preco'] - ($produto['preco'] * $produto['desconto'] / 100); } return $precoFinal = $produto['preco'];}

Outro exemplofunction precoFinal($produto){ $precoFinal = $produto['preco']; if ($produto['desconto'] > 0) { $precoFinal = $produto['preco'] - ($produto['preco'] * $produto['desconto'] / 100); } return $precoFinal;}

Page 54: Código legado - PHP Conference Brasil - 2014

CRIE OBJETOS PARA TIPOS PRIMITIVOS E STRINGS SE ELESPOSSUIREM ALGUM COMPORTAMENTO

Page 55: Código legado - PHP Conference Brasil - 2014

CRIE OBJETOS PARA TIPOS PRIMITIVOS E STRINGS SE ELESPOSSUIREM ALGUM COMPORTAMENTO

function desconto(array $produtos, $desconto){ $total = 0; foreach($produtos as $produto) { $total += $produto['valor_real']; } return $total - ($total * $desconto / 100);}

Page 56: Código legado - PHP Conference Brasil - 2014

CRIE OBJETOS PARA TIPOS PRIMITIVOS E STRINGS SE ELESPOSSUIREM ALGUM COMPORTAMENTO

class ProdutosLista { protected $produtos;

public function __construct(array $produtos) { $this->produtos = $produtos; }

public function valor_real_total() { $total = 0; foreach ($this->produtos as $produto) { $total += $produto['valor_real']; } return $total; }}

Page 57: Código legado - PHP Conference Brasil - 2014

CRIE OBJETOS PARA TIPOS PRIMITIVOS E STRINGS SE ELESPOSSUIREM ALGUM COMPORTAMENTO

class Numeral { protected $valor;

public function __construct($valorInicial = 0) { $this->valor = $valorInicial; } public function valor() { return $this->valor; } public function adiciona(Numeral $valor) { $this->valor += $valor->valor(); } public function removerPercentual(Numeral $percentual) { $this->valor -= $this->valor() * $percentual / 100; }}

Page 58: Código legado - PHP Conference Brasil - 2014

CRIE OBJETOS PARA TIPOS PRIMITIVOS E STRINGS SE ELESPOSSUIREM ALGUM COMPORTAMENTO

function desconto(ProdutosLista $produtos, Numeral $desconto){ $total = new Numeral($produtos->valor_real_total()); $total->removerPercentual($desconto); return $total;}

Page 59: Código legado - PHP Conference Brasil - 2014

USE APENAS UM PONTO ( -> ) POR LINHA SE NÃO FOR UMENCADEAMENTO OU UM GETTER

Page 60: Código legado - PHP Conference Brasil - 2014

USE APENAS UM ( -> ) POR LINHA SE NÃO FOR UMENCADEAMENTO OU UM GETTER

function categoria(ProdutoLista $produtos){ return $produtos->primeiro->categoria->nome->humanizado();}

Page 61: Código legado - PHP Conference Brasil - 2014

USE APENAS UM ( -> ) POR LINHA SE NÃO FOR UMENCADEAMENTO OU UM GETTER

function categoria(ProdutoLista $produtos){ $categoria = $produtos->primeiraCategoria(); $template = $categoria->decorator(new HumanizadoDecorator); return $template->renderiza();}

Page 62: Código legado - PHP Conference Brasil - 2014

USE APENAS UM ( -> ) POR LINHA SE NÃO FOR UMENCADEAMENTO OU UM GETTER

$this possui um valor especial no PHPclass Produtos{ protected $produtos;

public function primeiraCategoria() { // em java: primeiroProduto.categoria() return $this->primeiroProduto->categoria(); }}

Page 63: Código legado - PHP Conference Brasil - 2014

USE APENAS UM ( -> ) POR LINHA SE NÃO FOR UMENCADEAMENTO OU UM GETTER

$this possui um valor especial no PHP$filtros->adicionaImagem($imagem) ->adicionarFiltro(new PretoBranco) ->adicionarFiltro(new BordaMadeira);

Page 64: Código legado - PHP Conference Brasil - 2014

NÃO ABREVIE

Page 65: Código legado - PHP Conference Brasil - 2014

ESTÁ ESCREVENDO A MESMA VARIÁVEL MUITAS VEZES?Parece que temos um código reutilizado várias vezes.

Talvez tenhamos duplicação de código

Page 66: Código legado - PHP Conference Brasil - 2014

O NOME DO MÉTODO ESTÁ MUITO GRANDE?Talvez sua classe/metodo está executando mais do que deveria.

Talvez tenhamos um problema de responsabilidade

Page 67: Código legado - PHP Conference Brasil - 2014

MANTENHA TODAS AS ENTIDADES PEQUENASNada de classes com mais de 50 linhas

Nada de pacotes/diretórios com mais de 10 arquivos

Page 68: Código legado - PHP Conference Brasil - 2014

MANTENHA TODAS AS ENTIDADES PEQUENASNada de classes com mais de 100 linhas

Nada de pacotes/diretórios com mais de 15 arquivos

Page 69: Código legado - PHP Conference Brasil - 2014

NÃO USE CLASSES COM MAIS DE DUAS VARIÁVEISINSTANCIADAS

Page 70: Código legado - PHP Conference Brasil - 2014

TÁ... EU SEI...

Page 71: Código legado - PHP Conference Brasil - 2014

NÃO USE CLASSES COM MAIS DE CINCO VARIÁVEISINSTANCIADAS

Page 72: Código legado - PHP Conference Brasil - 2014

USE COLEÇÕES COMO PRIMEIRA-CLASSEclass Usuario{ protected $fotos = array(); protected $nome = '';

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

public function linkFotos() { $links = array(); foreach($this->fotos as $foto) { $links[] = $foto['link']; } return implode("\n", $links); }}

Page 73: Código legado - PHP Conference Brasil - 2014

USE COLEÇÕES COMO PRIMEIRA-CLASSEclass Usuario{ protected $fotos = null; protected $nome = ''; public function nome() { return $this->nome; } public function fotos() { return $this->fotos; }}

ListaFotos { protected $fotos = array();}

Page 74: Código legado - PHP Conference Brasil - 2014

USE COLEÇÕES COMO PRIMEIRA-CLASSE$fotos->filtrar(...);$fotos->mapear(...);$fotos->adicionar(...);$fotos->original(...);

Page 75: Código legado - PHP Conference Brasil - 2014

NÃO USE GETTERS/SETTERSclass Pessoa{ protected $nome; public getNome() { return $this->nome; } public setNome($nome) { $this->nome = $nome; }}

Page 76: Código legado - PHP Conference Brasil - 2014

USE GETTERS/SETTERSclass Pessoa{ protected $nome;

public getNome() { return $this->nome; }

public maiusculizaNome() { $this->nome = strtoupper($this->nome); }}

Page 77: Código legado - PHP Conference Brasil - 2014

SURPRESA! DOCUMENTE SEU CÓDIGO

// verifica se tem mais de 20 produtosif ($produtos->total() > 20) { $produtos->aplicaDesconto(new Desconto(10));}

Page 78: Código legado - PHP Conference Brasil - 2014

DOCUMENTE SEU CÓDIGO// resgata somente fotos ativas$fotos = array_map( $fotos->filter('ativos'), create_function('$foto', 'return $foto["link"];'));

Não explique um código ruim, corrijá-o!$fotos->filter('ativos')->links();

Page 79: Código legado - PHP Conference Brasil - 2014

PHPDOC/** * Verifica se as credenciais do usuário estão corretas * * @todo implementar conexao com banco de dados * @param String $email Email do usuario * @param String $senha Senha do usuario * * @return Boolean */function verificaLogin(String $email, String $senha) { // ...}

Page 80: Código legado - PHP Conference Brasil - 2014

DÚVIDAS?Seu momento de me deixar sem graça! ;-)

Page 81: Código legado - PHP Conference Brasil - 2014

OBRIGADO! - @dgmike http://www.slideshare.net/dgmike