TitleText
Guilherme

Blanco
PHP4Adults
Object Calisthenics
Clean Code
Guilherme

Blanco
PHP4Adults
Who speaks
English?
Guilherme

Blanco
PHP4Adults
"Vamos lá, Sucker! Mexa esse
traseiro gordo!"
Fucker & Sucker: A Pair of Two Double Cops
Guilherme

Blanco
PHP4Adults
Guilherme Blanco
@guilhermeblanco
github.com/guilhermeblanco
Guilherme

Blanco
PHP4Adults
Instaclick
• ~300 empregados
• Mais de 67 milhões de usuários 

(somente em um website)
• 120...
Guilherme

Blanco
PHP4Adults
Motivação
• Legibilidade
• Mantenabilidade
• Reusabilidade
• Testabilidade
Guilherme

Blanco
PHP4Adults
Resumindo…
Guilherme

Blanco
PHP4Adults
Guilherme

Blanco
PHP4Adults
Clean Code
Guilherme

Blanco
PHP4Adults
S T U P I Dingleton
ightcoupling
ntestability
rematureoptimization
ndescriptivenaming
uplicat...
Guilherme

Blanco
PHP4Adults
S O L I D
ingleresponsibility
pen/closeprinciple
iskovsubstitution
nterfacesegregation
epende...
Guilherme

Blanco
PHP4Adults
Liskov
Substitution
Principle
Guilherme

Blanco
PHP4Adults !
interface Bird!
{!
public function setLocation($longitude, $latitude);!
!
public function s...
Guilherme

Blanco
PHP4Adults !
class Penguim implements Bird!
{!
public function setAltitude($altitude)!
{!
// Do nothing!...
Guilherme

Blanco
PHP4Adults !
interface Bird!
{!
public function setLocation($longitude, $latitude);!
!
public function d...
Guilherme

Blanco
PHP4Adults
Dependency
Inversion Principle
Guilherme

Blanco
PHP4Adults !
namespace DatingUserBundleEntity!
{!
class User!
{!
/**!
* @var DatingUserBundleEntityImage...
Guilherme

Blanco
PHP4Adults !
namespace DatingUserBundleEntity!
{!
class User!
{!
/**!
* @var AvatarInterface!
*/!
! prot...
Guilherme

Blanco
PHP4Adults
Object Calisthenics
Termo grego,
significa "exercício"
Guilherme

Blanco
PHP4Adults
Somente um nível
de indentação por
método
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters='', $validators='', $options='')!
{ !
$data = $_POST;...
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters='', $validators='', $options='')!
{ !
$data = $_POST;...
Guilherme

Blanco
PHP4Adults
Early returns
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters=array(), $validators=array(), $options=null)!
{ !
$da...
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters=array(), $validators=array(), $options=null)!
{ !
$da...
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters=array(), $validators=array(), $options=null)!
{ !
$da...
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters=array(), $validators=array(), $options=null)!
{ !
$da...
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters=array(), $validators=array(), $options=null)!
{ !
$da...
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters=array(), $validators=array(), $options=null)!
{ !
$da...
Guilherme

Blanco
PHP4Adults !
public function validateForm($filters=array(), $validators=array(), $options=null)!
{ !
$da...
Guilherme

Blanco
PHP4Adults
Benefícios
• Single Responsibility Principle 

("S" de SOLID)
• Favorece reusabilidade
Guilherme

Blanco
PHP4Adults
Não existe "else"
Guilherme

Blanco
PHP4Adults !
public function createPost($request)!
{!
$entity = new Post();!
$form = new MyForm($entity)...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults
UML
Normal vs. Alternate

flows
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults !
public function createPost(Request $request)!
{!
$repository = $this->getRepository('MyBund...
Guilherme

Blanco
PHP4Adults
Benefícios
• Evita duplicação de código
• Aumenta legibilidade
• Reduz cyclomatic complexity
Guilherme

Blanco
PHP4Adults
Encapsule todos
os tipos primitivos
e strings
Guilherme

Blanco
PHP4Adults
Encapsule todos
os tipos primitivos
e strings
Caso haja comportamento
Guilherme

Blanco
PHP4Adults
Mas… por que?
Guilherme

Blanco
PHP4Adults
O uso excessivo de
objetos no PHP aumenta
significativamente o
consumo de memória
Guilherme

Blanco
PHP4Adults !
class Item !
{!
final public static function find($id)!
{!
if (is_string($id) && trim($id) ...
Guilherme

Blanco
PHP4Adults !
class Item !
{!
final public static function find($id)!
{!
if ( ! is_string($id) || trim($i...
Guilherme

Blanco
PHP4Adults !
class Item !
{!
final public static function find($id)!
{!
if ( ! is_string($id) || trim($i...
Guilherme

Blanco
PHP4Adults !
final class Id!
{!
private $value;!
!
public function __construct($value)!
{!
if ( ! is_str...
Guilherme

Blanco
PHP4Adults !
class Item !
{!
final public static function find(Id $id)!
{!
// do find ...!
}!
!
final pu...
Guilherme

Blanco
PHP4Adults
Benefícios
• Type hinting
• Encapsulamento de código
• Auxilia na prevenção de código duplica...
Guilherme

Blanco
PHP4Adults
Um único operador
de objeto (->) por
linha
Guilherme

Blanco
PHP4Adults
$this->manager->getConfig()->getSegment()->setName("foo");
Propriedades são

difíceis de "moc...
Guilherme

Blanco
PHP4Adults
NULL Object?
Guilherme

Blanco
PHP4Adults !
final class NullObject!
{!
! public function __get($property)!
! {!
! return new self;!
! }...
Guilherme

Blanco
PHP4Adults
Por que é ruim?
• Esconde um problema de encapsulamento
• Difícil de debugar e tratar exceçõe...
Guilherme

Blanco
PHP4Adults
Exceção a interface
fluente com o mesmo
nome de método
Guilherme

Blanco
PHP4Adults
$filterChain

->addFilter(new Zend_Filter_Alpha())!
->addFilter(new Zend_Filter_StringToLower...
Guilherme

Blanco
PHP4Adults
Benefícios
• Lei de Demeter
• Legibilidade
• Aumenta testabilidade (mais fácil "mockar")
• Fa...
Guilherme

Blanco
PHP4Adults
Não abrevie
Guilherme

Blanco
PHP4Adults
– Tim Bray (mencionando Phil Karlton)
“Há apenas 2 problemas difíceis na
computação: invalida...
Guilherme

Blanco
PHP4Adults
Por que você
abrevia?
TitleText
Guilherme

Blanco
PHP4Adults
Problema de duplicação de
código!
Escrever o mesmo nome repetidamente
TitleText
Guilherme

Blanco
PHP4Adults
Problema de múltiplas
responsabilidades
Nome muito longo
Guilherme

Blanco
PHP4Adults
public function getPage($data) { ... }!
!
!
!
public function startProcess() { ... }!
!
!
!
$...
Guilherme

Blanco
PHP4Adults
Benefícios
• Melhora na comunicação e legibilidade
• Melhora mantenabilidade
• Bom indicador ...
Guilherme

Blanco
PHP4Adults
Mantenha suas
classes pequenas
Guilherme

Blanco
PHP4Adults
Objetivo
• Máximo 200 linhas por classe 

(incluindo docblocks/documentação)
• 10 métodos por...
Guilherme

Blanco
PHP4Adults
Benefícios
• Single Responsibility Principle
• Métodos claros e objetivos
• Melhor segregação...
Guilherme

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

Blanco
PHP4Adults
class MyRegistrationService!
{!
protected $userService;!
protected $passwordService;!
protect...
Guilherme

Blanco
PHP4Adults
class MyRegistrationService!
{!
protected $userService;!
protected $passwordService;!
protect...
Guilherme

Blanco
PHP4Adults
class MyRegistrationService!
{!
protected $userService;!
protected $passwordService;!
protect...
Guilherme

Blanco
PHP4Adults
Benefícios
• Single Responsibility Principle
• Baixo acoplamento
• Melhor encapsulamento
• Me...
Guilherme

Blanco
PHP4Adults
Use coleções de
primeiro nível
Guilherme

Blanco
PHP4Adults
Em outros
termos…
Guilherme

Blanco
PHP4Adults
Qualquer classe que
contenha um array não
deve conter outras
propriedades
Guilherme

Blanco
PHP4Adults !
class User!
{!
private $name;!
// ...!
! private $albumList;!
!
! public function getPublic...
Guilherme

Blanco
PHP4Adults !
class AlbumList extends Collection!
{!
public function getPublic()!
{!
$filteredAlbumList =...
Guilherme

Blanco
PHP4Adults !
class AlbumList extends Collection!
{!
public function getPublic()!
{!
return new ArrayColl...
Guilherme

Blanco
PHP4Adults
Benefícios
• Single Responsibility Principle
• Implementação de operações sobre
coleções nas ...
Guilherme

Blanco
PHP4Adults
Use getters e
setters
Guilherme

Blanco
PHP4Adults !
class BankAccount !
{!
public $balance = 0;!
!
public function deposit($amount) !
{!
$this-...
Guilherme

Blanco
PHP4Adults
Benefícios
• Injeção de operações
• Encapsulamento de transformações
• Promove Open/Close Pri...
Guilherme

Blanco
PHP4Adults
Perguntas?
Guilherme

Blanco
PHP4Adults
Thanks! =)
@guilhermeblanco
github.com/guilhermeblanco
Upcoming SlideShare
Loading in...5
×

PHP para Adultos: Clean Code e Object Calisthenics

4,399

Published on

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

Published in: Software

PHP para Adultos: Clean Code e Object Calisthenics

  1. 1. TitleText Guilherme
 Blanco PHP4Adults Object Calisthenics Clean Code
  2. 2. Guilherme
 Blanco PHP4Adults Who speaks English?
  3. 3. Guilherme
 Blanco PHP4Adults "Vamos lá, Sucker! Mexa esse traseiro gordo!" Fucker & Sucker: A Pair of Two Double Cops
  4. 4. Guilherme
 Blanco PHP4Adults Guilherme Blanco @guilhermeblanco github.com/guilhermeblanco
  5. 5. Guilherme
 Blanco PHP4Adults Instaclick • ~300 empregados • Mais de 67 milhões de usuários 
 (somente em um website) • 12000 requisições/segundo • Nós usamos PHP!
  6. 6. Guilherme
 Blanco PHP4Adults Motivação • Legibilidade • Mantenabilidade • Reusabilidade • Testabilidade
  7. 7. Guilherme
 Blanco PHP4Adults Resumindo…
  8. 8. Guilherme
 Blanco PHP4Adults
  9. 9. Guilherme
 Blanco PHP4Adults Clean Code
  10. 10. Guilherme
 Blanco PHP4Adults S T U P I Dingleton ightcoupling ntestability rematureoptimization ndescriptivenaming uplication
  11. 11. Guilherme
 Blanco PHP4Adults S O L I D ingleresponsibility pen/closeprinciple iskovsubstitution nterfacesegregation ependencyinversion
  12. 12. Guilherme
 Blanco PHP4Adults Liskov Substitution Principle
  13. 13. Guilherme
 Blanco PHP4Adults ! interface Bird! {! public function setLocation($longitude, $latitude);! ! public function setAltitude($altitude);! ! public function draw();! }!
  14. 14. Guilherme
 Blanco PHP4Adults ! class Penguim implements Bird! {! public function setAltitude($altitude)! {! // Do nothing! }! }!
  15. 15. Guilherme
 Blanco PHP4Adults ! interface Bird! {! public function setLocation($longitude, $latitude);! ! public function draw($altitude);! }! ! interface FlightfulBird extends Bird! {! ! public function setAltitude($altitude);! }!
  16. 16. Guilherme
 Blanco PHP4Adults Dependency Inversion Principle
  17. 17. Guilherme
 Blanco PHP4Adults ! namespace DatingUserBundleEntity! {! class User! {! /**! * @var DatingUserBundleEntityImage! */! ! protected $avatar;! }! }! ! namespace DatingMediaBundleEntity! {! class Image! {! /**! * @var DatingUserBundleEntityUser! */! ! protected $owner;! ! }! }
  18. 18. Guilherme
 Blanco PHP4Adults ! namespace DatingUserBundleEntity! {! class User! {! /**! * @var AvatarInterface! */! ! protected $avatar;! }! ! interface AvatarInterface! {! // ...! }! }! ! namespace DatingMediaBundleEntity! {! use DatingUserBundleEntityAvatarInterface;! ! class Image implements AvatarInterface! {! /**! * @var DatingUserBundleEntityUser! */! ! protected $owner;! ! }! }!
  19. 19. Guilherme
 Blanco PHP4Adults Object Calisthenics Termo grego, significa "exercício"
  20. 20. Guilherme
 Blanco PHP4Adults Somente um nível de indentação por método
  21. 21. Guilherme
 Blanco PHP4Adults ! 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;! }
  22. 22. Guilherme
 Blanco PHP4Adults ! 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 1 2 3 4
  23. 23. Guilherme
 Blanco PHP4Adults Early returns
  24. 24. Guilherme
 Blanco PHP4Adults ! 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;! } !
  25. 25. Guilherme
 Blanco PHP4Adults ! 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;! } ! 0 1 2 3
  26. 26. Guilherme
 Blanco PHP4Adults ! 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;! } !
  27. 27. Guilherme
 Blanco PHP4Adults ! 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;! } ! 0 1 2
  28. 28. Guilherme
 Blanco PHP4Adults ! 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;! } !
  29. 29. Guilherme
 Blanco PHP4Adults ! 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;! } ! 0 1 Logical blocks Variable interpolation
  30. 30. Guilherme
 Blanco PHP4Adults ! 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;! } !
  31. 31. Guilherme
 Blanco PHP4Adults Benefícios • Single Responsibility Principle 
 ("S" de SOLID) • Favorece reusabilidade
  32. 32. Guilherme
 Blanco PHP4Adults Não existe "else"
  33. 33. Guilherme
 Blanco PHP4Adults ! 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
  34. 34. Guilherme
 Blanco PHP4Adults ! 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);! } ! }!
  35. 35. Guilherme
 Blanco PHP4Adults ! 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);! } ! }!
  36. 36. Guilherme
 Blanco PHP4Adults ! 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);! } ! }!
  37. 37. Guilherme
 Blanco PHP4Adults UML Normal vs. Alternate
 flows
  38. 38. Guilherme
 Blanco PHP4Adults ! 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);! } ! }!
  39. 39. Guilherme
 Blanco PHP4Adults ! 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);! } ! }!
  40. 40. Guilherme
 Blanco PHP4Adults ! 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);! } ! }!
  41. 41. Guilherme
 Blanco PHP4Adults ! 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);! }! }!
  42. 42. Guilherme
 Blanco PHP4Adults ! 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);! }! }!
  43. 43. Guilherme
 Blanco PHP4Adults ! 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');! }
  44. 44. Guilherme
 Blanco PHP4Adults ! 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');! }
  45. 45. Guilherme
 Blanco PHP4Adults Benefícios • Evita duplicação de código • Aumenta legibilidade • Reduz cyclomatic complexity
  46. 46. Guilherme
 Blanco PHP4Adults Encapsule todos os tipos primitivos e strings
  47. 47. Guilherme
 Blanco PHP4Adults Encapsule todos os tipos primitivos e strings Caso haja comportamento
  48. 48. Guilherme
 Blanco PHP4Adults Mas… por que?
  49. 49. Guilherme
 Blanco PHP4Adults O uso excessivo de objetos no PHP aumenta significativamente o consumo de memória
  50. 50. Guilherme
 Blanco PHP4Adults ! 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 ...! }! }
  51. 51. Guilherme
 Blanco PHP4Adults ! 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 ...! }! }
  52. 52. Guilherme
 Blanco PHP4Adults ! 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 ...! }! }
  53. 53. Guilherme
 Blanco PHP4Adults ! 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;! }! }!
  54. 54. Guilherme
 Blanco PHP4Adults ! class Item ! {! final public static function find(Id $id)! {! // do find ...! }! ! final public static function create(Id $id, array $data)! {! // do create ...! }! }
  55. 55. Guilherme
 Blanco PHP4Adults Benefícios • Type hinting • Encapsulamento de código • Auxilia na prevenção de código duplicado
  56. 56. Guilherme
 Blanco PHP4Adults Um único operador de objeto (->) por linha
  57. 57. Guilherme
 Blanco PHP4Adults $this->manager->getConfig()->getSegment()->setName("foo"); Propriedades são
 difíceis de "mockar" E se a chamada ao método anterior retornasse NULL?
  58. 58. Guilherme
 Blanco PHP4Adults NULL Object?
  59. 59. Guilherme
 Blanco PHP4Adults ! 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';! ! }! }
  60. 60. Guilherme
 Blanco PHP4Adults 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
  61. 61. Guilherme
 Blanco PHP4Adults Exceção a interface fluente com o mesmo nome de método
  62. 62. Guilherme
 Blanco PHP4Adults $filterChain
 ->addFilter(new Zend_Filter_Alpha())! ->addFilter(new Zend_Filter_StringToLower());
  63. 63. Guilherme
 Blanco PHP4Adults Benefícios • Lei de Demeter • Legibilidade • Aumenta testabilidade (mais fácil "mockar") • Facilidade para debugar
  64. 64. Guilherme
 Blanco PHP4Adults Não abrevie
  65. 65. Guilherme
 Blanco PHP4Adults – Tim Bray (mencionando Phil Karlton) “Há apenas 2 problemas difíceis na computação: invalidação de cache, nomear coisas e errar por 1.”
  66. 66. Guilherme
 Blanco PHP4Adults Por que você abrevia?
  67. 67. TitleText Guilherme
 Blanco PHP4Adults Problema de duplicação de código! Escrever o mesmo nome repetidamente
  68. 68. TitleText Guilherme
 Blanco PHP4Adults Problema de múltiplas responsabilidades Nome muito longo
  69. 69. Guilherme
 Blanco PHP4Adults public function getPage($data) { ... }! ! ! ! public function startProcess() { ... }! ! ! ! $trx->process('site.login'); Obter de onde? Que p. é essa? $extendedTranslator fork, create, begin, open renderHomePage()
  70. 70. Guilherme
 Blanco PHP4Adults Benefícios • Melhora na comunicação e legibilidade • Melhora mantenabilidade • Bom indicador para problemas de encapsulamento e duplicação de código
  71. 71. Guilherme
 Blanco PHP4Adults Mantenha suas classes pequenas
  72. 72. Guilherme
 Blanco PHP4Adults 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)
  73. 73. Guilherme
 Blanco PHP4Adults Benefícios • Single Responsibility Principle • Métodos claros e objetivos • Melhor segregação de código • Namespaces mais limpos
  74. 74. Guilherme
 Blanco PHP4Adults Limite o número de variáveis de instância numa classe (2 a 5)
  75. 75. Guilherme
 Blanco PHP4Adults class MyRegistrationService! {! protected $userService;! protected $passwordService;! protected $logger;! protected $translator;! protected $entityManager;! protected $imageCropper;! ! // ...! }
  76. 76. Guilherme
 Blanco PHP4Adults class MyRegistrationService! {! protected $userService;! protected $passwordService;! protected $logger;! protected $translator;! protected $entityManager;! protected $imageCropper;! ! // ...! } Interações com o 
 banco de dados devem
 estar em $userService
  77. 77. Guilherme
 Blanco PHP4Adults class MyRegistrationService! {! protected $userService;! protected $passwordService;! protected $logger;! protected $translator;! protected $entityManager;! protected $imageCropper;! ! // ...! } Utilize um event system
 e mova esta instância 
 para um listener
  78. 78. Guilherme
 Blanco PHP4Adults Benefícios • Single Responsibility Principle • Baixo acoplamento • Melhor encapsulamento • Melhora testabilidade
  79. 79. Guilherme
 Blanco PHP4Adults Use coleções de primeiro nível
  80. 80. Guilherme
 Blanco PHP4Adults Em outros termos…
  81. 81. Guilherme
 Blanco PHP4Adults Qualquer classe que contenha um array não deve conter outras propriedades
  82. 82. Guilherme
 Blanco PHP4Adults ! 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();
  83. 83. Guilherme
 Blanco PHP4Adults ! 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();
  84. 84. Guilherme
 Blanco PHP4Adults ! 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();
  85. 85. Guilherme
 Blanco PHP4Adults 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
  86. 86. Guilherme
 Blanco PHP4Adults Use getters e setters
  87. 87. Guilherme
 Blanco PHP4Adults ! 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 ser
 alterado sem que a 
 classe saiba, causando
 erros inesperados
  88. 88. Guilherme
 Blanco PHP4Adults Benefícios • Injeção de operações • Encapsulamento de transformações • Promove Open/Close Principle 
 ("O" em SOLID)
  89. 89. Guilherme
 Blanco PHP4Adults Perguntas?
  90. 90. Guilherme
 Blanco PHP4Adults Thanks! =) @guilhermeblanco github.com/guilhermeblanco
  1. Gostou de algum slide específico?

    Recortar slides é uma maneira fácil de colecionar informações para acessar mais tarde.

×