Slide 1

Slide 1 text

Marcel Gonçalves dos Santos @marcelgsantos T php criando aplicações em com tipos robustas

Slide 2

Slide 2 text

pensandonaweb.com.br desenvolvedor web full-stack Marcel Gonçalves dos Santos @marcelgsantos

Slide 3

Slide 3 text

@phpsp phpsp.org.br

Slide 4

Slide 4 text

Interaja nas mídias sociais! 
 
 - fale sobre o evento, palestrantes e conteúdo - tire fotos do evento e publique 
 - interaja com outros participantes do evento - tire dúvidas ou dê feedbacks para os palestrantes

Slide 5

Slide 5 text

O que são tipos?

Slide 6

Slide 6 text

os tipos podem ser considerados como um conjunto de valores, isto é, os valores são agrupados por tipos

Slide 7

Slide 7 text

eles de fi nem quais operações podem ser realizadas sobre um dado

Slide 8

Slide 8 text

os tipos possuem cardinalidade

Slide 9

Slide 9 text

eles de fi nem a forma como um valor é armazenado é representado

Slide 10

Slide 10 text

os tipos de fi nem o signi fi cado semântico do valor

Slide 11

Slide 11 text

um tipo é uma classi fi cação do dado que de fi ne a operação que pode ser feita sobre aquele dado, o signi fi cado do dado e o conjunto de valores permitidos

Slide 12

Slide 12 text

Por que utilizar tipos?

Slide 13

Slide 13 text

a utilização de tipos ajuda a prevenir erros de uma categoria especí fi ca

Slide 14

Slide 14 text

a medida que a complexidade de um software cresce, é necessário que o código possua garantias de corretude

Slide 15

Slide 15 text

os tipos fornecem provas genéricas de que o código funcionará de acordo com a entrada

Slide 16

Slide 16 text

os erros que acontecem em tempo de execução e que podem causar problemas na aplicação…

Slide 17

Slide 17 text

…podem ser transformados em erros em tempo de compilação e evitar causar sérios problemas na aplicação

Slide 18

Slide 18 text

existem esforços para trazer type checking em tempo de compilação para linguagens dinamicamente tipadas

Slide 19

Slide 19 text

o TypeScript é uma linguagem criada para fornecer checagem de tipo em tempo de compilação para o JavaScript

Slide 20

Slide 20 text

os principais benefícios dos tipos são corretude, imutabilidade, encapsulamento, componibilidade e legibilidade

Slide 21

Slide 21 text

O que é sistema de tipos?

Slide 22

Slide 22 text

um sistema de tipos é um conjunto de regras que atribui e impõe tipos para elementos de uma linguagem de programação

Slide 23

Slide 23 text

um sistema de tipos permite atribuir tipos através de uma notação no código ou implicitamente deduzindo o tipo de certos elementos baseados no contexto

Slide 24

Slide 24 text

ele permite várias conversões de tipos e proíbe outras

Slide 25

Slide 25 text

utiliza-se o sistema de tipos para projetar código menos propenso a erros, melhor componentizável e fácil de entender

Slide 26

Slide 26 text

um código correto significa que ele se com- porta de acordo com a sua especi fi cação, produz resultados esperados e sem criar erros em tempo de execução

Slide 27

Slide 27 text

ao utilizar um sistema de tipos transforma-se o que seria um erro em tempo de execução que poderia acontecer em produção e afetar o cliente final…

Slide 28

Slide 28 text

…em um inofensivo erro em tempo de compilação que pode ser corrigido antes de fazer o deploy do código

Slide 29

Slide 29 text

um sistema de tipos permite otimização em tempo de execução, funciona como documentação e pode ser interno ou externo a linguagem

Slide 30

Slide 30 text

Como os tipos podem 
 ser classi fi cados?

Slide 31

Slide 31 text

os tipos podem ser classi fi cados como primitivo, composto ou recursivo

Slide 32

Slide 32 text

os tipos primitivos são aqueles cujos valores são atômicos, ou seja, não podem ser decompostos em valores mais simples

Slide 33

Slide 33 text

os tipos compostos são aqueles cujos valores são compostos por valores de tipos primitivos

Slide 34

Slide 34 text

os tipos recursivos é de fi nido em termos de si e a cardinalidade de tipos recursivos é in fi nita

Slide 35

Slide 35 text

as linguagens podem ter tipagem estática ou tipagem dinâmica

Slide 36

Slide 36 text

uma linguagem com tipagem estática realiza a veri fi cação de tipos em tempo de compilação

Slide 37

Slide 37 text

uma linguagem com tipagem dinâmica realiza a veri fi cação de tipos em tempo de execução

Slide 38

Slide 38 text

as linguagens podem ter tipagem forte e tipagem fraca

Slide 39

Slide 39 text

em uma linguagem com tipagem forte a conversão de tipos deve ser feita de forma explícita e operações entre valores de tipos diferentes não são permitidas

Slide 40

Slide 40 text

em uma linguagem com tipagem fraca a conversão de tipos é feita de forma implícita e operações entre valores de tipos diferentes são permitidas e feitas de forma automática

Slide 41

Slide 41 text

o PHP possui tipagem dinâmica e fraca pois a veri fi cação de tipos é feita em tempo de execução e é feita a conversão automática de tipos em operações com tipos diferentes

Slide 42

Slide 42 text

ao utilizar ferramentas de análise estática como Phan, PHPStan e Psalm é possível realizar a veri fi cação de tipos em tempo de “compilação” na linguagem

Slide 43

Slide 43 text

Operações comuns 
 relacionadas à tipos

Slide 44

Slide 44 text

a veri fi cação de tipo ou type checking é um processo de veri fi cação e garantia das restrições de tipos

Slide 45

Slide 45 text

a verificação de tipo pode ser executada em tempo de compilação ou tempo de execução

Slide 46

Slide 46 text

ela garante a integridade do dado, impõe restrições de acesso e interpreta os dados como pretendidos pelo(a) programador(a)

Slide 47

Slide 47 text

a conversão de tipos pode ser realizada de forma implícita e explícita

Slide 48

Slide 48 text

a conversão implícita ou coerção é realizada de forma automática pelo compilador ou interpretador

Slide 49

Slide 49 text

a conversão explícita ou cast é realizada de forma manual pelo(a) programador(a)

Slide 50

Slide 50 text

a inferência de tipos permite que o(a) programador(a) não declare o tipo mas que o compilador ou interpretador conheça o tipo com base no valor informado

Slide 51

Slide 51 text

um erro de tipo ocorre se o programa executa 
 uma operação com tipos incompatíveis

Slide 52

Slide 52 text

Como funcionam os tipos no PHP?

Slide 53

Slide 53 text

Conceitos básicos

Slide 54

Slide 54 text

os tipos são divididos em tipos escalares, compostos e especiais

Slide 55

Slide 55 text

escalares boolean, integer, float ou string

Slide 56

Slide 56 text

compostos array, object, callable ou iterable

Slide 57

Slide 57 text

especiais resource e null

Slide 58

Slide 58 text

também existem os pseudo-tipos

Slide 59

Slide 59 text

pseudo-tipos mixed, number, callback, array|object e void

Slide 60

Slide 60 text

os tipos são de fi nidos em tempo de execução

Slide 61

Slide 61 text

/ / variables of several different types 
 $a_boolean = true; $an_int = 10; $a_float = 3.14; $a_string = 'joe'; $a_null = null; $a_array = []; $a_callable = function() { return 'Hey!'; }; $a_object = new stdClass;

Slide 62

Slide 62 text

as funções get_debug_type, gettype e var_dump são utilizadas para conhecer o tipo da variável ou expressão

Slide 63

Slide 63 text

/ / get variable type using var_dump() function var_dump($a_boolean); / / bool(true) var_dump($an_int); / / int(10) var_dump($a_float); / / float(3.14) var_dump($a_string); / / string(3) "joe" var_dump($a_null); / / NULL var_dump($a_array); / / array(0) {} var_dump($a_callable); / / object(Closure)#1 (0) {} var_dump($a_object); / / object(stdClass)#2 (0) {}

Slide 64

Slide 64 text

/ / get variable type using gettype() function echo gettype($a_boolean); / / boolean echo gettype($an_int); / / integer echo gettype($a_float); / / double echo gettype($a_string); / / string echo gettype($a_null); / / NULL echo gettype($a_array); / / array echo gettype($a_callable); / / object echo gettype($a_object); / / object

Slide 65

Slide 65 text

/ / get variable type using get_debug_type() / / function available on PHP 8.0 echo get_debug_type($a_boolean); / / bool echo get_debug_type($an_int); / / int echo get_debug_type($a_float); / / float echo get_debug_type($a_string); / / string echo get_debug_type($a_null); / / null echo get_debug_type($a_array); / / array echo get_debug_type($a_callable); / / Closure echo get_debug_type($a_object); / / stdClass

Slide 66

Slide 66 text

as funções is_int, is_boolean, is_string, is_array são utilizadas para veri fi car o tipo da variável ou expressão

Slide 67

Slide 67 text

/ / check if variables are from a specif i c / / type using is_*() functions var_dump(is_bool($a_boolean)); / / bool(true) var_dump(is_bool($an_int)); / / bool(false) 
 var_dump(is_int($an_int)); / / bool(true) var_dump(is_int($a_float)); / / bool(false) 
 var_dump(is_float($a_float)); / / bool(true) var_dump(is_float($a_string)); / / bool(false)

Slide 68

Slide 68 text

/ / check if variables are from a specif i c / / type using is_*() functions var_dump(is_string($a_string)); / / bool(true) var_dump(is_string($a_null)); / / bool(false) 
 var_dump(is_array($a_array)); / / bool(true) var_dump(is_array($a_object)); / / bool(false) 
 var_dump(is_null($a_null)); / / bool(true) var_dump(is_null($a_array)); / / bool(false)

Slide 69

Slide 69 text

Conversão de tipos

Slide 70

Slide 70 text

conversão explícita e automática

Slide 71

Slide 71 text

/ / explicit type conversion var_dump((bool) "1.5"); / / bool(true) var_dump((int) "1.5"); / / int(1) var_dump((float) "1.5"); / / float(1.5) var_dump((string) 1.5); / / string(3) "1.5"

Slide 72

Slide 72 text

/ / explicit type conversion var_dump((array) 1.5); / / array(1) { [0] = > float(1.5) } var_dump((array) "1.5"); / / array(1) { [0] = > string(3) "1.5" } var_dump((object) 1.5); / / object(stdClass)#1 (1) {["scalar"] = > … var_dump((object) "1.5"); / / object(stdClass)#1 (1) {["scalar"] = > …

Slide 73

Slide 73 text

/ / implicit or automatic type conversion / / using `+` operator 
 $var = "0"; var_dump($var); / / string(2) "0" $var += 5; var_dump($var); / / int(5) $var = $var + 3.1; var_dump($var); / / float(8.1)

Slide 74

Slide 74 text

Declaração de tipos

Slide 75

Slide 75 text

as declarações de tipos garantem que o valor é do tipo especi fi cado no momento da chamada

Slide 76

Slide 76 text

as declarações de tipos podem ser utiliza- das em argumentos de funções, retornos de valores e propriedades de classe

Slide 77

Slide 77 text

caso o valor informado não seja do tipo especi fi cado na declaração do tipo a exceção TypeError é lançada*

Slide 78

Slide 78 text

declarações de tipos 
 
 1. tipos escalares 
 2. tipos compostos 
 3. classes e interfaces 
 4. object, mixed, self, parent, never 
 5. union types e intersection type 
 6. enums

Slide 79

Slide 79 text

/ / type declaration using classes class Mammal {} class Cat extends Mammal {} class Duck {} function sayHi(Mammal $mammal) { echo 'Hi ' . get_class($mammal) . '!'; } sayHi(new Mammal); / / Hi Mammal! sayHi(new Cat); / / Hi Cat! 
 sayHi(new Duck); 
 / / Uncaught TypeError: Argument 1 passed to / / sayHi() must be an instance of Mammal, instance of Duck given

Slide 80

Slide 80 text

Modo estrito

Slide 81

Slide 81 text

o PHP realiza, por padrão, a conversão automática de tipos de um valor para o tipo esperado quando necessário

Slide 82

Slide 82 text

/ / not using strict types function sum(int $a, int $b) { return $a + $b; } var_dump(sum(1, 2)); / / int(3) var_dump(sum(1.5, 2.5)); / / int(3) var_dump(sum("2", "5")); / / int(7) var_dump(sum(true, true)); / / int(2)

Slide 83

Slide 83 text

pode-se ativar o modo estrito para garantir que a conversão automática de tipos não seja realizada

Slide 84

Slide 84 text

e, caso o valor tenha um tipo incompatível com o tipo esperado, a exceção TypeError será lançada

Slide 85

Slide 85 text

/ / using strict types declare(strict_types=1); / / throws an exception when a value / / with incompatible type are provided function sum(int $a, int $b) { return $a + $b; } var_dump(sum(1, 2)); / / int(3) 
 var_dump(sum(1.5, 2.5)); Uncaught TypeError: Argument 1 passed to sum() must be of the type integer, float given

Slide 86

Slide 86 text

o modo estrito funciona da mesma forma para declarações de tipos de retorno

Slide 87

Slide 87 text

/ / the value returned is converted / / to the correct type function sum($a, $b) : int { return $a + $b; } var_dump(sum(1, 2)); / / int(3) var_dump(sum(1.7, 2.5)); / / int(4) var_dump(sum(true, true)); / / int(2)

Slide 88

Slide 88 text

declare(strict_types=1); / / a type exception is thrown function sum($a, $b) : int { return $a + $b; } var_dump(sum(1, 2)); / / int(3) var_dump(sum(1.7, 2.5)); / / Uncaught TypeError: sum() : Return value must be of type int, float returned

Slide 89

Slide 89 text

Propriedades tipadas

Slide 90

Slide 90 text

as typed properties ou propriedades tipadas foram adicionadas no PHP 7.4

Slide 91

Slide 91 text

utilizavam-se docblocks e métodos getters e setters para a garantia de tipos

Slide 92

Slide 92 text

/ / code with unnecessary boilerplate to enforce type contracts class User { /** @var int $id * / private $id; /** @var string $name * / private $name; public function _ _ construct(int $id, string $name) { $this - > id = $id; $this - > name = $name; } public function getId() : int { return $this - > id; } / / setId, getName and setName implementation . . . }

Slide 93

Slide 93 text

/ / more concise code with same type contracts class User { public int $id; public string $name; public function _ _ construct(int $id, string $name) { $this - > id = $id; $this - > name = $name; } }

Slide 94

Slide 94 text

as propriedades tipadas permitem a garantia de tipos em tempo de execução

Slide 95

Slide 95 text

se uma propriedade tipada não tiver um valor padrão ela será considerada não inicializada

Slide 96

Slide 96 text

/ / uninitialized properties and / / default null (PHP 7.3) class User { public $id; public $name; } $user = new User; var_dump($user); / / class User#1 (2) { / / public $id = > NULL / / public $name = > NULL / / }

Slide 97

Slide 97 text

/ / uninitialized properties and no / / null default (PHP 7.4) class User { public int $id; / / no null default public ?string $name; / / also no null default } $user = new User; var_dump($user); / / object(User)#1 (0) { / / ["id"] = > uninitialized(int) / / ["name"] = > uninitialized(?string) / / }

Slide 98

Slide 98 text

ao tentar fazer a leitura de uma propriedade não inicializada será lançado um erro do tipo TypeError

Slide 99

Slide 99 text

/ / try to access a uninitialized property class User { public int $id; public string $name; } $user = new User; echo $user - > id; / / Uncaught Error: Typed property User : : $id must 
 / / not be accessed before initialization

Slide 100

Slide 100 text

Nullable types

Slide 101

Slide 101 text

um nullable type é um tipo que pode ser de um tipo especí fi co ou nulo e é representado por ?Type

Slide 102

Slide 102 text

/ / annotate email property with nullable string type class Person { function _ _ construct( public string $name, public ?string $email, ) {} } 
 
 $person1 = new Person('Alice', 'alice@example.com'); $person2 = new Person('Bob', null);

Slide 103

Slide 103 text

var_dump($person1); var_dump($person2); / / object(Person)#1 (2) { / / ["name"] = > string(5) "Alice" / / ["email"] = > string(17) "alice@example.com" / / } / / object(Person)#2 (2) { / / ["name"] = > string(3) "Bob" / / ["email"] = > NULL / / }

Slide 104

Slide 104 text

Union Types

Slide 105

Slide 105 text

um union type permite fazer uma anotação de tipos com diferentes tipos

Slide 106

Slide 106 text

o PHP já possui dois tipos especiais de union types: nullable types e iterable

Slide 107

Slide 107 text

o tipo nullable possui a sintaxe ?Type e pode ser do tipo Type|null, isto é, Type ou null

Slide 108

Slide 108 text

o tipo iterable pode ser do tipo array| Traversable, isto é, array ou Traversable

Slide 109

Slide 109 text

declare(strict_types=1); / / using union type to annotate a function parameter function power(float|int $number, int $exponent) : int|float { return $number * * $exponent; } echo power(3, 2); / / 9 echo power(3.5, 2); / / 12.25 echo power('3', 2.5); / / Uncaught TypeError: power() : Argument #1 ($number) must be of type int|float, string given

Slide 110

Slide 110 text

os union types são muito utilizado em projetos open-source e funções internas do PHP

Slide 111

Slide 111 text

o suporte nativo permite a garantia de tipos pelo interpretador PHP e reduz a necessida- de de docblocks

Slide 112

Slide 112 text

Intersection Types

Slide 113

Slide 113 text

um intersection type permite anotar o tipo de um valor que satisfaça múltiplas restrições de tipos ao mesmo tempo

Slide 114

Slide 114 text

/ / using intersection type to annotate a property of a test / / class that represents a mocked object class CreateUserTest { private MockObject&UserRepository $userRepositoryMock; }

Slide 115

Slide 115 text

só é posível utilizar intersection types com classes e interfaces

Slide 116

Slide 116 text

não é permitido combinar em uma declara- ção union types e intersection types

Slide 117

Slide 117 text

Enums

Slide 118

Slide 118 text

uma enum de fi ne um novo tipo que possui número fi xo e limitado de valores possíveis

Slide 119

Slide 119 text

/ / creates an enum for the suits of a deck enum Suit { case Hearts; case Diamonds; case Clubs; case Spades; } $value = Suit : : Hearts; var_dump($value); / / enum(Suit : : Hearts)

Slide 120

Slide 120 text

por padrão, os casos enumerados não possuem equivalentes escalares, isto é, eles são objetos singleton

Slide 121

Slide 121 text

esse tipo de valor é chamado de pure case e uma enum que contém apenas pure cases é chamada de pure enum

Slide 122

Slide 122 text

uma função ou método podem ser tipados com o tipo enum

Slide 123

Slide 123 text

/ / annotate a function parameter with an enum type function pick_a_card(Suit $suit) {} pick_a_card($value); / / ok pick_a_card(Suit : : Clubs); / / ok pick_a_card('Spades'); / / Fatal error: Uncaught TypeError: pick_a_card() : Argument #1 ($suit) must be of type Suit, string given

Slide 124

Slide 124 text

contudo, existem casos de usos em que é necessário ter equivalentes escalares para, por exemplo, persistir em uma base de dados

Slide 125

Slide 125 text

/ / create an enum backed with scalar values enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } var_dump(Suit : : Hearts); / / enum(Suit : : Hearts) var_dump(Suit : : Hearts - > name); / / string(6) "Hearts" var_dump(Suit : : Hearts - > value); / / string(1) "H"

Slide 126

Slide 126 text

um case que tem um equivalente escalar é chamado de backed case pois é “suportado" por um valor mais simples

Slide 127

Slide 127 text

uma enum que contém backed cases é chamado de backed enum

Slide 128

Slide 128 text

um backed enum implementa a interface interna BackedEnum que expõe dois métodos adicionais que são from e tryFrom

Slide 129

Slide 129 text

o método from() recebe um tipo escalar e retorna o case correspondente e, caso o valor não seja encontrado, a exceção ValueError é lançada

Slide 130

Slide 130 text

o método tryFrom() possui comportamento similar mas, caso o valor não seja encontra- do, retorna nulo

Slide 131

Slide 131 text

/ / create an order status enum enum OrderStatus: string { case PendingPayment = 'pending_payment'; case Processing = 'processing'; case Completed = 'completed'; case Refunded = 'refunded'; case Cancelled = 'cancelled'; }

Slide 132

Slide 132 text

/ / create an enum value using from() method with a valid value $orderStatus = OrderStatus : : from('processing'); var_dump($orderStatus); / / enum(OrderStatus : : Processing) echo $orderStatus - > value; / / processing / / try to create an enum value using from() method with an invalid value $orderStatus = OrderStatus : : from('non_existent'); / / Fatal error: Uncaught ValueError: "non_existent" is not a / / valid backing value for enum "OrderStatus" / / try to create an enum value using tryFrom() method with an invalid value $orderStatus = OrderStatus : : tryFrom('non_existent'); var_dump($orderStatus); / / null

Slide 133

Slide 133 text

Type Never

Slide 134

Slide 134 text

o tipo never é um novo tipo de retorno adicionado no PHP 8.1

Slide 135

Slide 135 text

uma função ou método declarados com o tipo de retorno never indica que nunca retornará um valor…

Slide 136

Slide 136 text

…isto é, sempre lançará uma exceção ou terminará com die() ou exit()

Slide 137

Slide 137 text

/ / creates a function with never return type function redirect(string $url) : never { echo "redirected to $url . . . \n"; header('Location: ' . $url); exit(); } redirect('https: / / w w w .example.com'); / / redirected to https: / / w w w .example.com . . . 
 / / The rest of the code will not be executed! echo 'this will not be shown . . . ';

Slide 138

Slide 138 text

o objetivo do tipo de retorno never é indicar uma função que previne que o resto do código chamado seja executado

Slide 139

Slide 139 text

se uma função ou método com o tipo de retorno never não lançar uma exceção ou não terminar o programa será lançada a exceção TypeError

Slide 140

Slide 140 text

/ / create a function with never return type function dispatch(string $message) : never { echo $message; } dispatch('test'); / / Uncaught TypeError: dispatch() : never - returning / / function must not implicitly return

Slide 141

Slide 141 text

o suporte ao tipo de retorno never torna possível não utilizar mais a annotation @return noreturn

Slide 142

Slide 142 text

Conclusão

Slide 143

Slide 143 text

o PHP tem tido uma enorme evolução em relação a tipos e tem se tornado uma linguagem mais robusta

Slide 144

Slide 144 text

porém, sem perder a fl exibilidade e a pequena curva de aprendizado que o torna uma linguagem tão democrática

Slide 145

Slide 145 text

as novas funcionalidades ajudarão o seu código a ter mais garantias, ser mais expressivo e te dar mais poderes

Slide 146

Slide 146 text

vá em frente e divirta-se!

Slide 147

Slide 147 text

Avalie!

Slide 148

Slide 148 text

@marcelgsantos speakerdeck.com/marcelgsantos Obrigado. Perguntas?