I'm writing a database interface in PHP and I have a base dbTables
class, as well as a base dbTableFields
class.
dbTables
has a function, getFields()
, that instantiates dbTableFields
objects, each of which carries essential data on each table field, and puts it into dbTableFields->fields=array();
dbTables
has several children.
Now I've realized that the children need to use different versions of getFields()
. But they only differ in one place: they need to instantiate dbTableFields
children, rather than dbTableFields
objects.
I've solved this problem. I took advantage of PHP's ability to use variables to represent class names. All I had to do was, in dbTables->getFields()
replace:
$this->fields = new dbTableFields();
with
$this->fields = new self::$field_model();
Where self::$field_model = 'dbTableFields'; // string value for class
Now, in the child classes, I just have to override the $field_model
property with the name of the appropriate dbTableFields
descendents.
Is this parallel inheritance scheme good form? Or am I creating an uncompromising mess? Is there some more-elegant and more maintainable method for achieving the same effect?
-
2My spider sense is tingling, but I can't pinpoint what's wrong here. You should post your full code on Code Review Stack Exchange, our sister site for peer reviews of working code, to get the full Stack Exchange experience ;)yannis– yannis2012年05月05日 12:35:08 +00:00Commented May 5, 2012 at 12:35
-
@YannisRizos Calling functions/classes by way of stored name like that isn't a good thing, without very strict guidelines. Some of my co-workers tried it out a several years ago before I started there, and that section of our system has become a horrible mess of spaghetti code that they no longer understand. I spent months figuring it out and am now slowly converting it to something more sane.Izkata– Izkata2012年05月06日 00:24:04 +00:00Commented May 6, 2012 at 0:24
-
1After working on this code for a few more months, I have to say that I agree with @Izkata. That part of the system is very fragile. Rather than refactor it, I've ended up creating new classes to handle the same data, and left the old ones in place for use in the scripts that already work.Buttle Butkus– Buttle Butkus2012年08月13日 07:58:34 +00:00Commented Aug 13, 2012 at 7:58
2 Answers 2
The principle you want is to "favor composition over inheritance." This is a fairly classic example of where the strategy pattern would be useful: separate your "getFields" logic into several FieldStrategy objects, and reference the appropriate one for your parent and your children.
I'm not explaining this very well, but please google "strategy pattern" and play with it.
-
Would you suggest a FieldStrategy class, where the __construct() takes arguments that set the field strategy? And then each class that needs a FieldStrategy can set its own version of the class?Buttle Butkus– Buttle Butkus2012年08月13日 08:02:18 +00:00Commented Aug 13, 2012 at 8:02
-
Yes, that sounds right.Matthew Flynn– Matthew Flynn2012年08月13日 11:41:04 +00:00Commented Aug 13, 2012 at 11:41
NO, usually.
Parallel inheritance hierarchies are bad smell in code.
I have heard that Martin Fowler indicated this as a code smell in his famous book "Refactoring : Improving the Design of Existing Code".
However, it is not something absolute. Sometimes parallel inheritance hierarchy may be the best design among the alternatives your team could come up with.
Google with "Parallel inheritance hierarchy". Who knows better design may pop-out!
Explore related questions
See similar questions with these tags.