3

I'm fiddling with an MVC framework, and I stumbled upon a problem I'm not sure how to solve.

I want to make a DomainObjectFactory for the Model layer of my application, however, each Domain object would have a different set of arguments, for instance:

  • Person - $id, $name, $age.
  • Post - $id, $author, $title, $content, $comments
  • Comment - $id, $author, $content

And so on. How can I easily tell my factory what kinds of object do I require?

I've came up with several options:

  • Pass an array - I dislike this one, because you can't rely on the constructor's contract to tell what the object needs for his work.
  • Make the DomainObjectFactory an interface, and make concrete classes - Problematic, because that's an awful lot of factories to make!
  • Use Reflection - Service locator much? I don't know, it just seems that way to me.

Is there a useful deign pattern I can employ here? Or some other clever solution?

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308

1 Answers1

3

Why do you want to initialize a Domain Object with all the properties assigned?

Instead just create an empty Domain Object. You might in the factory check, if it has prepare() method to execute. Oh .. and if you are using DAO, instead of directly interacting with Mappers, you might want to construct and inject the appropriate DAO in your Domain Object.

The assignment of values should just happen in the Service. By the use of ordinary setters.

Some examples:

Retrieving existing article

public function retrieveArticle( $id )
{
    $mapper = $this->mapperFactory->create('Article');
    $article = $this->domainFactory->create('Article');
    
    $article->setId( $id );
    $mapper->fetch( $article );
    $this->currentArticle = $article;
}

Posting new comment

public function addComment( $id, $content )
{

    $mapper = $this->mapperFactory->create('article');
    $article = $this->domainFactory->create('Article');
    $comment = $this->domainFactory->create('Comment');

    $comment->setContent( $content );
    $comment->setAuthor( /* user object that you retrieved from Recognition service */ );

    $article->setId( $id );
    $article->addComment( $comment );
    // or you might retrieve the ID of currently view article
    // and assign it .. depends how you build it all
    
    $mapper->store( $article ); // or 
}

Passing user input

public function getArticle( $request )
{
    $library = $this->serviceFactory->build('Library');
    $library->retrieveArticle( $request->getParameter('articleId'));
}
Community
  • 1
  • 1
tereško
  • 58,060
  • 25
  • 98
  • 150
  • So you're saying I should generate empty Domain Objects, and let my Data Mappers alone fill them? How do I deal with user input? – Madara's Ghost Jan 20 '13 at 14:04
  • When factory releases the DO, it is empty. You assign some conditions to it, and then fetch the values .. or store them. – tereško Jan 20 '13 at 14:07
  • But then, how would you deal with user input? Making a DM of its own doesn't sound right – Madara's Ghost Jan 20 '13 at 14:14
  • I am not sure this is correct, but my [Front Controller](http://www.martinfowler.com/eaaCatalog/frontController.html) captures user input (usually from the POST array, but it could be from other input), and creates a Request object that contains the data entered by the user, which is then passed into the appropriate controller (based on the requested action). – Steve Cooke Feb 10 '14 at 00:56
  • @tereško in code examples, you used [create] method for mapper/domain factories and [build] method for service factory. Was this on purpose (service 'build' does something different?) or just different name for the same thing? – Andrew Jul 26 '14 at 18:43
  • @Andrew honestly, no idea. I probably lost my train-of-thought at some point and forgot which name I was using. Then again, the name of the method that you use for supplying instances doesn't matter, – tereško Jul 27 '14 at 07:32