Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Law of Demeter and return values

According to the Law of Demeter, can you call methods on returned objects?

E.g.

<?php
class O
{
    public function m($http)
    {
        $response = $http->get('http://www.google.com');
        return $response->getBody(); // violation?
    }
}
?>

$http->get() returns an object. Does this count as an object created/instantiated within M? If you can not call methods on it (according to LoD), how would you handle this situation?

like image 675
Sjoerd Avatar asked Jun 09 '10 13:06

Sjoerd


3 Answers

This is not a violation of the Law of Demeter, given:

More formally, the Law of Demeter for functions requires that a method M of an object O may only invoke the methods of the following kinds of objects:

  • O itself
  • M's parameters
  • any objects created/instantiated within M
  • O's direct component objects
  • a global variable, accessible by O, in the scope of M

Since $response is an object that is created within M, you can invoke a method upon that object without violation. However, it would be a violation to access properties beyond getBody():

$length = $response->getBody()->length;

Sometimes you can say that the law can be simplified by saying it's the "one dot" rule, meaning that you can access one property or method deep.

like image 186
Jeff Schumacher Avatar answered Oct 05 '22 22:10

Jeff Schumacher


On the one hand, $response appears to have been created within method m, so the answer would appear to be yes.

On the other hand, since $http has been passed in to m, the object returned by $http->get() that is now represented by $response might be a member of $http that might have been created prior to entry to m.

Considering the "only one dot" (or, in this case arrow) interpretation of the Law, rewriting the body of your function as return $http->get('http://www.google.com')->getBody(); suggests that it might be a violation. Saving the intermediate members as local variables seems like a dodgy way to avoid the one-dot principle.

I can't give a definitive answer. To some extent, I think it depends on how much you trust the $http->get() to give you a newly created object rather than a pre-existing member.

like image 27
Paul Butcher Avatar answered Oct 05 '22 23:10

Paul Butcher


One possibility to solve this is to create the object within m(), and let http->get() fill it with information.

class O
{
    public function m($http)
    {
        $response = new HttpResponse();
        $http->get('http://www.google.com', & $response);
        return $response->getBody(); // no violation, since we made $response ourselves.
    }
}
like image 28
Sjoerd Avatar answered Oct 05 '22 23:10

Sjoerd