Slide 1

Slide 1 text

OBJECT CALISTHENICS 9 regras que vão mudar sua forma de programar

Slide 2

Slide 2 text

Sou Junior Grossi twitter.com/junior_grossi github.com/jgrossi

Slide 3

Slide 3 text

Paciência!

Slide 4

Slide 4 text

https://github.com/corcel/corcel

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

◽ 2004 php ◽ 2016 ◽

Slide 7

Slide 7 text

https://www.glofox.com/careers

Slide 8

Slide 8 text

QUALIDADE DE CÓDIGO

Slide 9

Slide 9 text

CLEAN CODE / SOLID

Slide 10

Slide 10 text

Você realmente escreve códigos 100% SOLID? #sinceridade

Slide 11

Slide 11 text

SOBRE SOLID: É um objetivo muito ousado Exige muitos conceitos de OOP Envolve muita experiência em abstração Exige um time muito "Maduro "

Slide 12

Slide 12 text

SOLID não é um processo SOLID é o objetivo final... ...de um processo muito longo

Slide 13

Slide 13 text

COMO COMEÇAR O PROCESSO?

Slide 14

Slide 14 text

É impossível aplicar SOLID em uma classe "gorda"

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Sua classe precisa de uma dieta

Slide 17

Slide 17 text

OBJECT CALISTHENICS ❤

Slide 18

Slide 18 text

Jeff Bay, 2008 The Thoughtworks Anthology

Slide 19

Slide 19 text

9 REGRAS/EXERCÍCIOS para deixar seus objetos em forma

Slide 20

Slide 20 text

ATENÇÃO Não se engane Algumas regras são bem difíceis Aplique com cautela Não seja um extremista Invista tempo em cada regra Algumas regras são dependentes

Slide 21

Slide 21 text

REGRA 1 Apenas um nível de indentação por método

Slide 22

Slide 22 text

MOTIVOS Evitar efeito hadouken Facilitar leitura do código Promover SRP (Single Responsibility Principle)

Slide 23

Slide 23 text

public function notify(DateInterval $dateInterval): void { $posts = $this­>postsRepository ­>findByDateInterval($dateInterval); foreach ($posts as $post) { $totals = $this­>report­>calculateTotals($post); foreach ($post­>authors() as $author) { $this­>message­>sendTo($author, $totals); } } } 1 2 3 4 5 6 7 8 9 10 11 12

Slide 24

Slide 24 text

$totals = $this­>report­>calculateTotals($post); foreach ($post­>authors() as $author) { $this­>message­>sendTo($author, $totals); } public function notify(DateInterval $dateInterval): void 1 { 2 $posts = $this­>postsRepository 3 ­>findByDateInterval($dateInterval); 4 5 foreach ($posts as $post) { 6 7 8 9 10 } 11 } 12

Slide 25

Slide 25 text

$this­>notifyAuthors($post); private function notifyAuthors(Post $post): void { $totals = $this­>report ­>calculateTotals($post); foreach ($post­>authors() as $author) { $this­>message ­>sendTo($author, $totals); } } public function notify(DateInterval $dateInterval): void 1 { 2 $posts = $this­>postsRepository 3 ­>findByDateInterval($dateInterval); 4 5 foreach ($posts as $post) { 6 7 } 8 } 9 10 11 12 13 14 15 16 17 18 19 20

Slide 26

Slide 26 text

REGRA 2 Não use ELSE

Slide 27

Slide 27 text

MOTIVOS Porque else não serve para nada Porque você não precisa do else Na verdade você nunca precisou do else

Slide 28

Slide 28 text

private function authorizeUser(User $user): bool { if ($user­>isAdmin()) { $result = true; } else { $result = false; } return $result; } private function authorizeUser(User $user): bool { if ($user­>isAdmin()) { return true; } return false; // Ou só return $user­>isAdmin() }

Slide 29

Slide 29 text

private function response(Request $request): Response { if ($request­>expectsJson()) { $response = $this­>createJsonResponse(); } else { $response = $this­>createHtmlResponse(); } return $this­>formatResponse($response); }

Slide 30

Slide 30 text

private function response(Request $request): Response { $response = $this­>buildFromRequest($request); return $this­>formatResponse($response); } private function buildFromRequest(Request $request): Response { if ($request­>expectsJson()) { return $this­>createJsonResponse(); } return $this­>createHtmlResponse(); }

Slide 31

Slide 31 text

REGRA 3 Envolva seus tipos primitivos

Slide 32

Slide 32 text

MOTIVOS Tipos primitivos são muito permissivos Não possuem nenhum significado/comportamento Encapsulamento Value Objects em DDD

Slide 33

Slide 33 text

public function charge(int $amount, string $currency): string { $this­>paymentProvider­>chargeUser( $this­>user­>id(), $amount, $currency ); return $this­>paymentProvider ­>confirmationNumber(); }

Slide 34

Slide 34 text

class Money { private int $amount; private Currency $currency; public function __construct(int $amount, string $currency) { $this­>amount = $amount; $this­>currency = new Currency($currency); } public function amount(): int { return $this­>amount; } public function currencyAbbreviation(): string { return $this­>currency ­>abbreviation(); } }

Slide 35

Slide 35 text

class Currency { private string $abbreviation; public function __construct(string $abbreviation) { if (!$this­>abbreviationIsValid($abbreviation)) { throw new InvalidCurrencyAbbreviationException; } $this­>abbreviation = strtoupper($abbreviation); } public function abbreviation(): string { return $this­>abbreviation; } // Code }

Slide 36

Slide 36 text

public function charge(Money $price): string { $this­>paymentProvider­>chargeUser( $this­>user­>id(), $price­>amount(), $price­>currencyAbbreviation(), ); return $this­>paymentProvider ­>confirmationNumber(); }

Slide 37

Slide 37 text

REGRA 4 Envolva suas collections em classes

Slide 38

Slide 38 text

MOTIVOS Te força a usar SRP Agrupa ações semelhantes na mesma classe

Slide 39

Slide 39 text

CONCEITO Manipular objectos similares em um só lugar Somente uma propriedade por classe collection Métodos realizam ações no conjunto de objectos

Slide 40

Slide 40 text

class ActiveUsersCollection implement Iterator { private array $users = []; public function __construct(array $users) { $this­>users = $users; } public function filterByActivationProcess(): self { // Code } }

Slide 41

Slide 41 text

REGRA 5 Use apenas um ponto (­>) por linha

Slide 42

Slide 42 text

MOTIVOS Facilita a leitura Lei de Demeter (fale com amigos) Reforça o Open-close principle

Slide 43

Slide 43 text

EXCEÇÕES Fluent Interfaces / Chaining Pattern $builder­>where(...)­>order(...)­>limit(...)­>get()

Slide 44

Slide 44 text

class RemoteCompany { private CountriesCollection $countries; public function addCountries(EmployeesCollection $employees): void { foreach ($employees as $employee) { $this­>countries­>add( $employee­>address­>country­>code(); ) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13

Slide 45

Slide 45 text

class Employee { public function addToCollection(CountriesCollection $countries): void { $countries­>add( $this ­>address ­>addToCollection($countries) ); } }

Slide 46

Slide 46 text

class RemoteCompany { private CountriesCollection $countries; public function addCountries(EmployeesCollection $employees): void { foreach ($employees as $employee) { $employee­>addToCollection( $this­>countries ); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13

Slide 47

Slide 47 text

REGRA 6 Não abrevie

Slide 48

Slide 48 text

MOTIVOS Aumentar entendimento do contexto Porque abreviação é uma merda Porque eu não sou obrigado a entender

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

EXEMPLOS $cfClient quer dizer $cloudflareClient $rsp quer dizer $requestServiceProvider $mgSrv quer dizer $mongoService

Slide 51

Slide 51 text

DICA MAROTA TRILEGAL Nomes estão ficando muito grandes? Reveja SRP! Sua classe/método pode estar fazendo coisa demais

Slide 52

Slide 52 text

REGRA 7 Mantenha todas as classes pequenas

Slide 53

Slide 53 text

MOTIVOS Mais fáceis de manter SRP Porque classe grande é uma merda

Slide 54

Slide 54 text

REGRINHAS Classes com até 50 linhas 150 linhas (PHP) Pacotes com no máximo 10 arquivos

Slide 55

Slide 55 text

REGRA 8 Não tenha mais que duas variáveis de instância em sua classe

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

MOTIVOS SRP Porque classe grande é uma merda

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

class Customer { private Name $name; private int $customerId; } class Name { private string $firstName; private string $lastName; }

Slide 60

Slide 60 text

Não seja um extremista! para lógica de domínio para representação de dados (Entity)

Slide 61

Slide 61 text

REGRA 9 Não use getters ou setters A galera de Java pira

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

MOTIVOS Podem ferir SRP / Encapsulamento Regra: Tell, don't ask! Não possuem significado algum "Immutable classes" pra accessors (sem tomada de decisão)

Slide 64

Slide 64 text

class Company { private EmployeesCollection $employees; public function setEmployees(EmployeesCollection $employees): void { $this­>employees = $employees; } }

Slide 65

Slide 65 text

class Company { private EmployeesCollection $employees; public function hireEmployee(Employee $employee): void { $this­>employees­>add($employee) } }

Slide 66

Slide 66 text

class Exam { private int $total; public function setTotal(int $total): void { $this­>total = $total; } }

Slide 67

Slide 67 text

class Exam { private int $total; public function addCorrectQuestion(Question $question): void { $this­>total += $question­>total(); } }

Slide 68

Slide 68 text

Getters/Setters. Evil. Period. Yegor Bugayenko https://www.yegor256.com/2014/09/16/getters-and-setters-are-evil.html

Slide 69

Slide 69 text

ALGUMAS VERDADES Lemos mais código que escrevemos Escrever bem é difícil Exige prática Requer tempo

Slide 70

Slide 70 text

Você escreve para outro dev ler Você pode ser esse outro dev Devs são burros preguiçosos Incluindo eu e você Previna problemas com devs

Slide 71

Slide 71 text

Extremely Defensive PHP - Marco Pivetta (@Ocramius) PHPSW: Coding Practices, June 2015 https://youtu.be/8d2AtAGJPno

Slide 72

Slide 72 text

Próximos Passos Hexagonal Architecture / DDD (abstrações) ⬇ SOLID / Clean Code

Slide 73

Slide 73 text

Domain-Driven Design in PHP Carlos Buenosvinos, Christian Soronellas, and Keyvan Akbary https://leanpub.com/ddd-in-php

Slide 74

Slide 74 text

OBRIGADO Perguntas? Dúvidas? Críticas? Sugestões? twitter.com/junior_grossi github.com/jgrossi grossi.dev