Last active
February 25, 2019 12:38
-
-
Save garethellis36/a98f41274f85993bcc8d15b3d1667106 to your computer and use it in GitHub Desktop.
LSP example in PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
LSP: "Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program." | |
<?php | |
namespace App\User; | |
// imagine the following interface | |
interface Repository | |
{ | |
public function getById($id); | |
} | |
// without parameter type-hints, return types, or even a doc-block, it is impossible for client code to be able | |
// to rely on the correctness of the implementation | |
// a programmer trying to implement this interface will be having to guess at what to return, what to accept, etc. | |
// it would be very easy to inadvertently create an implementation which breaches LSP and causes problems for client code | |
// We can address this by adding parameter type-hints and a return type | |
interface Repository | |
{ | |
/** | |
* @throws \App\User\Error\NotFound | |
*/ | |
public function getById(int $id): User; | |
} | |
// Note that we have also added a @throws annotation. | |
// According to the definition of the interface, client code should be able to reliably work as follows: | |
try { | |
$user = $repository->getById($id); | |
} catch (NotFound $e) { | |
// handle exception | |
} | |
// It is still possible to breach LSP even with parameter type-hints and return types in place | |
// The following implementation would be a breach of LSP | |
// Even though it meets the interface implementation according to PHP's language-level requirements, | |
// it throws something which is not defined by the behaviour of the `Repository` type. | |
// The above client code would break because it is not expecting to need to catch an exception of type \Exception | |
class Database implements Repository | |
{ | |
public function getById(int $id): User | |
{ | |
$row = $this->db->query("SELECT * FROM users WHERE id = ?", [$id]); | |
if ($row) { | |
return User::fromRow($row); | |
} | |
throw new \Exception("User not found!"); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment