06/2016 / Milan "perún" Herda / @moriquend / prezentacie.perunhq.org
Príklady prebrané z knihy Principles of Package DesignSkratka predstavujúca 5 základných princípov dobrého softvérového návrhu
Odvodená trieda musí byť náhradou svojej základnej triedy
interface FileInterface
{
public function rename($name);
public function changeOwner($user, $group);
}
class DropboxFile implements FileInterface
{
public function rename($name)
{
// ...
}
public function changeOwner($user, $group)
{
throw new BadMethodCallException(
'Not implemented for Dropbox files'
);
}
}
Upravte kód tak, aby DropboxFile nemal prázdnu implementáciu metódy
Prečo má FileInterface metódu changeOwner, keď ju nevedia implementovať všetci potomkovia?
interface FileInterface {
public function rename($name);
}
interface FileWithOwnerInterface extends FileInterface {
public function changeOwner($user, $group);
}
class DropboxFile implements FileInterface {
public function rename($name) {
// ...
}
}
class LocalFile implements FileWithOwnerInterface {
public function rename($name) {
// ...
}
public function changeOwner($user, $group) {
//...
}
}
interface RouterInterface {
/**
* @return Route[]
*/
public function getRoutes();
}
class SimpleRouter implements RouterInterface {
public function getRoutes() {
$routes = [];
// ...
return $routes;
}
}
class AdvancedRouter implements RouterInterface {
public function getRoutes() {
$routeCollection = new RouteCollection();
// ...
return $routeCollection;
}
}
class RouteCollection implements Iterator { /* ... */}
Keď by sme si dali návratovú hodnotu spočítať funkciou count
, tak nám jedna implementácia zhavaruje.
interface RouterInterface {
/**
* @return RouteCollectionInterface
*/
public function getRoutes();
}
interface RouteCollectionInterface extends Iterator, Countable {
}
interface MassMailerInterface {
public function sendMail(
TransportInterface $transport,
MessageInterface $message,
RecipientsInterface $recipients
);
}
class SmtpMassMailer implements MassMailerInterface {
public function sendMail(
TransportInterface $transport,
MessageInterface $message,
RecipientsInterface $recipients
) {
if (!($transport instanceof SmtpTransport)) {
throw new InvalidArgumentException(
'SmtpMassMailer only works with SMTP'
);
}
// ...
}
}
Hoci trieda o sebe tvrdí, že akceptuje inštancie TransportInterface, tak v skutočnosti akceptuje iba SmtpTransport a inak zhavaruje.
class SmtpTransport implements TransportWithMassMailSupportInterface {
// ...
}
interface MassMailerInterface {
public function sendMail(
TransportWithMassMailSupportInterface $transport,
MessageInterface $message,
RecipientsInterface $recipients
);
}
class SmtpMassMailer implements MassMailerInterface {
public function sendMail(
TransportWithMassMailSupportInterface $transport,
MessageInterface $message,
RecipientsInterface $recipients
) {
// ...
}
}
interface HttpKernelInterface {
public function handle(Request $request);
}
class HttpKernel implements HttpKernelInterface {
public function handle(Request $request) {
// ...
}
public function getEnvironment() {
// ...
}
}
class CachedHttpKernel implements HttpKernelInterface {
public function __construct(HttpKernelInterface $kernel) {
if ($kernel->getEnvironment() === 'dev') {
// ...
}
}
public function handle(Request $request) {
//...
}
}
Keď do konštruktoru vložíme inšťanciu HttpKernelInterface, ktorá nemá metódu getEnvironment, tak kód zhavaruje
interface HttpKernelWithEnvironmentInterface extends HttpKernelInterface {
public function getEnvironment();
}
class CachedHttpKernel implements HttpKernelInterface
{
public function __construct(
HttpKernelWithEnvironmentInterface $kernel
) {
// ...
}
}