{"id":270,"date":"2009-11-04T12:59:42","date_gmt":"2009-11-04T17:59:42","guid":{"rendered":"http:\/\/thaylin.info\/blog\/?p=270"},"modified":"2009-11-11T09:32:45","modified_gmt":"2009-11-11T14:32:45","slug":"mvc-model-view-controller-introduction-simplified","status":"publish","type":"post","link":"https:\/\/www.thaylin.com\/blog\/2009\/11\/04\/mvc-model-view-controller-introduction-simplified\/","title":{"rendered":"MVC (Model-View-Controller) introduction simplified"},"content":{"rendered":"<p>It recently came to my attention that while working alone I have lost a bit of the ability to explain programming patterns. It&#8217;s not that I&#8217;ve forgotten about them, as I use variations of them in everyday work, but I&#8217;ve just lost touch with the ability to easily explain the workings of them.<\/p>\n<p>So what better way to refresh myself than to publish some tutorials on them!<\/p>\n<p>Looking through the web I&#8217;ve noticed there&#8217;s not to many just simplified and easy to understand explanations of MVC, how it really works, and why would one even want to use that as opposed to just coding willy nilly.<\/p>\n<p>I&#8217;ll spare you the history of MVC and just send you to the wiki page instead to read for yourself if you want : <a href=\"http:\/\/en.wikipedia.org\/wiki\/Model\u2013view\u2013controller\" target=\"_blank\">MVC Wiki<\/a><\/p>\n<p>Basically it works like this:<br \/>\n<!--more--><br \/>\n<strong>Model <\/strong>&#8211; Holds the data and business logic. This item in the triage is what is considered &#8220;<strong>loosely coupled<\/strong>&#8220;, meaning that it knows nothing about the controller or the view. It just sits there doing it&#8217;s thing and when something is changed it let&#8217;s anyone that may be listening know that something has been changed. In actionscript you would extend the <a href=\"http:\/\/livedocs.adobe.com\/flash\/9.0\/ActionScriptLangRefV3\/index.html?flash\/events\/EventDispatcher.html&amp;flash\/events\/class-list.html\" target=\"_blank\">EventDispatcher<\/a> class. This way it has the ability to dispatch events when updated. It would look something like the code below.<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">package info.thaylin.model\r\n{\r\n\timport flash.events.Event;\r\n\timport flash.events.EventDispatcher;\r\n\t\/**\r\n\t *\r\n\t * @author Thaylin Burns\r\n\t * Stores data and when changed, dispatches events\r\n\t *\/\r\n\tpublic class Model extends EventDispatcher\r\n\t{\r\n\t\tpublic static const SOME_DATA_CHANGED:String = 'someDataChanged'\r\n\t\tprivate var _someData:String = '';\t\r\n\r\n\t\tpublic function Model()\r\n\t\t{\r\n\t\t}\r\n\t\tpublic function set someData(value:String):void\r\n\t\t{\r\n\t\t\t_someData = value;\r\n\t\t\tdispatchEvent( new Event( SOME_DATA_CHANGED ) );\r\n\t\t}\r\n\t\tpublic function get someData():String\r\n\t\t{\r\n\t\t\treturn _someData;\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>The class above is a very simple Model that just stores a variable &#8220;_someData&#8221; and has a setter to alert anything listening that the data has changed. There may be other things that need to be done in this level like string manipulation or any other business logic that could occur. All of that should be generally stored in this class.<\/p>\n<p><strong>View<\/strong> &#8211; The view is just basically that, the visual part of something. The Graphical User Interface by which a user can interact with your application. This could be buttons, textfields, or various other things. It just contains these elements and no real functionality. That is left to the controller which it is &#8220;<strong>tightly coupled<\/strong>&#8221; to. Below is an example of what you may have as a view to maybe interact with our model from above.<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">package info.thaylin.view\r\n{\r\n\timport flash.display.Sprite;\r\n\timport flash.events.MouseEvent;\r\n\timport flash.text.TextField;\r\n\timport flash.text.TextFieldType;\r\n\r\n\timport info.thaylin.controller.Controller;\r\n\timport info.thaylin.model.Model;\r\n\t\/**\r\n\t *\r\n\t * @author thaybur\r\n\t * Contains the visual elements the user interacts with. There generally shouldn't\r\n\t * be any functionality that resides within this part of our triage.\r\n\t *\r\n\t *\/\r\n\tpublic class View extends Sprite\r\n\t{\r\n\t\tpublic var nameInput:TextField = new TextField();\r\n\t\tpublic var addressInput:TextField = new TextField();\r\n\t\tpublic var textContainer:TextField = new TextField();\r\n\t\tpublic var submitButton:Sprite = new Sprite();\r\n\r\n\t\tprivate var model:Model;\r\n\t\tprivate var controller:Controller;\r\n\r\n\t\tpublic function View(model:Model)\r\n\t\t{\r\n\t\t\tthis.model = model;\r\n\t\t\tcontroller = new Controller(this, model);\r\n\t\t\tinit();\r\n\t\t}\r\n\t\tprivate function init():void\r\n\t\t{\r\n\t\t\tnameInput.type = TextFieldType.INPUT;\r\n\t\t\tnameInput.background = nameInput.border = true;\r\n\t\t\tnameInput.width = 200;\r\n\t\t\tnameInput.height = 20;\r\n\t\t\taddChild(nameInput)\r\n\t\t\t\r\n\t\t\taddressInput.type = TextFieldType.INPUT;\r\n\t\t\taddressInput.background = addressInput.border = true;\r\n\t\t\taddressInput.width = 200;\r\n\t\t\taddressInput.height = 20;\r\n\t\t\taddressInput.y = 30;\r\n\t\t\taddChild(addressInput);\r\n\t\t\t\r\n\t\t\tsubmitButton.graphics.beginFill(0xCCCCCC);\r\n\t\t\tsubmitButton.graphics.drawRect(0,0,100, 20);\r\n\t\t\tsubmitButton.graphics.endFill();\r\n\t\t\tsubmitButton.addEventListener(MouseEvent.CLICK, submitButton_clickHandler);\r\n\t\t\tsubmitButton.buttonMode = true;\r\n\t\t\tsubmitButton.y = 60\r\n\t\t\taddChild(submitButton)\r\n\t\t\t\r\n\t\t\ttextContainer.type = TextFieldType.INPUT;\r\n\t\t\ttextContainer.background = true;\r\n\t\t\ttextContainer.selectable = false;\r\n\t\t\ttextContainer.width = 200;\r\n\t\t\ttextContainer.height = 100;\r\n\t\t\ttextContainer.y = 90;\r\n\t\t\taddChild(textContainer)\r\n\t\t}\r\n\t\tprivate function submitButton_clickHandler(event:MouseEvent):void\r\n\t\t{\r\n\t\t\tdispatchEvent(new Event('submitButtonClick'))\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>You&#8217;ll notice here that we&#8217;re passing a reference of the model to the constructor of our View class. This is then passed to the controller along with a reference of our view as &#8220;this&#8221;. So the model is created in our main class along with our view. We then pass the model to the view and if there&#8217;s any default values within the model you might set them at this point in your view. But basically, you see, this view contains no functional methods. We do, however, set a callback \u00a0for a mouse click event on line 51. That tells our view to dispatch an event of &#8220;submitButtonClick&#8221; which our controller will be listening for.<\/p>\n<p><strong>Controller <\/strong>&#8211; The controller contains the methods in which you will change your view or model. It handles any real functionality, as in the mouse click event set in our view. Here is our controller.<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">package info.thaylin.controller\r\n{\r\n\timport flash.events.Event;\r\n\timport flash.events.MouseEvent;\r\n\r\n\timport info.thaylin.model.Model;\r\n\timport info.thaylin.view.View;\r\n\r\n\tpublic class Controller\r\n\t{\r\n\t\tprivate var model:Model;\r\n\t\tprivate var view:View;\r\n\t\tpublic function Controller(view:View, model:Model)\r\n\t\t{\r\n\t\t\tthis.view = view;\r\n\t\t\tview.addEventListener('submitButtonClick', submitButton_clickHandler)\r\n\t\t\tthis.model = model;\r\n\t\t\tthis.model.addEventListener(Model.SOME_DATA_CHANGED, model_changeHandler);\r\n\t\t}\r\n\t\tpublic function submitButton_clickHandler(event:MouseEvent):void\r\n\t\t{\r\n\t\t\tif(view.addressInput.text &amp;&amp; view.nameInput.text)\r\n\t\t\t\tthis.model.someData = view.nameInput.text + '\\n' + view.addressInput.text\r\n\t\t}\r\n\t\tprivate function model_changeHandler(event:Event):void\r\n\t\t{\r\n\t\t\tview.nameInput.text = view.addressInput.text = ''\r\n\t\t\tview.textContainer.text = this.model.someData;\r\n\t\t}\r\n\r\n\t}\r\n}<\/pre>\n<p>So here you can see we&#8217;ve got our controller that gets passed the reference to the view that it&#8217;s tightly coupled with and the model. We add an event listener to the model to inform us of when any change has happened and we perform our view changes in that method (model_changeHandler). For instance here we first have a handler for the &#8220;submitButtonClick&#8221; that is dispatched from the view. This checks if our view&#8217;s addressInput.text and nameInput.text values contain something. If so, we set our model&#8217;s data to the name text and address text on a separate line.<\/p>\n<p>After the change has been made to the model, it then fires off our &#8220;SOME_DATA_CHANGED&#8221; event which we then handle in the mode_changeHandler method. In this method we reset our input textfields and set the textContainer text to equal the someData variable in the model.<\/p>\n<p><strong>Why?<\/strong><\/p>\n<p>So why would we go through all of this shenanigans you say? Just to fill a textbox? Well, no. Generally this is to be used for a bit more complex structures. But just to kinda show you how this could be handy once you&#8217;ve set all this up. Let&#8217;s implement this view in our main class.<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">package {\r\n\timport flash.display.Sprite;\r\n\timport flash.display.StageAlign;\r\n\timport flash.display.StageScaleMode;\r\n\r\n\timport info.thaylin.model.Model;\r\n\timport info.thaylin.view.View;\r\n\r\n\tpublic class main extends Sprite\r\n\t{\r\n\t\tpublic function main()\r\n\t\t{\r\n\t\t\tstage.align = StageAlign.TOP_LEFT;\r\n\t\t\tstage.scaleMode = StageScaleMode.NO_SCALE;\r\n\r\n\t\t\tvar model:Model = new Model();\r\n\t\t\tvar view:View = new View(model);\r\n\t\t\taddChild(view);\r\n\t\t\tvar view2:View = new View(model);\r\n\t\t\tview2.x = 300;\r\n\t\t\taddChild(view2)\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>So here we&#8217;ve implement 2 of our views and passed the same model. Run this and you&#8217;ll see two terrible looking little components. Enter text into the left side&#8217;s textboxes and hit the grey square we&#8217;re calling a button. You&#8217;ll notice that both instances&#8217; textContainers update with the same data. Entering text in the one on the right does the same thing.<\/p>\n<p>You may be starting to see how this could be beneficial. Maybe we have a slew of items that could all update a single data source. By loosely coupling your items like this it&#8217;s made a lot easier. Maybe you have a View with a single textField that displays the data of either of those views we&#8217;ve made, or maybe it even adds the text on a new line.<\/p>\n<p>I hope I&#8217;ve at least helped someone a little bit in the understanding of the MVC pattern and how it could be beneficial by using it when needed.<\/p>\n<p>I&#8217;ll be doing more of these with the various patterns, trying to make them as simplified as possible. If you can think of anything you&#8217;d like to see or if there&#8217;s anything you just aren&#8217;t quite getting send me a comment and I&#8217;ll try and accommodate.<\/p>\n<p>\ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It recently came to my attention that while working alone I have lost a bit of the ability to explain programming patterns. It&#8217;s not that I&#8217;ve forgotten about them, as I use variations of them in everyday work, but I&#8217;ve just lost touch with the ability to easily explain the workings of them. So what [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11,25],"tags":[32,16,15,23,31,24],"_links":{"self":[{"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/posts\/270"}],"collection":[{"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/comments?post=270"}],"version-history":[{"count":15,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/posts\/270\/revisions"}],"predecessor-version":[{"id":300,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/posts\/270\/revisions\/300"}],"wp:attachment":[{"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/media?parent=270"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/categories?post=270"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/tags?post=270"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}