6

I've been reading up about the repository pattern, with a view to implementing it in my own application. Almost all examples I've found on the internet use some kind of existing framework rather than showing how to implement it 'from scratch'. Here's my first thoughts of how I might implement it - I was wondering if anyone could advise me on whether this is correct?

I have two tables, named CONTAINERS and BITS. Each CONTAINER can contain any number of BITs. I represent them as two classes:

class Container{
    private $bits;
    private $id;
    //...and a property for each column in the table...

    public function __construct(){
        $this->bits = array();
    } 

    public function addBit($bit){
        $this->bits[] = $bit;
    }

    //...getters and setters...
}

class Bit{
    //some properties, methods etc...
}

Each class will have a property for each column in its respective table. I then have a couple of 'repositories' which handle things to do with saving/retrieving these objects from the database:

//repository to control saving/retrieving Containers from the database
class ContainerRepository{

    //inject the bit repository for use later
    public function __construct($bitRepo){
        $this->bitRepo = $bitRepo;
    }

    public function getById($id){
        //talk directly to Oracle here to all column data into the object 

        //get all the bits in the container
        $bits = $this->bitRepo->getByContainerId($id);
        foreach($bits as $bit){
            $container->addBit($bit);
        }

        //return an instance of Container
    }

    public function persist($container){
      //talk directly to Oracle here to save it to the database
        //if its ID is NULL, create a new container in database, otherwise update the existing one

        //use BitRepository to save each of the Bits inside the Container
        $bitRepo = $this->bitRepo;
        foreach($container->bits as $bit){
            $bitRepo->persist($bit);
        }
    }
}

//repository to control saving/retrieving Bits from the database
class BitRepository{
    public function getById($id){}
    public function getByContainerId($containerId){}
    public function persist($bit){}
}

Therefore, the code I would use to get an instance of Container from the database would be:

$bitRepo = new BitRepository();
$containerRepo = new ContainerRepository($bitRepo);
$container = $containerRepo->getById($id);

Or to create a new one and save to the database:

$bitRepo = new BitRepository();
$containerRepo = new ContainerRepository($bitRepo);

$container = new Container();
$container->setSomeProperty(1);
$bit = new Bit();
$container->addBit($bit);
$containerRepo->persist($container);

Can someone advise me as to whether I have implemented this pattern correctly? Thanks!

  • 1
    +1 for a clear, on-topic question with readable PHP code in it, especially since it is your first question on Programmers.SE. – Arseni Mourzenko Aug 19 '14 at 16:49
  • Thanks, wasn't sure if the question would be closed for being 'too opinion oriented' as it probably would on Stack Overflow! I'm just starting to learn about design patterns so expect a lot more of these questions in the coming months! – user1578653 Aug 20 '14 at 9:22
4

The implementation looks correct for me.

The approach may not scale well, because:

  • You recreate an object every time in getById,

  • You loop through all the objects in persist, while maybe only one changed,

But doing premature optimization would be worse: if performance corresponds to your expectations right now, don't change anything.

Later, if performance becomes an issue, consider:

  • Implementing caching strategy (given that it will probably be outside the repository, as an additional layer between the repository and the code which uses the repository),

  • Using observer pattern to track the changes in the objects: this way, when persisting changes, you don't need to do extra work, and can update only the data which actually changed.

3

I think you are doing more of a Data Mapper, and as such, it seems correct to me.

In a strict DDD (Domain driven design) point of view, the Repository pattern is one of the most misunderstood/misused patterns. In many examples you will find online, the "repository" is implemented as a database abstraction layer, often implemented with an ORM. However, in a DDD context, a Repository is a collection of Aggregates, not belonging in the data access layer, but in the domain/business logic layer of the application. An Aggregate encapsulates a cluster of objects in order to protect it's invariants, exposing only it's root entity (check this question for more details: https://stackoverflow.com/questions/1958621/whats-an-aggregate-root).

I would "forget" about the Repository pattern and take a look at CQRS (Command Query Responsibility Segregation) instead. If your application contains complex business logic, it might be a good idea to implement it with the tactical patterns of DDD though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.