tags:

views:

106

answers:

5

In the project my team is currently working on, we're modifying a commercial PHP application. The app is strewn with code where a parent class checks for and works with a property that doesn't exist in the parent class, like so:

class A 
{
    function doSomething()
    {
        if (property_exists($this, 'some_property'))
        {
            $this->some_property = $_REQUEST['val'];
        }
    }

}

class B extends A
{
    protected $some_property;

    function doSomething()
    {
        parent::doSomething();
    }
}

We feel vaguely dirty having to modify this code; is this proper design? What are the ways (other than the obvious) something like this can be avoided?

A: 

Does the concept of "dirty code" even exist in PHP ?

peufeu
Although I understand you were intending to put PHP down, I can answer that question definitively based on the code I'm working with.The answer is yes.
Chris Miller
A lot of people play football very badly but it's not blamed on the sport
David Caunt
A: 

You can create a virtual method hook in the parent class which can later be overridden by children.

Dinah
A: 

I think it's more neat to create a sub-class, where all members have function doSomething(). In that case you don't create a not-working function in a parent class (with eventual hacks), but still have the general "super-function".

class A 
{


}
class C extends A {

    protected $some_property;

    function doSomething()
    {
        $this->some_property = $_REQUEST['val'];
    }
}

class B extends C
{
    protected $some_property;

    function doSomething()
    {
        parent::doSomething();
    }
}
vstrien
+3  A: 

You might consider abstracting the parent class. So the methods that the children must have are declared in the parent, but not implemented.

dnagirl
Agreed. Unfortunately the parent class in this case is considered 'core code', which we're not allowed to touch.
Chris Miller
I agree with this answer. What you found is a technique you'll encounter more than once. It can be very useful. But an abstract base class should be used because the class is obviously not complete and should be completed using polymorphism.
koen
Based on a comment from a team member, s/not allowed to/strongly advised not to/
Chris Miller
@Chris Miller: Well, if you can't abstract the parent, then you could implement an interface on all the children. It's not as good since you have to remember to do it in each class definition (and it's not really what interfaces were meant for), but it's better than nothing.
dnagirl
@dnagirl good point. I'll bring it up.
Chris Miller
A variation that might make you feel more comfortable is to use an abstract method, eg getThatProperty(). Or have a default implementation in the base class and let subclasses decide wether or not to override it.
koen
+2  A: 

Relying upon methods that must exist in a subclass is not dirty, as long as you can declare them as abstract.

However, it is not good practice to rely on and manipulate properties outside of a class. It's best to use abstract setters, like this:

abstract class A 
{
    abstract protected function setSomeProperty($data);

    public function doSomething()
    {
        $this->setSomeProperty($_REQUEST['val']);
    }
}

class B extends A
{
    private $some_property;

    public function doSomething()
    {
        parent::doSomething();
    }

    protected function setSomeProperty($data)
    {
        $this->some_property = $data;
    }
}

More info here: PHP Class Abstraction

However, since you said you're not allowed to modify the parent class, I would suggest making a subclass that acts as an Adapter to what the parent class "expects", and a class that you're able to design "properly".

philfreo
Thank you all for very good answers. I think we're more or less stuck with what we have, due to less-than-technical restrictions (>.<), but something about this strikes my fancy.
Chris Miller