Re: How do I handle covariant parameters and not fall foul of LSP.

From: Date: Tue, 14 Feb 2017 05:52:09 +0000
Subject: Re: How do I handle covariant parameters and not fall foul of LSP.
References: 1 2  Groups: php.general 
Request: Send a blank email to php-general+get-325963@lists.php.net to get a copy of this message
I think LSP becomes an issue in situations where you want to swap implementations. Since I can't really think of such a use case when using repositories, you can even name your methods more specifically. abstract class BaseRepo { protected function processEntity(BaseEntity $anEntity) { ... } } class PersonRepo extends BaseRepo { public function processPerson(PersonEntity $aPerson) { $this->processEntity($aPerson); } } class CatRepo extends BaseRepo { public function processCat(CatEntity $aCat) { $this->processEntity($aCat); } } If the process method is doing storage related things I don't think is a good idea to move it to the Entity hierarchy. The main idea of repositories is to provide a collection like interface to storage, the other idea common to persistence related patterns is to free entities from persistence responsibilities and make them more focused on the domain logic. On Mon, Feb 13, 2017 at 8:55 PM, David Harkness <david.h@highgearmedia.com> wrote: > The problem with LSP is that every BaseRepo must be able to be substituted > for any other, but each concrete form only handles its own concrete entity > type. The contract of processEntity(BaseEntity) is "I will process any > concrete BaseEntity subclass", but PersonRepo violates this contract by > declaring that it will only process PersonEntity. > > Java uses Generics to solve this, but you'll have to fake it with > instanceof for safety. Note that you're *still* violating LSP here, but you > can't really avoid it given what you want to do. > > class PersonRepo extends BaseRepo > { > public function processEntity(BaseEntity $entity) > { > parent::processEntity($entity); > if (!($entity instanceof Person) { > throw new RepoException('Must be a Person'); > } > ... > } > } > > Well, you could invert the responsibility to save LSP by moving the > concrete functionality into the entity, but it will probably be a little > hacky. > > abstract class BaseEntity { > public abstract function process(); > } > > class PersonRepo extends BaseRepo > { > public function processEntity(BaseEntity $entity) > { > parent::processEntity($entity); > $entity->process(); > ... > } > } > > Cheers! > David >

« previous php.general (#325963) next »