2009年6月3日星期三

Re: [fw-mvc] get and set accessors

-- Ed Lazor <edlazor@internetarchitects.biz> wrote
(on Wednesday, 03 June 2009, 08:23 AM -0700):
> > Userland code -- code built on top of the framework -- has fewer
> > restrictions in this regard, and I often find myself using public
> > properties in such situations. I just find it hard to justify them
> > within development of the framework itself.
>
> When you find yourself using public properties, is that just a matter
> of convenience or is there some sort of benefit? For example, are you
> trying to save the overhead of calling a method?

Some cases where public properties make sense:

* Simple value objects you want to serialize or pass between objects

* Interactions between objects. For instance, setting some metadata in
one object, and then another object that has knowledge of it can use
that metadata in order to change state on the original (as an
example, this is how I originally did the ContextSwitch action
helper, and it's still a great usage for action helpers).

> Do you draw a distinction between personal code and professional
> (non-ZF) code when using accessors?
>
> So far, it seems like I should just be using magic methods to create
> accessors, use them in my code so I don't have to search my code for
> changes if I decide to wrap a property in business logic, define
> non-magic methods when I want to add business logic, and minimize the
> need for accessors by assigning as much responsibility to objects as
> possible. Does that sound like the best approach for code that I
> would be creating for others in a professional capacity?

This is actually the exact approach I typically use, and am using now in
working up some examples for my DPC workshop.

For those of you who want a visual:

class Foo
{
public function __set($name, $value)
{
$method = 'set' . $name;
if (method_exists($this, $method)) {
$this->$method($value);
return;
}

$prop = '_' . $name;
$this->$prop = $value;
}

public function __get($name)
{
$method = 'get' . $name;
if (method_exists($this, $method)) {
return $this->$method();
}

$prop = '_' . $name;
if (!property_exists($this, $prop)) {
return null;
}
return $this->$prop;
}

public function __call($method, $args)
{
if ('set' == substr($method, 0, 3)) {
$name = substr($method, 3);
$value = array_shift($args);
$this->__set($name, $value);
return;
}
if ('get' == substr($method, 0, 3)) {
$name = substr($method, 3);
return $this->__get($name);
}
throw new BadMethodCallException();
}
}

What the above scaffolding does is that it allows you to create
"virtual" accessors for any given property, and also provides standard
property access notation that forwards to accessors if they exist. You
can then add protected members with default values to the class,
accessors to provide business logic, etc -- without breaking the API.

--
Matthew Weier O'Phinney
Project Lead | matthew@zend.com
Zend Framework | http://framework.zend.com/

没有评论: