Php – Static is bad, but what about the Factory pattern

PHPstatic-accesstdd

I'm on a TDD project, so I try to stick as much as possible to the good pratices involved with that kind of development. One of them is avoiding as much as possible static and global.

I'm facing this problem:
I've an object "article" that can have "options" (additionnal "micro-articles") linked to it.

I can't figure out how to have a good approach that will not be counter productive or generate too much queries because I would be in a situation where everything is so decoupled that I'll basically need to make 1 query per object.

From my actual perspective, I see 3 options:

1) Build inside article:

class Article
{
    //[...]
    public function getArrOption(){
        //Build an array of Options instance.
        //return an array of Options.
    }
}

Pro: Straight forward

Const: Maintenability: The article object now contain the building logic for the Option object. This will probably lead to code duplication.

2) Using an optionFactory

class Article
{
    //[...]
    public function getArrOption(){
        return OptionFactory::buildFromArticleId($this->getId());
    }
}

Pro: Building logic is not out of the Article class

Const: I'm breaking the "static is hard to mock" rule, making my Article class hard to test.

3) Separate all logics.

//Build the array of Option instance in a controller somewhere, using a Factory:
$arrOption = OptionFactory::buildFromArticleId($article->getId());

Pro: Article only handle his own responsability, and doesn't care about his "father" link to the options. Things are really decoupled

Const: Will require more code inside the Controller everytime I'll need to access the Options. That mean that I should never use a Factory inside an object, and that sound kind of utopic to me…

What's the best way to go ? ( Did I've miss something ? )
thanks.

Edit:

Not to mention that if I can't call factory inside class, I can basicaly never use the lazy initialization pattern too…

Best Answer

  1. Static isn't "bad", it's unmockable. You can still use it where mocking doesn't make sense.

  2. That isn't a Factory pattern, it looks like a Repository pattern, although it may not be. Factory is where you have multiple classes with the same interface / base class and you want to separate out the logic which decides which class to return. Repository gets the data from its repository, abstracting out the implementation of that repository (the Article doesn't need to know if its options are stored in the same DB, another one, an XML file, a CSV file, whatever).

  3. You've ignored the possibility of giving the Article class an ObjectFactory (or Repository, or whatever) object in the constructor on which it can call the buildFromArticle method.

My PHP is rusty, but I think it looks like this:

class Article
{
    private $_option_repository;

    public function __construct($option_repository) {
        $_option_repository = $option_repository;
    }

    //[...]

    public function getArrOption(){
        return $_option_repository->buildFromArticleId($this->getId());
    }
}

I think this fulfils all of your pros above.

Related Topic