php para adultos: clean code e object calisthenics

90
Title Text Guilherme Blanco PHP 4 Adults Object Calisthenics Clean Code

Upload: guilherme-blanco

Post on 27-Aug-2014

1.584 views

Category:

Software


14 download

DESCRIPTION

Palestra apresentada no InterconPHP em São Paulo. Data do evento: 2014-07-19

TRANSCRIPT

Tit

le T

ext

GuilhermeBlanco

PH

P 4

Adults

Object Calisthenics Clean Code

GuilhermeBlanco

PH

P 4

Adults

Who speaks English?

GuilhermeBlanco

PH

P 4

Adults

"Vamos lá, Sucker! Mexa esse traseiro gordo!"

Fucker & Sucker: A Pair of Two Double Cops

GuilhermeBlanco

PH

P 4

Adults

Guilherme Blanco

@guilhermeblanco

github.com/guilhermeblanco

GuilhermeBlanco

PH

P 4

Adults

Instaclick

• ~300 empregados

• Mais de 67 milhões de usuários (somente em um website)

• 12000 requisições/segundo

• Nós usamos PHP!

GuilhermeBlanco

PH

P 4

Adults

Motivação

• Legibilidade

• Mantenabilidade

• Reusabilidade

• Testabilidade

GuilhermeBlanco

PH

P 4

Adults

Resumindo…

GuilhermeBlanco

PH

P 4

Adults

GuilhermeBlanco

PH

P 4

Adults

Clean Code

GuilhermeBlanco

PH

P 4

Adults S T U P I D

ingleton

ight c

ouplin

g

ntestabil

ity

remature o

ptim

izatio

n

ndescrip

tiv

e n

amin

g

uplic

atio

n

GuilhermeBlanco

PH

P 4

Adults S O L I D

ingle r

esponsib

ilit

y

pen/c

lose p

rin

cip

le

iskov s

ubstit

utio

n

nterface s

egregatio

n

ependency in

versio

n

GuilhermeBlanco

PH

P 4

Adults

Liskov Substitution

Principle

GuilhermeBlanco

PH

P 4

Adults

<?php!!interface Bird!{! public function setLocation($longitude, $latitude);!! public function setAltitude($altitude);!! public function draw();!}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!class Penguim implements Bird!{! public function setAltitude($altitude)! {! // Do nothing! }!}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!interface Bird!{! public function setLocation($longitude, $latitude);!! public function draw($altitude);!}!!interface FlightfulBird extends Bird!{!! public function setAltitude($altitude);!}!

GuilhermeBlanco

PH

P 4

Adults

Dependency Inversion Principle

GuilhermeBlanco

PH

P 4

Adults

<?php!!namespace Dating\UserBundle\Entity!{! class User! {! /**! * @var \Dating\UserBundle\Entity\Image! */!! protected $avatar;! }!}!!namespace Dating\MediaBundle\Entity!{! class Image! {! /**! * @var \Dating\UserBundle\Entity\User! */!! protected $owner;!! }!}

GuilhermeBlanco

PH

P 4

Adults

<?php!!namespace Dating\UserBundle\Entity!{! class User! {! /**! * @var AvatarInterface! */!! protected $avatar;! }!! interface AvatarInterface! {! // ...! }!}!!namespace Dating\MediaBundle\Entity!{! use Dating\UserBundle\Entity\AvatarInterface;!! class Image implements AvatarInterface! {! /**! * @var \Dating\UserBundle\Entity\User! */!! protected $owner;!! }!}!

GuilhermeBlanco

PH

P 4

Adults

Object Calisthenics

Termo grego, significa "exercício"

GuilhermeBlanco

PH

P 4

Adults

Somente um nível de indentação por

método

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters='', $validators='', $options='')!{ ! $data = $_POST; !! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ($input->hasInvalid() || $input->hasMissing()) {! foreach ($input->getMessages() as $field => $messageList) {! foreach ($messageList as $message) {! if (strpos($message, "empty")) {! throw new Tss_FormException(! "The field {$field} cannot be empty!", ! 3, ! "javascript:history.back();"! );! } else { ! throw new Tss_FormException(! "{$message}", ! 3, ! "javascript:history.back();"! );! }! }! }! }!! return $input;!}

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters='', $validators='', $options='')!{ ! $data = $_POST; !! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ($input->hasInvalid() || $input->hasMissing()) {! foreach ($input->getMessages() as $field => $messageList) {! foreach ($messageList as $message) {! if (strpos($message, "empty")) {! throw new Tss_FormException(! "The field {$field} cannot be empty!", ! 3, ! "javascript:history.back();"! );! } else { ! throw new Tss_FormException(! "{$message}", ! 3, ! "javascript:history.back();"! );! }! }! }! }!! return $input;!}

0

Class prototype

12

34

GuilhermeBlanco

PH

P 4

Adults

Early returns

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters=array(), $validators=array(), $options=null)!{ ! $data = $_POST; !! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ( ! ($input->hasInvalid() || $input->hasMissing())) {! ! return $input;!! }!! foreach ($input->getMessages() as $field => $messageList) {! foreach ($messageList as $message) {! if (strpos($message, "empty")) {! throw new Tss_FormException(! "The field {$field} cannot be empty!", ! 3, ! "javascript:history.back();"! );! } else { ! throw new Tss_FormException(! "{$message}", ! 3, ! "javascript:history.back();"! );! }! }! }!! return $input;!} !

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters=array(), $validators=array(), $options=null)!{ ! $data = $_POST; !! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ( ! ($input->hasInvalid() || $input->hasMissing())) {! ! return $input;!! }!! foreach ($input->getMessages() as $field => $messageList) {! foreach ($messageList as $message) {! if (strpos($message, "empty")) {! throw new Tss_FormException(! "The field {$field} cannot be empty!", ! 3, ! "javascript:history.back();"! );! } else { ! throw new Tss_FormException(! "{$message}", ! 3, ! "javascript:history.back();"! );! }! }! }!! return $input;!} !

01

23

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters=array(), $validators=array(), $options=null)!{ ! $data = $_POST; !! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ( ! ($input->hasInvalid() || $input->hasMissing())) {! ! return $input;!! }!! foreach ($input->getMessages() as $field => $messageList) {! foreach ($messageList as $message) {! $errorMessage = (strpos($message, "empty") === false)! ? "The field {$field} cannot be empty!"! : $message;!! throw new Tss_FormException(! $errorMessage, ! 3, ! "javascript:history.back();"! );! }! }!! return $input;!} !

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters=array(), $validators=array(), $options=null)!{ ! $data = $_POST; !! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ( ! ($input->hasInvalid() || $input->hasMissing())) {! ! return $input;!! }!! foreach ($input->getMessages() as $field => $messageList) {! foreach ($messageList as $message) {! $errorMessage = (strpos($message, "empty") === false)! ? "The field {$field} cannot be empty!"! : $message;!! throw new Tss_FormException(! $errorMessage, ! 3, ! "javascript:history.back();"! );! }! }!! return $input;!} !

01

2

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters=array(), $validators=array(), $options=null)!{ ! $data = $_POST; !! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ( ! ($input->hasInvalid() || $input->hasMissing())) {! ! return $input;!! }!! foreach ($input->getMessages() as $field => $messageList) {! $message = array_shift($messageList);! $errorMessage = (strpos($message, "empty") === false)! ? "The field {$field} cannot be empty!"! : $message;!! throw new Tss_FormException(! $errorMessage, ! 3, ! "javascript:history.back();"! );! }!! return $input;!} !

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters=array(), $validators=array(), $options=null)!{ ! $data = $_POST; !! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ( ! ($input->hasInvalid() || $input->hasMissing())) {! ! return $input;!! }!! foreach ($input->getMessages() as $field => $messageList) {! $message = array_shift($messageList);! $errorMessage = (strpos($message, "empty") === false)! ? "The field {$field} cannot be empty!"! : $message;!! throw new Tss_FormException(! $errorMessage, ! 3, ! "javascript:history.back();"! );! }!! return $input;!} !

01

Logical blocks

Variable interpolation

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function validateForm($filters=array(), $validators=array(), $options=null)!{ ! $data = $_POST; ! $input = new Zend_Filter_Input($filters, $validators, $data, $options); ! ! $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); !! if ( ! ($input->hasInvalid() || $input->hasMissing())) {! ! return $input;!! }!! foreach ($input->getMessages() as $field => $messageList) {! $message = array_shift($messageList);! $errorMessage = (strpos($message, "empty") === false)! ? sprintf("The field %s cannot be empty!", $field)! : $message;!! throw new Tss_FormException(! $errorMessage, ! 3, ! "javascript:history.back();"! );! }!! return $input;!} !

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Single Responsibility Principle ("S" de SOLID)

• Favorece reusabilidade

GuilhermeBlanco

PH

P 4

Adults

Não existe "else"

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost($request)!{! $entity = new Post();! $form = new MyForm($entity);! $form->bind($request);! if ($form->isValid()){! $repository = $this->getRepository('MyBundle:Post');! if (!$repository->exists($entity)) {! $repository->save($entity);! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";! return array('form' => $form, 'error' => $error);! }! } else {! $error = "Invalid fields";! return array('form' => $form, 'error' => $error);! } !}

Type-cast

Separe o código em blocos.

Considere como

parágrafos!

Espaçamento

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ($form->isValid()) {! if ( ! $repository->exists($entity)) {! $repository->save($entity);!! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";!! return array('form' => $form, 'error' => $error);! }! } else {! $error = "Invalid fields";! ! return array('form' => $form, 'error' => $error);! } !}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ($form->isValid()) {! if ( ! $repository->exists($entity)) {! $repository->save($entity);!! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";!! return array('form' => $form, 'error' => $error);! }! } else {! $error = "Invalid fields";! ! return array('form' => $form, 'error' => $error);! } !}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ($form->isValid()) {! if ( ! $repository->exists($entity)) {! $repository->save($entity);!! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";!! return array('form' => $form, 'error' => $error);! }! } else {! $error = "Invalid fields";! ! return array('form' => $form, 'error' => $error);! } !}!

GuilhermeBlanco

PH

P 4

Adults

UML Normal vs. Alternate

flows

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ($form->isValid()) {! if ( ! $repository->exists($entity)) {! $repository->save($entity);!! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";!! return array('form' => $form, 'error' => $error);! }! } else {! $error = "Invalid fields";! ! return array('form' => $form, 'error' => $error);! } !}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ($form->isValid()) {! if ( ! $repository->exists($entity)) {! $repository->save($entity);!! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";!! return array('form' => $form, 'error' => $error);! }! } else {! $error = "Invalid fields";! ! return array('form' => $form, 'error' => $error);! } !}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ($form->isValid()) {! if ( ! $repository->exists($entity)) {! $repository->save($entity);!! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";!! return array('form' => $form, 'error' => $error);! }! } else {! $error = "Invalid fields";! ! return array('form' => $form, 'error' => $error);! } !}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ( ! $form->isValid()) {! return array('form' => $form, 'error' => "Invalid fields");! }!! if ( ! $repository->exists($entity)) {! $repository->save($entity);!! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";!! return array('form' => $form, 'error' => $error);! }!}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ( ! $form->isValid()) {! return array('form' => $form, 'error' => "Invalid fields");! }!! if ( ! $repository->exists($entity)) {! $repository->save($entity);!! return $this->redirect('create_ok');! } else {! $error = "Post Title already exists";!! return array('form' => $form, 'error' => $error);! }!}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ( ! $form->isValid()) {! return array('form' => $form, 'error' => "Invalid fields");! }!! if ($repository->exists($entity)) {! return array('form' => $form, 'error' => "Post Title already exists");! }!! $repository->save($entity);!! return $this->redirect('create_ok');!}

GuilhermeBlanco

PH

P 4

Adults

<?php!!public function createPost(Request $request)!{! $repository = $this->getRepository('MyBundle:Post');! $entity = new Post();! $form = new MyForm($entity);!! $form->bind($request);!! if ( ! $form->isValid()) {! return array('form' => $form, 'error' => "Invalid fields");! }!! if ($repository->exists($entity)) {! return array('form' => $form, 'error' => "Post Title already exists");! }!! $repository->save($entity);!! return $this->redirect('create_ok');!}

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Evita duplicação de código

• Aumenta legibilidade

• Reduz cyclomatic complexity

GuilhermeBlanco

PH

P 4

Adults

Encapsule todos os tipos primitivos

e strings

GuilhermeBlanco

PH

P 4

Adults

Encapsule todos os tipos primitivos

e strings

Caso haja comportamento

GuilhermeBlanco

PH

P 4

Adults

Mas… por que?

GuilhermeBlanco

PH

P 4

Adults

O uso excessivo de objetos no PHP aumenta

significativamente o consumo de memória

GuilhermeBlanco

PH

P 4

Adults

<?php!!class Item !{! final public static function find($id)! {! if (is_string($id) && trim($id) != '') {! // do find ...! }!! throw new \InvalidArgumentException('$id must be a non-empty string');! }!! final public static function create($id, array $data)! {! if ( ! is_string($id)) {! throw new \InvalidArgumentException('$id must be a string');! }!! if (empty(trim($id))) {! throw new \InvalidArgumentException('$id must be a non-empty string');! }!! // do create ...! }!}

GuilhermeBlanco

PH

P 4

Adults

<?php!!class Item !{! final public static function find($id)! {! if ( ! is_string($id) || trim($id) === '') {! throw new \InvalidArgumentException('$id must be a non-empty string');! }!! // do find ...! }!! final public static function create($id, array $data)! {! if ( ! is_string($id) || trim($id) === '') {! throw new \InvalidArgumentException('$id must be a non-empty string');! }! ! // do create ...! }!}

GuilhermeBlanco

PH

P 4

Adults

<?php!!class Item !{! final public static function find($id)! {! if ( ! is_string($id) || trim($id) === '') {! throw new \InvalidArgumentException('$id must be a non-empty string');! }!! // do find ...! }!! final public static function create($id, array $data)! {! if ( ! is_string($id) || trim($id) === '') {! throw new \InvalidArgumentException('$id must be a non-empty string');! }! ! // do create ...! }!}

GuilhermeBlanco

PH

P 4

Adults

<?php!!final class Id!{! private $value;!! public function __construct($value)! {! if ( ! is_string($value) || trim($value) === '') {! throw new \InvalidArgumentException(! sprintf('%s must be a non-empty string', $value)! );! }!! $this->value = $value;! }!! public function getValue()! {! return $this->value;! }!}!

GuilhermeBlanco

PH

P 4

Adults

<?php!!class Item !{! final public static function find(Id $id)! {! // do find ...! }!! final public static function create(Id $id, array $data)! {! // do create ...! }!}

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Type hinting

• Encapsulamento de código

• Auxilia na prevenção de código duplicado

GuilhermeBlanco

PH

P 4

Adults

Um único operador de objeto (->) por

linha

GuilhermeBlanco

PH

P 4

Adults

$this->manager->getConfig()->getSegment()->setName("foo");

Propriedades são difíceis de "mockar"

E se a chamada ao método anterior

retornasse NULL?

GuilhermeBlanco

PH

P 4

Adults

NULL Object?

GuilhermeBlanco

PH

P 4

Adults

<?php!!final class NullObject!{!! public function __get($property)!! {!! return new self;!! }!!! public function __set($property, $value)!! {!! return new self;!! }!!! public function __call($method, array $arguments)!! {!! ! return new self;!! }!!! public function __callStatic($method, array $arguments)!! {!! return new self;!! }!!! public function __toString()!! {!! return 'null';!! }!}

GuilhermeBlanco

PH

P 4

Adults

Por que é ruim?

• Esconde um problema de encapsulamento

• Difícil de debugar e tratar exceções

• Código deve ser todo estruturado para utilizar NullObject

• Difícil de ler e entender

GuilhermeBlanco

PH

P 4

Adults

Exceção a interface fluente com o mesmo

nome de método

GuilhermeBlanco

PH

P 4

Adults

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

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Lei de Demeter

• Legibilidade

• Aumenta testabilidade (mais fácil "mockar")

• Facilidade para debugar

GuilhermeBlanco

PH

P 4

Adults

Não abrevie

GuilhermeBlanco

PH

P 4

Adults

– Tim Bray (mencionando Phil Karlton)

“Há apenas 2 problemas difíceis na computação: invalidação de cache,

nomear coisas e errar por 1.”

GuilhermeBlanco

PH

P 4

Adults

Por que você abrevia?

Tit

le T

ext

GuilhermeBlanco

PH

P 4

Adults

Problema de duplicação de código!

Escrever o mesmo nome repetidamente

Tit

le T

ext

GuilhermeBlanco

PH

P 4

Adults

Problema de múltiplas responsabilidades

Nome muito longo

GuilhermeBlanco

PH

P 4

Adults

public function getPage($data) { ... }!!!!public function startProcess() { ... }!!!!$trx->process('site.login');

Obter de onde?

Que p. é essa? $extendedTranslator

fork, create, begin, open

renderHomePage()

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Melhora na comunicação e legibilidade

• Melhora mantenabilidade

• Bom indicador para problemas de encapsulamento e duplicação de código

GuilhermeBlanco

PH

P 4

Adults

Mantenha suas classes pequenas

GuilhermeBlanco

PH

P 4

Adults

Objetivo

• Máximo 200 linhas por classe (incluindo docblocks/documentação)

• 10 métodos por classe

• Até 20 linhas por método

• 15 classes por namespace (folder/pasta)

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Single Responsibility Principle

• Métodos claros e objetivos

• Melhor segregação de código

• Namespaces mais limpos

GuilhermeBlanco

PH

P 4

Adults

Limite o número de variáveis de instância numa classe (2 a 5)

GuilhermeBlanco

PH

P 4

Adults class MyRegistrationService!

{! protected $userService;! protected $passwordService;! protected $logger;! protected $translator;! protected $entityManager;! protected $imageCropper;!! // ...!}

GuilhermeBlanco

PH

P 4

Adults class MyRegistrationService!

{! protected $userService;! protected $passwordService;! protected $logger;! protected $translator;! protected $entityManager;! protected $imageCropper;!! // ...!}

Interações com o banco de dados devemestar em $userService

GuilhermeBlanco

PH

P 4

Adults class MyRegistrationService!

{! protected $userService;! protected $passwordService;! protected $logger;! protected $translator;! protected $entityManager;! protected $imageCropper;!! // ...!}

Utilize um event systeme mova esta instância

para um listener

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Single Responsibility Principle

• Baixo acoplamento

• Melhor encapsulamento

• Melhora testabilidade

GuilhermeBlanco

PH

P 4

Adults

Use coleções de primeiro nível

GuilhermeBlanco

PH

P 4

Adults

Em outros termos…

GuilhermeBlanco

PH

P 4

Adults

Qualquer classe que contenha um array não

deve conter outras propriedades

GuilhermeBlanco

PH

P 4

Adults

<?php!!class User!{! private $name;! // ...!! private $albumList;!!! public function getPublicAlbumList()!! {!! $filteredAlbumList = array();!!! foreach ($this->albumList as $album) {! if ($album->getPrivacy() === AlbumPrivacy::PUBLIC) {! $filteredAlbumList[] = $album;! }!! }!!! return $filteredAlbumList;!! }!! // ...!}!!// Exemplo:!$publicAlbumList = $user->getPublicAlbumList();

GuilhermeBlanco

PH

P 4

Adults

<?php!!class AlbumList extends Collection!{! public function getPublic()! {! $filteredAlbumList = array();!! foreach ($this->value as $album) {! if ($album->getPrivacy() === AlbumPrivacy::PUBLIC) {! $filteredAlbumList[] = $album;! }! }!! return $filteredAlbumList;! }!}!!class User!{! private $name;! private $albumList = new AlbumList();!! // ...!}!!// Exemplo:!$publicAlbumList = $user->getAlbumList()->getPublic();

GuilhermeBlanco

PH

P 4

Adults

<?php!!class AlbumList extends Collection!{! public function getPublic()! {! return new ArrayCollection(! array_filter(! $this->value,! function ($album)! {! return $album->isPublic();! }! )! );! }!}!!class User!{! private $name;! private $albumList = new AlbumList();!! // ...!}!!// Exemplo:!$publicAlbumList = $user->getAlbumList()->getPublic();

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Single Responsibility Principle

• Implementação de operações sobre coleções nas coleções

• Usar classes de SPL

• Facilidade em agrupar coleções sem se preocupar com o comportamento dos membros dela

• Filtragem, ordenação, mapeamento, combinação são bons exemplos de métodos

GuilhermeBlanco

PH

P 4

Adults

Use getters e setters

GuilhermeBlanco

PH

P 4

Adults

<?php!!class BankAccount !{! public $balance = 0;!! public function deposit($amount) ! {! $this->balance += $amount;! }!! public function withdraw($amount)! {! $this->balance -= $amount;! }!}!!// Exemplo:!$account = new BankAccount();!!$account->deposit(100.00);!!// ...!!$account->balance = 0;!!// ...!!$account->withdraw(10.00);!!echo $account->balance . PHP_EOL;

Balance pode seralterado sem que a

classe saiba, causandoerros inesperados

GuilhermeBlanco

PH

P 4

Adults

Benefícios

• Injeção de operações

• Encapsulamento de transformações

• Promove Open/Close Principle ("O" em SOLID)

GuilhermeBlanco

PH

P 4

Adults

Perguntas?

GuilhermeBlanco

PH

P 4

Adults

Thanks! =)

@guilhermeblanco

github.com/guilhermeblanco