{"id":93,"date":"2009-02-07T12:45:57","date_gmt":"2009-02-07T16:45:57","guid":{"rendered":"http:\/\/www.peteonsoftware.com\/?p=93"},"modified":"2024-03-02T16:39:34","modified_gmt":"2024-03-02T21:39:34","slug":"liskov-substitution-principle","status":"publish","type":"post","link":"https:\/\/www.peteonsoftware.com\/index.php\/2009\/02\/07\/liskov-substitution-principle\/","title":{"rendered":"Liskov Substitution Principle"},"content":{"rendered":"<p>I was listening to Hanselminutes a few weeks back and Scott Hanselman <a href=\"http:\/\/www.hanselminutes.com\/default.aspx?ShowID=163\">had Uncle Bob Martin on<\/a> to talk about the SOLID principles of object-oriented design.  SOLID stands for <\/p>\n<ul>\n<li>Single responsibility principle<\/li>\n<li>Open closed principle<\/li>\n<li>Liskov substitution principle<\/li>\n<li>Interface segregation principle<\/li>\n<li>Dependency inversion principle<\/li>\n<\/ul>\n<p>Obviously, each one of those could warrant its own blog post and Robert Martin himself has written and spoken about them extensively.  Uncle Bob did bring up a classic problem on Hanselminutes, though, that I wanted to take some time to talk about.<\/p>\n<p>We who design object-oriented systems have a problem.  We&#8217;ve been taught that the whole world is made of objects and that we are supposed to model our software after the real world.  However, as I&#8217;ll cover in this post, sometimes that is a mistake.<\/p>\n<p>The Liskov Substitution Principle says that &#8220;Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it&#8221; (Uncle Bob&#8217;s paraphrase).  I have found this one somewhat confusing in the past, but I think that this Rectangle-Square problem explains the problem very well.<\/p>\n<p>In math, the definition of a rectangle is &#8220;a parallelogram with four right angles&#8221;.  One Webster&#8217;s definition of a square is &#8220;a rectangle with all four sides equal&#8221;.  Right in the definition from the real world, a square is a rectangle.  &#8220;Is a&#8221; is often a key phrase in object-oriented design used to denote an inheritance relationship.<\/p>\n<p>So, let&#8217;s pretend we have the following code:<\/p>\n<pre>\r\npublic class Rectangle\r\n    {\r\n        public virtual int Width { get; set; }\r\n        public virtual int Height { get; set; }\r\n\r\n        public virtual int ComputeArea()\r\n        {\r\n            return Width * Height;\r\n        }\r\n    }\r\n\r\n    public class Square : Rectangle\r\n    {\r\n        private int _height;\r\n        public override int Width \r\n        {\r\n            get { return _height; }\r\n            set\r\n            {\r\n                _height = value;\r\n            }\r\n        }\r\n\r\n        public override int Height\r\n        {\r\n            get { return _height; }\r\n            set\r\n            {\r\n                _height = value;\r\n            }\r\n        }\r\n        \r\n        public override int ComputeArea()\r\n        {\r\n            return base.ComputeArea();\r\n        }\r\n    }\r\n<\/pre>\n<p>Okay, that works.  You can run code against it and at first blush it behaves like it should.  However, the Liskov Substitution Principle says that you should be able to have <\/p>\n<pre>Rectangle r = new Square();<\/pre>\n<p>and have no problems.  <\/p>\n<p>While you can do that and can then operate on r as if it were a rectangle, there is a problem.  A person who only knows about rectangles might do this to our r.<\/p>\n<pre>\r\nRectangle r = someMethodThatWillReturnASquareSometimes();\r\nr.Width = 10;\r\nr.Height = 15;\r\n<\/pre>\n<p>They would then get entirely unpredictable results when they computed the area or even went back in to retrieve the properties (finding one had changed without their knowledge).  A person who would want to operate in a safe way would have to eventually do the following:<\/p>\n<pre>\r\nRectangle r = someMethodThatWillReturnASquareSometimes();\r\n\r\nif (r is Square)\r\n{\r\n  \/\/ Special Square Processing\r\n}\r\nelse\r\n{\r\n  \/\/ Normal Rectangle Stuff\r\n}\r\n<\/pre>\n<p>That now pretty much defeats the purpose of using base classes and interfaces.  If you have to know about derived classes and their implementation, you&#8217;ve lost the battle.  I think that this is a great reminder to model objects logically how they affect the program, not how they reflect &#8220;real life&#8221;.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was listening to Hanselminutes a few weeks back and Scott Hanselman had Uncle Bob Martin on to talk about the SOLID principles of object-oriented design. SOLID stands for Single responsibility principle Open closed principle &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,30,39],"tags":[40,89,104],"class_list":["post-93","post","type-post","status-publish","format-standard","hentry","category-code-tips","category-podcasts","category-solid-principles","tag-add-new-tag","tag-code-tips","tag-solid-principles"],"_links":{"self":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/93","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/comments?post=93"}],"version-history":[{"count":0,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/93\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/media?parent=93"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/categories?post=93"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/tags?post=93"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}