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?
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.
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.
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.
}
}
精彩评论