{"id":606,"date":"2008-09-12T10:44:20","date_gmt":"2008-09-12T00:44:20","guid":{"rendered":"http:\/\/www.somethinkodd.com\/oddthinking\/?p=606"},"modified":"2008-09-12T10:44:20","modified_gmt":"2008-09-12T00:44:20","slug":"animal-fight-a-question-about-oo-mvc","status":"publish","type":"post","link":"https:\/\/www.somethinkodd.com\/oddthinking\/2008\/09\/12\/animal-fight-a-question-about-oo-mvc\/","title":{"rendered":"Animal Fight: A Question about OO &#038; MVC"},"content":{"rendered":"<h4>Introduction<\/h4>\n<p>I have a Object-Orientation question, related to the Model-View-Controller (MVC) pattern. I suspect it will have a simple &#8220;here is the idiom everyone uses for this situation&#8221; type answer, but I haven&#8217;t found it. Here&#8217;s a fictional piece of software that demonstrates my problem.<\/p>\n<h4>Background<\/h4>\n<p>Suppose I am writing a program to solve, once and for all, all those school-boy questions about &#8220;Who would win a fight between a giraffe and a kangaroo?&#8221;<\/p>\n<p>I am writing it in Python, which gives a fair bit (too much?) of flexibility in its Object Model, but I am happy to hear how the problem is solved in other (more strict?) languages.<\/p>\n<p>I am using a nice Model-View-Controller (MVC) pattern. <\/p>\n<p>My model includes a database of animals. It has a nice class hierarchy &#8211; everything inherits from the Animal class.<\/p>\n<p>In version 1, my view includes a visual display of photographs of each of the animals. In version 2, I hope to add a separate view which contains cartoon representations of the losing animals&#8217; carcass (with markings highlighting where the animal was injured) and another view which plays appropriate animal noises.<\/p>\n<p>So that means (a) each animal class may have a corresponding view class that knows how to display it, and (b) each animal class may have <em>more than one<\/em> corresponding view class, depending on the purpose of the view.<\/p>\n<p>So far, so good. I think I am describing an ordinary use of the MVC.<\/p>\n<h4>The Problem<\/h4>\n<p>Now, I have decided to display the first 20 animals on the screen, so I pass a collection of animals to the code responsible for creating the view instances.<\/p>\n<p>Here&#8217;s the dilemma. That code knows only that each instance it is some sort of animal. How can it create the correct corresponding view?<\/p>\n<h4>Solutions?<\/h4>\n<p>I have a number of potential solutions.<\/p>\n<h5>Model knows about the Views<\/h5>\n<p>Each animal class could contain a factory for the view class. For example, I could ask the Zebra instance to create a ZebraPhotoView for me.<\/p>\n<p>This is an ugly reversal of the dependencies. I don&#8217;t mind the model being aware that there exist view classes (e.g. that might subscribe to changes) but I don&#8217;t like the idea that every time a new view is added, all of the model objects need to change.<\/p>\n<h5>Switch Statement<\/h5>\n<p>Each animal class could contain a &#8220;id&#8221; method, that simply returns a static value. Some separate factory code could ask the object for its id, and then contain a giant switch statement that creates a corresponding view depending on the value of that id.<\/p>\n<p>Every time I see a switch statement, I think &#8220;Why didn&#8217;t the object model successfully hide this in some good clean polymorphism?&#8221;<\/p>\n<p>Note also that the switch statement, in this case, is very fragile to changes in the model class hierarchy.<\/p>\n<h5>Reflection<\/h5>\n<p>Python (and several other modern languages) offer access to meta-data about the class. In particular, Python offers the ability to check if a variable is an instance of a specified class.<\/p>\n<p>I could hard-code a static list of animal class, view class pairs &#8211; e.g. <code>[(Aardvark, AardvarkView), (Aardwolf, AardwolfView), <\/code>&#8230;]<\/p>\n<p>Then for each object, iterate down the list, checking if it is an instance of that class, and, if so, create an instance of the corresponding view.<\/p>\n<p>Iterate through a list looking for a match? Sounds inefficient. Yes, a dictionary would be faster if there were many different animal types, but I would lose one of the benefits: you can still take advantage of the inheritance hierarchy this way. For example, one of the entries could be <code>(Bird, BirdView)<\/code>, which could display a generic picture for all the birds that I don&#8217;t have photographs for. I could make the list a little less fragile to additional animals being added.<\/p>\n<p>So, this has a very slight improvement in &#8220;Object-Orientedness&#8221; over the switch statement, but it still requires careful maintenance to make sure the hard-coded list matches the rest of the code.<\/p>\n<p>Also, while I appreciate the utility of features such as <code>isinstance<\/code> for debuggers, instrumentors, object browsers and other &#8220;meta-programs&#8221;, using reflection (e.g. <code>isinstance()<\/code>) in my regular code adds a rather pungent code smell to me.<\/p>\n<div class=\"aside\">This is what I went with, in real life, on a non-animal related problem. It is workable, but not pretty.<\/div>\n<h5>Registration<\/h5>\n<p>Registration has the right feel to me, but I can&#8217;t quite get the mechanics.<\/p>\n<p>The idea is that the ZebraView <em>class<\/em>, when it is first &#8220;elaborated&#8221; (to use an Ada term &#8211; this is after start up, but prior to the first instance being created), could call a <em>class<\/em> method on the Zebra class and say &#8220;Hey, if anyone comes around here asking for a &#8220;photograph&#8221; of you, send them to me.&#8221;<\/p>\n<p>The Zebra class would have to know that view classes exist, to be able to store references to them in a dictionary, and to be able to return a reference to one when asked, but there would be no hard-coded knowledge of what they are, or even what &#8220;photograph&#8221; means, beyond being a cookie.<\/p>\n<p>The trouble here is I am looking for inheritance behaviour on class (static) methods, and it doesn&#8217;t work that way. I can&#8217;t write a <code>registerView<\/code> static method on the Animal class, and call it on the Zebra class, let alone have it access the Zebra class&#8217;s static data member representing only the views registered on the Zebra class. <\/p>\n<div class=\"aside\">I am aware that above paragraph isn&#8217;t a model of clarity. If you start to think about how you would write such registration functionality, you should get stuck very quickly. If you don&#8217;t, please tell me.<\/div>\n<p>Actually, with Python&#8217;s ability to define lambda function, decorators and adding functions to classes at runtime (Hell, it even supports <a href=\"http:\/\/www.somethinkodd.com\/oddthinking\/2007\/07\/22\/python-3000-exposes-dos-vulnerability-in-oo-brain\/\">dynamically specified base classes<\/a>!) it might be possible to tack such functionality on, but before I massively over-engineer what should be such a common problem, I thought I would ask the lazyweb first.<\/p>\n<p>So, can anyone with more MVC experience, please explain the idiom I am missing?<\/p>\n<p>Thanks; one of the downsides of no longer working with dozens of expert developers is that I haven&#8217;t anywhere else to bounce the &#8220;Surely someone must have been here before&#8221; technical questions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have a Object-Orientation question, related to the Model-View-Controller (MVC) pattern. I suspect it will have a simple &#8220;here is the idiom everyone uses for this situation&#8221; type answer, but I haven&#8217;t found it. Here&#8217;s a fictional piece of software that demonstrates my problem.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_s2mail":"","footnotes":""},"categories":[34],"tags":[302,301,81,232],"class_list":["post-606","post","type-post","status-publish","format-standard","hentry","category-software-development","tag-mvc","tag-oo","tag-python","tag-software-architecture"],"_links":{"self":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts\/606","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/comments?post=606"}],"version-history":[{"count":2,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts\/606\/revisions"}],"predecessor-version":[{"id":608,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts\/606\/revisions\/608"}],"wp:attachment":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/media?parent=606"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/categories?post=606"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/tags?post=606"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}