Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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...

share|improve this question
    
I'm not sure if it's pertinent, but I'm coding in PHP, so the "application" is state less. We must reload all the data between each page if it's not stored in a session cookie. That mean that we can't pre-load everything like in an application language. –  FMaz008 Apr 7 '11 at 19:49
    
@job: Well it's because a static call inside a method is mostly impossible to replace when unit testing. The goal is to use dependency injection. But a factory is usually static, so it can't be injected. –  FMaz008 Apr 7 '11 at 19:51
add comment

2 Answers

up vote 6 down vote accepted
  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.

share|improve this answer
    
So it's ok to have instances of Factory/Repository/Mapper ? I'll need a dependency container or something because if we need to inject all the factory/repository/mapper for all the possible object that can be returned by an object, that quickly made a lot. ( Article -> OptionGroup -> Option -> Article , etc.. ) –  FMaz008 Apr 7 '11 at 20:09
1  
It's more than ok, it's preferable. I generally reserve static use to removing repeated code, where it's small enough to be tested in multiple classes. And yes, an IOC / DI Container is going to make your life a lot easier. Use one. –  pdr Apr 7 '11 at 20:12
add comment

There's a paper that argues that you never need static methods, that abstract factories have been demonstrated to be confusing, and suggests a slight language change towards dependency injection as the solution:

Seuss: Decoupling responsibilities from static methods for fine-grained configurability

share|improve this answer
1  
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. –  gnat Dec 21 '12 at 10:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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