2

I have a design problem where my classes are set up in such a way:

abstract class Advertiser        abstract class AdvertiserCampaign
      |                                    |
      |                                    |
class AdvUno extends Advertiser  class AdvUnoCampaign extends AdvertiserCampaign
class AdvDos extends Advertiser  class AdvDosCampaign extends AdvertiserCampaign
class AdvTre extends Advertiser  class AdvTreCampaign extends AdvertiserCampaign

The problem is that AdvUno and AdvUnoCampaign both need a special authentication method that's not necessary for the others. Right now I've placed it in AdvUno, but again, it'll be needed by AdvUnoCampaign (and a bunch of other classes that are set up in this way).

  • I can't make AdvUnoCampaign extend AdvUno since there's no multiple inheritance in PHP, but also because it's just generally not a good, clean design practice.
  • If I make AdvertiserCampaign extend Advertiser, then all of the extending classes below (AdvUnoCampaign, AdvDosCampaign, etc) must implement a bunch of abstract methods that are of no concern to them, and which are already implemented in each of the Advertiser classes.

In short, what's the best design practice in this sort of situation? I'd rather not just copy and paste the code into all of the AdvOne classes. Any help or advice would be appreciated. Thanks!

Mike Cialowicz
  • 9,892
  • 9
  • 47
  • 76
  • DI comes to mind. Maybe read these threads: http://stackoverflow.com/questions/8837239/puzzled-with-dependency-injection-in-php-chains-of-classes, http://stackoverflow.com/questions/4176520/what-is-the-difference-between-strategy-pattern-and-dependency-injection, and http://stackoverflow.com/questions/5050734/dependency-injection-in-real-life And of course Fowler is always good for patterns: http://martinfowler.com/articles/injection.html – ficuscr Mar 14 '13 at 18:52

2 Answers2

3

Parallel Inheritance Hierarchies are considered a code smell, something that should be refactored.

Martin Fowler suggests in "Refactoring":

The general strategy for eliminating the duplication is to make sure that instances of one hierarchy refer to instances of the other. If you use Move Method and Move Field, the hierarchy on the referring class disappears.

But I think you can go one step further. I don't know, what your decision was based on to make sub classes for each advertiser and their campaigns, but I would challenge this decision. A good practise to follow is to Favor Composition over Inheritance.

You could start like that:

class Advertiser
{
  protected $authentication;
}

class AdvertiserCampaign
{
  protected $authentication;
}

interface AdvertiserAuthentication
{
}

class SpecialAuthenticationForAdvertiserUno implements AdvertiserAuthentication
{
}

class NoSpecialAuthenticationForOtherAdvertisers implements AdvertiserAuthentication
{
}

Now the first difference between the advertisers is moved into another class. Go on with other differences until each advertiser is just an object of Advertiser composed in a different way. The same goes for the campaigns. I would like to be more concrete but as stated before, I have no idea why your advertisers all have their own classes in the first place.

Fabian Schmengler
  • 24,155
  • 9
  • 79
  • 111
  • Hmmmm, I do understand that parallel class hierarchies are a smell. However, in this case I'm doing it because the "has-a" relationships aren't steadfast. In any case, it's a complex case that I have here. If my choice now isn't quite right, I'm happy to refactor later once the path becomes more clear. For now I've done something very similar to what you've suggested, and I've created an `AdvertiserAuthentication` object which has all the necessary info injected, and each "Uno" Advertiser object has one of these. – Mike Cialowicz Mar 15 '13 at 17:25
0

In general, to resolve problems similar to yours the Bridge design pattern is commonly used.

http://sourcemaking.com/design_patterns/bridge

gphilip
  • 1,114
  • 15
  • 33