lundi 22 février 2016

Inheritance dead end

Please use more object composition!
image: www.funny-potato.com

TLDR; There are problems with inheritance. Often composition is a better alternative. Below is an example where inheritance is employed for code reuse, but it ends up forcing duplication! The post continues with showing the more flexible alternative, object/function composition, and exposes several of its advantages.

Too often I come across codebases where there are big inheritance hierarchies. But it doesn't even have to be huge, I get suspicious when I see more than one level of inheritance or more than one overridden method in a subclass. Reluctance to refactor or lack of knowledge of alternatives drives those hierarchies to grow and become inflexible and difficult to grasp.

As an example take a restaurant that served only a single menu to start with. Then as business grew it added two variations of its menu MeatLoversMenu and GourmetsMenu. Its single public method serveMenu() serves an apetizer, then the main course, then dessert and finally coffee. For variation in which mainCourse() and which dessert() is served it uses TemplateMethod overriding the default implementations. 


7Vldb+o4EP01SLsPrfIBlD42tPfuQytV26vdZ5OYxKpjcx0DbX/9ncHjfBC2wFK2Wqm8EE/ssT3nHM8YBvG0fPlu2KJ40BmXgyjIXgbx7SCKwvB6CF9oeXWWq+DaGXIjMurUGJ7EGydjQNalyHjV6Wi1llYsusZUK8VT27ExY/S6222uZXfWBcv9jI3hKWWyb/1bZLbw+xrTNvDFH1zkBU09icbuxYylz7nRS0XzDaJ4vvm41yXzvmijL4Fresev1L6uJ1KdFb1pXXYMhldN9Gi3ohsQxVadOaVQz934zLTJuGl1iu8AXaM1OMKn8mXKJSLswbuK4pRFYxYMh8PJkKcXzvW3Q7vX8TVc0WJPdRk7lysmlxSOhFf2L2w+cLV0byv76iGu1qKUTEErKWwpwRjC41wr+0SdsM2kyBGBFNaJEUpW3FgBRLmhF1YvwJoWQmb37FUvcTeVBRb4VlJoI97ALfNzwGtjifPAm3aPJxwJZmBB4pB99CHCkc50zyo0YJ9US8kWlZjVCy6ZyYVKtLUbomAnv9NvQsqpltoB7XkZJwvJhLrIDefqAFgIOowD93qvKQMHAtclt+YVuU1vr4l3dBaEAbXXjbJqbhYtUYXeyIitee27IQY8EDcO5Mmox5MeNUAgW7SorNHP9VHQJobkcwR5mxalyDJ0l1QLlgqV/0Ca3ELwasv9ZuBt3Fj+pK2jyWjLLHOwIoaSzbh81JWwQqN/4/omCy2U3YRnlAxGtxuLsVOtYMWAKrrjQJc1SKGFNHMhfB9oL6j9QBOw/gzch+vkDKjS1B1UE0SVmxXpfywxBBBrYHkL7fHPJR5zCYJ+4Zd5A13CS/Dh38JTjt+//e4dwRKdL/fCmzOxesd0gftecAsqNh1X7w8DtW6Sh1BTvTQVx6HAClzlz6VIC46nujaIODwe5RTSLMTItjzOIH0qscfPXu+401TP53yz2N2DtmQHNNucl43s9ojMnb1dPQ37ekLTuhCWP4Ed51pD0QI2Df7mUq/BUoBc4fTr666rrwTYPA0uR6i0aAptEIRvHyw+PGZhclyjReXEOM859BhTEbZXjySeDxUkibwlyAfO7D3GvPrKx5+Zj6+66Tia9NNx6G2ddOzz9ofyJOwT5e7FcpVVPYaA8QZre2jNpEZcEjARcCECB00MKsW5RaPjQkpLAlrk/J/6kGZ41rlI9IPejuqYAmi4ZFasulX7rqiSu0c8hBoAPTh+RAU5IeXUqV0yb42LhlsD3QZ7AzcY1lv4d7DS9eXUKmvekojSm/7/y8LrcNKdVG7t1O05yi1/T+/ge0zZAsCCtOAloAZx/SoQPqBAOJpBOwqEnQwan6NACH3iaij0HVgCjr/qg0+tD+LRAQWCv9P/BwUCZY6vVHJwKqmldVIu2QXxWXJJ/5e7I26rqeElXn9TZliJv0J/ZZLTM8nxBNqVSnYR6DyppF9tfvodgiLoavM9Yf6Qi4aH6YqQ8L+2ehR2XUQOv3Nsu61vkUdfQsbjyyAexdeTKA6CyYR+jt1e7clXFGg2/1+47s1fVfHdLw==




Now, a few months later, it would like to offer a NoGlutenMenu as there is a lot of business in this niche. 
In theory it could serve the main course from the MeatLoversMenu and the dessert from GourmetsMenu as they don't contain any gluten. It's a simple need, but impossible to satisfy without duplicating some code given the current architecture (without multiple inheritance), where there's no way of inheriting the code of both MeatLoversMenu and GourmetsMenu.


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






In this case we'd be much better off using the StrategyPattern or the CommandPattern for serving the main course and the dessert.


Lets refactor the code so that Menu is a concrete class that calls an object of Type MainCourse to serve the main course and Dessert to serve the dessert. It does NOT know which one it is serving, it doesn't care. When the chef composes a noGlutenMenu he simply creates a new Menu instance using an instance of FiletMignon and CremeCaramel as shown in the bottom right corner of the diagram.


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





We have gained less coupling:
  • No more duplication of the logic of serving filet mignon and creme caramel
  • The chef is really happy as he can add new MainCourses and Desserts and compose menus as he like!
  • It is a lot easier to test classes like FiletMignon than MeatLoversMenu as there is less setup code involved, and less duplication between tests.
  • We even have the flexibility of opening up the restaurant in the afternoon serving only desserts. I.e. Reusing the small objects outside the context of a Menu.


Conclusion
Consider composition every time you override. If you can't visualize what the composition alternative would look like, then practice it. Your code is going to be much better off if you master this technique!


There are some general guidelines on when Composition over inheritance applies. Additionally Steven Lowe has some interesting insights. My personal experience tells me that I was a poor judge before I was experienced in composition and in particular knew how to refactor away an inheritance hierarchy.


Here’s a simple example of the refactoring


Note: object composition has lost a lot of boiler-plate code with the introduction of lambda-expressions in most languages. Nowadays we don't have to create interfaces for Dessert and MainCourse and no classes for the concrete implementations (unless we chose to for explicitness). An example of a modern strategy/command pattern in java

Aucun commentaire:

Enregistrer un commentaire