http://peter.michaux.ca/peter.michaux.ca2018-12-19T19:38:21-08:00http://peter.michaux.ca/articles/iOS-AppDelegate-and-programmatic-views-with-swiftiOS AppDelegate and Programmatic Views with Swift2018-12-19T19:38:21Z<p>The negative impact of Xcode storyboards on the development of iOS apps is well documented across the Web. Git merge nightmares usually tops the list of problems for programmers working in teams and this one issue is a deal breaker. My primary gripe with storyboards are they make the good practice of initializer dependency injection impossible resulting in many optionally typed properties for dependencies injected after object initialization.</p>
<p>There are plenty of <a href="https://medium.com/@hooliooo/yet-another-ios-post-about-creating-views-programmatically-9249a7ab1e93" target="_blank">written</a> and <a href="https://youtu.be/1hCwOIgjLBA" target="_blank">video</a> tutorials available online showing how to bootstrap an iOS app without using storyboards. Most of the examples have <code>AppDelegate</code> code that looks like the following.</p>
<pre><code>import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = FirstController()
window?.makeKeyAndVisible()
return true
}
}</code></pre>
<p>The code above works just fine. As an exercise, how can it be improved? After a bit of fiddling, I came up with the following.</p>
<pre><code>import UIKit
@UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate {
private let win = UIWindow(frame: UIScreen.main.bounds)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
win.rootViewController = FirstController()
win.makeKeyAndVisible()
return true
}
}</code></pre>
<p>The property <code>window</code> in the first example is an optional part of the <code>UIApplicationDelegate</code> protocol and exists specifically for working with storyboards. It says so in the documentation. When programming without storyboards, it is still possible to use a property called <code>window</code> to retain the reference to the <code>UIWindow</code> object and avoid undesired garbage collection. Unfortunately, the protocol requires that the <code>window</code> property be the <code>UIWindow?</code> optional type. Whenever optional types can be avoided, it is definitely best to avoid them. In this case, we must choose a different variable name to avoid a conflict with the <code>UIApplicationDelegate</code> protocol. I’ve chosen <code>win</code> as the name and most importantly the property is not of optional type.</p>
<p>The <code>win</code> property is now immutable thanks to the use of <code>let</code>. Immutable properties definitely beat mutable properties.</p>
<p>The <code>win</code> property is now <code>private</code>. Private properties are definitely better than public properties.</p>
<p>Because the <code>win</code> property is the non-optional type <code>UIWindow</code>, there is no need to check for <code>nil</code> when setting the root view controller and when making the window key and visible. Every time a <code>?</code> or <code>!</code> can be removed from Swift code, it is an improvement.</p>
<p>The <code>AppDelegate</code> class will not be extended in our app. Marking the class as <code>final</code> emphasizes this. In Kotlin, <code>final</code> is the default if a class is not otherwise marked. It seems Kotlin was right in choosing <code>final</code> as the default.</p>
<p>In my own app, I’d actually go a few more steps and write the following with all types, <code>self</code>, and semicolons included. I have found that including these details makes it much easier to work with the code over time. It is easier to read the code and the compiler can catch more issues for me as I add features and refactor.</p>
<pre><code>import UIKit;
@UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate {
private let win: UIWindow = UIWindow(frame: UIScreen.main.bounds);
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.win.rootViewController = FirstController();
self.win.makeKeyAndVisible();
return true;
}
}</code></pre>
http://peter.michaux.ca/articles/use-the-correct-http-method-in-your-xhrsUse the Correct HTTP Method in Your XHRs2016-02-22T18:00:00Z<p>The <a href="https://tools.ietf.org/html/rfc7231#section-4" target="_blank">HTTP/1.1 standard</a> includes the following HTTP methods.</p>
<ul>
<li><code>GET</code></li>
<li><code>HEAD</code></li>
<li><code>POST</code></li>
<li><code>PUT</code></li>
<li><code>DELETE</code></li>
<li><code>CONNECT</code></li>
<li><code>OPTIONS</code></li>
<li><code>TRACE</code></li>
</ul>
<p>HTML <code>form</code> elements only allow the <code>GET</code> and <code>POST</code> methods. This is still true even in <a href="https://www.w3.org/TR/html5/forms.html#attr-fs-method" target="_blank">the HTML5 specification</a>. The HTML5 specification authors temporarily added other methods to the HTML5 specification but later removed them.</p>
<p>Long ago, regular browser <code>GET</code> requests to load pages and HTML form <code>GET</code> and <code>POST</code> requests were the only ways web browsers were communicating with web servers. As a result, servers were implemented to support only the <code>GET</code> and <code>POST</code> methods. Send a request using a different HTTP method and you’d be taking your chances.</p>
<p>The Ruby on Rails community hopped on the REST train sometime around 2007 and their evangelism forever changed for the better the way web developers design their server APIs. Interest was high for using the <code>PUT</code> and <code>DELETE</code> methods, in particular, so that the four basic CRUD operations could be performed.</p>
<ul>
<li>Create = <code>POST</code></li>
<li>Read = <code>GET</code></li>
<li>Update = <code>PUT</code></li>
<li>Delete = <code>DELETE</code></li>
</ul>
<p>It wasn’t so easy to just starting to use the desired HTTP methods.</p>
<p>Progressive enhancements was a theme of the day. Web pages needed to work with JavaScript disabled. If JavaScript was disabled, regular HTML forms needed to work and that meant being limited to only <code>GET</code> and <code>POST</code> methods. If your server-side delete API was built to expect the <code>DELETE</code> method, then there was no way for a JavaScript-disabled browser to send the appropriate delete request. So the server needed to also be ready for a <code>POST</code> request. We ended up “tunnelling” the HTTP method through a <code>POST</code> request using a hidden parameter <code>_method</code> which, if present, the server would use instead of the actual HTTP method of the request. In an address book app, a form to delete a contact might look like the following.</p>
<pre><code><form action="/contact/537" method="POST">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="Delete">
</form></code></pre>
<p>Which would generate the HTTP request.</p>
<pre><code>POST /contact/537 HTTP/1.1
Host: contact.me
_method=DELETE</code></pre>
<p>The above request uses <code>POST</code> which is not at all what the <code>POST</code> method is intended to signify. <code>POST</code> is intended to signify that a new resource is to be <em>created</em> on the server. The <em>opposite</em> of what the request actually does.</p>
<p>If you are building a Web 1.0 site today, you still need to resort to the above hacking.</p>
<p>If you are building a JavaScript-rich, browser-based app then read on.</p>
<p>When JavaScript is enabled, we are able to use an <code>XMLHttpRequest</code> to send requests to the server. In the case of the delete example above, we can use the <code>DELETE</code> method directly in our request.</p>
<pre><code>var xhr = new XMLHttpRequest();
xhr.open('DELETE', '/contact/537', true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
// do something successful
} else {
// handle errors
}
}
};
xhr.send();</code></pre>
<p>Which would generate the HTTP request.</p>
<pre><code>DELETE /contact/537 HTTP/1.1
Host: contact.me</code></pre>
<p>This is the HTTP request we want to send but, as is often the case, the web of 2007 beat our good intentions painfully down into the ground. Sadly the web servers were not implemented to handle the <code>DELETE</code> method. A developer could update his own web server but had no control over the proxy web servers between the web browser and his own web server. Back to the tunnelling hack...</p>
<pre><code>var xhr = new XMLHttpRequest();
xhr.open('POST', '/contact/537', true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
// do something successful
} else {
// handle errors
}
}
};
xhr.send("_method=DELETE");</code></pre>
<p>This results in the same undesirable HTTP request as the HTML form submission example above.</p>
<pre><code>POST /contact/537 HTTP/1.1
Host: contact.me
_method=DELETE</code></pre>
<p>It usually takes a long time for the web to upgrade. It especially takes a long time for users to upgrade their web browsers. It was pleasantly surprising how quickly web servers were upgraded to support more HTTP methods.</p>
<p>Since 2012 or even earlier, I’ve been using the <code>PUT</code> and <code>DELETE</code> method directly with <code>XMLHttpRequest</code>. In 2014, we started using the newer <code>PATCH</code> method for partially updating a resource on the server. As of 2016, with tens of thousands of users and millions of server requests, we have never had even a single bug report that could be attributed to our direct use of these HTTP methods with <code>XMLHttpRequest</code>.</p>
<p>If you have been using the HTTP method tunnelling hack with <code>XMLHttpRequest</code> patiently waiting for the day the web was ready, as far as I know, you can stop the tunnelling without any worry. The web of 2016 is plenty ready and capable.</p>
<p>If you have any experience contradicting this recommendation, please let me know.</p>
http://peter.michaux.ca/articles/use-the-accept-header-in-your-xhrsUse the Accept Header in Your XHRs2016-02-22T05:00:00Z<p>An example of a common scenario: You are building a browser-based app for a grocery store. The app shows a list of all the valid coupons this week. Your browser-based app needs to load all of the store’s coupons by requesting the coupon data from the server. The server is capable of returning the coupons in JSON or XML format. Your browser app only knows how to deal with a JSON response and you need to indicate that in your request. You consider several options to indicate the desired response format.</p>
<p>Your first option, and probably the most popular option in use today, is to use a format extension in the request URL.</p>
<pre><code>var xhr = new XMLHttpRequest();
xhr.open('GET', '/coupons.json', true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
// do something with data
} else {
//handle errors
}
}
};
xhr.send();</code></pre>
<p>The resulting HTTP request</p>
<pre><code>GET /coupons.json HTTP/1.1
Accept: */*
Host: api.nestorsmarket.com</code></pre>
<p>(Note that the above <code>Accept</code> header says the browser can handle any response format. That’s a lie as you know your app can only handle a JSON response.)</p>
<p>Your second option, which is very similar to the first option, is to use a format parameter in the query string of the request URL.</p>
<pre><code>var xhr = new XMLHttpRequest();
xhr.open('GET', '/coupons?format=json', true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
// do something with data
} else {
//handle errors
}
}
};
xhr.send();</code></pre>
<p>The resulting HTTP request</p>
<pre><code>GET /coupons?format=json HTTP/1.1
Accept: */*
Host: api.nestorsmarket.com</code></pre>
<p>(More lying.)</p>
<p>Your third option, and probably the least commonly used option, is to use the <code>Accept</code> header.</p>
<pre><code>var xhr = new XMLHttpRequest();
xhr.open('GET', '/coupons', true);
xhr.setRequestHeader('Accept', 'application/json');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
// do something with data
} else {
//handle errors
}
}
};
xhr.send();</code></pre>
<p>The resulting HTTP request</p>
<pre><code>GET /coupons HTTP/1.1
Accept: application/json
Host: api.nestorsmarket.com</code></pre>
<p>The first and second options are ugly hacks. These hacks were only ever used because, in the past, the third option didn’t work or server-side programmers did not know how to deal with it. You may be asking, “what is so terribly wrong with the first and second options?”</p>
<h2>Intermediary Cache</h2>
<p>Imagine you have two types of client apps that want to access the same data. The first client type is a browser-based app that can only handle JSON responses. The second client type is a native iOS app that can handle JSON or XML responses. Also imagine there is an intermediary caching server somewhere between the clients and your web server. A browser-based client makes an XHR request for the JSON format using the format extension technique.</p>
<pre><code>GET /coupons.json HTTP/1.1
Accept: */*
Host: api.nestorsmarket.com</code></pre>
<p>The cache on the intermediary server is empty so the request is passed on to the web server. The web server responds with</p>
<pre><code>HTTP/1.1 200 OK
Cache-Control: max-age=86400
Content-Type: application/json
[
{
"upc": 827454737,
"description": "20% OFF Rib Eye Steak!"
},
{
"upc": 546373635,
"description": "Save $3.18 on Rocket Fuel french roast coffee!"
}
]</code></pre>
<p>The caching server sees from the <code>Cache-Control</code> header that this response is cacheable for one more day so it caches it to speed up responses for the remainder of the day. It passes the response back to the client.</p>
<p>Soon after, the iOS app makes a request. It uses the <code>Accept</code> header technique indicating it can handle both data formats.</p>
<pre><code>GET /coupons HTTP/1.1
Accept: application/json, application/xml
Host: api.nestorsmarket.com</code></pre>
<p>When the request arrives to the caching server, the server checks to see if it has a response cached for <code>/coupons</code>. There is nothing matching in the cache. What a pity. There is a match for <code>/coupons.json</code> but that does not match <code>/coupons</code>. The caching server has no idea how to interpret these strings. It checks for exact matches only.</p>
<p>Because the caching server cannot make a match, the caching server must again pass the request to the web server. The web server must again generate the response. The caching server will again cache the response. This wastes end user time, bandwidth, CPU time on the web server, and storage space on the caching server.</p>
<p>Suppose that instead, the browser-based app had originally made this request indicating only one acceptable response format.</p>
<pre><code>GET /coupons HTTP/1.1
Accept: application/json
Host: api.nestorsmarket.com</code></pre>
<p>Then when the iOS app made its request, the caching server would see it has a match in the cache and could respond quickly to the client without bothering the web server.</p>
<p>The intermediary cache is only one compelling example demonstrating that if we use HTTP as it was designed, many things are improved.</p>
<h2>Opera Bug</h2>
<p>My exploration into this topic started way back in 2008 with the discovery described in the email to the authors of the XMLHttpResponse specification.</p>
<pre><code>From: "Peter Michaux" <petermichaux@gmail.com>
To: public-webapi@w3.org
Date: Wed, 16 Apr 2008 16:49:44 -0700
Subject: XHR setting headers
The XMLHttpRequest spec says "The setRequestHeader() method appends a
value if the HTTP header given as argument is already part of the list
of request headers."
This is fine but what is a problem is whether or not a new
XHMHttpRequest object has any default headers. I was trying to use the
Accept header a few days ago and I wanted to have only
Accept: application/json
but Opera has a default header
Accept: text/html, text/xhtml, etc
so my application/json was appended to the front of that list which
makes my Accept header useless as part of the client-server
communication. The server thinks that the client knows what to do with
text/html. My JavaScript certainly does NOT know what to do with
text/html. My JavaScript only knows how to handle application/json.
I think all XMLHttpRequest headers should be specified as blank when
the object is created. Then the JavaScript can add any headers it
needs to add. If, when the call to send() occurs, some essential
header(s) is missing the XHMLHttpRequest object should add these
automatically but only according to specified behavior.
Peter</code></pre>
<p>To make the problem described in my email above more clear, in Opera 9.27, I would do this.</p>
<pre><code>var xhr = new XMLHttpRequest();
xhr.open('GET', '/coupons', true);
xhr.setRequestHeader('Accept', 'application/json');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
// do something with data
} else {
//handle errors
}
}
};
xhr.send();</code></pre>
<p>The resulting HTTP request would be this.</p>
<pre><code>GET /coupons HTTP/1.1
Accept: application/json, text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg,
Host: api.nestorsmarket.com</code></pre>
<p>You can <a href="http://arc.opera.com/pub/opera/" target="_blank">download old versions of Opera</a> to try for yourself.</p>
<p>The final email in the thread of discussion was from the author of the XMLHttpRequest specification (who’s email address happened to end in <code>opera.com</code>.)</p>
<pre><code>From: "Anne van Kesteren" <annevk@opera.com>
To: "Julian Reschke" <xxxx.xxxx@xxx.de>
Cc: "Peter Michaux" <petermichaux@gmail.com>, public-webapi@w3.org
Date: Tue, 27 May 2008 14:14:02 +0200
Subject: Re: XHR setting headers
On Tue, 13 May 2008 09:24:42 +0200, Julian Reschke <xxxx.xxxx@xxx.de> wrote:
> Anne van Kesteren wrote:
> > On Mon, 12 May 2008 17:24:16 +0200, Julian Reschke <xxxx.xxxx@xxx.de> wrote:
> > > Well, we just heard from people complaining about XHR implementations
> > > pre-filling request headers, and thus causing clients to create broken
> > > content-type headers (because of the append functionality).
> >
> > Actually, that was specifically about Accept and it seems to be simply
> > an Opera bug per the specification.
>
> So does the specification say which headers may be prefilled by the
> implementation, and when?
It is now made clear that user agents can only control the headers that
authors can not set and can control a limited set of headers if the author
has not set them (e.g. the specification allows the author to control
caching himself, but if he does not do that the user agent can do it).</code></pre>
<p>You can read <a href="https://lists.w3.org/Archives/Public/public-webapi/2008Apr/0168.html" target="_blank">the whole email thread in the mailing list archives</a>.</p>
<p>The related parts of the XMLHttpRequest specification are in <a href="https://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method" target="_blank">The <code>setRequestHeader()</code> method</a> and <a href="https://www.w3.org/TR/XMLHttpRequest/#the-send()-method" target="_blank">The <code>send()</code> method</a> sections where the "author request headers" are discussed.</p>
<p>I was happy with the outcome. The specification was improved. Of course, at that time, it was still 2008 and the buggy versions of Opera were still out there in the wild being used. I thought, "Great! In 10 years I can start using the <code>Accept</code> header!!" Well, it is almost 8 years now and I think it is time to start.</p>
<p>The first version of Opera to ship with this bug fixed was Opera 10.50 beta 1 which was released on February 11, 2010. That is only 6 years ago but Opera has released new versions and has fallen in popularity. For one site I monitor, in the year prior to the release of Opera 10.50 beta 1, 1 out of 125 sessions was from the buggy versions of Opera. Now, only 1 out of 17241 sessions comes from the old buggy versions of Opera. Low enough for me.</p>
<p>I’m not aware of any other browser that has had this bug or any other bug preventing the proper use of the <code>Accept</code> header...and I’ve been looking. All of the following browsers worked.</p>
<table cellspacing="0" border="1" cellpadding="4" style="border-collapse:collapse;">
<thead>
<tr><th>Operating System</th><th>Browser</th></tr>
</thead>
<tbody>
<tr><td rowspan="5">Windows XP SP2</td><td>Internet Explorer 6.0.2900.2180.xpsp_sp2_rtm.040803-2158</td></tr>
<tr> <td>Internet Explorer 7.0.5720.13</td></tr>
<tr> <td>Firefox 42.0</td></tr>
<tr> <td>Chrome 48.0.2564.11 m</td></tr>
<tr> <td>Opera 10.50 Beta 1</td></tr>
<tr><td rowspan="5">Windows 7</td><td>Internet Explorer 8.0.7600.16385</td></tr>
<tr> <td>Firefox 14.0.1</td></tr>
<tr> <td>Chrome 47.0.2526.111 m</td></tr>
<tr> <td>Internet Explorer 9.0.8112.16421</td></tr>
<tr> <td>Firefox 35.0.1</td></tr>
<tr><td>Windows 10</td><td>Internet Explorer 11.63.10586.0</td></tr>
<tr><td rowspan="2">OS X 10.4.11</td><td>Safari 4.0.5 (4531.22.7)</td></tr>
<tr> <td>Firefox 3.6.28</td></tr>
<tr><td rowspan="6">OS X 10.11.3</td><td>Firefox 44.0.2</td></tr>
<tr> <td>Chrome 48.0.2564.116</td></tr>
<tr> <td>Safari 9.0.3 (11601.4.4)</td></tr>
<tr> <td>Opera 10.50 Beta 1</td></tr>
<tr> <td>Opera 11.11</td></tr>
<tr> <td>Opera 35.0.2066.68</td></tr>
<tr><td>Debian 7.4</td><td>Iceweasel 17.0.10</td></tr>
<tr><td>Ubuntu 15.10</td><td>Firefox 44.0.2</td></tr>
<tr><td>iOS 6.1.6</td><td>Safari 6.0</td></tr>
<tr><td rowspan="2">iOS 9.2.1</td><td>Safari 9.0</td></tr>
<tr> <td>Chrome 48.0.2564.87</td></tr>
<tr><td rowspan="2">Android 4.4.2</td><td>Internet 4.4.2.I747MVLUFFOB3</td></tr>
<tr> <td>Chrome 47.0.2526.83</td></tr>
<tr><td>Windows Phone 8.1</td><td>Internet Explorer Mobile 11.0</td></tr>
</tbody>
</table>
<p>Even good-old Internet Explorer 6 allowed successful control and setting of the <code>Accept</code> header in an XHR!</p>
<h2>Conclusion</h2>
<p>In the browser world, it takes a long time for old bugs to go away. I think it is now time to ditch the format hacks and take advantage of the proper use of HTTP <code>Accept</code> header.</p>
<p>Do you already use the <code>Accept</code> for your XHR requests from browser-based apps?</p>
<p>Have you tried to use <code>Accept</code> for your XHR requests from browser-based apps and had problems?</p>
<p>I’d like to know about your experiences.</p>
http://peter.michaux.ca/articles/smalltalk-mvc-translated-to-javascriptSmalltalk MVC Translated to JavaScript2015-01-03T17:01:00Z <p>The original Smalltalk MVC is an elegant way to structure an application. Unfortunately, the JavaScript community takes more inspiration from Dr. Frankenstein than from Smalltalk. The community appears to have done its best to saw off many good parts from MVC and bolt on unnecessary ugly bits to create framework monsters unsuitable for building real-world JavaScript applications.</p>
<p>Over the past several years, I've tried to understand why the JavaScript community has done this. My only surviving theory is that no one took the time to go back to the Smalltalk code to actually see how MVC was implemented there. Had they had the interest and patience to do so, rather than jumping in with their own largely unproven ideas, they would have seen a easy path to translating Smalltalk’s MVC into beautifully organized JavaScript applications.</p>
<p>I hope this article will remove the necessary historical digging to read and understand the implementation of Smalltalk MVC. Also, I hope it inspires better JavaScript frameworks and applications.</p>
<p>This article does not teach Smalltalk. You don’t need to be able to read much Smalltalk to read this article. You can make it through the article skipping the Smalltalk and reading the JavaScript translations only. If you are looking for an introduction, the first 89 pages of <a href="http://www.amazon.com/gp/product/0201113716/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201113716&linkCode=as2&tag=petermichauxc-20&linkId=W3CAO2WE3FC2FWKZ" target="_blank">Smalltalk-80: The Language and its Implementation</a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=petermichauxc-20&l=as2&o=1&a=0201113716" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> are a joy to read.</p>
<p>The Smalltalk code is taken directly from <a href="http://www.squeak.org/Downloads" target="_blank">the Squeak All-In-One image</a>. I have elided a very few lines of Smalltalk that are unrelated to the MVC aspects of the methods shown. In place of these lines you’ll see a Smalltalk comment <code>"..."</code>.
<p>A nice way to read this article is on a large screen with two browser windows both displaying this article. You can position the Smalltalk and JavaScript versions of the code side-by-side to compare lines easily.</p>
<h2>Models with Smalltalk's <code>Object</code> Class</h2>
<p>Quite high in Smalltalk’s class hierarchy is the <code>Object</code> class. Almost all classes in Smalltalk inherit from the <code>Object</code> class. Therefore almost all objects in a Smalltalk application have the instance methods defined in <code>Object</code>.<p>
<p>The observable-related methods (i.e. <code>dependents</code>, <code>addDependent:</code>, <code>removeDependent:</code>, <code>changed</code>, <code>changed:</code>, <code>changed:with:</code>) are defined in Smalltalk’s <code>Object</code>. This means almost all objects in Smalltalk can participate in the application as model objects. That is, they can be observed.</p>
<p>The observer-related methods (i.e. <code>update</code> and <code>update:with:</code>) are also defined in Smalltalk’s <code>Object</code> class. This means almost all objects in Smalltalk can participate in the application as observers. Typically this ability is exploited by an application’s view objects.</p>
<p>Having both observable-related methods and observer-methods on almost all objects in an application means that almost all objects can communicate in the very decoupled way that the observer pattern enables. This indirect style of communication can be lead to code that is frustratingly difficult to debug. “Where is the call that initiated this error?!” Good choices about which objects should use this communication mechanism are required of the application programmer. The communication between models and views is the main use of the observer pattern in an MVC application. Models observing other models is common too. Some applications might (also) have controllers observing the model but this is much less common.</p>
<p>The <code>Object</code> class has a class variable <code>DependentFields</code> that references an instance of <code>WeakIdentityKeyDictionary</code>. The class <code>WeakIdentityKeyDictionary</code> is not shown here but it is just a dictionary that maps objects to objects and has methods for adding and removing key-value pairs of the dictionary.</p>
<p>So here they are: The fundamental MVC-related parts of Smalltalk’s <code>Object</code> class taken from Squeak. (If the Smalltalk really scares you too much, you can safely skip down to the discussion below and catch up with the JavaScript translation that follows.)</p>
<pre><code>ProtoObject subclass: #Object
instanceVariableNames: ''
classVariableNames: 'DependentsFields'
poolDictionaries: ''
category: 'Kernel-Objects'</code></pre>
<h4>class methods</h4>
<h5>class initialization</h5>
<pre><code>initialize
"Object initialize"
DependentsFields ifNil:[self initializeDependentsFields].
initializeDependentsFields
"Object initialize"
DependentsFields := WeakIdentityKeyDictionary new.</code></pre>
<h4>instance methods</h4>
<h5>dependent access</h5>
<pre><code>myDependents
"Private. Answer a list of all the receiver's dependents."
^ DependentsFields at: self ifAbsent: []
myDependents: aCollectionOrNil
"Private. Set (or remove) the receiver's dependents list."
aCollectionOrNil
ifNil: [DependentsFields removeKey: self ifAbsent: []]
ifNotNil: [DependentsFields at: self put: aCollectionOrNil]
dependents
"Answer a collection of objects that are 'dependent' on the receiver;
that is, all objects that should be notified if the receiver changes."
^ self myDependents ifNil: [#()]
addDependent: anObject
"Make the given object one of the receiver's dependents."
| dependents |
dependents := self dependents.
(dependents includes: anObject) ifFalse:
[self myDependents: (dependents copyWithDependent: anObject)].
^ anObject
removeDependent: anObject
"Remove the given object as one of the receiver's dependents."
| dependents |
dependents := self dependents reject: [:each | each == anObject].
self myDependents: (dependents isEmpty ifFalse: [dependents]).
^ anObject</code></pre>
<h5>updating</h5>
<pre><code>changed
"Receiver changed in a general way; inform all the dependents by
sending each dependent an update: message."
self changed: self
changed: aParameter
"Receiver changed. The change is denoted by the argument aParameter.
Usually the argument is a Symbol that is part of the dependent's change
protocol. Inform all of the dependents."
self dependents do: [:aDependent | aDependent update: aParameter]
changed: anAspect with: anObject
"Receiver changed. The change is denoted by the argument anAspect.
Usually the argument is a Symbol that is part of the dependent's change
protocol. Inform all of the dependents. Also pass anObject for additional information."
self dependents do: [:aDependent | aDependent update: anAspect with: anObject]
update: aParameter
"Receive a change notice from an object of whom the receiver is a
dependent. The default behavior is to do nothing; a subclass might want
to change itself in some way."
^ self
update: anAspect with: anObject
"Receive a change notice from an object of whom the receiver is a
dependent. The default behavior is to call update:,
which by default does nothing; a subclass might want
to change itself in some way."
^ self update: anAspect</code></pre>
<p>It is particularly odd to me that the dependents of all instances are stored in a dictionary that is a class variable. I do not understand the motivation for this. I would have made it so that each instance has its own private array of dependents.</p>
<h3>A Simple Translation to JavaScript</h3>
<p>The code that follows is a translation of the above Smalltalk <code>Object</code> observer-pattern-related methods to plain old JavaScript. By “old JavaScript” I mean ECMAScript 3. This translation could actually be used in a real JavaScript application.</p>
<p>In Smalltalk, almost all objects have the <code>addDependent:</code>, <code>changed</code>, <code>update:</code>, etc methods because almost all classes inherit from Smalltalk’s <code>Object</code> class. In JavaScript, we could add similar properties <code>Object.prototype.addDependent</code>, <code>Object.prototype.changed</code>, <code>Object.prototype.update</code>, etc so that almost all objects in JavaScript have these methods. Unfortunately, since ECMAScript 3 did not allow us to add non-enumerable properties to an object, adding these properties to <code>Object.prototype</code> would likely break for-in loops in our applications. Instead of all those headaches, we create a new <code>Model</code> constructor function. Either prototype-based inheritance or mixins can be used to add the model functionality to any other constructor that needs it.</p>
<p>We need a dictionary object of some type assigned to <code>Model.dependentsFields</code> to store all dependents of each <code>Model</code> instance. We cannot use an empty JavaScript object as the dictionary because JavaScript objects only allow string keys. This dictionary needs object keys. We will assume the presence of an <code>IdentityKeyDictionary</code> constructor function. (Note that the name has changed slightly from Smalltalk’s <code>WeakIdentityKeyDictionary</code> because ECMAScript 3 didn’t have any kind of weak references.) Implementation of this <code>IdentityKeyDictionary</code> constructor would be relatively straight forward and use an array to store object keys and their associated object values.</p>
<pre><code>function Model() {}
Model.initialize = function () {
this.initializeDependentsFields();
};
Model.initializeDependentsFields = function () {
this.dependentsFields = new IdentityKeyDictionary();
};
Model.prototype.myDependents = function (aCollectionOrNil) {
if (arguments.length < 1) {
return Model.dependentsFields.atIfAbsent(self, function () {});
} else {
if (aCollectionOrNil) {
Model.dependentsFields.atPut(self, aCollectionOrNil);
} else {
Model.dependentsFields.removeKeyIfAbsent(self, function () {});
}
}
};
Model.prototype.dependents = function () {
var dependents = this.myDependents();
return dependents ? dependents : [];
};
Model.prototype.addDependent = function (anObject) {
var dependents;
dependents = this.dependents();
if (!dependents.includes(anObject)) {
this.myDependents(dependents.copyWithDependent(anObject));
}
return anObject;
};
Model.prototype.removeDependent = function (anObject) {
var dependents;
dependents = this.dependents().reject(function (each) {return each === anObject;});
this.myDependents(dependents.isEmpty() ? null : dependents)
};
Model.prototype.changed = function (aParameter) {
if (arguments.length < 1) {
aParameter = this;
}
var dependents = this.dependents();
for (var i = 0, ilen = dependents.length; i < ilen; i++) {
dependents[i].update(aParameter);
}
};
Model.prototype.changedWith = function (anAspect, anObject) {
var dependents = this.dependents();
for (var i = 0, ilen = dependents.length; i < ilen; i++) {
dependents[i].updateWith(anAspect, anObject);
}
};
Model.prototype.update = function (aParameter) {
return this;
};
Model.prototype.updateWith = function (anAspect, anObject) {
this.update(anAspect);
};</code></pre>
<p>Note that somewhere in the program before using the <code>Model</code> class, there must be a call <code>Model.initialize();</code>. Given this awkward requirement, we would almost surely write the JavaScript differently. The main goal of any other strategy would be to make an initialization call unnecessary.</p>
<p>First option: We could remove the definitions of the <code>Model.initialize</code> and <code>Model.initializeDependentsFields</code> functions. Then add a simple assignment that runs when the code is initially loaded and evaluated.<p>
<pre><code>Model.dependentsFields = new IdentityKeyDictionary();</pre></code>
<p>Second option: We could remove the definitions of the <code>Model.initialize</code> and <code>Model.initializeDependentsFields</code> functions. Then change <code>Model.prototype.myDependents</code> to lazily create the <code>Model.dependentsFields</code> dictionary.
<pre><code>Model.prototype.myDependents = function (aCollectionOrNil) {
if (!Model.dependentsFields) {
Model.dependentsFields = new IdentityKeyDictionary();
}
if (arguments.length < 1) {
return Model.dependentsFields.atIfAbsent(self, function () {});
} else {
if (aCollectionOrNil) {
Model.dependentsFields.atPut(self, aCollectionOrNil);
} else {
Model.dependentsFields.removeKeyIfAbsent(self, function () {});
}
}
};</code></pre>
<h2>Views with Smalltalk’s <code>View</code> Class</h2>
<p>Smalltalk’s <code>View</code> class is a meaty one because it participates in the three main design patterns of the MVC architecture. It participates in the observer pattern by observing its model. It participates in the strategy pattern by delegating decision making to its controller. It participates in the composite pattern by being a super view and having sub views.</p>
<pre><code>Object subclass: #View
instanceVariableNames: 'model controller superView subViews transformation
viewport window displayTransformation insetDisplayBox borderWidth borderColor
insideColor boundingBox'
classVariableNames: ''
poolDictionaries: ''
category: 'ST80-Framework'</code></pre>
<h4>instance methods</h4>
<h5>initialize-release</h5>
<pre><code>initialize
"Initialize the state of the receiver. Subclasses should include 'super
initialize' when redefining this message to insure proper initialization."
self resetSubViews.
"..."
release
"Remove the receiver from its model's list of dependents (if the model
exists), and release all of its subViews. It is used to break possible cycles
in the receiver and should be sent when the receiver is no longer needed.
Subclasses should include 'super release.' when redefining release."
model removeDependent: self.
model := nil.
controller release.
controller := nil.
subViews ~~ nil ifTrue: [subViews do: [:aView | aView release]].
subViews := nil.
superView := nil</code></pre>
<h5>model access</h5>
<pre><code>model
"Answer the receiver's model."
^model
model: aModel
"Set the receiver's model to aModel. The model of the receiver's controller
is also set to aModel."
self model: aModel controller: controller</code></pre>
<h5>controller access</h5>
<pre><code>controller
"If the receiver's controller is nil (the default case), answer an initialized
instance of the receiver's default controller. If the receiver does not
allow a controller, answer the symbol #NoControllerAllowed."
controller == nil ifTrue: [self controller: self defaultController].
^controller
controller: aController
"Set the receiver's controller to aController. #NoControllerAllowed can be
specified to indicate that the receiver will not have a controller. The
model of aController is set to the receiver's model."
self model: model controller: aController
defaultController
"Answer an initialized instance of the receiver's default controller.
Subclasses should redefine this message only if the default controller
instances need to be initialized in a nonstandard way."
^self defaultControllerClass new
defaultControllerClass
"Answer the class of the default controller for the receiver. Subclasses
should redefine View|defaultControllerClass if the class of the default
controller is not Controller."
^Controller
model: aModel controller: aController
"Set the receiver's model to aModel, add the receiver to aModel's list of
dependents, and set the receiver's controller to aController. Subsequent
changes to aModel (see Model|change) will result in View|update:
messages being sent to the receiver. #NoControllerAllowed for the value
of aController indicates that no default controller is available; nil for the
value of aController indicates that the default controller is to be used
when needed. If aController is neither #NoControllerAllowed nor nil, its
view is set to the receiver and its model is set to aModel."
model ~~ nil & (model ~~ aModel)
ifTrue: [model removeDependent: self].
aModel ~~ nil & (aModel ~~ model)
ifTrue: [aModel addDependent: self].
model := aModel.
aController ~~ nil
ifTrue:
[aController view: self.
aController model: aModel].
controller := aController</code></pre>
<h5>subView access</h5>
<pre><code>subViews
"Answer the receiver's collection of subViews."
^subViews
resetSubViews
"Set the list of subviews to an empty collection."
subViews := OrderedCollection new
firstSubView
"Answer the first subView in the receiver's list of subViews if it is not
empty, else nil."
subViews isEmpty
ifTrue: [^nil]
ifFalse: [^subViews first]
lastSubView
"Answer the last subView in the receiver's list of subViews if it is not
empty, else nil."
subViews isEmpty
ifTrue: [^nil]
ifFalse: [^subViews last]</code></pre>
<h5>subView inserting</h5>
<pre><code>addSubView: aView
"Remove aView from the tree of Views it is in (if any) and adds it to the
rear of the list of subViews of the receiver. Set the superView of aView
to be the receiver. It is typically used to build up a hierarchy of Views
(a structured picture). An error notification is generated if aView is the
same as the receiver or its superView, and so on."
self addSubView: aView ifCyclic: [self error: 'cycle in subView structure.']
addSubView: aView ifCyclic: exceptionBlock
"Remove aView from the tree of Views it is in (if any) and add it to the
rear of the list of subViews of the receiver. Set the superView of aView
to be the receiver. It is typically used to build up a hierarchy of Views
(a structured picture). An error notification is generated if aView is the
same as the receiver or its superView, and so on."
(self isCyclic: aView)
ifTrue: [exceptionBlock value]
ifFalse:
[aView removeFromSuperView.
subViews addLast: aView.
aView superView: self]</code></pre>
<h5>subView removing</h5>
<pre><code>removeSubView: aView
"Delete aView from the receiver's list of subViews. If the list of subViews
does not contain aView, create an error notification."
subViews remove: aView.
aView superView: nil.
"..."
removeSubViews
"Delete all the receiver's subViews."
subViews do:
[:aView |
aView superView: nil.
"..."].
self resetSubViews
<!--releaseSubView: aView
"Delete aView from the receiver's list of subViews and send it the
message 'release' (so that it can break up cycles with subViews, etc.)."
self removeSubView: aView.
aView release
releaseSubViews
"Release (see View|releaseSubView:) all subViews in the receiver's list of
subViews."
subViews do: [:aView | aView release].
self resetSubViews
-->removeFromSuperView
"Delete the receiver from its superView's collection of subViews."
superView ~= nil ifTrue: [superView removeSubView: self]</code></pre>
<h5>superView access</h5>
<pre><code>isTopView
"Answer whether the receiver is a top view, that is, if it has no
superView."
^superView == nil
superView
"Answer the superView of the receiver."
^superView
topView
"Answer the root of the tree of Views in which the receiver is a node.
The root of the tree is found by going up the superView path until
reaching a View whose superView is nil."
superView == nil
ifTrue: [^self]
ifFalse: [^superView topView]</code></pre>
<h5>private</h5>
<pre><code>superView: aView
"Set the View's superView to aView and unlock the View (see
View|unlock). It is sent by View|addSubView: in order to properly set all
the links."
superView := aView.
"..."
isCyclic: aView
"Answer true if aView is the same as this View or its superView, false
otherwise."
self == aView ifTrue: [^true].
self isTopView ifTrue: [^false].
^superView isCyclic: aView</pre></code>
<h5>updating</h5>
<pre><code>update
"Normally sent by the receiver's model in order to notify the receiver of
a change in the model's state. Subclasses implement this message to do
particular update actions. A typical action that might be required is to
redisplay the receiver."
self update: self
update: aParameter
"Normally sent by the receiver's model in order to notify the receiver of
a change in the model's state. Subclasses implement this message to do
particular update actions. A typical action that might be required is to
redisplay the receiver."
^self</code></pre>
<h3>A Simple Translation to JavaScript</h3>
<p>Let’s rewrite Smalltalk’s <code>View</code> class in JavaScript.</p>
<pre><code>function View() {}
View.prototype.initialize = function() {
this.resetSubViews();
};
View.prototype.release = function () {
this._model.removeDependent(this);
this._model = null;
this._controller.release();
this._controller = null;
if (this._subViews) {
for (var i = 0, ilen = this._subViews.length; i < ilen; i++) {
this._subViews[i].release();
}
}
this._subViews = null;
this._superView = null;
};
View.prototype.model = function (aModel) {
if (arguments.length < 1) {
return this._model;
} else {
this.modelController(aModel, this._controller);
}
};
View.prototype.controller = function (aController) {
if (arguments.length < 1) {
if (!this._controller) {
this._controller(this.defaultController());
}
return this._controller;
} else {
this.modelController(this._model, aController);
}
};
View.prototype.defaultController = function () {
return new (this.defaultControllerClass())();
};
View.prototype.defaultControllerClass = function () {
return Controller;
};
View.prototype.modelController = function (aModel, aController) {
if (this._model && (this._model !== aModel)) {
this._model.removeDependent(this);
}
if (aModel && (aModel !== this._model)) {
aModel.addDependent(this);
}
this._model = aModel;
if (aController) {
aController.view(this);
aController.model(aModel);
}
this._controller = aController;
};
View.prototype.subViews = function () {
return this._subViews;
};
View.prototype.resetSubViews = function () {
this._subViews = [];
};
View.prototype.firstSubView = function () {
return this._subViews[0];
};
View.prototype.lastSubView = function () {
return this._subViews[this._subViews.length - 1];
};
View.prototype.addSubView = function (aView) {
this.addSubViewIfCyclic(aView, function () {
throw new Error('cycle in subView structure.');
});
};
View.prototype.addSubViewIfCyclic = function (aView, exceptionBlock) {
if (this.isCyclic(aView)) {
exceptionBlock();
} else {
aView.removeFromSuperView();
this._subViews.push(aView);
aView.superView(this);
}
};
View.prototype.isCyclic = function(aView) {
if (this === aView) {
return true;
}
if (this.isTopView()) {
return false;
}
return this._superView.isCyclic(aView);
};
View.prototype.removeSubView = function (aView) {
for (var i = 0, ilen = this._subViews.length; i < ilen; i++) {
if (aView === this._subViews[i]) {
this._subViews.splice(i, 1);
break;
}
}
aView.superView(null);
};
View.prototype.removeSubViews = function () {
for (var i = this._subViews.length; i--; ) {
this._subViews[i].superView(null);
}
this.resetSubViews();
};
View.prototype.removeFromSuperView = function () {
if (this._superView) {
this._superView.removeSubView(this);
}
};
View.prototype.superView = function (aView) {
if (arguments.length < 0) {
return this._superView;
} else {
this._superView = aView;
}
};
View.prototype.isTopView = function () {
return !!this._superView;
};
View.prototype.topView = function () {
return this._superView ? this._superView.topView() : this;
};</code></pre>
<h2>Controllers with Smalltalk's <code>Controller</code> Class</h2>
<p>The final member of the MVC class trio, is <code>Controller</code>. A controller’s behavior is almost completely application dependent and so the class is quite small with simple model and view properties and accessors. It is up to the application programmer to flesh out things in subclasses.</p>
<pre><code>Object subclass: #Controller
instanceVariableNames: 'model view sensor deferredActionQueue lastActivityTime'
classVariableNames: 'MinActivityLapse'
poolDictionaries: ''
category: 'ST80-Controllers'</code></pre>
<h4>instance methods</h4>
<h5>initialize-release</h5>
<pre><code>release
"Breaks the cycle between the receiver and its view. It is usually not
necessary to send release provided the receiver's view has been properly
released independently."
model := nil.
view ~~ nil
ifTrue:
[view controller: nil.
view := nil]</code></pre>
<h5>model access</h5>
<pre><code>model
"Answer the receiver's model which is the same as the model of the
receiver's view."
^model
model: aModel
"Controller|model: and Controller|view: are sent by View|controller: in
order to coordinate the links between the model, view, and controller. In
ordinary usage, the receiver is created and passed as the parameter to
View|controller: so that the receiver's model and view links can be set
up by the view."
model := aModel</code></pre>
<h5>view access</h5>
<pre><code>view
"Answer the receiver's view."
^view
view: aView
"Controller|view: and Controller|model: are sent by View|controller: in
order to coordinate the links between the model, view, and controller. In
ordinary usage, the receiver is created and passed as the parameter to
View|controller: and the receiver's model and view links are set up
automatically by the view."
view := aView</code></pre>
<h3>A Simple Translation to JavaScript</h3>
<p>Translating Smalltalk’s <code>Controller</code> class to JavaScript we have</p>
<pre><code>function Controller() {}
Controller.prototype.release = function () {
this._model = null;
if (this._view) {
this._view.controller(null);
this._view = null;
}
};
Controller.prototype.model = function (aModel) {
if (arguments.length < 1) {
return this._model;
} else {
this._model = aModel;
}
};
Controller.prototype.view = function (aView) {
if (arguments.length < 1) {
return this._view;
} else {
this._view = aView;
}
};</code></pre>
<h2>Summary</h2>
<p>So there you have the three main classes in the MVC architecture as they were written in Smalltalk decades ago and translated to JavaScript. As you can see, these are relatively simple classes. With experience over the past few years, JavaScript versions of these classes in <a href="http://peter.michaux.ca/maria/">the Maria framework</a> have shown me why MVC is deservingly the most famous architecture for applications with user interfaces. I think it is unfortunate that most JavaScript developers have only been exposed to one of the three MVC design patterns, the observer pattern, in popular MV* frameworks.</p>
<p>If you enjoyed this article, I think you might also like the following.</p>
<ul>
<li><a href="http://peter.michaux.ca/articles/uMVC">uMVC - A micro MVC framework in JavaScript</a></li>
<li><a href="http://peter.michaux.ca/articles/introducing-maria-the-real-mvc">Introducing Maria: The Real MVC</a></li>
<li><a href="http://peter.michaux.ca/articles/mvc-architecture-for-javascript-applications">MVC Architecture for JavaScript Applications</a></li>
<li><a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">Wikipedia MVC article</a></li>
<li><a href="http://www.itu.dk/courses/VOP/E2005/VOP2005E/8_mvc_krasner_and_pope.pdf" target="_blank">A Description of the Model-View-Controller User Interface Paradigm in the Smalltalk-80 System. 1988.</a></li>
</ul>
http://peter.michaux.ca/articles/introducing-maria-the-real-mvcIntroducing Maria: The Real MVC2013-06-02T19:05:00Z<p>In December 2011, <a href="http://www.jamesladdcode.com/" target="_blank">James Ladd</a> (<a href="https://twitter.com/jamesladd" target="_blank">@jamesladd</a>) and I were chatting about JavaScript, its dynamic nature, and program design. During the discussion, James asked detailed questions and I needed to illustrate a few points about MVC. I created <a href="https://github.com/petermichaux/maria">a GitHub repository</a> with code we could discuss.</p>
<p>Fast forward 1.5 years, through many more conversations, much more research, testing, and refining, and <a href="http://peter.michaux.ca/maria/">the Maria framework</a> for building MVC application in JavaScript is 1.0.0!</p>
<p>Over the past several years, the JavaScript community has been inundated with MV* frameworks. In the wake of the one-page app explosion, many JavaScript developers searched for ways to structure their larger browser applications more manageably. You can see in the source code of the frameworks that the authors were struggling away on their own attempting to solve the same problems. I’m willing to bet they went through a similar process I did trying to find discussions tailored to JavaScript about this famous MVC that was supposed to solve all their problems and more.</p>
<p>Why no one else chose to write an true MVC framework, I cannot figure. There is no doubt that the early Smalltalk MVC architecture inspired today’s MV* frameworks for JavaScript. My take on it was straight forward. The MVC architecture has withstood a 30 year test. It has passed that brutal test. It is still used for application programming. It is very useful for browser programming. Why not take this time-tested architecture and make a JavaScript framework true to the MVC that is implemented in <a href="http://www.squeak.org" target="_blank">Squeak Smalltalk</a> and written about in <a href="http://www.amazon.com/gp/product/0201633612/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=petermichauxc-20">Design Patterns</a><img src="http://www.assoc-amazon.com/e/ir?t=petermichauxc-20&l=as2&o=1&a=0201633612" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;">? My experience with Maria has shown it was a good choice.</p>
<p>How true is Maria to the real MVC? Somewhere along the way, I downloaded the Smalltalk Squeak implementation, found the model, view, and controller classes, and started porting lines of Smalltalk to JavaScript. In places, the two really are that close. And it wasn’t like pounding a square peg in a round hole. It was a natural fit. As my detailed understanding of the Smalltalk implementation improved, more of my “creative” lines of code in the growing Maria were deleted and in their place appeared more ported lines from Smalltalk. Every single time it was an improvement. The Squeak classes have been around a long time. They are some of the best lines of code in all the world’s aggregate of software. They are a solid foundation on top of which to build an important application.</p>
<p>So if you want to build your applications on a solid foundation, I recommend you check out <a href="http://peter.michaux.ca/maria/">the Maria framework</a>.</p>
http://peter.michaux.ca/articles/early-mixins-late-mixinsEarly Mixins, Late Mixins2012-10-26T23:17:00Z<p>In JavaScript, the language supplies us with several code reuse patterns. Prototype chaining gives us the primary single inheritance mechanism. Mixins are also an important pattern when we want one object to “inherit” functionality from multiple objects. There are several ways to implement the mixin process. This article looks at two contrasting implementations: early mixins and late mixins.</p>
<h2>Late Binding</h2>
<p>Let’s start with a quick review of what late binding gives us.</p>
<pre><code>var adam = {
greet: function() {
return "hello";
}
};
adam.greet(); // "hello"</code></pre>
<p>When we ask <code>adam</code> to <code>greet</code>, the method to be executed is looked up at the time of the call. This is late binding and means if we redefine the greet method, subsequent calls will use the new definition.</p>
<pre><code>adam.greet = function(name) {
return "hello" + (name ? (", " + name) : "");
};
adam.greet("world"); // "hello, world";</code></pre>
<p>This ability to redefine a method is valuable because it makes it possible for plugins to modify the behaviour of an existing code library.</p>
<h2>Late Binding and Prototype Chaining</h2>
<p>How does late binding work with prototype chaining? Let’s start with a fresh example. First we’ll make a new object <code>adam</code> who introduces himself.</p>
<pre><code>var adam = {
_name: "Adam";
greet: function() {
return "hello. I am " + this._name;
}
};</code></pre>
<p>Someone named Adam seems like a suitable prototype for all existing people. We can make a constructor function to produce more people.</p>
<pre><code>function Person(name) {
this._name = name;
}
Person.prototype = adam;
var eve = new Person("Eve");
eve.greet(); // "hello. I am Eve"</code></pre>
<p>Thanks to the combination of late binding and the prototype chain, a change to <code>adam</code> will result in a change to <code>eve</code> instantly. The following could be some plugin for the library that provides the <code>adam</code> object. This redefinition could happen at runtime due to user interaction.</p>
<pre><code>adam.greet = function(name) {
return "hello" + (name ? (", " + name) : '') + ". I am " + this._name;
};
eve.greet("world"); // "hello, world. I am Eve"</code></pre>
<h2>Early Mixins</h2>
<p>Another way to create a reusable bunch of code as a library is to provide one object who’s properties can be mixed into another object. This is usually done with an early mixin implementation.</p>
<p>First, a generic function that can mix properties from one object into another object.</p>
<pre><code>function earlyMixin(sink, source) {
for (var property in source) {
sink[property] = source[property];
}
}</code></pre>
<p>Now a object containing methods that would be useful on another object. Here is a library called Speeches.JS.</p>
<pre><code>var speeches = {
greet: function() {
return "hello. I am " + this._name;
},
farewell: function() {
return "goodbye. I am " + this._name;
}
};</code></pre>
<p>Since this Speeches.JS library is already written and well unit tested, we’d like to reuse that code in our code.</p>
<pre><code>function Person(name) {
this._name = name;
}
earlyMixin(Person.prototype, speeches);
var adam = new Person('Adam');
adam.greet(); // "hello. I am Adam"</code></pre>
<p>Now suppose we have mixed this <code>speeches</code> object into several other objects (like the <code>Person.prototype</code> object.) Also suppose we want to modify the <code>speeches</code> object at some later time and have all objects who’ve had the <code>speeches</code> object mixed into it be updated. This is what a plugin for Speeches.JS might want to do.</p>
<pre><code>speeches.greet = function(name) {
return "hello" + (name ? (", " + name) : '') + ". I am " + this._name;
};</code></pre>
<p>Unfortunately we cannot do this because the <code>speeches</code> methods have been mixed into the <code>Person.prototype</code> object early (i.e. at the time of mixin.) We still have</p>
<pre><code>adam.greet("world"); // "hello. I am Adam"</code></pre>
<h2>Late Mixins</h2>
<p>In order to make it possible to modify <code>speeches</code> and have all objects use the modified methods, we need one level of indirection in the mixin process.</p>
<pre><code>function lateMixin(sink, source) {
for (var property in source) {
(function(property) {
sink[property] = function() {
return source[property].apply(this, arguments);
}
}(property));
}
}</code></pre>
<p>Instead of directly borrowing the methods of the <code>source</code>, the <code>sink</code> is given methods that call the methods of <code>source</code>. This means that the method on <code>source</code> are mixed in late because they are looked up when they are called (rather than when they are mixed in.)</p>
<p>Now we can go through the same example with a different result.</p>
<pre><code>var speeches = {
greet: function() {
return "hello. I am " + this._name;
},
farewell: function() {
return "goodbye. I am " + this._name;
}
};
function Person(name) {
this._name = name;
}
lateMixin(Person.prototype, speeches);
var adam = new Person('Adam');
adam.greet(); // "hello. I am Adam"
speeches.greet = function(name) {
return "hello" + (name ? (", " + name) : '') + ". I am " + this._name;
};
adam.greet("world"); // "hello, world. I am Adam"</code></pre>
<p>When <code>adam.greet</code> is called it uses the most recent definition of <code>speeches.greet</code>. Yay! Late mixins have given us the same dynamic power that late binding and the prototype chain give us. This makes a library like Speeches.JS more flexible and opens it up for various kinds of modification at run time.</p>
<h2>Not Quite Everything</h2>
<p>Late mixins give us some of the power of late binding and the prototype chain but not everything. If we add another method to the <code>speeches</code> object it is not added to the other objects into which <code>speeches</code> has been mixed. There are several ways to accomplish this type of functionality. Something like <a href="http://wiki.ecmascript.org/doku.php?id=harmony%3adirect_proxies" target="_blank">proxies</a> might be our answer to get closer to real multiple inheritance.</p>
http://peter.michaux.ca/articles/uMVCuMVC - A micro MVC framework in JavaScript2012-10-13T20:00:00Z<p><a href="https://twitter.com/petermichaux/status/221671174915104768" title="@petermichaux on Twitter" target="_blank">I tweeted:</a></p>
<blockquote>
<p>You can write an MVC framework in one hundred lines of JavaScript & write about its effective use for one hundred thousand lines of English.</p>
</blockquote>
<p>I wondered exactly how small I could write a respectable MVC framework that included the three fundamental design patterns of the traditional Smalltalk-style MVC: the observer, composite, and strategy patterns.</p>
<p>See <a href="https://github.com/petermichaux/uMVC/blob/master/uMVC.js" target="_blank">the uMVC code on Github</a>.</p>
<p>Hopefully this code is educational for those new to the MVC paradigm. I think this code is something every JavaScript programmer should understand inside out and be able to explain every individual line’s significance to another programmer new to MVC.</p>
<p>If you are looking for a more fully-featured MVC framework that follows the same principles of uMVC to use in real browser applications, I suggest you take a look at <a href="https://github.com/petermichaux/maria" target="_blank">Maria</a>.</p>
http://peter.michaux.ca/articles/less-English-more-JavaScriptLess English, more JavaScript2012-10-13T19:00:00Z<p>I haven’t written much for my website this year. It wasn’t an accident. I wasn’t too busy. It was a choice. My new year’s resolution for 2012 was to write less English and more JavaScript.</p>
<p>Three quarters of the year is now gone and I feel like I’ve satisfied that resolution with 11 new JavaScript repositories <a href="https://github.com/petermichaux" target="_blank">on Github</a>. Most of the work was driven by the development of the <a href="https://github.com/petermichaux/maria" target="_blank">Maria framework</a> for writing MVC-style browser application. That particular project has been great fun and satisfying.</p>
<p>Now I feel as through I should tell the world about these projects … but part of me just wants to continue writing more JavaScript.</p>
http://peter.michaux.ca/articles/organizing-browser-application-filesOrganizing Browser Application Files2012-10-12T23:00:00Z<p>If you are building a large, one-page browser application with the usual suspects of HTML, CSS, JavaScript, images, etc, you’ll have many files and staying organized is important. Here is a way to organize your files.</p>
<h2>General Structure</h2>
<pre><code>MyApp/
Makefile
README
etc/
lib/
src/
tst/</code></pre>
<p>Perhaps the first thing you will do when starting the project is fill the <code>lib</code> directory with all the third-party libraries you know you’ll be using. These libraries are dropped into the <code>lib</code> directory without modification. Just plop them there in the same form they are distributed. You aren’t allowed to edit these files. This directory is the only directory where you put files created by a third party.</p>
<p>The <code>src</code> directory contains all of the files that you create and write that will become part of the files downloaded by the browser of a user of your application. These are the files we are excited about writing.</p>
<p>The <code>tst</code> directory contains all the files that test the files in the <code>src</code> directory. These are the files we are not excited about writing.</p>
<p>The <code>Makefile</code> has a default <code>build</code> target that generates the directory called <code>bld</code> which is filled with production-ready files that can be copied to the production web servers. The files in the <code>lib</code> and <code>src</code> directories are combined, minified, compressed, and otherwise mutated to become the files in the <code>bld</code> directory. This target can possibly generate a <code>MyApp.tar.gz</code> file if that is how the distribution to production will be done.</p>
<p>The build process may be guided by data in files in the <code>etc</code> directory. For example, there may be manifest files that state which files are concatenated together during the build and the name of the resulting files. Exactly which files with which data are in your <code>etc</code> directory depend on which tools you are using in your build process.</p>
<p>The <code>Makefile</code> should have a <code>clean</code> target that deletes the <code>bld</code> directory.</p>
<p>The <code>Makefile</code> might have a <code>test</code> target that runs the tests in the <code>tst</code> directory.</p>
<p>The <code>README</code> should at least explain what the targets in the Makefile do and how to run the tests.</p>
<p>You should not need to run <code>make build</code> in order to test your application either with the files in the <code>tst</code> directory or in the browser while developing. You may have files in your <code>etc</code> directory that control how the development environment is configured.</p>
<h2>An MVC-style Application</h2>
<p>You might be using an MVC framework like <a href="https://github.com/petermichaux/maria" target="_blank">Maria</a> to help structure your JavaScript. In this case, there is a natural way to divide your application at a finer scale.</p>
<pre><code>MyApp/
Makefile
README
etc/
lib/
maria.js
src/
css/
html/
index.html
templates/
img/
js/
bootstrap.js
controllers/
models/
views/
util/
tst/</code></pre>
<p>The <code>index.html</code> files is the page that the user loads into their browser to start the one-page application. This may be named something different like <code>myapp.html</code>. This file loads the necessary CSS, image, template, and JavaScript files needed to run the application.</p>
<p>The <code>templates</code> directory contains any HTML templates used by your JavaScript views. These can be compiled to JavaScript and concatenated into one or a few JavaScript files during the build process.</p>
<p>The <code>bootstrap.js</code> file is the one with the call to <code>window.onload</code> that fires up the whole application. It will start the loading of the data from the server, create the model layer, build the views, and add those views to the page so the user can begin interacting with the application.</p>
<p>The <code>controllers</code>, <code>models</code>, and <code>views</code> directories contain the obvious.</p>
<p>The <code>util</code> directory contains utility code that is not specific to any of the model, view, or controller layers. There may be pure functions that make computations with no side effects. You might have some obscure DOM related utilities that you wish were written by a third party for your <code>lib</code> directory but that you have to write yourself for your unique browser scripting requirements.</p>
http://peter.michaux.ca/articles/mixins-and-constructor-functionsMixins and Constructor Functions2012-04-23T20:16:00Z<p>JavaScript allows programmers to take properties from one object and mix them into another object. There are several ways to accomplish this mixing and a few of them are explored here.</p>
<h2>Observable Mixin</h2>
<p>Here is a simple example of the observer pattern that can be mixed into other objects.</p>
<pre><code>var observableMethods = {
observe: function(observer) {
if (!this.hasOwnProperty('observers')) {
this.observers = [];
}
this.observers.push(observer);
},
notify: function(data) {
if (this.hasOwnProperty('observers')) {
for (var i=0, ilen=this.observers.length; i<ilen; i++) {
this.observers[i](data);
}
}
}
};</code></pre>
<p>It is possible to use the <code>observableMethods</code> function as a observable itself.</p>
<pre><code>observableMethods.observe(function() {
alert('hi');
});
observableMethods.notify();</code></pre>
<p>A little mixin function to make other things observable.</p>
<pre><code>function mixinObservable(sink) {
for (var p in observableMethods) {
if (observableMethods.hasOwnProperty(p) &&
typeof observableMethods[p] === 'function') {
sink[p] = observableMethods[p];
}
}
}</code></pre>
<p>We can mixin to an person created with an object literal.</p>
<pre><code>var person = {
name: 'Steve',
setName: function(name) {
var oldName = this.name;
this.name = name;
this.notify({oldName: oldName, newName: this.name});
}
};
mixinObservable(person);
person.observe(function(data) {
alert(data.oldName + ' was renamed to ' + data.newName);
});
person.setName('Sarah');</code></pre>
<p>Alternately we write a constructor function for observable people that we can rename.</p>
<pre><code>function Person(name) {
this.setName(name);
};
mixinObservable(Person.prototype);
Person.prototype.setName = function(name) {
var oldName = this.name;
this.name = name;
this.notify({oldName:oldName, newName:this.name});
};</code></pre>
<p>We can then make a person and manipulate it.</p>
<pre><code>var person = new Person('Steve');
person.observe(function(data) {
alert(data.oldName + ' was renamed to ' + data.newName);
});
person.setName('Sarah');</code></pre>
<p>In all of the above code, the three uses of <code>hasOwnProperty</code> are critical to understand.</p>
<p>The first two uses of <code>hasOwnProperty</code> in <code>observe</code> and <code>notify</code> ensure that the object into which the methods have been mixed, will have its own set observers and not share some set of observers with any other object. The unfortunate part is that these checks run every time the <code>observe</code> and <code>notify</code> methods are called. This is inefficient and something we want to fix.</p>
<p>The third use of <code>hasOwnProperty</code> in <code>mixinObservable</code> means that only properties directly on <code>observableMethods</code> will be mixed into other objects. This is important because if we do not use <code>hasOwnProperty</code> then we copy all of the enumerable <code>Object.prototype</code> properties which is either wasteful or will overwrite any custom methods with the same names on other objects.</p>
<p>The <code>mixinObservable</code> function also copies only functions. If this check was not made and someone had observed the <code>observableMethods</code> object itself then the <code>observableMethods.observes</code> array would be copied as part of every mixin and observers would be shared by some observable objects (e.g. <code>observableMethods</code> and <code>Person.prototype</code> in the example above.)</p>
<p>A simpler <code>mixinObservable</code> method could be the following but this could be more difficult to maintain. If more methods are added to <code>observableMethods</code> then they need to be explicitly listed in <code>mixinObservable</code>.</p>
<pre><code>function mixinObservable(sink) {
sink.observe = observableMethods.observe;
sink.notify = observableMethods.notify;
}</code></pre>
<h2>Fixing the Inefficiency</h2>
<p>The inefficiency in <code>observe</code> and <code>notify</code> can be fixed by making a constructor function for <code>Observable</code> objects.</p>
<pre><code>function Observable() {
this.observers = [];
}
Observable.prototype.observe = function(observer) {
this.observers.push(observer);
};
Observable.prototype.notify = function(data) {
for (var i=0, ilen=this.observers.length; i<ilen; i++) {
this.observers[i](data);
}
};
Observable.call(Observable.prototype); // optional depending what you want</code></pre>
<p>Now the <code>observe</code> and <code>notify</code> methods of an observable function are more efficient as we know the <code>observers</code> property was created when the <code>Observable</code> constructor function ran.</p>
<p>The last line, <code>Observable.call(Observable.prototype);</code>, is a bit of an unusual one but it makes it possible to observe <code>Observable.prototype</code> just like <code>observableMethods</code>.</p>
<p>A new mixin function.</p>
<pre><code>function mixinObservable(sink) {
for (var p in Observable.prototype) {
if (Observable.prototype.hasOwnProperty(p) &&
typeof Observable.prototype[p] === 'function') {
sink[p] = Observable.prototype[p];
}
}
Observable.call(sink); // optional depending what you want
}</code></pre>
<p>Mixing into a person created with an object literal just like it was done above. The last line of this new <code>mixinObservable</code> insures the <code>observers</code> property is created.</p>
<pre><code>var person = {
name: 'Steve',
setName: function(name) {
var oldName = this.name;
this.name = name;
this.notify({oldName: oldName, newName: this.name});
}
};
mixinObservable(person);
person.observe(function(data) {
alert(data.oldName + ' was renamed to ' + data.newName);
});
person.setName('Sarah');</code></pre>
<p>The trick comes when we create a <code>Person</code> constructor function.</p>
<pre><code>function Person(name) {
Observable.call(this);
this.setName(name);
};
mixinObservable(Person.prototype);
Person.prototype.setName = function(name) {
var oldName = this.name;
this.name = name;
this.notify({oldName:oldName, newName:this.name});
};</code></pre>
<p>The first line of the constructor function, <code>Observable.call(this);</code>, ensures that each <code>Person</code> object has its own set of observers. Without this call, all the people will share the same list of observers which is the set of observers on the <code>Person.prototype</code> object. If this makes you squint then it is well worth the effort to think about it until it is clear why.</p>
<p>To use some class vocabulary, the first line of the constructor function can be thought of as a <code>super</code> call and that the Person class inherits from the Observable class. Some JavaScript diehards cringe at the mention of this vocabulary but I think the comparison is worth consideration.</p>
<h2>Multiple Mixins</h2>
<p>Multiple mixins follow the same pattern.</p>
<pre><code>function Person(name) {
Observable.call(this);
Common.call(this);
this.setName(name);
}
mixinObservable(Person.prototype);
mixinCommon(Person.prototype);
// By coincidence mixinCommon also added a notify method which
// clobbered the method of the same name added by mixinObservable.
// Fix this problem making appropriate decisions about how
// to call both.
Person.prototype.notify = function() {
Common.prototype.notify.call(this);
Observable.prototype.notify.apply(this, arguments);
};
// ...</code></pre>
<h2>Prototype Chaining vs. Mixins</h2>
<p>There is one primary difference between prototype chaining and mixins. For example,</p>
<pre><code>function Person(name) {
Observable.call(this);
Base.call(this);
this.setName(name);
}
// chain prototypes so that all Person objects
// inherit from Base.prototype.
Person.prototype = Object.create(Base.prototype);
Person.prototype.constructor = Person;
Base.call(Person.prototype); // optional depending what you want
mixinObservable(Person.prototype);</code></pre>
<p>Now if we add methods to both <code>Base.prototype</code> and <code>Observable.prototype</code> <em>after</em> the above code has executed. Only the method added to <code>Base.prototype</code> will be added to <code>Person</code> objects.</p>
<pre><code>Base.prototype.getId = function() {/*...*/};
Observable.prototype.getObservers = function() {/*...*/};
var person = new Person('Steve');
person.getId(); // ok
person.getObservers(); // error: getObservers not defined</code></pre>
<p>Enjoy your mixins.</p>