Download - DevTalk Zoox 04/2016
![Page 1: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/1.jpg)
ZOOX DEV TALK 04/2016
Princípios para melhorar um código
![Page 2: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/2.jpg)
MOTIVAÇÃO
Por que devemos sempre melhorar o código?
Por que um código que funciona não é suficiente?
![Page 3: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/3.jpg)
AVISO
Estes princípios são sugestões e não regras!
![Page 4: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/4.jpg)
STUPID
Singleton
Tight Coupling
Untestability
Premature Optimization
Indescriptive Naming
Duplication
![Page 5: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/5.jpg)
SINGLETON
Representa um estado global do seu código
Programas que usam estado global são difíceis de testar e debugar
Programas que dependem do estado global mascaram suas dependências
![Page 6: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/6.jpg)
TIGHT COUPLING
Generalização do problema com Singleton
Se mudar um módulo te obriga a mudar outro módulo
Torna o código difícil de reusar e testar
Para evitar, favorecer composição sobre herança e usar injeção dedependência sempre que possível
![Page 7: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/7.jpg)
UNTESTABILITY
Testes não devem ser difíceis
Deixar de escrever um teste economiza tempo de imediato, mas perdemuito mais depois ”caçando” bugs e testando manualmente (falho)
Se escrever um teste é difícil, o problema está no código
Normalmente, untestability é causada por tight coupling
![Page 8: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/8.jpg)
PREMATURE OPTIMIZATION
Não super complique o código para otimizá-lo
Terá apenas custo e não benefício
Meça a performance antes de otimizar (benchmarks)
YAGNI = You Ain’t Gonna Need It (Você não vai precisar disso)
![Page 9: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/9.jpg)
INDESCRIPTIVE NAMING
Nomeie classes, métodos, atributos apropriadamente
Não abrevie
Se não consegue achar um nome apropriado para uma classe, talvez a responsabilidade dela não esteja bem definida.
Linguagem de programação é para humanos
Para o computador, $vlna é o mesmo que $valorLitraoNoAlto
![Page 10: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/10.jpg)
DUPLICAÇÃO
Se duplicar código e tiver que fazer um ajuste, terá que mexer emvários lugares (e se esquecer de um?)
DRY = Don’t Repeat Youself
KISS = Keep It Simple, Stupid!
![Page 11: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/11.jpg)
SOLID
Single Responsibility Principle
Open/Close Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
![Page 12: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/12.jpg)
SINGLE RESPONSIBILITY PRINCIPLE
Nunca deve haver mais de uma razão para uma classe mudar
Divida classes grandes
Use camadas
Evite classes God
![Page 13: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/13.jpg)
SRP - EXEMPLO
<?php
class Livro
{
function getAutor()
{
return 'João da Silva';
}
function getTitulo()
{
return 'Grande Livro';
}
function virarPagina()
{
// Avança ponteiro de página
}
function mostraPaginaAtual()
{
echo 'Conteúdo da página';
}
}
O que há de errado no código?
![Page 14: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/14.jpg)
SRP – EXEMPLO MELHORADO
<?php
class Livro
{
function getTitulo()
{
return 'Grande Livro';
}
function getPaginaAtual()
{
echo 'Conteúdo da página';
}
}
interface Printer
{
function printPage($page);
}
class PlainTextPrinter implements Printer
{
function printPage($page) {
echo $page;
}
}
class HtmlPrinter implements Printer
{
function printPage($page) {
echo '<div style="single-page">' . $page . '</div>';
}
}
$livro = new Livro();
$printer = new HtmlPrinter();
$printer->printPage($livro->getPaginaAtual());
![Page 15: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/15.jpg)
OPEN/CLOSE PRINCIPLE
Classes devem ser abertas para expansão, mas fechadas para alteração
Defina todos os atributos como private
Sem variáveis globais
Evite setter (sempre que possível)
![Page 16: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/16.jpg)
OCP - EXEMPLO
<?php
class Retangulo
{
public $altura;
public $largura;
}
class Area
{
public function calculaArea(Retangulo $retangulo)
{
return $retangulo->altura * $retangulo->largura;
}
}
![Page 17: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/17.jpg)
OCP – EXEMPLO DE VIOLAÇÃO
<?php
class Retangulo
{
public $altura;
public $largura;
}
class Circulo
{
public $radio;
}
class Area
{
public function calculaArea($objeto)
{
if ($objeto instanceof Retangulo) {
return $objeto->altura * $objeto->largura;
} elseif ($objeto instanceof Circulo) {
return $objeto->circulo * $objeto->circulo * PI;
}
}
}
![Page 18: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/18.jpg)
OCP – EXEMPLO DE VIOLAÇÃO
<?php
class Retangulo
{
public $altura;
public $largura;
}
class Circulo
{
public $radio;
}
class Area
{
public function calculaArea($objeto)
{
if ($objeto instanceof Retangulo) {
return $objeto->altura * $objeto->largura;
} elseif ($objeto instanceof Circulo) {
return $objeto->circulo * $objeto->circulo * PI;
}
}
}
Tivemos que alterar a classe Area para poder extendê-la. Ela não é
fechada para modificações = não éaberta para expansão
![Page 19: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/19.jpg)
OCP – EXEMPLO MELHORADO
<?php
abstract class Forma
{
abstract function calculaArea();
}
class Retangulo extends Forma
{
public $altura;
public $largura;
public function calculaArea()
{
return $this->altura * $this->largura;
}
}
class Circulo extends Forma
{
public $radio;
public function calculaArea()
{
return $this->circulo * $this->circulo * PI;
}
}
class Area
{
public function calculaArea(Forma $objeto)
{
return $objeto->calculaArea();
}
}
![Page 20: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/20.jpg)
LISKOV SUBSTITUTION PRINCIPLE
Subclasses devem poder ser substituidas por sua classe base
Classes filhas não devem quebrar as definições de suas bases
Objetos num código devem poder ser substituídos por seus subtipossem alterar o funcionamento correto do programa
![Page 21: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/21.jpg)
LSP - EXEMPLO
<?php
class Retangulo
{
protected $altura;
protected $largura;
public function setLargura($largura)
{ $this->largura = $largura; }
public function setAltura($altura)
{ $this->altura = $altura; }
public function getArea()
{
return $this->altura * $this->largura;
}
}
$retangulo = new Retangulo();
$retangulo->setAltura(10);
$retangulo->setLargura(20);
if ($retangulo->getArea() !== 200) {
throw new \Exception('Área errada');
}
0
![Page 22: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/22.jpg)
LSP - EXEMPLO DE VIOLAÇÃO
<?php
class Retangulo
{
protected $altura;
protected $largura;
public function setLargura($largura) { $this->largura = $largura; }
public function setAltura($altura) { $this->altura = $altura; }
public function getArea()
{
return $this->altura * $this->largura;
}
}
class Quadrado extends Retangulo
{
public function setLargura($largura)
{ $this->largura = $this->altura = $largura; }
public function setAltura($altura)
{ $this->altura = $this->largura = $altura; }
}
$quadrado = new Quadrado();
$quadrado->setAltura(10);
$quadrado->setLargura(20);
if ($quadrado->getArea() !== 200) {
throw new \Exception('Área errada');
}
![Page 23: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/23.jpg)
INTERFACE SEGREGATION PRINCIPLE
Melhor ter várias interfaces específicas a uma só genérica
Uma classe não deveria implementar métodos que não usa
Usando ISP você garante low coupling e high coersion
![Page 24: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/24.jpg)
ISP - EXEMPLO
<?php
interface Veiculo
{
public function liga();
public function abreMala();
public function numEixos();
public function ehMensalista();
}
class Carro implements Veiculo
{
}
class Estacionamento
{
public function permiteEntrada(Veiculo $veiculo)
{
return $veiculo->ehMensalista();
}
}
class Pedagio
{
public function custo(Veiculo $veiculo)
{
return $veiculo->numEixos() * 5;
}
}
![Page 25: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/25.jpg)
ISP – EXEMPLO DE VIOLAÇÃO
<?php
interface Veiculo
{
public function liga();
public function abreMala();
public function numEixos();
public function ehMensalista();
}
class Carro implements Veiculo {}
class Moto implements Veiculo {}
class Estacionamento
{
public function permiteEntrada(Veiculo $veiculo)
{
return $veiculo->ehMensalista();
}
}
class Pedagio
{
public function custo(Veiculo $veiculo)
{
return $veiculo->numEixos() * 5;
}
}
![Page 26: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/26.jpg)
ISP – EXEMPLO MELHORADO
<?php
interface Veiculo
{
public function liga();
}
interface Mensalista
{
public function ehMensalista();
}
interface Mala
{
public function abreMala();
}
interface Eixos
{
public function numEixos();
}
class Carro implements Veiculo, Mensalista, Mala, Eixos {}
class Moto implements Veiculo, Mensalista, Eixos {}
class Estacionamento
{
public function permiteEntrada(Mensalista $veiculo)
{
return $veiculo->ehMensalista();
}
}
class Pedagio
{
public function custo(Eixos $veiculo)
{
return $veiculo->numEixos() * 5;
}
}
![Page 27: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/27.jpg)
DEPENDENCY INVERSION PRINCIPLE
Módulos de alto nível não devem depender de baixo nível, ambos devem depender de abstrações
Abstrações não devem depender de detalhes. Detalhes devemdepender de abstrações
Use o mesmo nível de abstração num determinado nível
![Page 28: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/28.jpg)
DIP - EXEMPLO
<?php
class PDFReader {
private $book;
function __construct(PDFBook $book) {
$this->book = $book;
}
function read() {
return $this->book->read();
}
}
class PDFBook {
function read() {
return "lendo um livro pdf.";
}
}
class Test extends PHPUnit_Framework_TestCase {
function testItCanReadAPDFBook() {
$b = new PDFBook();
$r = new PDFReader($b);
$this->assertRegExp('/livro pdf/', $r->read());
}
}
![Page 29: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/29.jpg)
DIP – EXEMPLO DE VIOLAÇÃO
<?php
class EBookReader {
private $book;
function __construct(PDFBook $book) {
$this->book = $book;
}
function read() {
return $this->book->read();
}
}
class PDFBook {
function read() {
return “lendo um livro pdf.";
}
}
class Test extends PHPUnit_Framework_TestCase {
function testItCanReadAPDFBook() {
$b = new PDFBook();
$r = new EBookReader($b);
$this->assertRegExp('/livro pdf/', $r->read());
}
}
![Page 30: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/30.jpg)
DIP – EXEMPLO MELHORADO
<?php
interface EBook {
function read();
}
class EBookReader {
private $book;
function __construct(EBook $book) {
$this->book = $book;
}
function read() {
return $this->book->read();
}
}
class PDFBook implements Ebook {
function read() {
return " lendo um livro pdf.";
}
}
class Test extends PHPUnit_Framework_TestCase {
function testItCanReadAPDFBook() {
$b = new PDFBook();
$r = new EBookReader($b);
$this->assertRegExp('/livro pdf/', $r->read());
}
}
![Page 31: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/31.jpg)
DIP – EXEMPLO MELHORADO 2
<?phpinterface EBook {
function read();}
class EBookReader {
private $book;
function __construct(EBook $book) {$this->book = $book;
}
function read() {return $this->book->read();
}
}
class PDFBook implements EBook {
function read() {return “lendo um livro pdf.";
}}
class MobiBook implements EBook {
function read() {return “lendo um livro mobi.";
}}
class Test extends PHPUnit_Framework_TestCase {
function testItCanReadAPDFBook() {$b = new PDFBook();$r = new EBookReader($b);
$this->assertRegExp('/livro pdf/', $r->read());}
function testItCanReadAMobiBook() {$b = new MobiBook();$r = new EBookReader($b);
$this->assertRegExp('/livro mobi/', $r->read());}
}
![Page 32: DevTalk Zoox 04/2016](https://reader031.vdocuments.mx/reader031/viewer/2022030402/58a4f7f61a28abce778b4ae3/html5/thumbnails/32.jpg)
DIP – EXEMPLO MELHORADO 2
<?phpinterface EBook {
function read();}
class EBookReader {
private $book;
function __construct(EBook $book) {$this->book = $book;
}
function read() {return $this->book->read();
}
}
class PDFBook implements EBook {
function read() {return “lendo um livro pdf.";
}}
class MobiBook implements EBook {
function read() {return “lendo um livro mobi.";
}}
class Test extends PHPUnit_Framework_TestCase {
function testItCanReadAPDFBook() {$b = new PDFBook();$r = new EBookReader($b);
$this->assertRegExp('/livro pdf/', $r->read());}
function testItCanReadAMobiBook() {$b = new MobiBook();$r = new EBookReader($b);
$this->assertRegExp('/livro mobi/', $r->read());}
}
• Não precisamos mudar a classe EBooReader = OCP• Separamos as responsabilidades = SRP• Segregamos nossas interfaces = ISP• Usamos corretamente o subtipo = LSP
• DIP nos ajuda a manter os outros 4 princípios