SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    SitePoint Evangelist
    Join Date
    Nov 2009
    Posts
    471
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Levels of inheritance

    From a technical perspective, are there limits to how many levels deep inheritance can go?

    Same question from a practical perspective. Is there a rule of thumb that says if you've gone x levels deep, you've probably done something wrong on the design side?

    In the real world, can and does this cause problems and if so, what types of problems should I expect or look for? i.e. performance, readability, usability, etc.

    Thanks

  2. #2
    SitePoint Evangelist
    Join Date
    Aug 2005
    Location
    Winnipeg
    Posts
    498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Technically I don't imagine there is a limit that is virtually impractical. Practically speaking, it is usually accepted as a best practice that inheritence be avoided in favor of composition - although inheritence still makes sense.

    As a basic rule of thumb, the deeper the inheritence heirarchy the more rigid your code will become and thus more difficult to change so inherit with caution and favor inheritence until it becomes glaringly clear that inheritence is a better/more elgant solution than composition.

    Cheers,
    Alex
    The only constant in software is change itself

  3. #3
    SitePoint Evangelist
    Join Date
    Aug 2005
    Location
    Winnipeg
    Posts
    498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    To answer your last question, deep inheritence trees can cause a few issues, mainly code comprehension. The indirection caused by deeply nested hierarchies means you have to step through code in sequence as opposed to random access when investigating a method. Some IDEs and documentation tools will assist you but it's usually more work than a flat collection of classes.

    Using DI/composition the relationship (or rather usage/linkage) of classes is usually implied at the time of calling code, not disguised in deep hierarchies. That is to say, just looking at the container class at the time of it's use I can usually deduce exactly what classes are involved right there, not having to read docs or traverse complex hierarchies to figure which classes are being pulled into scope.

    Also, ridigidy of code. There are many examples of rigid hierarchies, but assume a DB class (which is most common) where someone inherits a custom DB class from say a MySQL base class. Sometime later in the future, MySQL is dropped in favor of MSSQL and the base class must now be adjusted/refactored to reflect the RDBMS change.

    Properly designed DB classes/library would allow a more fluid/dynamic change without possibly even requiring a change to the code - which makes the code more dynamic
    The only constant in software is change itself

  4. #4
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,034
    Mentioned
    65 Post(s)
    Tagged
    0 Thread(s)
    How many times does a change of RDMS actually occur? There is such a thing as over preparing and causing the software to become nightmarishly complex trying to account for situations that will never arise.

  5. #5
    SitePoint Evangelist
    Join Date
    Aug 2005
    Location
    Winnipeg
    Posts
    498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    How many times does a change of RDMS actually occur? There is such a thing as over preparing and causing the software to become nightmarishly complex trying to account for situations that will never arise.
    Common counter argument. I suppose it depends on your market segment. I worked for a well known white label software development firm with a global customer base in the past. There were enoguhb requests for PG or MSSQL (or other) support for me to justify looking into properly abstracting the RDBMS in order to accommodate even more customers.

    I think you missed my point though, it was not whether DB abstraction was practical or not, it was as common real-world scenario of less than ideal usage of inheritence.

    PHP Code:
    class CMySQL{
      
    // Implement methods
    }

    class 
    Database extends CMySQL{

    }

    $db = new Database();
    $db->connect($h$u$p);

    $db->query('SELECT * FROM table LIMIT 1, 25'); 
    This is IMO more work to maintain and comprehend than a dynamic and upfront DI solution, which might look like:

    PHP Code:
    class MySQL{

    }

    class 
    Database{

    }

    $db = new Database(new MySQL($h$u$p)); 
    No changing inheritence and breaking interfaces potentially (refactoring made easier). Plus the DB in question is clearly obvious - no browsing docs or relying on advanced IDE features to determine which DB is being used. Additionally (and perhaps in the case of a RDBMS is a moot point as you mention) the fact is, you can easily swap out provider/implementations, even dynamically using a strategy/factory.

    Cheers,
    Alex
    The only constant in software is change itself

  6. #6
    SitePoint Addict webaddictz's Avatar
    Join Date
    Feb 2006
    Location
    Netherlands
    Posts
    295
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hello.

    Quote Originally Posted by Michael Morris View Post
    How many times does a change of RDMS actually occur?
    Agreed; I've only encountered a RDBMS change once in my years of development, and even that went rather smoothly. It generally is a bad example because it's not only the inheritance that might cause troubles, it's the dialect of SQL just as well.

    Nevertheless, I've found that composition generally causes less headaches than inheritance, but it's no silver bullet either. Actually, the two techniques tend to work together to get the most flexible design possible. You've probably heard of the rule of thumb that you should only ever use inheritance if there's an "is-a" relationship.

    I've extended that rule for myself: the type has to be the same (so Guest is a User), and the motivation for inheritance should be *changing* the existing behaviour rather than reusing code. If there's a few lines of code I want to reuse, I try to split it out into another object and inject that object into the client.

    Another rule of thumb is that I try never to extend more than once, so I'm not setting up inheritance trees. As PCSpectra already mentioned, experience tells me that a large inheritance tree can be a disaster to debug. Apart from the debugging, there are other problems introduced by inheritance; for starters it's harder to test as you can't simply inject a mock or stub to replace the parent object.

    The inability to test is a direct result of the tight coupling between parent and child. Child-classes can make a whole lot of assumptions about the state the parent is in and indeed, most child classes I write do so. That's not a bad thing per se, but if it's like to change it would be, as it's harder to change the behaviour of a child class than it is once you've gone the mixing and matching route.

    This is not carved in stone, obviously. It takes experience and a healthy dose of logic to find the best ratio. I think that it is a good point of view to favour composition over inheritance, but I wouldn't say inheritance is useless, of even bad.

    Quote Originally Posted by Michael Morris View Post
    There is such a thing as over preparing and causing the software to become nightmarishly complex trying to account for situations that will never arise.
    Yes, of course. If the chance of change is low, you shouldn't be worrying a whole lot about it. Nevertheless, the cost of abstracting repetitive code into a different object and inject that object into the object that uses that behaviour is not that much higher than extending the object to reduce repetitive code. It doesn't get "nightmarishly complex" as you put it, if you try to keep sane and remember that at the end of the day, accomplishing the goal is more important than the means to accomplish it.

    You can shoot yourself in the foot with either way; the only thing I can tell you is that the hole in my foot was bigger when I had a large inheritance tree.
    Yes, I blog, too.

  7. #7
    SitePoint Evangelist
    Join Date
    Aug 2005
    Location
    Winnipeg
    Posts
    498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can shoot yourself in the foot with either way; the only thing I can tell you is that the hole in my foot was bigger when I had a large inheritance tree
    Amen
    The only constant in software is change itself

  8. #8
    SitePoint Evangelist
    Join Date
    Nov 2009
    Posts
    471
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Pretty funny, I get the picture


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •