Interfaces - Como os objetos deveriam se comportar

Preview:

Citation preview

InterfacesComo objetos se comportam deveriam se comportar

Nelson Senna

• Github: https://github.com/nelsonsar

• Twitter: https://twitter.com/nelson_senna

• Tripda: https://tripda.com.br

• Membro do PHPSP

• Moderador eventual do PHP Brasil no Facebook

Motivação

Um pouco de teoria…

Assim como nós humanos, sistemas se

comunicam

Apesar de ter variantes, a comunicação de maneira simplista

se resume em passar uma mensagem

Emissor -> Mensagem -> Receptor

Mas, para que a comunicação seja bem sucedida o emissor

precisa ter prévio conhecimento do receptor

Ou, em outras palavras o receptor precisa ser capaz

receber a mensagem

“Hmm… Exemplo?”

<?php

class Teenager { public function listenToKatyPerry() { // Teenager knows this kinda of music } }

$teenager = new Teenager; $teenager->listenToLedZeppelin(); // The line above outputs: Fatal error: Call to undefined method Teenager::listenToLedZeppelin

A interface da classe Teenager não contemplava o

comportamento de escutar Led Zeppelin

Interfaces definem comportamento

E possibilitam a comunicação, já que mostram qual mensagens o

receptor pode receber

E como definir interfaces?

Primeiro você tem que respeitar as leis!

Uma interface deve fazer o que seu método diz que faz

<?php

class FileReader { public function readLine() { $f = fopen('/tmp/file', 'w'); fputs($f, 'bullshit'); } }

(╯°□°)╯︵ ┻━┻

A implementação de uma interface não deve causar mal

<?php

class FileReader { public function readLine() { $f = fopen('/tmp/file', 'r'); $totalNumberOfBytes = filesize('/tmp/file'); $numberOfReadBytes = 0; $line = ''; while ($totalNumberOfBytes != $numberOfReadBytes) { $byte = fgets($f, 1); if ($byte == PHP_EOL) return $line; $line .= $byte; }

return $line; } }

(╯°□°)╯︵ ┻━┻

Uma interface tem que notificar quem a chama se não conseguir

executar o que foi pedido

<?php

class FileReader { public function readLine() { $f = @fopen(‘/tmp/file', ‘r’);

if (!$f) return ‘’;

// code to read a line } }

(╯°□°)╯︵ ┻━┻

Segundo, ela tem que ser coesa*!

Os métodos nela devem ter um conceito em

comum

<?php

interface FileReader { public function readLine(); public function sendEmail(); }

(╯°□°)╯︵ ┻━┻

Quantos métodos ela tem que ter?

Depende…

Você prefere uma interface mínima ou uma completa? Uma simples

ou complexa? Stateless ou stateful?

Mínima

<?php

interface File { public function open(); public function read(); public function write(); public function close(); }

Completa

<?php

interface File { public function open(); public function read(); public function readLine(); public function readFrom($fromBytes); public function write(); public function writeLine(); public function close(); }

Mínima

<?php

interface ConnectionInterface { public beginTransaction() public commit() public excuteQuery($statement, array $params) public rollBack() }

Completa

<?php

class PDO { public beginTransaction() public commit() public errorCode() public errorInfo() public exec($statement) public getAttribute($attribute) public static getAvailableDrivers() public inTransaction() public lastInsertId($name = NULL) public prepare($statement, array $driver_options = array()) public query($statement) public quote($string, $parameter_type = PDO::PARAM_STR) public rollBack() public setAttribute($attribute, $value) }

Simples

<?php

interface LegCostCalculator { public function calculate($leg); }

Complexa

<?php

interface LegCostCalculator { public function calculateGasCostByDistance($leg); public function calculateTollCost($leg); public function calculateTripdaFee($leg); }

Stateful

<?php

interface File { public function open(); public function read(); public function write(); public function close(); }

Stateless

<?php

interface HttpClient { public function get($url); public function post($url, array $params); }

Herança e composição

–Sandi Metz

“Duplication is far cheaper than the wrong abstraction.”

Com interfaces eu posso criar “papéis”. Combinações de

interfaces que definem uma classe de objetos. De maneira explícita.

<?php

interface ReadableStream { public function read($bytes); }

interface WritableStream { public function write($data); }

interface SeekableStream { public function seek($offset); }

<?php

class FileStream implements ReadableStream, WritableStream, SeekableStream { public function read($bytes); public function write($data); public function seek($offset); }

Considerações finais

Dúvidas?

Fim