This blog has been moved to http://info.timkellogg.me/blog/

Wednesday, March 23, 2011

Object Incest

Note: I thought I had read this term from somewhere else, but after a quick internet search turned up only dirty videos, I think I may be the sole "coiner" of the term. 


Many inexperience developers (and experienced ones too) have been known to make several common mistakes in object oriented design. Hence, the coining of the terms anti-pattern and code smell to refer to patterns of development (like design patterns) that lead to convoluted, overly complex code that costs exponentially to maintain and exhibits little value.

Object incest is a pattern where two unrelated classes are intimately dependent on each other. Simply put, if object A directly relies on object B and B relies directly on A, you have two incestual objects. This usually happens to intermediate developers who realize that they need separation of concerns and break a class into two classes without actually breaking the dependencies. While it is understandable (and almost respectable) why a developer might commit object incest, it is no less dangerous and harmful to a code base full of child objects.

Here is an example of object incest:

class Brother {
 public Sister MySister { get; set; }

 private void GetMyHairBrushed() {
  MySister.BrushHair(this);
 }

 public void DefendFromBullies(Sister sis) {
  // ...
 }
}

class Sister {
 public Brother MyBrother { get; set; }

 public void BrushHair(Brother bro) {
  // ...
 }

 private void GetRidOfBullies() {
  MyBrother.DefendFromBullies(this);
 }
}

This is wrong because the two objects are so involved that it's hard to tell them apart, breaking the principal of separation of concerns. You can fix this by extracting roles from the objects as interfaces. Therefore, each object depends on some kind of object that can fulfill a role. A brother object needs someone to brush his hair, a sister needs someone to defend her from bullies.

class Brother : IDefenderOfTheWeak, IPersonWithHair {
 public IHairBrusher MyHairBrushPartner { get; set; }
 
 private void BrushMyHair() {
  MyHairBrushPartner.BrushHair(this);
 }
 
 public void DefendFromBullies(IWeakling weakling) {
  // ...
 }
}

class Sister : IWeakling, IHairBrusher {
 public IDefenderOfTheWeak Defender { get; set; }
 
 public void BrushHair(IPersonWithHair hairyPerson) {
  // ...
 }
 
 private void FightOffBullies() {
  Defender.DefendFromBullies(this);
 }
}

In the second example, the two objects are no longer reliant on each other. Now they only rely on the roles that each of them provide. Down the road it will be much easier to create other objects that implement those interfaces (roles) like Husband and Wife.

No comments:

Post a Comment