<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-31592724</id><updated>2024-09-11T13:01:57.719-04:00</updated><category term="technology"/><category term="eclipse"/><category term="pluto"/><category term="scala"/><category term="javascript"/><category term="media queries"/><category term="portlet"/><category term="responsive"/><category term="spa"/><category term="git"/><category term="html5"/><category term="backbone"/><category term="apache"/><category term="cake-pattern"/><category term="css"/><category term="ember"/><category term="geo"/><category term="google"/><category term="jquery"/><category term="jquerymobile"/><category term="mac"/><category term="maven"/><category term="music"/><category term="notebook"/><category term="parenting"/><category term="review"/><category term="tivo"/><category term="traits"/><category term="twitter"/><category term="unix"/><category term="webapps"/><title type='text'>Marcus Christie&#39;s Blog</title><subtitle type='html'>Wherein I write about stuff that I find interesting.  Most of entries will probably be technology related (Java, Web development, Python, Flex, etc.).  But I will also write about: my adventures in homeschooling and parenting, reviews of books I&#39;ve read, and anything else I&#39;ve learned or seen that I think is cool enough to share.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default?start-index=26&amp;max-results=25'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>70</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-31592724.post-3507846098318231477</id><published>2015-02-15T17:31:00.000-05:00</published><updated>2015-02-15T17:31:38.314-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ember"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="notebook"/><title type='text'>From the Notebook: An Ember Bootstrap Modal Dialog and How to Deal with state in Ember controllers</title><content type='html'>&lt;!--
Title: From the Notebook: An Ember Bootstrap Modal Dialog and How to Deal with
state in Ember controllers
--&gt;

&lt;h1&gt;Bootstrap Modal Dialog for Ember&lt;/h1&gt;
&lt;p&gt;To create a Bootstrap styled modal dialog for an Ember app at work, I mostly
&lt;a href=&quot;http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/&quot;&gt;followed the Ember cookbook entry on modal
dialogs&lt;/a&gt;.
One difference is using Bootstrap for the modal dialog, of course. Here are the
steps I took.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Added a modal outlet to the application template&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;outlet&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;outlet&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;modal&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On my ApplicationRoute.js I have the following:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;openModal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;modalName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;modalName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

            &lt;span class=&quot;nx&quot;&gt;into&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;application&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;outlet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;modal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;closeModal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;disconnectOutlet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

            &lt;span class=&quot;nx&quot;&gt;outlet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;modal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;parentView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;application&amp;#39;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This allows me to pass a model to the modal.  One implication of this is that
the modal view needs to have a corresponding Controller so that Ember can set
the model on that Controller.  It appears that by default Ember Routes will
supply an ArrayController or ObjectController for routes that don&#39;t have one
defined, but the same doesn&#39;t hold for these non-route views.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I then defined a &lt;code&gt;modal-dialog&lt;/code&gt; component, but also split out &lt;code&gt;modal-body&lt;/code&gt;
   and &lt;code&gt;modal-footer&lt;/code&gt; components since those are the ones I&#39;m expecting to
   customize from modal dialog to modal dialog.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/x-handlebars&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-template-name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;components/modal-dialog&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal fade&amp;quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tabindex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;-1&amp;quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;dialog&amp;quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;aria&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;labelledby&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;dialogTitle&amp;quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;aria&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hidden&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal-dialog&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal-content&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal-header&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;close&amp;quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dismiss&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal&amp;quot;&lt;/span&gt;
                    &lt;span class=&quot;nx&quot;&gt;aria&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Close&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;span&lt;/span&gt;
                    &lt;span class=&quot;nx&quot;&gt;aria&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hidden&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;times&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/span&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;h4&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal-title&amp;quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;dialogTitle&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/h4&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/div&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/x-handlebars&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-template-name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;components/modal-body&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal-body&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/x-handlebars&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-template-name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;components/modal-footer&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal-footer&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For the component code I need to call &lt;code&gt;.modal()&lt;/code&gt; on the modal dialog to pop
   it up. I also wanted to handle the Bootstrap modal closed event and then
   remove the modal from the DOM (i.e., disconnect the outlet).  Removing the
   modal from the DOM is not strictly necessary I guess, but I think it is nice
   to remove it from the DOM when it is no longer needed. If it is rendering a
   model, there&#39;s no point for the hidden modal to re-render when that model
   changes.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ModalDialogComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ember&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;sendCloseAction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sendAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;didInsertElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.modal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;modal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.modal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hidden.bs.modal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sendCloseAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;willDestroyElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.modal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hidden.bs.modal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To use it, just need to create a view that uses the &lt;code&gt;modal-dialog&lt;/code&gt; component.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/x-handlebars&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-template-name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;myModal&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#modal-dialog&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;closeModal&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#modal-body&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
            &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;/modal-body&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#modal-footer&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;btn btn-default&amp;quot;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;save&amp;#39;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Save&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/button&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;btn btn-primary&amp;quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dismiss&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modal&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/button&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;/modal-footer&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
    &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;/modal-dialog&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;One problem I ran into was that Components can only send actions based on
names that they are given.  My ModalDialogComponent can&#39;t call
&lt;code&gt;this.sendAction(&#39;closeModal&#39;)&lt;/code&gt; and have that be handled by the
ApplicationRoute.  Instead ModalDialogComponent calls
&lt;code&gt;this.sendAction(&#39;close&#39;)&lt;/code&gt; where the actual named action to send is
specified in the view using the component.  Here in the myModal template I&#39;m
specifying that for &lt;em&gt;close&lt;/em&gt; the component should send the &lt;em&gt;closeModal&lt;/em&gt;
action. See &lt;a href=&quot;http://emberjs.com/guides/components/sending-actions-from-components-to-your-application/&quot;&gt;Sending Actions from Components to Your
Application&lt;/a&gt;
for more details.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;Ember Controllers Are Singletons&lt;/h1&gt;
&lt;p&gt;One surprising thing about Ember for me as I&#39;ve been learning over the past
couple months is that Controllers are (kind of, sort of) singletons.  Ember
instantiates a controller for a route once.  So any state in a Controller is
&lt;em&gt;sticky&lt;/em&gt;. But often times you&#39;ll want to reset the state in your Controller when
switching from one model to another. So what to do?&lt;/p&gt;
&lt;p&gt;Found a couple of interesting blogs regarding this problem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://gregbabiars.com/case-against-ember-controllers/&quot;&gt;Case Against Ember Controllers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://balinterdi.com/2014/06/26/ember-gotcha-controllers-are-singletons.html&quot;&gt;Ember Gotcha: Controllers Are Singletons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both suggest resetting the controller in Route&#39;s &lt;code&gt;setupController&lt;/code&gt; as one way to
address this problem. (Note: Ember.Route also has a &lt;code&gt;resetController&lt;/code&gt; hook;
haven&#39;t used it but seems to cover exactly this need.) Balint Erdi&#39;s post has an
interesting idea about having the reset logic in the Controller itself and having it
observe some property that can be used to trigger a reset.&lt;/p&gt;
&lt;p&gt;When thinking about Controller state and Routes, and where to put this state, it
occurs to me that there are 3 kinds of view state. A view might want to take
advantage of all 3 types of view state.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Transient view state&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is view state that you don&#39;t want to be sticky at all.  Maybe
expanding/collapsing an accordion type view, or form validation error display.&lt;/p&gt;
&lt;p&gt;Basically, if the model changes, you want to reset this the transient state.
For this you can define a resetState function that is called whenever the model
changes.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;resetState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// reset transient stuff here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;observes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;model&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sticky state, but not serialized to the URL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This would be view state that you want to be sticky so that when the user
moves from view to view this state remains. However, for whatever reason,
you don&#39;t want to serialize this state to a Route URL.  &lt;em&gt;This is the default
way that Ember works.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Can&#39;t actually think of a good example here. Maybe a sub-view that you
expand or show and as you move through different models you want to keep
showing that sub-view?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sticky state that should be serialized to the URL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you have some view state that you want to be persistent, then you should
really think about moving that to the Route and serializing to the URL.  If
that works for your use case, then you can do that and move that view state
out of the Controller entirely.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To me, #1 is a more common type of view state than #2, so it seems weird that
the default for Ember Controllers is #2. However, the fact that Ember
Controllers are singletons makes #2 possible and then one just needs to reset
state to make #1 work.  If Ember Controllers weren&#39;t singletons, its hard to see
where #2 style view state would be stored.&lt;/p&gt;
&lt;h1&gt;Odds and Ends&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Console2: a better Windows console.&lt;/strong&gt; I played around with setting up
  Console2 to get a better console window than &lt;code&gt;cmd.exe&lt;/code&gt;.  The following were
  helpful resources&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.hanselman.com/blog/Console2ABetterWindowsCommandPrompt.aspx&quot;&gt;http://www.hanselman.com/blog/Console2ABetterWindowsCommandPrompt.aspx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.kevwebdev.com/blog/in-search-of-a-better-windows-console-using-ansicon-console2-and-git-bash.html&quot;&gt;http://www.kevwebdev.com/blog/in-search-of-a-better-windows-console-using-ansicon-console2-and-git-bash.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&#39;s what I like about Console2:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can configure it to copy on select and paste with a right click.&lt;/li&gt;
&lt;li&gt;You can resize the window (but you have to configure it to have more
  columns first, which is kind of weird). I sometimes like to have the
  console take up a full screen.&lt;/li&gt;
&lt;li&gt;It is tabbed.&lt;/li&gt;
&lt;li&gt;You can configure it to start a cmd shell or Git bash. I have Git bash as
  a default and hitting Ctrl+Shift+T opens a new Git bash tab.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ember dot notation&lt;/strong&gt;. Learned that in Ember instead of doing&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;bar&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;baz&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can do&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;foo.bar.baz&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If &lt;code&gt;bar&lt;/code&gt; is not defined, then the first one would fail but the second would
return &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Git: counting words in a specific revision of a file&lt;/strong&gt;.  I wanted to be able
  to count how many words are in a previous version of a blog post.  There might
  be a better way to do this, but here&#39;s how I did it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Get the file&#39;s blob hash.  You can do&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git log --raw -- path/to/file
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Seems the easiest way. This prints the before and after blob hash for
each revision&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;...
:100644 100644 c5d00fe... 2403611... M  path/to/file
...
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Where &lt;code&gt;2403611&lt;/code&gt; is the blob hash for this revision and &lt;code&gt;c5d00fe&lt;/code&gt; is the blob
hash for the previous revision.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;cat the blob and count the words.  Getting the blob hash was the hard
   part, now we can simply do&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git cat-file -p 2403611 | wc -w
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/3507846098318231477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/3507846098318231477' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3507846098318231477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3507846098318231477'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2015/02/from-notebook-ember-bootstrap-modal.html' title='From the Notebook: An Ember Bootstrap Modal Dialog and How to Deal with state in Ember controllers'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-5331394635276356819</id><published>2015-02-08T09:08:00.001-05:00</published><updated>2015-02-08T09:08:15.908-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="media queries"/><category scheme="http://www.blogger.com/atom/ns#" term="responsive"/><category scheme="http://www.blogger.com/atom/ns#" term="spa"/><category scheme="http://www.blogger.com/atom/ns#" term="webapps"/><title type='text'>Responsive Webapp Conclusions</title><content type='html'>

&lt;p&gt;I&#39;ve spent a few weeks now reading and thinking about whether it makes sense to
use responsive web design techniques to build a single page web application
(SPA) that works well on mobile and desktop computers.  I &lt;a href=&quot;http://marcus-christie.blogspot.com/2014/12/initial-thoughts-on-responsive-single.html&quot;&gt;started with my
initial
thoughts&lt;/a&gt;
and reviewed arguments &lt;a href=&quot;http://marcus-christie.blogspot.com/2015/01/researching-responsive-webapps.html&quot;&gt;for responsive
webapps&lt;/a&gt;
and &lt;a href=&quot;http://marcus-christie.blogspot.com/2015/02/an-alternative-to-responsive-webapps.html&quot;&gt;against responsive
webapps&lt;/a&gt;.
I haven&#39;t done as much reading as I would like and there is still a lot of good
stuff out there to read and learn from. But I think I have learned enough to
come to some conclusions.&lt;/p&gt;
&lt;h5&gt;Recommendation&lt;/h5&gt;
&lt;p&gt;The first step in deciding whether to go responsive or not with a single page
web application is to first design the ideal mobile UI and the ideal desktop UI
for your app. Obviously phones and desktop computers have different real estate
to work with, but when you are designing an ideal UI for your app think also
about the different use cases that users on mobile versus desktop computers will
have.  Don&#39;t just think &quot;how do I make this work on small and large screens&quot;.
For example, consider an email campaign management app.  On desktop the UI would
likely be optimized for creating new email messages or templates and bulk
loading and editing of email lists.  On a mobile device the UI would be more
geared to checking the status of email campaigns: open rates, bounceback rates,
unsubscribes. Design a UI that makes the most sense for your users on both
platforms.&lt;/p&gt;
&lt;p&gt;Now, if the UI is basically the same except for layout, then Responsive Web
Design techniques could be a good fit. You can use media queries to adapt the
layout of the app on different devices.&lt;/p&gt;
&lt;p&gt;However, you might still not choose to go responsive. Why?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You might want to optimize what is downloaded on mobile devices.  Not only to
   achieve a smaller download size but also to exclude running JavaScript code
   that would be a performance burden on mobile devices.&lt;/li&gt;
&lt;li&gt;You want the flexibility to diverge the UIs in the future.  Sure, today,
   maybe before you even have any users, you think that the ideal mobile and
   desktop UIs only differ in layout.  But apps should evolve based on feedback
   from users and as they grow new capabilities. (This point might actually be
   the nail in the coffin for me regarding responsive SPAs. It seems far more
   pragmatic to start by having separate mobile and desktop UIs.)&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;Other recommendations&lt;/h5&gt;
&lt;h6&gt;Only two device classes: phone and desktop (or small and large)&lt;/h6&gt;
&lt;p&gt;There used to be such a clear cut divide between phones and tablets, but any
more I don&#39;t see much point in developing separate UIs for them.  They share a
lot of the same considerations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;modest computational resources&lt;/li&gt;
&lt;li&gt;on mobile networks&lt;/li&gt;
&lt;li&gt;access to sensors like GPS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think it is sufficient to just have two device classes.&lt;/p&gt;
&lt;p&gt;One thing that does seem reasonable is to use responsive web design techniques
to have your mobile UI adapt to larger screen area.  For example, you could
implement the kind of UI like in the iPad Mail app where in portrait you see
only the email message but in landscape you see a list of emails in that folder
on the left and the email message on the right.&lt;/p&gt;
&lt;p&gt;Also, allow the user to switch between the phone and desktop UIs if they desire.
A theme running throughout these blog posts is to try to not make any hard
assumptions and this is, to me, one of the big advantages of the &lt;a href=&quot;http://marcus-christie.blogspot.com/2015/02/an-alternative-to-responsive-webapps.html&quot;&gt;device class
approach&lt;/a&gt;.
You might think that the user will best be served by the mobile UI but that user
may want the desktop UI. (This also dovetails nicely with thinking about
different use cases on mobile and desktop: the user may be on a desktop computer
but want to use the mobile UI because it is optimized for the kind of task the
user currently has in mind.)&lt;/p&gt;
&lt;h6&gt;Make everything optimized for touch&lt;/h6&gt;
&lt;p&gt;Whether you go responsive or take the device classes approach, make everything
optimized for touch. Size controls so that they can be tapped on and respond to
touch events.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/5331394635276356819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/5331394635276356819' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5331394635276356819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5331394635276356819'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2015/02/responsive-webapp-conclusions.html' title='Responsive Webapp Conclusions'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4653788590945632972</id><published>2015-02-08T08:49:00.000-05:00</published><updated>2015-02-08T08:55:06.776-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html5"/><category scheme="http://www.blogger.com/atom/ns#" term="media queries"/><category scheme="http://www.blogger.com/atom/ns#" term="responsive"/><category scheme="http://www.blogger.com/atom/ns#" term="spa"/><title type='text'>An alternative to responsive webapps: Device Classes</title><content type='html'>

&lt;p&gt;This week I spent some time with Boris Smus&#39; article, &lt;a href=&quot;http://www.html5rocks.com/en/mobile/cross-device/&quot;&gt;A non-responsive approach
to building cross-device
webapps&lt;/a&gt;. As the title
suggests, Boris presents an alternative to using media queries and responsive
design for building webapps that work on a range of devices. It&#39;s a good article
and I recommend reading it.  In this blog post I&#39;ll review his arguments and
give my thoughts on the matter.&lt;/p&gt;
&lt;p&gt;To start with, Boris sees a few problems with Media Queries (or at least, with
using just media queries to adapt layout for different screen sizes):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All devices get the same assets: the same JavaScript, CSS, images etc. So
  there is a good chance that devices are downloading a lot more than they would
  absolutely need to.&lt;/li&gt;
&lt;li&gt;All devices start with the same DOM.  To get the DOM to look one way on one
  device and look another way on a different device could lead to overly
  complicated CSS.&lt;/li&gt;
&lt;li&gt;Not much flexibility to customize the UI for different types of devices.  You
  &lt;em&gt;can&lt;/em&gt; do it with a media query approach but if you have a mobile view that is
  just completely different from a desktop view, you will have duplicate views
  and the application code has to be careful to handle both views at once,
  depending on screen size. That is, while creating a custom view for a certain
  type of device, you have to think about how it will work for all other types
  of devices.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Smus recommends developing separate UIs for three different &lt;em&gt;device classes&lt;/em&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;mobile phones (small screen width + touch)&lt;/li&gt;
&lt;li&gt;tablets (large screen width + touch)&lt;/li&gt;
&lt;li&gt;desktops (no touch)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;He suggests using device width and whether the device is touch enabled to
distinguish between these device classes.  How reasonable are these criteria?&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;http://www.html5rocks.com/en/mobile/cross-device/#comment-762768971&quot;&gt;one of the commenters
mentions&lt;/a&gt;,
hindsight is 20/20. We live in an era of touchscreen desktop Windows 8
computers, and they don&#39;t appear to be going anywhere.  We can no longer assume
that lack of touch support equals desktop or vice versa. One of my big takeaways
from this whole investigation is that &lt;strong&gt;all controls should be designed to be
touch friendly&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;What about the small screen/large screen divide?  As I wrote &lt;a href=&quot;http://marcus-christie.blogspot.com/2015/01/researching-responsive-webapps.html&quot;&gt;in my previous
post&lt;/a&gt;,
we now have many large phones and small tablets such that the height of a large
phone can easily exceed the width of a tablet. I still think a line can be drawn
somewhere and I do think that it is useful to design a mobile friendly version
of a webapp.  But that line is continually moving and blurring.&lt;/p&gt;
&lt;p&gt;Okay, now that we have 3 device classes (personally I only see two: mobile and
desktop), what does Smus recommend for detecting and serving up these different
experiences?  Smus compares doing server side and client side detection and
comes down on client side detection, mostly because it is feature detection
based (more future proof) instead of user agent based.  I agree there.&lt;/p&gt;
&lt;p&gt;Smus suggests using &lt;a href=&quot;https://github.com/borismus/device.js&quot;&gt;Device.js&lt;/a&gt;
(apparently one of his open source projects) to do this client side detection.&lt;/p&gt;
&lt;p&gt;He also suggests using a MVC framework and only making separate View classes for
the difference device classes.  This allows you to get a lot of reuse while also
being able to fully tailor the UI for a particular device class.&lt;/p&gt;
&lt;p&gt;Overall, I&#39;m impressed with this approach. &lt;strong&gt;If your application is best
implemented with a different UI on mobile versus desktop, I think this is
probably the best approach&lt;/strong&gt;.  Responsive Web Design seems to be a good fit only
when the UI is basically the same on mobile and desktop with only the layout
needing to be a little different. For example, at &lt;a href=&quot;http://walkerinfo.com&quot;&gt;Walker
Information&lt;/a&gt;, we have a survey application. On mobile and
on desktop, the essential UI is the same, with only layout differing. Each page
has a list of questions and controls for providing answers, with &lt;em&gt;Back&lt;/em&gt; and
&lt;em&gt;Next&lt;/em&gt; buttons to navigate through the survey.  This is a good candidate for
being designed responsively.  As a counter example, consider something like a
webapp for MailChimp. On desktop it might be optimized for creating emails and
setting up campaigns whereas on mobile the UI might be quite different and be
focused on monitoring open rates, bounceback rates, etc. In this case, having
two completely different apps would be a better fit.&lt;/p&gt;
&lt;p&gt;There are some downsides with this separate app for device classes approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the device class is part of the URL then bookmarks, shared links would
  include it as part of the URL. It would be nice to have canonical URLs.&lt;/li&gt;
&lt;li&gt;Separate views for the device classes is extra work and has its own
  maintenance overhead&lt;/li&gt;
&lt;li&gt;Doesn&#39;t respond to orientation changes or browser resizing&lt;ul&gt;
&lt;li&gt;However, it would be possible to combine both approaches. You might create
  a separate view for the mobile device class that itself uses media queries
  to adjust the UI between phone-like sizes and tablet-like sizes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On a closing note, there is one other thing I like about Smus&#39; approach.  He
recommends having links in the app to the different device classes. This way if
you are on a mobile phone and really want the desktop view, you can get to it. I
think this is in line with the thinking from the last blog post that challenges
the &lt;em&gt;consensual hallucination&lt;/em&gt; that we as web developers tend to participate in.
Our assumption about what is mobile, what is a desktop computer are being
challenged all the time. It would be good to make fewer assumptions. Letting a
user switch to a non-default device class, to me, fits in with that line of
thinking.  We only have a limited understanding of the kinds of devices that
exist today. Hopefully the devices that arrive in the future will surprise us
and challenge our assumptions. And hopefully our webapps will be ready.&lt;/p&gt;
&lt;p&gt;Additional Resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Really liked &lt;a href=&quot;http://bradfrost.com/blog/web/responsive-web-design-missing-the-point/&quot;&gt;this post by Brad
  Frost&lt;/a&gt;
  that Smus links to. He makes the point that while media queries are great, the
  most important thing to optimize on mobile is performance.&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4653788590945632972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/4653788590945632972' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4653788590945632972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4653788590945632972'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2015/02/an-alternative-to-responsive-webapps.html' title='An alternative to responsive webapps: Device Classes'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7694510877307418673</id><published>2015-01-18T20:35:00.000-05:00</published><updated>2015-02-08T08:55:44.490-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html5"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="media queries"/><category scheme="http://www.blogger.com/atom/ns#" term="responsive"/><category scheme="http://www.blogger.com/atom/ns#" term="spa"/><title type='text'>Researching Responsive Webapps</title><content type='html'>&lt;p&gt;In a previous post I wrote about my initial thoughts regarding responsive Single
Page Applications (SPAs).  I&#39;ve now done a bit of digging to find out what other
folks think about this topic.&lt;/p&gt;
&lt;p&gt;Among the blog posts I read I found Jason Grigsby&#39;s series of blog posts
&lt;a href=&quot;http://blog.cloudfour.com/responsive-design-for-apps-part-1/&quot;&gt;Responsive Design for
Apps&lt;/a&gt; especially
interesting.&lt;/p&gt;
&lt;h4&gt;Consensual Hallucination&lt;/h4&gt;
&lt;p&gt;In the first blog post in this series, Jason makes the case that web developers
and web UI framework authors have been participating in a &lt;a href=&quot;http://adactio.com/articles/5826/&quot;&gt;consensual
hallucination&lt;/a&gt; regarding what phones and
tablets and desktop computers are limited to, just as we once assumed desktop
browsers were 960 pixels wide. Web UI frameworks tend to have a library of
mobile widgets (e.g, jQuery Mobile) and a separate library of desktop widgets
(e.g. jQuery UI). The reasoning given by framework authors is that phones and
tablets and desktops are fundamentally different platforms.  But what are these
fundamental differences? A cellular radio? The answer isn&#39;t clear and Jason is
dubious that a good answer exists.&lt;/p&gt;
&lt;p&gt;Jason looks at the size of phones and tablets and points out that the height of
the larger phones out there easily exceeds the width of the smaller tablets
available.  His article was published in early 2013 and since then the gap has
only narrowed. In fact Jason at one point says&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The small gaps that exist are either things that seem inevitable (high-dpi on
large screens) or are so small to be inconsequential (does it matter that we
don&#39;t have six inch displays?).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And of course, we now have &lt;a href=&quot;http://www.google.com/nexus/6/&quot;&gt;6-inch phones&lt;/a&gt; and
&lt;a href=&quot;http://www.amazon.com/dp/B00KC6I06S&quot;&gt;6-inch tablets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&#39;s no clear line between phones and tablets, but what about desktops?  We
used to be able to assume that touch was a fundamentally distinct mode of
interaction on mobile devices.  However, Windows 8 and all of the touch screen
desktop and laptop products that are built for it obliterates that assumption.
He points to research to suggest that touchscreen desktops are not a fad.  I&#39;ve
yet to have a chance to play with a Windows 8 touchscreen device myself but I
agree. I have to believe that eventually Apple will have to catch up too.&lt;/p&gt;
&lt;p&gt;One of the key takeaways for me from this article is that every application
should be designed for touch interaction. Primarily this means making targets
big enough to be easily tapped on with fingers. Because of &lt;a href=&quot;https://en.wikipedia.org/wiki/Fitts%27s_law&quot;&gt;Fitts&#39;s
Law&lt;/a&gt;, desktop users using a mouse
will also benefit because these larger targets are easier to hit.&lt;/p&gt;
&lt;h4&gt;Making desktop app responsive&lt;/h4&gt;
&lt;p&gt;In &lt;a href=&quot;http://blog.cloudfour.com/responsive-design-for-apps-part-2/&quot;&gt;Jason&#39;s second
post&lt;/a&gt; he looks at
a typical desktop app and tries to reimagine it as a responsive web app.&lt;/p&gt;
&lt;p&gt;One of the problems he ran into is that if you take a desktop app design and try
to make it responsive, you kind of run into a brick wall. He starts making
progress when he takes a &lt;em&gt;mobile first&lt;/em&gt; strategy. He designs a version of the
web app that is optimized for mobile.&lt;/p&gt;
&lt;p&gt;Once he has an optimized mobile design, he then looks at how it maps to the
desktop app and finds that it maps pretty well. That&#39;s important for a
responsive web app; each screen in the mobile design needs to be able to map to
a corresponding screen in the desktop design.  If there isn&#39;t a mapping, that
is, if the mobile design is not just a different layout compared to the desktop
design, then responsive web design probably won&#39;t work.&lt;/p&gt;
&lt;p&gt;Finally, he takes another look at the desktop design and rethinks it in terms of
the mobile design. This is also an important step in evaluating if responsive
web design is feasible.  For the mobile design he had to compromise in some
places and display less information than on the desktop design.  So its
important to step back and look at if these mobile design components can be used
in the desktop design.&lt;/p&gt;
&lt;h4&gt;Desktop and mobile design patterns&lt;/h4&gt;
&lt;p&gt;In the &lt;a href=&quot;http://blog.cloudfour.com/responsive-design-for-apps-part-3/&quot;&gt;third part of the Jason&#39;s
series&lt;/a&gt; Jason
looks at how desktop operating systems have been incorporating mobile design
ideas. In particular he looks at Apple&#39;s Mail app on iPhone, iPad and Mac OS X.&lt;/p&gt;
&lt;p&gt;The iPhone Mail app uses a &lt;em&gt;nested doll&lt;/em&gt; design pattern: moving froma  list of
items to greater detail or sub-lists of that item.  On the iPad, we see a
slightly different pattern, what has been called the &lt;em&gt;bento box&lt;/em&gt; pattern: the
list of email messages is displayed on the same screen as the detail. The iPhone
and iPad app actually share views (for example, mail accounts and folders
listing screens).&lt;/p&gt;
&lt;p&gt;On Mac OS X, the Mail app there shares a lot of similar design elements although
it does have a different look. One could definitely imagine there being a single
Mail app that runs across all Apple devices and that adapts to the available
screen real estate.&lt;/p&gt;
&lt;p&gt;To me it is a little bit of stacking the deck to use the Mail app. Because
information in the Mail app is arranged hierarchically (mail accounts list,
folders list, messages list), it is not too hard to design a responsive Mail
app.  But not all apps are so simple. Word processing apps tend to have a main
content area and several controls for affecting layout and formatting. A mobile
word processing app design would be quite a different design, not likely to
share much with its desktop counterpart.&lt;/p&gt;
&lt;p&gt;Also, Jason only looks at views that display lists of accounts and emails and
the views that display the email itself. That is, he only considers the views
related to reading email.  The desktop Mail app includes formatting options and
stationary options when composing email, which would take up too much real
estate on mobile. This is because on mobile users are typically more interested
in reading and filing and flagging and deleting email.  On mobile users only
need to be able to write short responses, typically.  On desktop the email
composing needs are very different.&lt;/p&gt;
&lt;p&gt;Nevertheless, I think his conclusion that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;responsiveness for apps is inevitable&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;is mostly true.  Responsive web design can be a good fit for some apps and even
apps that are better served by different UI designs on mobile and desktop will
benefit from responsive design techniques on mobile (for example a mobile UI
that responds to more real estate on a tablet versus a phone).&lt;/p&gt;
&lt;h4&gt;Conclusions&lt;/h4&gt;
&lt;p&gt;I find Jason&#39;s arguments compelling. The idea that phones are fundamentally
different from tablets and desktops and so require different UI frameworks and
separate apps is undermined by the evidence that not much actually separates
these different devices in terms of technical capability.&lt;/p&gt;
&lt;p&gt;However, one thing that I think is missing a little from the discussion is how
these different devices are used and what they are used for. Yes, technically,
there isn&#39;t much difference between phones and tablets and desktops except
screen size. On the other hand, users on mobile devices may have different tasks
in mind that they want to accomplish versus users on desktop devices.  As I
mentioned above regarding the Mail app example, mobile users mostly want to read
and deal with email by flagging, filing, deleting etc.  Composing longer or more
format heavy emails are saved for when the user is at a desktop computer. Now,
this isn&#39;t a big difference in goals for mobile and desktop users for this
particular app, but for certain apps mobile users may have very different goals
from desktop users.  This needs to be kept in mind when designing optimal
desktop and mobile UIs. I&#39;ll expand on this a bit in future posts, but to me
this is one of the most important reasons why you might want separate mobile and
desktop apps.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7694510877307418673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/7694510877307418673' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7694510877307418673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7694510877307418673'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2015/01/researching-responsive-webapps.html' title='Researching Responsive Webapps'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-2782808552791146915</id><published>2014-12-20T14:24:00.000-05:00</published><updated>2014-12-20T14:24:28.623-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html5"/><category scheme="http://www.blogger.com/atom/ns#" term="media queries"/><category scheme="http://www.blogger.com/atom/ns#" term="responsive"/><category scheme="http://www.blogger.com/atom/ns#" term="spa"/><title type='text'>Initial thoughts on Responsive Single Page Applications</title><content type='html'>&lt;blockquote&gt;
&lt;p&gt;Is it feasible to build a responsive, mobile-first Single Page Application
(SPA)? Here are my initial thoughts on the feasibility and challenges of
building a responsive SPA. I plan to do more research in the coming weeks to
hopefully answer this question more completely.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was recently working on a mobile version of
&lt;a href=&quot;http://fuelmyroute.com&quot;&gt;FuelMyRoute&lt;/a&gt;. I started by using jQuery Mobile and
Backbone, but I found trying to use jQuery Mobile as a UI framework frustrating
so I decided to give &lt;a href=&quot;http://getbootstrap.com/&quot;&gt;the Bootstrap CSS framework&lt;/a&gt; a
try. I was able to convert my code over to Bootstrap fairly easily, but I
started reading about and thinking about the responsive features of Bootstrap.
This got me to thinking maybe I could make a responsive Single Page Application,
one website that would work well on mobile devices and on desktop computers.&lt;/p&gt;
&lt;p&gt;The benefits are pretty obvious I think. I don&#39;t relish the idea of maintaining
two separate web applications. Especially when a lot of the non-UI code would be
very similar.  I could get a mobile site for my application while at the same
time updating and modernizing the existing desktop site.  That&#39;s a huge win!&lt;/p&gt;
&lt;p&gt;I should probably define what I mean by &lt;em&gt;responsive SPA&lt;/em&gt;.  First of all, a
Single Page Application is a web application where there is only an initial full
page load. From that point forward AJAX is used to interact with the server to
fetch data (e.g. get new mail) or to perform server side actions (e.g. send an
email). The DOM is manipulated as appropriate in response to user actions and
requested information. A &lt;em&gt;responsive SPA&lt;/em&gt; is one where the UI of the SPA changes
based on the size of the viewport, so that it is more appropriate/usable on
smaller viewports but also can adapt and take advantage of more screen space on
larger viewports. &lt;em&gt;Responsive&lt;/em&gt; to me means also taking a &lt;em&gt;mobile-first&lt;/em&gt; approach
to web application development, where the mobile phone/small tablet use case is
given primary (or at least equal) consideration.&lt;/p&gt;
&lt;p&gt;But, I don&#39;t really see or hear much about responsive SPAs. I&#39;m talking strictly
about web &lt;em&gt;applications&lt;/em&gt;, not web &lt;em&gt;sites&lt;/em&gt;. If you are building, for example, a
blog, then there is a lot of advice and support for making it responsive.
However, for applications, it&#39;s different. The received wisdom is that it is
better to have two different sites, one for mobile and one for desktop.  Why?
This is a question I want to answer along with the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What are the problems/tradeoffs that are encountered when making a responsive
  SPA?&lt;/li&gt;
&lt;li&gt;Is it possible to use only CSS, only media queries to switch between different
  layouts for &lt;em&gt;mobile&lt;/em&gt; and &lt;em&gt;desktop&lt;/em&gt; usage? Or would it be necessary to have the
  JavaScript code be aware of whether the application is in &lt;em&gt;mobile&lt;/em&gt; or
  &lt;em&gt;desktop&lt;/em&gt; mode? (Ideally the responsiveness would be implemented in CSS only)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this blog post I cover my initial thoughts about how a responsive SPA could
work and what the challenges are likely to be.&lt;/p&gt;
&lt;h4&gt;Responsive Mobile UI Patterns&lt;/h4&gt;
&lt;p&gt;How would this work in practice?  In this section I&#39;ll go over a couple of
common mobile UI patterns and how they would adapt to a larger viewport.&lt;/p&gt;
&lt;h5&gt;Separate &quot;pages&quot; (mobile) vs in-page controls (desktop)&lt;/h5&gt;
&lt;p&gt;Sometimes the ideal view on mobile is very different from the ideal view on
desktop. A common pattern here is that on desktop you have enough room to
display all controls on the same screen, but on mobile you might want a separate
full page view for certain actions.  For example, imagine an airplane flight
search application.  On desktop you could have the fields for departing city and
arriving city and dates on one page and display the results under those
controls.  On mobile, there isn&#39;t enough room for this so you would rather have
a separate full page view for specifying search criteria.&lt;/p&gt;
&lt;p&gt;In some ways, this is the least ideal situation. It is always better to be able
to reuse the same controls and just style them differently using media queries.
However, we must anticipate that this might not always be possible and think
about what we could do in that situation.&lt;/p&gt;
&lt;p&gt;To accomplish this, we could simply include the mobile full page alternate view
in the page, hidden unless the width of the page is wide enough.  By default,
the mobile view is hidden.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nf&quot;&gt;#mobile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#fff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;absolute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;480px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;.desktop-only&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;#mobile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I created a &lt;a href=&quot;http://jsfiddle.net/machristie/01kypvf5/&quot;&gt;very simple demo of this concept using the airplane ticket search
example&lt;/a&gt;. In practice, you would want
to have your application code add and remove CSS classes from a top level
element to drive hiding and showing different views, but I&#39;ve left that sort of
thing out.&lt;/p&gt;
&lt;p&gt;This &quot;separate page&quot; view could possible have a use on the desktop layout. You
might have a situation where not all controls fit on the desktop layout so the
same view to show all controls can be used on mobile and desktop.  On mobile it
might be styled as a full page view, whereas on desktop it could be styled as a
modal popup.&lt;/p&gt;
&lt;p&gt;Data binding is a little complicated in such a situation.  Ideally, if the user
changes the size of the browser window then switching from &quot;mobile&quot; to &quot;desktop&quot;
or vice versa should be seamless from a user input perspective. Using the
airplane ticket search example, if I am in the &quot;mobile&quot; view and I type in a
&lt;em&gt;Departing from&lt;/em&gt; city and then decide to expand my browser and get the &quot;desktop&quot;
view, then ideally the &lt;em&gt;Departing from&lt;/em&gt; control in the &quot;desktop&quot; layout should
be populated with what I had typed on the &quot;mobile&quot; view. This means that I need
to bind to the &lt;em&gt;keypress&lt;/em&gt; event and update my model as each key is typed in
&lt;em&gt;Departing from&lt;/em&gt; and keep the &quot;mobile&quot; and &quot;desktop&quot; &lt;em&gt;Departing from&lt;/em&gt; fields in
sync.&lt;/p&gt;
&lt;p&gt;Another challenge with this approach is that you, obviously, have two different
views that have to be maintained. Arguably, this is one of the benefits of
adopting MVC in the first place: your models are independent of views and models
can have more than one view. However, it is still something extra that has to be
maintained. It is probably better than having two separate sites though.&lt;/p&gt;
&lt;h5&gt;List and detail views on separate pages (mobile) vs both on the same page (desktop)&lt;/h5&gt;
&lt;p&gt;A common pattern with mobile apps is that you have a view(s) that display lists
of data and tapping on a list item takes you to a view that displays details for
that item.  Examples include inbox listing/email detail and contact
listing/contact details.&lt;/p&gt;
&lt;p&gt;On desktop however there is enough space to show both the list and the detail,
typically with the list on the left hand side and the detail view on the right.
For example, an email client.&lt;/p&gt;
&lt;p&gt;Media queries can be used to achieve both of these layouts. One nice thing here
is that the same views are used on mobile and on desktop. Its just on mobile
they are separate &quot;pages&quot; and on desktop they are all on one page.&lt;/p&gt;
&lt;p&gt;How would you achieve this with media queries?  I won&#39;t flesh out an entire
example here, but I will outline how it would be done.  The key I think is to
have your SPA router add/remove CSS classes to a root element of the DOM. When
the &quot;list&quot; class is added to the root element, the mobile media query will make
just the list view visible, hiding the detail view.  For desktop, there is no
additional work needed. Likewise, when transitioning to the detail route, the
&quot;list&quot; class is removed from the root element and a &quot;detail&quot; class is added. The
mobile media query would then hide the list view and make the detail view
visible.  On desktop, the presence of the &quot;detail&quot; class on the root element
might cause the currently selected item to be highlighted.&lt;/p&gt;
&lt;p&gt;One challenge that this approach highlights (and this was true of the &quot;separate
view&quot; UI pattern above) is that although on mobile the user is seeing only one
view at a time, those other views are still there.  For example, in an email
client app, only the detail view may be visible, but the list view is still
there and still responding to model updates.  So for example, if you have a
periodic check for new email, then the list view is updating to display new
email received.  This is more of a problem for mobile where off screen updates
may cause performance to drag. On desktop the presence of alternate views that
aren&#39;t on screen is unlikely to cause much of a problem.&lt;/p&gt;
&lt;h4&gt;Challenges with doing responsive SPA&lt;/h4&gt;
&lt;p&gt;Some of these challenges were mentioned above. Here I&#39;ll summarize them and also
discuss how to address some of them. Not having experience developing a
responsive SPA, this is mostly speculation about what I anticipate would be
challenges building one.&lt;/p&gt;
&lt;h5&gt;Sizing of controls&lt;/h5&gt;
&lt;p&gt;It&#39;s possible to use media queries to size controls differently. You could for
example make buttons large, more &quot;tap friendly&quot; on mobile screens and smaller on
desktop screens.&lt;/p&gt;
&lt;p&gt;However, one would have to assume that small screens are tapped on and large
screens are clicked on. And that assumption isn&#39;t valid in a lot of cases. For
example, a mobile phone might have a stylus that is able to make very precise
touches. As another example, there are now several Windows 8 devices, some that
are tablet/laptop hybrids, that are basically desktop devices but allow for
touch interaction.&lt;/p&gt;
&lt;p&gt;So I think a reasonable approach is to just &lt;strong&gt;size all controls for tapping&lt;/strong&gt;.
The tradeoff is that on desktop the controls are going to be &quot;fatter&quot; than
necessary, meaning you won&#39;t be able to fit as many controls on the same page,
but I don&#39;t think there is any reasonable alternative unless you want to
aggravate uses with large touch screens.&lt;/p&gt;
&lt;p&gt;Also, the fact that you can&#39;t have as many controls on a desktop view is not
necessarily a bad thing. It will lead to a simplification of the UI, which will
probably end up being easier to use.&lt;/p&gt;
&lt;h5&gt;Off screen view updates on mobile&lt;/h5&gt;
&lt;p&gt;I mentioned this one above.  What can be done?  For one, I think some testing
and validation that this causes an issue is necessary first.  Are DOM updates
that are off screen as intensive as on screen ones for the browser to handle?
Maybe, hopefully, not. I think it can very much depend on the application and
might only affect certain views but not others.&lt;/p&gt;
&lt;p&gt;If it becomes a problem I think one thing that could be done is to delay
re-rendering the view if the view is off screen.  Whenever it is ready to be
brought back on screen the view could first be fully re-rendered. The problem
here is that JS code now needs to know if the app is in &quot;mobile&quot; mode or
&quot;desktop&quot; mode and so far I&#39;ve been trying to keep the differences purely in CSS
media queries.&lt;/p&gt;
&lt;h5&gt;Duplicate UIs&lt;/h5&gt;
&lt;p&gt;This one is mentioned above too.  This is most applicable when the &quot;mobile&quot;
version of the app needs a completely different view from the &quot;desktop&quot; version.&lt;/p&gt;
&lt;p&gt;To mitigate this, first, obviously, try to use the same views for &quot;mobile&quot; and
&quot;desktop&quot; and simply have them laid out differently.&lt;/p&gt;
&lt;p&gt;Also it should be said that the duplication of effort and maintenance is
probably not nearly so much as having two separate sites.&lt;/p&gt;
&lt;p&gt;Also as mentioned above, there is also the data binding consideration: you&#39;ll
want to keep the &quot;mobile&quot; and &quot;desktop&quot; views in sync at all times because the
user could at any time transition from one to the other. In practice I think
this requires only a little extra effort.  See the discussion on listening for
&lt;em&gt;keypress&lt;/em&gt; events above.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Well that&#39;s it for my initial thoughts. I hope to investigate this further and
try some of these techniques out.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/2782808552791146915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/2782808552791146915' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2782808552791146915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2782808552791146915'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/12/initial-thoughts-on-responsive-single.html' title='Initial thoughts on Responsive Single Page Applications'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-2092265809386996187</id><published>2014-06-24T23:04:00.000-04:00</published><updated>2014-06-24T23:04:42.788-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="backbone"/><category scheme="http://www.blogger.com/atom/ns#" term="jquery"/><category scheme="http://www.blogger.com/atom/ns#" term="jquerymobile"/><title type='text'>A Backbone-JQuery Mobile skeleton project -</title><content type='html'>&lt;!-- A Backbone-JQuery Mobile skeleton project --&gt;

&lt;p&gt;I&#39;ve been playing around with integrating Backbone and jQuery Mobile. I&#39;m
planning on using them as the framework for implementing a mobile version of
&lt;a href=&quot;http://fuelmyroute.com&quot;&gt;FuelMyRoute&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I started with Christophe Coenraets&#39;
&lt;a href=&quot;https://github.com/ccoenraets/backbone-jquerymobile&quot;&gt;backbone-jquerymobile&lt;/a&gt;
sample app and made changes to bring it up to date with the most recent versions
of jQuery Mobile and jQuery.  I also made a couple different design choices.  In
this post I&#39;ll go over the changes I made.&lt;/p&gt;
&lt;h1&gt;jQuery.on&lt;/h1&gt;
&lt;p&gt;A couple of jQuery&#39;s event listener methods were removed in 1.9: &lt;code&gt;live&lt;/code&gt; and
&lt;code&gt;bind&lt;/code&gt;. I updated several event listeners, like the &lt;code&gt;mobileinit&lt;/code&gt; event listener,
to use &lt;a href=&quot;http://api.jquery.com/on/&quot;&gt;jQuery.on&lt;/a&gt; instead.&lt;/p&gt;
&lt;h1&gt;mobileinit&lt;/h1&gt;
&lt;p&gt;To configure jQuery Mobile, you set up a listener for the &lt;code&gt;mobileinit&lt;/code&gt; event and
set properties on the &lt;code&gt;$.mobile&lt;/code&gt; object.  Here&#39;s what I have so far.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;mobileinit&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mobile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajaxEnabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mobile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;linkBindingEnabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mobile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hashListeningEnabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mobile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pushStateEnabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mobile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;autoInitializePage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is identical to Coenraets&#39; config except that I also added setting
&lt;code&gt;autoInitializePage&lt;/code&gt; to false. We&#39;ll get to that in a bit.  The other settings
are there to turn off the routing and &lt;em&gt;link hijacking&lt;/em&gt; behaviour in jQuery
Mobile so we can use Backbone for routing instead. Coenraets explains &lt;a href=&quot;http://coenraets.org/blog/2012/03/using-backbone-js-with-jquery-mobile/&quot;&gt;in his
blog post on the
topic&lt;/a&gt;
and &lt;a href=&quot;http://demos.jquerymobile.com/1.4.2/backbone-requirejs/&quot;&gt;the jQuery Mobile project also has notes on integrating with
Backbone&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;autoInitializePage&lt;/h1&gt;
&lt;p&gt;By default jQuery Mobile will call &lt;code&gt;initializePage()&lt;/code&gt; when it starts up.
&lt;code&gt;initializePage()&lt;/code&gt; is important because it initializes the pagecontainer and
sets up navigation events.  It will try to find the first div with
data-role=&quot;page&quot; and change to that page. If there isn&#39;t a page in the DOM, it
will create an initial dummy page. This generally works out fine if you are
using jQuery Mobile in the more typical way where you have multiple pages
defined in the one page. However, with our Backbone integration, there isn&#39;t any
page until the router runs and injects the first page into the DOM so it doesn&#39;t
make sense to automatically call &lt;code&gt;initializePage()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So what I did was set &lt;code&gt;autoInitializePage&lt;/code&gt; to false. The Router will call
&lt;code&gt;initializePage()&lt;/code&gt; after it adds the first page to the DOM.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AppRouter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;changePage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Render and add page to DOM once&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;body&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// We turned off $.mobile.autoInitializePage, but now that we&amp;#39;ve&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// added our first page to the DOM, we can now call initializePage.&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mobile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initializePage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstPage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;:mobile-pagecontainer&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pagecontainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;change&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;changeHash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Managing Pages as Views&lt;/h1&gt;
&lt;p&gt;There are a couple different ways to go when managing page Views. You could
&lt;code&gt;remove&lt;/code&gt; them and recreate them each time or you could not &lt;code&gt;remove&lt;/code&gt; them and
just let jQuery Mobile hide and show them.  Coenraets went with the &quot;recreate
each time&quot; approach. I went with the approach of letting jQuery Mobile hide and
show pages.  My page Views are rendered and then added to the DOM once.&lt;/p&gt;
&lt;p&gt;I did this because it seems a better fit with jQuery Mobile.  Also I think there
is a performance benefit on mobile to keeping DOM manipulations to a minimum.&lt;/p&gt;
&lt;p&gt;However, I am still concerned about my page Views being bound to models even
when they aren&#39;t being shown.  Offscreen pages might re-render unnecessarily due
to model/collection updates.&lt;/p&gt;
&lt;p&gt;I might add to my router the ability to let pages know when they are being
hidden or shown and that would allow a page to deal with offscreen rendering
performance issues. One thing a page View might do is unbind its listeners when
being hidden and rebind them when being shown again, which might be appropriate
if intermediate events can be safely ignored.  Another thing a page View might
do when not being shown is continue to listen for events but defer any
re-rendering until actually shown.  I&#39;ll explore this more as needed, but I need
a real world example to guide the design.&lt;/p&gt;
&lt;h1&gt;Enhancing pages&lt;/h1&gt;
&lt;p&gt;I did a little exploration into how you would handle jQuery Mobile enhancement
if you re-rendered page.  Basically, whenever render() is called, the page needs
to be re-enhanced. jQuery Mobile will automatically enhance a page the first
time it is changed to, but after that you need to call it yourself. I
implemented a &lt;code&gt;View&lt;/code&gt; base class I call &lt;a href=&quot;https://github.com/machristie/backbone-jquerymobile/blob/master/js/views/PageView.js&quot;&gt;PageView&lt;/a&gt; that has an &lt;code&gt;enhance&lt;/code&gt; method.
It allows you to implement &lt;code&gt;render&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// do some rendering&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;enhance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// See PageView.enhance for details&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Keep in mind, though, re-rendering and re-enhancing the entire page is
discouraged for performance reasons.&lt;/p&gt;
&lt;h1&gt;Minor stuff&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;$.mobile.changePage is deprecated. I switched to the &lt;code&gt;change&lt;/code&gt; method on the
  &lt;code&gt;pagecontainer&lt;/code&gt;. See the &lt;code&gt;changePage&lt;/code&gt; method on the AppRouter above.&lt;/li&gt;
&lt;li&gt;Instead of &lt;code&gt;&amp;lt;div data-role=&quot;content&quot;&amp;gt;&lt;/code&gt;, use &lt;code&gt;&amp;lt;div class=&quot;ui-content&quot;
  role=&quot;main&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Contrary to Coenraets, I didn&#39;t find I needed to disable the first page
  transition, so I removed that code.&lt;/li&gt;
&lt;li&gt;I also switched to project to use Bower and RequireJS to manage dependencies.&lt;/li&gt;
&lt;li&gt;I never got around to dealing with transitions. Delegating routing to Backbone
  means you miss out on the declarative transition stuff in jQuery Mobile. I&#39;m
  thinking that eventually I might add a &lt;code&gt;transitions&lt;/code&gt; hash to the Router that
  would allow you to define page to page transitions, something like&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;transitions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;page1:page2&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;s1&quot;&gt;&amp;#39;slide&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// etc...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/2092265809386996187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/2092265809386996187' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2092265809386996187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2092265809386996187'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/06/a-backbone-jquery-mobile-skeleton.html' title='A Backbone-JQuery Mobile skeleton project -'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4804225866797347446</id><published>2014-06-01T09:37:00.000-04:00</published><updated>2014-06-01T09:37:43.502-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="git"/><title type='text'>Git client setup</title><content type='html'>&lt;!--Git client setup--&gt;

&lt;p&gt;These are some settings and configuration I&#39;ve found useful so far while working
with Git.&lt;/p&gt;
&lt;h2&gt;Git global configuration&lt;/h2&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global user.name &lt;span class=&quot;s2&quot;&gt;&amp;quot;Marcus Christie&amp;quot;&lt;/span&gt;
git config --global user.email marc.christie@gmail.com
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Can also set an editor to use for commit messages&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global core.editor gvim
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Or &lt;a href=&quot;http://stackoverflow.com/questions/4737381/git-editor-not-working-with-macvim&quot;&gt;with MacVim on OS X&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global core.editor &lt;span class=&quot;s1&quot;&gt;&amp;#39;mvim -f&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;However, I think I prefer to edit commit messages in the terminal.&lt;/p&gt;
&lt;p&gt;You can also use gvimdiff as a merge tool, but I haven&#39;t tried this yet.&lt;/p&gt;
&lt;h2&gt;Excludes file&lt;/h2&gt;
&lt;p&gt;Set up a global excludes file in &lt;code&gt;~/.config/git/ignore&lt;/code&gt;. My entries so far:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;swp&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DS_Store&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Whitespace&lt;/h2&gt;
&lt;p&gt;On Windows you want&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global core.autoclrf &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I think this is the default on Windows also, so this may be unnecessary.&lt;/p&gt;
&lt;h2&gt;Credential helper&lt;/h2&gt;
&lt;p&gt;This tip is mainly for when you are working with a repo over HTTPS, for example,
with GitHub, and you authenticate with a username and password. You don&#39;t want
to have to type passwords over and over. For this you can specify a credential
helper that will securely store your password.  On OS X:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global credential.helper osxkeychain
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;On Windows, download &lt;a href=&quot;http://gitcredentialstore.codeplex.com/&quot;&gt;git-credential-store&lt;/a&gt;.  Then start up &lt;em&gt;Git Bash&lt;/em&gt;, go to
the directory where you downloaded the executable and then run it from the
command line&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git-credential-winstore.exe
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Aliases&lt;/h2&gt;
&lt;p&gt;Shortcuts so you can run &lt;code&gt;git ci -m &quot;fixed bug&quot;&lt;/code&gt; instead of typing out &lt;code&gt;commit&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global alias.ci commit
git config --global alias.st status
git config --global alias.co checkout
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Bash completions&lt;/h2&gt;
&lt;p&gt;On Windows, &lt;em&gt;Git Bash&lt;/em&gt; comes with these already configured. On OS X, I
downloaded &lt;a href=&quot;https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash&quot;&gt;git-completion.bash&lt;/a&gt;, dropped it in &lt;code&gt;~/bin&lt;/code&gt; and in
&lt;code&gt;.bash_profile&lt;/code&gt; I have&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;## Git completions&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/bin/git-completion.bash
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Web viewer&lt;/h2&gt;
&lt;p&gt;On OS X:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global instaweb.httpd webrick
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now you can start up a web viewer with&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git instaweb
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As a Mercurial refugee, I got used to &lt;code&gt;hg serve&lt;/code&gt; so I like to have a web view.&lt;/p&gt;
&lt;p&gt;Haven&#39;t tried doing this on Windows yet.&lt;/p&gt;
&lt;h2&gt;push.default&lt;/h2&gt;
&lt;p&gt;Set &lt;code&gt;push.default&lt;/code&gt; to simple:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global push.default simple
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This setting affects what happens when you do a &lt;code&gt;git push&lt;/code&gt; without specifing a
remote or branch to push.  With &lt;em&gt;simple&lt;/em&gt; git will push the current branch to the
upstream tracked branch.  This mode also is the new default in Git 2.0.&lt;/p&gt;
&lt;p&gt;Make sure that when you first push a branch to a remote server that you also set
it as the upstream tracked branch. You can do that with the &lt;code&gt;-u&lt;/code&gt; option:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git push -u origin mybranch
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;From then on every push can be done simply with&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git push
&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;merge.defaultToUpstream&lt;/h2&gt;
&lt;p&gt;Set &lt;code&gt;merge.defaultToUpstream&lt;/code&gt; to true&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git config --global merge.defaultToUpstream &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This setting affects what happens when you do a &lt;code&gt;git merge&lt;/code&gt; without specifying a
branch to merge from. With this set to true, git will merge in changes from the
upstream remote tracking branch, which is generally what you want.&lt;/p&gt;
&lt;h2&gt;Anything else?&lt;/h2&gt;
&lt;p&gt;Are there any other things you do to configure Git on a new machine? Let me know
in the comments or on &lt;a href=&quot;https://twitter.com/marcus_christie&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4804225866797347446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/4804225866797347446' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4804225866797347446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4804225866797347446'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/06/git-client-setup.html' title='Git client setup'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-1940916485537817412</id><published>2014-05-26T13:13:00.000-04:00</published><updated>2014-05-26T13:13:33.702-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="backbone"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><title type='text'>Backbone Overview</title><content type='html'>&lt;p&gt;&lt;a href=&quot;http://backbonejs.org/&quot;&gt;Backbone&lt;/a&gt; is a JavaScript Model-View-Controller (MVC)
library that can be used to create single page applications (SPAs). This article
introduces the most important concepts in Backbone (Models, Collections, Views,
Events, Router and Sync) and how they relate to building a client side
JavaScript application.&lt;/p&gt;
&lt;h4&gt;What is Model-View-Controller (MVC)?&lt;/h4&gt;
&lt;p&gt;Model-View-Controller might be one of the most misunderstood software patterns
ever.  I&#39;m not even sure I really understand what the original idea was (at
least, what it meant to Smalltalk developers when first developed at Xerox
PARC), and of course it has evolved over time into several different closely
related ideas.&lt;/p&gt;
&lt;p&gt;So this is far from authoritative, and I&#39;ll try to keep it simple.  To me, MVC
is a way to organize the implementation of a user interface in a way that
separates concerns.  Here, at a high level, are the various parts of a MVC
framework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; - this is the representation of data that models the domain of
  interest.  For example, for a TODO application, a model might be a TODO item.
  But Models aren&#39;t just data structures, they also contain the domain logic. A
  TODO item might expose a &lt;code&gt;complete&lt;/code&gt; method that knows how to mark a TODO item
  as completed and properly manage any additional details related to task
  completion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;View&lt;/strong&gt; - views are visual representations of models. A view reacts to
  changes in a model by updating the view to reflect that change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controller&lt;/strong&gt; - controllers handle user input, both displaying views that the
  user requests and handling keyboard and mouse events.  Controllers typically
  translate user input into updates on Model instances.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal is separation of concerns. Models know nothing of views; in a web
application, models would have nothing in them relating to HTML or CSS, for
example.  Views know only how to represent a model, but they contain no business
logic. Views respond to changes in a model, but know nothing of what the user is
doing.  Controllers are the only place in the application to handle things like
navigation through the application, display of multiple views at once,
transitions between views and translating user actions into model updates.  But
controllers don&#39;t contain business logic.&lt;/p&gt;
&lt;h4&gt;How does Backbone relate to traditional MVC?&lt;/h4&gt;
&lt;p&gt;The Backbone API has the following types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;li&gt;Model&lt;/li&gt;
&lt;li&gt;Collection&lt;/li&gt;
&lt;li&gt;View&lt;/li&gt;
&lt;li&gt;Router&lt;/li&gt;
&lt;li&gt;Sync&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where do each of these concepts fit into the traditional MVC pattern?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Backbone.Events&lt;/code&gt; are the primary mechanism for loose coupling between the
models and views. Backbone Views bind to changes on the Models or Collections.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Backbone.Model&lt;/code&gt; and &lt;code&gt;Backbone.Collection&lt;/code&gt; are the M of MVC: these types can be
extended to provide the data and the implementation of domain logic for the
application.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Backbone.View&lt;/code&gt; classes are a little V and a little C when compare to classical
MVC. &lt;code&gt;Backbone.View&lt;/code&gt; contains a &lt;code&gt;render&lt;/code&gt; method that is responsible for
generating/updating the DOM that is the view of the model, and for doing so it
is typical to have a template. The template is more the V of MVC than the View
class. &lt;code&gt;Backbone.View&lt;/code&gt; also acts as a Controller in that it binds user events to
methods on the View class that will update Models.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Backbone.Router&lt;/code&gt; is also fairly controller-ish in the traditional MVC
understanding.  The Router responds to user requests for specific URLs and can
handle them by showing the right type of Views and by making sure that Model
instances are available.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Backbone.sync&lt;/code&gt; is the RESTful persistence mechanism for saving/updating models.
In Backbone, the models (Model and Collection instances) know how to persist
themselves (which endpoint to call, how to serialize/deserialize, etc.). In that
sense, &lt;code&gt;sync&lt;/code&gt; is more in the M of MVC than anything else, but I&#39;m not sure that
persistence is in the scope of traditional MVC. (Another way to think of it is
that &lt;code&gt;sync&lt;/code&gt; is a translation layer between a client side model and a server side
model, which are just two representations of the same domain object.)&lt;/p&gt;
&lt;h4&gt;Events&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Backbone.Events&lt;/code&gt; provides standard event listening and triggering behavior.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Events.on(event, listener)&lt;/code&gt; adds a listener&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Events.off(event, listener)&lt;/code&gt; removes listener&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Events.trigger(event)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Backbone.Events&lt;/code&gt; can also be &lt;em&gt;mixed in&lt;/em&gt; to other objects or classes via
underscore&#39;s &lt;code&gt;_.extend&lt;/code&gt; mechanism, and it is mixed in to &lt;code&gt;Backbone.View&lt;/code&gt;,
&lt;code&gt;Backbone.Model&lt;/code&gt; etc. So these methods are available from most Backbone types.&lt;/p&gt;
&lt;p&gt;By convention, Backbone Events are often &lt;em&gt;namespaced&lt;/em&gt;. For example, you can listen to all changes
on a model with &lt;code&gt;model.on(&quot;change&quot;, listener)&lt;/code&gt;, but you can also listen to just
a change of the property &lt;code&gt;&quot;name&quot;&lt;/code&gt; with &lt;code&gt;model.on(&quot;change:name&quot;, listener)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But keep in mind there is no extra support in the implementation of
&lt;code&gt;Backbone.Events&lt;/code&gt; for namespaced events really, not like &lt;a href=&quot;http://marcus-christie.blogspot.com/2014/04/bootstraps-alertjs-plugin-line-by-line.html&quot;&gt;jQuery namespaced
events&lt;/a&gt;.
&lt;code&gt;&quot;change:name&quot;&lt;/code&gt; works because &lt;code&gt;Backbone.Model&lt;/code&gt; dispatches an event for each
property that changes and also a &quot;change&quot; event.  As another example, if you
listen for &lt;code&gt;&quot;foo&quot;&lt;/code&gt; and a &lt;code&gt;&quot;foo:bar&quot;&lt;/code&gt; event is triggered, your event listener
will not be called.  You would have to trigger both &lt;code&gt;&quot;foo&quot;&lt;/code&gt; and &lt;code&gt;&quot;foo:bar&quot;&lt;/code&gt; in
your code if you wanted to support namespacing.&lt;/p&gt;
&lt;p&gt;One problem with setting up event listeners, especially with a View listening to
changes on a Model, is that the object being listened to has a reference to the
listener.  For example, let&#39;s say you have a ContactView that is listening for
changes to a Contact Model instance. If you dispose of the ContactView but
forget to remove all of the event listeners, then the Contact Model still has a
reference to your ContactView.  This leads to a couple problems. First, your
ContactView instance won&#39;t get garbage collected, so your app is now leaking
memory. Second, whenever the Contact Model updates it will continue to call the
event listener on the &lt;em&gt;zombie&lt;/em&gt; ContactView and update it, so you have a lot of
unnecessary code execution (and debugging this can get really confusing when you
see code executed several times instead of just once as expected).&lt;/p&gt;
&lt;p&gt;To solve this, &lt;code&gt;Backbone.Events&lt;/code&gt; has two helpful methods, &lt;code&gt;listenTo&lt;/code&gt; and
&lt;code&gt;stopListening&lt;/code&gt;.  &lt;code&gt;listenTo&lt;/code&gt; has this method signature&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listenTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Whereas you call &lt;code&gt;on&lt;/code&gt; on the object you want to listen to, &lt;code&gt;listenTo&lt;/code&gt; is called
on the listening object.  The advantage here is that the listening object can
keep track of all of the listeners and can remove them all at once, which is
what &lt;code&gt;stopListening&lt;/code&gt; does.&lt;/p&gt;
&lt;p&gt;One other note about events. In a Backbone app, you typically have two types of
events: Backbone events and DOM events.  DOM events are typically set up for a
View in the &lt;em&gt;events hash&lt;/em&gt;, which we&#39;ll get to later.  When using the &lt;em&gt;events
hash&lt;/em&gt;, &lt;code&gt;this&lt;/code&gt; refers to the View, pretty much what you expect.  However, keep in
mind, if you programmatically use the jQuery API to bind to DOM events then
&lt;code&gt;this&lt;/code&gt; refers to the DOM element.&lt;/p&gt;
&lt;h4&gt;Model&lt;/h4&gt;
&lt;p&gt;To create a &lt;code&gt;Backbone.Model&lt;/code&gt;, extend the &lt;code&gt;Backbone.Model&lt;/code&gt; class.  You can
specify &lt;code&gt;default&lt;/code&gt; values for various properties.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Todo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Default attributes ensure that each todo created has `title` and `completed` keys.&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;completed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To instantiate a Model instance, call the constructor and pass in the attributes
for the instance.  Any defaulted attributes that aren&#39;t specified will receive
their default values.&lt;/p&gt;
&lt;p&gt;Models have &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; functions for reading and writing attribute values.
As mentioned above, calling &lt;code&gt;set(&quot;myattr&quot;, newvalue)&lt;/code&gt; causes two events to be
dispatched: &quot;change:myattr&quot; and &quot;change&quot;.&lt;/p&gt;
&lt;p&gt;Models also have a special property called &lt;code&gt;id&lt;/code&gt; which uniquely identifies a
Model instance. This can be set to an integer or UUID string.  You pass it in
the attributes hash when creating a Model instance. You can also set the
&lt;code&gt;idAttribute&lt;/code&gt; property on the Model class if you have a property on your Models
that can be used to uniquely identify instances.&lt;/p&gt;
&lt;h4&gt;Collection&lt;/h4&gt;
&lt;p&gt;Create a new Collection by extending &lt;code&gt;Backbone.Collection&lt;/code&gt;. You typically set
the &lt;code&gt;model&lt;/code&gt; property to the Model class of this collection.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TodoList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Reference to this collection&amp;#39;s model&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Collections redispatch Model events, so you can simply listen, for example, to
&quot;change&quot; events on the Collection and you&#39;ll be notified whenever a Model
instance changes.&lt;/p&gt;
&lt;p&gt;You can &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;remove&lt;/code&gt; Models to and from a Collection. These methods will
dispatch &quot;add&quot; and &quot;remove&quot; events.  Removing a model occurs when you call
&lt;code&gt;remove&lt;/code&gt; and pass in a Model instance that has the same &lt;code&gt;id&lt;/code&gt; as a Model instance
already in the Collection. Collections also have a &lt;code&gt;reset&lt;/code&gt; method which updates
the Collection all at once and dispatches just a single &quot;reset&quot; event, which is
more efficient for example when initially loading a Collection.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://backbonejs.org/#Collection-Underscore-Methods&quot;&gt;Collections have several Underscore
methods&lt;/a&gt;, like &lt;code&gt;_.each&lt;/code&gt;,
that you can call directly.&lt;/p&gt;
&lt;p&gt;Collections are typically where you will set up the RESTful URL by setting the
&lt;code&gt;url&lt;/code&gt; property.  You can then call &lt;code&gt;fetch&lt;/code&gt; to retrieve all of the model
instances in the collection and add them to the collection instance. We&#39;ll look
at this more in the &lt;em&gt;Sync&lt;/em&gt; section below.&lt;/p&gt;
&lt;h4&gt;View&lt;/h4&gt;
&lt;p&gt;Backbone View&#39;s always have a DOM element that they can render into. By default
&lt;code&gt;Backbone.View&lt;/code&gt; will create the DOM element for you, but if the DOM element you
want to attach this View instance to is already in the page you can set &lt;code&gt;el&lt;/code&gt; to
a selector for that DOM element&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MyView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;#myview&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you let Backbone create your DOM element, you can specify &lt;code&gt;tagName&lt;/code&gt;,
&lt;code&gt;className&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;attributes&lt;/code&gt; to be set on that DOM element and Backbone
will apply them. That is, if you specify a &lt;code&gt;tagName&lt;/code&gt; of &lt;em&gt;li&lt;/em&gt; and a &lt;code&gt;className&lt;/code&gt;
of &lt;em&gt;todo-item&lt;/em&gt;, Backbone will create a &lt;code&gt;&amp;lt;li class=&quot;todo-item&quot; /&amp;gt;&lt;/code&gt; element in the
DOM for you.&lt;/p&gt;
&lt;p&gt;As a convenience, View&#39;s also have a &lt;code&gt;$el&lt;/code&gt; property which is the jQuery wrapped
reference to the View&#39;s DOM element.&lt;/p&gt;
&lt;p&gt;A typical thing to do when you initialize a View is to pass it the &lt;code&gt;model&lt;/code&gt; or
&lt;code&gt;collection&lt;/code&gt; instance you want it to bind to.  In the View&#39;s &lt;code&gt;initialize&lt;/code&gt;
method, you can then bind to changes to that Model or Collection:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TodoView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;tagName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;li&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;todo-item&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listenTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;change&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//...&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TodoView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;aTodo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Besides binding to events on the Model, a View typically binds to DOM events.
This is one of the &lt;em&gt;controller-ish&lt;/em&gt; things a Backbone View does. To bind to DOM
events, specify the &lt;code&gt;events&lt;/code&gt; hash when creating the view. The keys in the events
hash are in the form of &lt;code&gt;&#39;eventName selector&#39;&lt;/code&gt; and the value of each is the name
of a function (or a function reference instead if you want).&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TodoView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;click .toggle&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;toggleCompleted&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Inside of a DOM event handler, &lt;code&gt;this&lt;/code&gt; refers to the View.&lt;/p&gt;
&lt;p&gt;To actually render a view to the page, you provide an implementation of
&lt;code&gt;render&lt;/code&gt;. The job of &lt;code&gt;render&lt;/code&gt; is to update &lt;code&gt;this.el&lt;/code&gt; however necessary.  The
typical way to do this is to have a String based template, by default, an
&lt;a href=&quot;http://underscorejs.org/#template&quot;&gt;Underscore template&lt;/a&gt;. You&#39;ll set &lt;code&gt;template&lt;/code&gt;
in a view to a template function that takes an object with the properties of
your model and returns a String of HTML with the model properties applied.&lt;/p&gt;
&lt;p&gt;There are several approaches to how to organize your templates, but the simplest
way is to put them in the web page inside a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag with type set to
&lt;em&gt;text/template&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/template&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;template-id&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;checkbox&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;completed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;checked&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;%-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/label&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;In your View class, you can read in the template once with &lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;//... inside View class&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;#template-id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then you can implement &lt;code&gt;render&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;//... inside View class&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toJSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Anything else you might want to do...&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note that &lt;code&gt;this.$&lt;/code&gt; is a reference to the jQuery object. Also, &lt;code&gt;render&lt;/code&gt; returns
&lt;code&gt;this&lt;/code&gt; so that parent View components can render child View components and then
include them in themselves.  For example, a container of these TodoView
instances might do something like:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todoView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TodoView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todoView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When you are done with a View, you can call &lt;code&gt;remove&lt;/code&gt; on it. This removes
&lt;code&gt;this.el&lt;/code&gt; from the DOM and also calls &lt;code&gt;stopListening&lt;/code&gt; to remove all of its event
listeners.&lt;/p&gt;
&lt;h4&gt;Router&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Backbone.Router&lt;/code&gt; allows mapping URLs to actions and events.  You create a
router instance by extending &lt;code&gt;Backbone.Router&lt;/code&gt;. You can specify a &lt;code&gt;routes&lt;/code&gt; hash
that maps url patterns to function names (or function references). This is
somewhat similar to the events hash in a View.&lt;/p&gt;
&lt;p&gt;Route url patterns can use the &lt;code&gt;:param&lt;/code&gt; syntax of the &lt;code&gt;*param&lt;/code&gt; splat syntax.
&lt;code&gt;:param&lt;/code&gt; is used to match a part of a URL.  A splat matches the rest of the URL.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Router&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;routes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;/search/:query&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;search&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//....&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As an example of how you would use a Router, consider an email application. When
the user navigates to an email folder, the app will display a list of the email
messages in that folder. You would set up a route for an email folder, maybe
like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;routes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;/folder/:folderId&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;goToFolder&amp;#39;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then when a user clicks on the email folder, you can call
&lt;code&gt;Router.navigate(&#39;/folder/123&#39;, {trigger: true})&lt;/code&gt;.  If you want to handle
updating the view to show the folder and just have the router update the URL,
you would not pass &lt;code&gt;{trigger: true}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So now you need to kick things off for your app and have your Router handle
whatever the current URL is (for example, if the user bookmarked that email
folder link and navigated to it directly). To do that you call &lt;code&gt;start&lt;/code&gt; on
&lt;code&gt;Backbone.history&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;appRouter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pushState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Backbone.history is a kind of global router. It can make use of the History API,
calling pushState if available, falling back to updating the URL fragment if not
available. You have to pass &lt;code&gt;{pushState: true}&lt;/code&gt; to &lt;code&gt;start&lt;/code&gt; to make use of
pushState; it is something you opt into in Backbone.&lt;/p&gt;
&lt;h4&gt;Sync&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Backbone.sync&lt;/code&gt; handles persistence. By default, it supports RESTfully
retrieving and saving models to a server, assuming a JSON API.  In the simplest
cases, you just define the base url on your Collections.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Library&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Backbone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/books&amp;#39;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When you call the following methods, the following URLs are invoked via AJAX:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Collection.create maps to a POST to the URL &lt;code&gt;/api/books&lt;/code&gt;&lt;ul&gt;
&lt;li&gt;Collection.create is a convenience function that saves the new model to
  the server and adds it to the Collection.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Collection.fetch maps to a GET to the URL &lt;code&gt;/api/books&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Collection.update maps to a PUT to the URL &lt;code&gt;/api/books/{id}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Collection.delete maps to a DELETE to the URL &lt;code&gt;/api/books/{id}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&#39;s a lot you can customize however.  Models can implement &lt;code&gt;Model.parse&lt;/code&gt; to
have custom response parsing logic.  You can override &lt;code&gt;Backbone.ajax&lt;/code&gt; to
customize the AJAX logic. And you can go whole hog and override &lt;code&gt;Backbone.sync&lt;/code&gt;
to completely customize how to load/persist data, for example, &lt;a href=&quot;https://github.com/jeromegn/Backbone.localStorage&quot;&gt;using
LocalStorage as a backing store for your app&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Additional Resources&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://addyosmani.github.io/backbone-fundamentals/&quot;&gt;Backbone Fundamentals&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;A lot of the code examples in this blog post come from Backbone
  Fundamentals. &lt;strong&gt;Highly recommended.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html&quot;&gt;History of MVC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://c2.com/cgi/wiki?ModelViewController&quot;&gt;C2&#39;s MVC page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/a/22803629/1419499&quot;&gt;Namespacing events is just a convention @ StackOverflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://caniuse.com/history&quot;&gt;Caniuse.com pushState&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/1940916485537817412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/1940916485537817412' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1940916485537817412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1940916485537817412'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/05/backbone-overview.html' title='Backbone Overview'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-1998861341439923857</id><published>2014-05-06T22:11:00.000-04:00</published><updated>2014-05-06T22:11:43.700-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="geo"/><category scheme="http://www.blogger.com/atom/ns#" term="google"/><title type='text'>Using Google&#39;s Places Autocomplete API to find directions</title><content type='html'>&lt;!--
# Using Google&#39;s Places Autocomplete API to find directions
--&gt;

&lt;p&gt;I&#39;m currently integrating Google&#39;s &lt;a href=&quot;https://developers.google.com/places/documentation/autocomplete&quot;&gt;Places Autocomplete
API&lt;/a&gt; into the
&lt;a href=&quot;http://fuelmyroute.com&quot;&gt;FuelMyRoute&lt;/a&gt; Android app.  This way as soon as a user
starts typing a destination, the location will autocomplete.&lt;/p&gt;
&lt;p&gt;The Places Autocomplete API response is something like this:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&amp;quot;predictions&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Barnes &amp;amp; Noble, East 3rd Street, Bloomington, IN, United States&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;5c94b4b6d6ffdc0402451f0ccacd65d04c92b1be&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;matched_substrings&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;length&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;offset&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;reference&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CoQBeAAAAIcYT-uv-ryTSOBQ8Cl3W313c9fuh-J5KCY8N0k-QDVPWGD65lIgs9ZpXar6eIMJ3ey5HL-3d1yMChPIwcO9uDSFdyl_NeHcOgpSFVfqsbBh-E_F0QfVviuZHGPicPRLsGvEXP5jC6NuBZ2-0jQnxVzRNN-6W9XaXxFURgW115mLEhD3vouWuAImM-yWSat1opedGhROZAG_tNmuisZo82H0DOvw-yqj5Q&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;terms&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;offset&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Barnes &amp;amp; Noble&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;offset&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;East 3rd Street&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;offset&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;33&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Bloomington&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;offset&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;46&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;IN&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;offset&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;United States&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;types&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;establishment&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;geocode&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I was then feeding the &lt;strong&gt;description&lt;/strong&gt; (in the case above, &lt;em&gt;Barnes &amp;amp; Noble, East 3rd Street, Bloomington, IN, United States&lt;/em&gt;) as the destination to Google&#39;s &lt;a href=&quot;https://developers.google.com/maps/documentation/directions/&quot;&gt;Directions API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, this turns out to only work sometimes. The &lt;strong&gt;description&lt;/strong&gt; returned by
the Autocomplete API is not necessarily detailed enough to resolve to a geocoded address.&lt;/p&gt;
&lt;p&gt;What you need to do instead is take the &lt;strong&gt;reference&lt;/strong&gt; field for a location and
pass it to yet another API, the &lt;a href=&quot;https://developers.google.com/places/documentation/details&quot;&gt;Place Details API&lt;/a&gt;. These request URLs look like&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nl&quot;&gt;https:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;//maps.googleapis.com/maps/api/place/details/json?\&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;    reference=CoQBeAAAAIcYT...&amp;amp;sensor=true&amp;amp;key=API_KEY_HERE&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The result of which looks like this&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&amp;quot;html_attributions&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&amp;quot;result&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;address_components&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;long_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2813&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;short_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2813&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;types&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;street_number&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;long_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;E 3rd St&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;short_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;E 3rd St&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;types&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;route&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;long_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Bloomington&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;short_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Bloomington&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;types&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;locality&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;political&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;long_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;IN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;short_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;IN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;types&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;administrative_area_level_1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;political&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;long_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;United States&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;short_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;US&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;types&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;country&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;political&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;long_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;47408&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;short_name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;47408&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;types&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;postal_code&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;adr_address&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;\u003cspan class=\&amp;quot;street-address\&amp;quot;\u003e2813 E 3rd St\u003c/span\u003e, \u003cspan class=\&amp;quot;locality\&amp;quot;\u003eBloomington\u003c/span\u003e, \u003cspan class=\&amp;quot;region\&amp;quot;\u003eIN\u003c/span\u003e \u003cspan class=\&amp;quot;postal-code\&amp;quot;\u003e47408\u003c/span\u003e, \u003cspan class=\&amp;quot;country-name\&amp;quot;\u003eUnited States\u003c/span\u003e&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;formatted_address&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2813 E 3rd St, Bloomington, IN, United States&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;formatted_phone_number&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;(812) 331-0669&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;geometry&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;location&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;lat&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;39.165632&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;lng&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;86.49625899999999&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can get the latitude/longitude from &lt;strong&gt;geometry.location&lt;/strong&gt; (also the
&lt;strong&gt;formatted_address&lt;/strong&gt; would likely work as well as a destination in a Directions
API request). Now you can make a Directions API request with an exact
destination.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/1998861341439923857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/1998861341439923857' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1998861341439923857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1998861341439923857'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/05/using-googles-places-autocomplete-api.html' title='Using Google&#39;s Places Autocomplete API to find directions'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7947851965462667148</id><published>2014-05-05T19:47:00.000-04:00</published><updated>2014-05-05T22:43:31.224-04:00</updated><title type='text'>Disjunctive Normal Form: Figuring out what part of a WHERE claused matched</title><content type='html'>
&lt;p&gt;At work we have a way for &lt;em&gt;filters&lt;/em&gt; to be defined by users and for these filters
to trigger other actions (at a very high level, the details aren&#39;t so important
for the purpose of this blog post).  These &lt;em&gt;filters&lt;/em&gt; translate to SQL WHERE
clauses.  I&#39;m currently working on a project to figure out, when a &lt;em&gt;filter&lt;/em&gt;
matches, what was it in the filter that actually matched.&lt;/p&gt;
&lt;p&gt;The problem is this. You can have a filter with arbitrary boolean logic in it.
To take a very simple example, consider the following filter as WHERE clause:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;COLUMN1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COLUMN2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;OR&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When you have a match, you might wonder: &lt;em&gt;Was it COLUMN1 and COLUMN2 that caused
the match, or was it COLUMN1 and COLUMN3?&lt;/em&gt; (or maybe all three matched the
conditions).&lt;/p&gt;
&lt;p&gt;So we can break this down into two problems.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What are all the possible sets of conditions that could satisfy the filter?&lt;/li&gt;
&lt;li&gt;Which of these sets of conditions are matched?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the first problem, we can transform the filter expression into &lt;a href=&quot;http://en.wikipedia.org/wiki/Disjunctive_normal_form&quot;&gt;Disjunctive
Normal Form&lt;/a&gt; (DNF).
Disjunctive Normal Form is an OR-ing of ANDs, where negation is pushed down to
the &quot;leaves&quot; of the boolean expression tree (in other words, negation applies
only to literals).&lt;/p&gt;
&lt;p&gt;Our example above rewritten in DNF becomes:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COLUMN1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;OR&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COLUMN1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For the second part of the problem, I can split apart this filter and apply each
part separately. If &lt;code&gt;(COLUMN1 = 1 AND COLUMN2 = 3)&lt;/code&gt; matches, then I know that
those conditions are true for that match. Likewise for &lt;code&gt;(COLUMN1 = 1 and COLUMN3
= &quot;foo&quot;)&lt;/code&gt;. Now I know what conditions were actually matched for a given match.&lt;/p&gt;
&lt;h1&gt;How to get to Disjunctive Normal Form?&lt;/h1&gt;
&lt;p&gt;Based on what I&#39;ve been reading, there are two main ways to convert a boolean
expression to DNF.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Algebraic - Use the laws of Boolean Algebra, like De Morgan&#39;s law, to rewrite
   the boolean expression into DNF.&lt;/li&gt;
&lt;li&gt;Algorithmic - Generate a truth table, or use an algorithm like
   &lt;a href=&quot;http://en.wikipedia.org/wiki/Quine%E2%80%93McCluskey_algorithm&quot;&gt;Quine-McCluskey&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Algebraic approach&lt;/h2&gt;
&lt;p&gt;The approach is pretty simple and is a two step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Convert first to &lt;a href=&quot;http://en.wikipedia.org/wiki/Negation_normal_form&quot;&gt;Negation Normal Form&lt;/a&gt;. This uses double negation elimination and &lt;a href=&quot;http://en.wikipedia.org/wiki/De_Morgan%27s_laws&quot;&gt;De Morgan&#39;s Laws&lt;/a&gt; to push negation down to the leaves of the boolean expression tree.&lt;/li&gt;
&lt;li&gt;Pull the ORs to the top of the expression tree using the &lt;a href=&quot;http://en.wikipedia.org/wiki/Distributive_property&quot;&gt;Distributive Law&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(Credit for this approach goes to &lt;a href=&quot;http://math.stackexchange.com/a/105638&quot;&gt;this StackExchange answer&lt;/a&gt;.)&lt;/p&gt;
&lt;h2&gt;Algorithmic approach&lt;/h2&gt;
&lt;p&gt;I&#39;ll give an example of this approach using a truth table.  Let&#39;s stick with the
current example:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;COLUMN1 = 1&lt;/th&gt;
&lt;th&gt;COLUMN2 = 3&lt;/th&gt;
&lt;th&gt;COLUMN3 = &quot;foo&quot;&lt;/th&gt;
&lt;th&gt;COLUMN1 = 1 AND (COLUMN2 = 3 OR COLUMN3 = &quot;foo&quot;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;You can see that the first three rows of this table evalute to true, so we can
convert each row to a clause in our DNF:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COLUMN1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;OR&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COLUMN1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;OR&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COLUMN1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COLUMN3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As you can see, this naive approach results in a rather large DNF, and this is a
very simple example.  To reduce this DNF to a simpler equivalent expression, you
can use something like the Quine-McCluskey algorithm.&lt;/p&gt;
&lt;h1&gt;Which approach to take?&lt;/h1&gt;
&lt;p&gt;I think in general the algebraic approach is preferred if you have a boolean
expession tree already for your boolean function.  You can fairly simply rewrite
this tree into DNF. This is the case with these SQL filters I&#39;m working with.&lt;/p&gt;
&lt;p&gt;If however the inputs to your boolean function are well defined (whether they
are true or false) but you don&#39;t know the implementation details of your boolean
function, then an algorithmic approach is going to be more appropriate.&lt;/p&gt;
&lt;p&gt;For me, I&#39;m going with the algebraic approach. I have the boolean expression
tree for these filters I&#39;m working with, but the &quot;inputs&quot; to the filter aren&#39;t
so easy to get at without a lot of work. By that I mean that our system
generally doesn&#39;t know that a row in a table has COLUMN1 = 1, etc., and rather
the filter is just evaluated directly against a table.  It would take a fair bit
of work to translate criteria like &lt;code&gt;COLUMN1 = 1&lt;/code&gt; into boolean inputs, and to
represent the criteria as boolean literals in the filter expression.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7947851965462667148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/7947851965462667148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7947851965462667148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7947851965462667148'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/05/disjunctive-normal-form-figuring-out.html' title='Disjunctive Normal Form: Figuring out what part of a WHERE claused matched'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-3010625149016433158</id><published>2014-05-04T22:10:00.000-04:00</published><updated>2014-05-04T22:14:03.723-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="git"/><title type='text'>Git: How to delete a branch</title><content type='html'>
&lt;p&gt;How do you create a temporary branch to do some work in (e.g, a feature branch), and then when you have merged it to &lt;em&gt;master&lt;/em&gt; and are done with it, how do you delete it, both locally and remotely?&lt;/p&gt;
&lt;p&gt;Let&#39;s create a simple repo to experiment with. We&#39;ll add just one file to it.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;mkdir myprj
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;myprj
git init
vim README.md
git add README.md
git commit -m &lt;span class=&quot;s2&quot;&gt;&amp;quot;adding a README&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Okay, this will be our &quot;central repo&quot;. Let&#39;s clone it, create a branch and do
some work on it.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;git clone myprj myprj2
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;myprj2
git branch install_notes
git checkout install_notes
vim README.md
git commit -a -m &lt;span class=&quot;s2&quot;&gt;&amp;quot;Adding some installation notes&amp;quot;&lt;/span&gt;
git push origin install_notes
&lt;span class=&quot;c&quot;&gt;# Oops, forgot to set upstream&lt;/span&gt;
git push --set-upstream origin install_notes
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The branch &lt;em&gt;install_notes&lt;/em&gt; now exists locally and in the &quot;central repo&quot;. Let&#39;s
merge it and then delete it locally and also remotely. Before we get started
though, here are all of our local and remote branches:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git branch -avv
    * install_notes                6a5ed4c &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;origin/install_notes&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; Adding some installation notes
    master                       27c8a05 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;origin/master&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; adding a README
    remotes/origin/HEAD          -&amp;gt; origin/master
    remotes/origin/install_notes 6a5ed4c Adding some installation notes
    remotes/origin/master        27c8a05 adding a README
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;First, let&#39;s switch back to &lt;em&gt;master&lt;/em&gt; and try to delete &lt;em&gt;install_notes&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout master
    Switched to branch &lt;span class=&quot;s1&quot;&gt;&amp;#39;master&amp;#39;&lt;/span&gt;
    Your branch is up-to-date with &lt;span class=&quot;s1&quot;&gt;&amp;#39;origin/master&amp;#39;&lt;/span&gt;.
marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git branch -d install_notes
    warning: deleting branch &lt;span class=&quot;s1&quot;&gt;&amp;#39;install_notes&amp;#39;&lt;/span&gt; that has been merged to
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;refs/remotes/origin/install_notes&amp;#39;&lt;/span&gt;, but not yet merged to HEAD.
    Deleted branch install_notes &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;was 6a5ed4c&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Hmm. It gave a warning, but proceeded to delete the branch anyways. Well, let&#39;s
try to check it back out.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout -b install_notes origin/install_notes
    Branch install_notes &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;up to track remote branch install_notes from origin.
    Switched to a new branch &lt;span class=&quot;s1&quot;&gt;&amp;#39;install_notes&amp;#39;&lt;/span&gt;
marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout master
    Switched to branch &lt;span class=&quot;s1&quot;&gt;&amp;#39;master&amp;#39;&lt;/span&gt;
    Your branch is up-to-date with &lt;span class=&quot;s1&quot;&gt;&amp;#39;origin/master&amp;#39;&lt;/span&gt;.
marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git merge install_notes
    Updating 27c8a05..6a5ed4c
    Fast-forward
    README.md | 4 ++++
    1 file changed, 4 insertions&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Okay, now we can delete the branch.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git branch -d -r origin/install_notes
Deleted remote branch origin/install_notes &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;was 6a5ed4c&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;.
marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git branch -d install_notes
Deleted branch install_notes &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;was 6a5ed4c&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And now my branches look like this&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;marcus&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git branch -avv
    * master                6a5ed4c &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;origin/master: ahead 1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; Adding some installation notes
    remotes/origin/HEAD   -&amp;gt; origin/master
    remotes/origin/master 27c8a05 adding a README
&lt;/pre&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/3010625149016433158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/3010625149016433158' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3010625149016433158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3010625149016433158'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/05/git-how-to-delete-branch.html' title='Git: How to delete a branch'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-8538834005231360607</id><published>2014-05-03T22:29:00.000-04:00</published><updated>2014-05-03T22:30:10.885-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="css"/><title type='text'>CSS :empty - hiding a border when an element is empty</title><content type='html'>
&lt;p&gt;I recently had a situation where I have an element in the DOM that draws a
border around some content, but the element is initially empty and isn&#39;t
populated until the user does some action. The problem is, even though the
element is empty, the border (or at least, part of it) gets drawn on the page.&lt;/p&gt;
&lt;p&gt;Let&#39;s say this is my element:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;count&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Well, what I can do to remove the border when the element is empty is to use the
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/:empty&quot;&gt;&lt;code&gt;:empty&lt;/code&gt; pseudo-class selector&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nc&quot;&gt;.count&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That&#39;s it. One caveat though, &lt;code&gt;:empty&lt;/code&gt; &lt;strong&gt;only works if the element is completely
empty, including whitespace&lt;/strong&gt;.  Firefox does have a
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-only-whitespace&quot;&gt;-moz-only-whitespace&lt;/a&gt;
pseudo-class selector, but its not standard and I&#39;m not sure if any other
browser has anything similar.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/8538834005231360607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/8538834005231360607' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/8538834005231360607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/8538834005231360607'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/05/css-empty-hiding-border-when-element-is.html' title='CSS :empty - hiding a border when an element is empty'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7828109877306646259</id><published>2014-04-09T19:32:00.000-04:00</published><updated>2014-04-09T19:32:16.318-04:00</updated><title type='text'>Bootstrap&#39;s Alert.js Plugin, line by line</title><content type='html'>&lt;p&gt;At work I recently needed to write a jQuery plugin that uses Bootstrap styling, so
I looked at how
&lt;a href=&quot;https://github.com/twbs/bootstrap/blob/master/js/alert.js&quot;&gt;alert.js&lt;/a&gt; is
implemented, since it is a fairly small plugin.  In this post I&#39;ll go over
&lt;code&gt;alert.js&lt;/code&gt; line by line, and do my best to explain what is going on. You should
have a decent understanding of JavaScript and some familiarity with jQuery, but
I&#39;ll assume no knowledge of how to write a jQuery plugin or anything specific to
Bootstrap.&lt;/p&gt;
&lt;h4&gt;Overview&lt;/h4&gt;
&lt;p&gt;Let&#39;s start with an overview of how the Alert plugin can be used. You can find
the &lt;a href=&quot;http://getbootstrap.com/javascript/#alerts&quot;&gt;Bootstrap Alert plugin documentation here&lt;/a&gt;.
Essentially there are two ways to use Alerts, and this applies to other
Bootstrap plugins as well&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use the jQuery plugin function directly.&lt;/strong&gt; For Alerts this looks like this&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;.alert&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// To close the alert:&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;.alert&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;close&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data API: use data-* attributes to configure in a more declarative
   style.&lt;/strong&gt; For Alerts, the primary data attribute is &lt;code&gt;data-dismiss&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;close&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-dismiss=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;alert&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;aria-hidden=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;times;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We&#39;ll see how the code in &lt;code&gt;alert.js&lt;/code&gt; supports both of these styles.&lt;/p&gt;
&lt;h4&gt;What&#39;s this &lt;code&gt;+function&lt;/code&gt; business?&lt;/h4&gt;
&lt;p&gt;Okay, let&#39;s start at the top. The first line of code is this&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We have an unnamed (anonymous) function, and a &lt;code&gt;+&lt;/code&gt; in front of it. What&#39;s going
on there? For the moment let&#39;s ignore the body of this JavaScript function
definition and look at how this function gets invoked:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is an example of the &lt;a href=&quot;http://benalman.com/news/2010/11/immediately-invoked-function-expression/&quot;&gt;Immediately Invoked Function
Expression&lt;/a&gt;
(IIFE) pattern. The intent of an IIFE is to introduce stronger lexical scoping
in JavaScript and to allow for some functions defined within the IIFE to remain
&lt;em&gt;private&lt;/em&gt;. There are several variations of this pattern. One way to do it is to
have the IIFE return an object with references to public functions while leaving
some functions private.  In this case, nothing is returned. Instead, the plugin
is added to the &lt;code&gt;jQuery&lt;/code&gt; object.  Because nothing is returned by the IIFE, we
can use a trick to get the JavaScript interpreter to call our anonymous function
immediately, and that trick is to put an unary operator in front of the function
definition.&lt;/p&gt;
&lt;p&gt;The sole argument passed to the function is &lt;code&gt;jQuery&lt;/code&gt; for the &lt;code&gt;$&lt;/code&gt; parameter.  Why
passing &lt;code&gt;jQuery&lt;/code&gt; as the &lt;code&gt;$&lt;/code&gt; parameter, why not just use &lt;code&gt;$&lt;/code&gt; from the global
scope like so?&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;#foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// etc...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We could do that, but that would only work as long as &lt;code&gt;$&lt;/code&gt; refers to the &lt;code&gt;jQuery&lt;/code&gt;
function.  There are other libraries that define the &lt;code&gt;$&lt;/code&gt; reference, so in order
to interoperate with them we&#39;ll assume only that there is a &lt;code&gt;jQuery&lt;/code&gt; reference
in the global scope.  But it&#39;s nice that we can essentially alias &lt;code&gt;jQuery&lt;/code&gt; to
&lt;code&gt;$&lt;/code&gt; within our plugin definition in a lexically scoped and tidy way.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;use strict&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;The next line of &lt;code&gt;alert.js&lt;/code&gt; is a String, &lt;code&gt;&#39;use strict&#39;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39;use strict&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;According to the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode&quot;&gt;Strict mode article on the Mozilla Developer Network&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ECMAScript 5&#39;s strict mode is a way to opt in to a restricted variant of
JavaScript. Strict mode isn&#39;t just a subset: it intentionally has different
semantics from normal code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Perl has something similar. &lt;code&gt;&#39;use strict&#39;&lt;/code&gt; is a way of running your JavaScript
code through the interpreter in a less loosy-goosy manner. Here are some
benefits of running in strict mode:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Impossible to accidentally create global variables (for example, mistyped
  variable names)&lt;/li&gt;
&lt;li&gt;Severals classes of silent errors become thrown exceptions&lt;/li&gt;
&lt;li&gt;Simplifies variable naming which allows JavaScript interpreters to better
  optimize code (for example, &lt;code&gt;eval&lt;/code&gt; doesn&#39;t introduce new variables into the
  surrounding scope)&lt;/li&gt;
&lt;li&gt;Several security enhancing restrictions are added&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the linked article for more information.&lt;/p&gt;
&lt;h4&gt;Alert class definition&lt;/h4&gt;
&lt;p&gt;Now for the Alert class definition.  Our Alert class has a constructor and one
method, &lt;code&gt;close&lt;/code&gt;. First, the &lt;code&gt;dismiss&lt;/code&gt; variable is defined. This is a jQuery
selector that is used here in the constructor to bind to the click event from a
DOM element that matches this selector. The way this works is that any DOM
element that is &lt;code&gt;el&lt;/code&gt; or a descendant of &lt;code&gt;el&lt;/code&gt; that has a &lt;code&gt;data-dismiss&lt;/code&gt; attribute
with value &lt;code&gt;alert&lt;/code&gt; that fires a click event will be handled by &lt;code&gt;this.close&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dismiss&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;[data-dismiss=&amp;quot;alert&amp;quot;]&amp;#39;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Alert&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dismiss&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Alert &lt;code&gt;close&lt;/code&gt; function&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;close&lt;/code&gt; method is defined for the &lt;code&gt;Alert&lt;/code&gt; class by adding it to &lt;code&gt;Alert&lt;/code&gt;&#39;s
prototype.  This method does the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Figure out the &lt;code&gt;$parent&lt;/code&gt; element (i.e., the alert div) that should be
   closed.  There are a few different ways to determine the &lt;code&gt;$parent&lt;/code&gt; and we&#39;ll
   look at those shortly.&lt;/li&gt;
&lt;li&gt;Trigger a custom event before closing the &lt;code&gt;$parent&lt;/code&gt; and one after it is
   closed.&lt;/li&gt;
&lt;li&gt;Use a CSS3 transition to fade the &lt;code&gt;$parent&lt;/code&gt; and then remove it.&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;Finding the &lt;code&gt;$parent&lt;/code&gt; to close&lt;/h5&gt;
&lt;p&gt;First, figure out the &lt;code&gt;$parent&lt;/code&gt; element.  Here&#39;s the first part of &lt;code&gt;close&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;Alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;data-target&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;href&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/.*(?=#[^\s]*$)/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// strip for ie7&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hasClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;In the first line of &lt;code&gt;close&lt;/code&gt;, &lt;code&gt;this&lt;/code&gt; refers to the element that is the target of
click event.  So in the standard case where you have a close &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; inside a
&lt;code&gt;&amp;lt;div class=&quot;alert&quot;&amp;gt;&lt;/code&gt; element, &lt;code&gt;this&lt;/code&gt; is the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;.  However, &lt;code&gt;close&lt;/code&gt; could
be called through the plugin function, as we&#39;ll see later, so &lt;code&gt;this&lt;/code&gt; might refer
to the alert itself (&lt;code&gt;&amp;lt;div class=&quot;alert&quot;&amp;gt;&lt;/code&gt;).  For now, we&#39;ll consider the case
that &lt;code&gt;this&lt;/code&gt; refers to the close button.&lt;/p&gt;
&lt;p&gt;The first option to check is a &lt;code&gt;data-target&lt;/code&gt; attribute on the close button. The
value is expected to be a selector. You would use it like this:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;myalert&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;close&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;aria-hidden=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;data-target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;#myalert&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;data-dismiss=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;alert&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;button&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;×&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Holy guacamole!&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
    Best check yo self, you&amp;#39;re not looking too good.
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Click on the button should cause &lt;code&gt;&amp;lt;div id=&quot;myalert&quot;&amp;gt;&lt;/code&gt; to be closed.&lt;/p&gt;
&lt;p&gt;The second option to check is the &lt;code&gt;href&lt;/code&gt; attribute. This can be used likewise.&lt;/p&gt;
&lt;p&gt;This line then checks to see if anything matches those options:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If we haven&#39;t set &lt;code&gt;data-target&lt;/code&gt; or &lt;code&gt;href&lt;/code&gt; on our close button, or if we have but
they don&#39;t match anything, then &lt;code&gt;$parent&lt;/code&gt; will have a length of 0.  That&#39;s what
is checked for next.  If we still haven&#39;t found &lt;code&gt;$parent&lt;/code&gt; there are a couple
more things to try.&lt;/p&gt;
&lt;p&gt;So the third option is to check to see if &lt;code&gt;$this&lt;/code&gt; has class &lt;strong&gt;alert&lt;/strong&gt;. If it does
then we assume that this is the element that should be faded and removed.  &lt;/p&gt;
&lt;p&gt;The fourth option, the default if none of the other checks matched anything, is
to set &lt;code&gt;$parent&lt;/code&gt; to the parent of &lt;code&gt;$this&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Like I said earlier, it&#39;s possible for the &lt;code&gt;close&lt;/code&gt; method to be called directly
in which case &lt;code&gt;$this&lt;/code&gt; is the alert itself.  In that case, it is the third
option that would typically be used for figuring out the &lt;code&gt;$parent&lt;/code&gt;.&lt;/p&gt;
&lt;h5&gt;Custom events for before and after closing&lt;/h5&gt;
&lt;p&gt;Before actually closing the alert, &lt;code&gt;close&lt;/code&gt; dispatches a &lt;code&gt;close.bs.alert&lt;/code&gt; event
on the &lt;code&gt;$parent&lt;/code&gt; element.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isDefaultPrevented&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first line creates the custom event, using jQuery&#39;s &lt;code&gt;$.Event&lt;/code&gt; and also sets
it to the variable &lt;code&gt;e&lt;/code&gt;.  The name of the event, &quot;close.bs.alert&quot;, utilizes
&lt;a href=&quot;https://api.jquery.com/on/&quot;&gt;jQuery event namespaces&lt;/a&gt;.  This just makes it
possible to listen for the close event just from Bootstrap&#39;s Alert plugin by
binding to the &lt;code&gt;close.bs.alert&lt;/code&gt; event. It also makes it easier in Bootstrap to
remove event handlers. For example, all of the following would work to remove an
event handler bound to &lt;code&gt;close.bs.alert&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.bs&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.bs&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For removing, only one of the namespaces need match.  I put together a &lt;a href=&quot;http://jsfiddle.net/machristie/eLKKb/&quot;&gt;JSFiddle
to demonstrate jQuery event namespaces&lt;/a&gt;
that I think helps demonstrate how they work:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;close.bs.alert handler&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;close.alert handler&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.bs&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;close.bs handler&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;close handler&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;triggering close...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// triggers &amp;#39;close.bs.alert&amp;#39;, &amp;#39;close.alert&amp;#39;,&lt;/span&gt;
                              &lt;span class=&quot;c1&quot;&gt;// &amp;#39;close.bs&amp;#39; and &amp;#39;close&amp;#39;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;triggering close.bs...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.bs&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// triggers &amp;#39;close.bs.alert&amp;#39; and &amp;#39;close.bs&amp;#39;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;triggering close.alert...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// triggers &amp;#39;close.bs.alert&amp;#39; and &lt;/span&gt;
                                    &lt;span class=&quot;c1&quot;&gt;// &amp;#39;close.alert&amp;#39;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;triggering close.bs.alert...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// triggers &amp;#39;close.bs.alert&amp;#39;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Remove close.alert handlers and triggering close...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// removes close.bs.alert and close.alert&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//$(document).off(&amp;#39;.alert&amp;#39;); // removes close.bs.alert and close.alert as well&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;close&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// triggers &amp;#39;close.bs&amp;#39; and &amp;#39;close&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So that&#39;s event namespacing and triggering the &lt;strong&gt;close&lt;/strong&gt; event.  The next line
is to return if the &lt;strong&gt;close&lt;/strong&gt; event had &lt;code&gt;preventDefault&lt;/code&gt; called on it. The idea
is that a listener for the &lt;strong&gt;close&lt;/strong&gt; event could call &lt;code&gt;e.preventDefault()&lt;/code&gt; to
prevent the alert from actually closing.&lt;/p&gt;
&lt;p&gt;The other custom event that the Alert plugin dispatches is the &lt;strong&gt;closed&lt;/strong&gt; event
which is named &lt;code&gt;closed.bs.alert&lt;/code&gt;.  It is dispatched when the Alert is actually
removed from the DOM. We&#39;ll see the code to trigger this event in the next
section where we&#39;ll look at how the Alert is faded out and removed from the DOM.&lt;/p&gt;
&lt;h5&gt;Removing and fading out the Alert&lt;/h5&gt;
&lt;p&gt;Now we&#39;ll look at how the Alert is faded out and removed from the DOM.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;removeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;in&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;removeElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;closed.bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;support&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hasClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;fade&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$parent&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;support&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;removeElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;emulateTransitionEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;150&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;removeElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Fading out the Alert is accomplished by using a CSS3 transition. To understand
how it works, let&#39;s look at the CSS:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nc&quot;&gt;.fade&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;opacity&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.15s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linear&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.fade.in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When an element has the &lt;strong&gt;fade&lt;/strong&gt; and &lt;strong&gt;in&lt;/strong&gt; classes, its opacity is 1 and when
it only has the &lt;strong&gt;fade&lt;/strong&gt; class its opacity is 0. The &lt;code&gt;transition&lt;/code&gt; CSS property
defines how quickly and in what way the &lt;code&gt;opacity&lt;/code&gt; property changes from 0 to 1
when &lt;strong&gt;in&lt;/strong&gt; is added to an element that already has &lt;strong&gt;fade&lt;/strong&gt;.  In this case
however, the &lt;code&gt;close&lt;/code&gt; method is removing the &lt;strong&gt;in&lt;/strong&gt; class which causes the
opacity to transition, linearly, from 1 to 0, causing it to fade out of view and
become invisible.&lt;/p&gt;
&lt;p&gt;Making the Alert invisible is not enough however. We want to actually remove it
from the DOM. If we don&#39;t then it will still take up space on the web page, it
just won&#39;t be visible.  To accomplish this we need to know when the transition
finishes.  Once the transition finishes we can then remove the Alert from the
DOM.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;removeElement&lt;/code&gt; function is defined so as to trigger the &lt;code&gt;closed.bs.alert&lt;/code&gt;
and then remove the Alert from the DOM.  In an ideal world, we&#39;d just bind the
&lt;strong&gt;transitionend&lt;/strong&gt; event to the &lt;code&gt;removeElement&lt;/code&gt; handler.  However there are a few
complications:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It&#39;s possible that the Alert doesn&#39;t have the &lt;strong&gt;fade&lt;/strong&gt; class, in other words,
   it is not desired that it actually fade out.  That&#39;s fine, the transition is
   optional.  That&#39;s what is checked for with &lt;code&gt;$parent.hasClass(&#39;fade&#39;)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It&#39;s possible that this browser doesn&#39;t support CSS transitions. That&#39;s what
   &lt;code&gt;$.support.transition&lt;/code&gt; is checking for. More on this later.&lt;/li&gt;
&lt;li&gt;It&#39;s possible that even if the browser supports CSS transitions that it
   doesn&#39;t call the &lt;em&gt;transition end&lt;/em&gt; event &lt;strong&gt;transitionend&lt;/strong&gt;. The
   &lt;code&gt;$.support.transition.end&lt;/code&gt; property holds the name of the &lt;em&gt;transition end&lt;/em&gt;
   event for that browser.&lt;/li&gt;
&lt;li&gt;Finally, it&#39;s possible that &lt;a href=&quot;http://blog.alexmaccaw.com/css-transitions&quot;&gt;the &lt;em&gt;transition end&lt;/em&gt; event won&#39;t be
   called&lt;/a&gt;.  So we need to
   programmatically dispatch the event if it isn&#39;t called. That&#39;s what
   &lt;code&gt;emulateTransitionEnd(150)&lt;/code&gt; is doing.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can see the tests Bootstrap does to determine the &lt;em&gt;transition end&lt;/em&gt; event
name in
&lt;a href=&quot;https://github.com/twbs/bootstrap/blob/master/js/transition.js&quot;&gt;transition.js&lt;/a&gt;.
Also defined in &lt;code&gt;transition.js&lt;/code&gt; is the &lt;code&gt;emulateTransitionEnd&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;So let&#39;s go line by line. First, we&#39;ll remove the &lt;strong&gt;in&lt;/strong&gt; class which will start
the transition from opacity 1 to 0 over the course of 0.15 seconds.  Next,
define a function, &lt;code&gt;removeElement&lt;/code&gt;, that will be called when the transition
finishes. We&#39;ll bind &lt;code&gt;removeElement&lt;/code&gt; to the &lt;em&gt;transition end&lt;/em&gt; event.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;removeElement&lt;/code&gt; will trigger the &lt;code&gt;closed.bs.alert&lt;/code&gt; event, the second custom
event, and it will remove the Alert from the DOM.&lt;/p&gt;
&lt;p&gt;So next we have a ternary expression. If the browser supports transitions and
the alert (the &lt;code&gt;$parent&lt;/code&gt;) has class &lt;strong&gt;fade&lt;/strong&gt;, then bind &lt;code&gt;removeElement&lt;/code&gt; to the
&lt;em&gt;transition end&lt;/em&gt; event exactly once (&lt;code&gt;$parent.one(...)&lt;/code&gt;). The call to
&lt;code&gt;emulateTransitionEnd(150)&lt;/code&gt; will set a 150 millisecond timeout and dispatch the
&lt;em&gt;transition end&lt;/em&gt; event if it hasn&#39;t already been dispatched (again, see
&lt;a href=&quot;https://github.com/twbs/bootstrap/blob/master/js/transition.js&quot;&gt;transition.js&lt;/a&gt;
for details).  If the browser doesn&#39;t support Transitions or &lt;code&gt;$parent&lt;/code&gt; doesn&#39;t
have the &lt;strong&gt;fade&lt;/strong&gt; class, then just call &lt;code&gt;removeElement&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Alert jQuery Plugin Definition&lt;/h4&gt;
&lt;p&gt;Ok, a brief recap. We&#39;ve defined the Alert class and it&#39;s single &lt;code&gt;close&lt;/code&gt; method,
which does almost all of the heavy lifting for this plugin. Now it&#39;s time to
actually define the Alert class as a jQuery plugin. Here&#39;s the code:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;old&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;option&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Constructor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Alert&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;First thing here is to capture the current value of &lt;code&gt;$.fn.alert&lt;/code&gt; into the &lt;code&gt;old&lt;/code&gt;
variable.  This is used later in &lt;code&gt;noConflict&lt;/code&gt;, and it just a way to prevent this
&lt;code&gt;alert&lt;/code&gt; plugin from interfering with another &lt;code&gt;alert&lt;/code&gt; plugin with the same name.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;$.fn.alert&lt;/code&gt; function is defined next. The way this function will be used is
like so&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So &lt;code&gt;this&lt;/code&gt; refers to the result of a jQuery selector, which means it is an Array
of DOM elements. So for each matching DOM element we&#39;ll run this function:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;option&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Within the scope of this function, &lt;code&gt;this&lt;/code&gt; refers to the current DOM element.
&lt;code&gt;$this&lt;/code&gt; is a jQuery wrapped reference to the DOM element.&lt;/p&gt;
&lt;p&gt;When this function creates an &lt;code&gt;Alert&lt;/code&gt; instance for this DOM element it will
store it as a reference associated with the DOM element.  &lt;code&gt;var data =
$this.data(&#39;bs.alert&#39;)&lt;/code&gt; is checking if we&#39;ve already created an &lt;code&gt;Alert&lt;/code&gt; instance
for this DOM element.  The third line of the function creates the &lt;code&gt;Alert&lt;/code&gt;
instance (&lt;code&gt;data = new Alert(this)&lt;/code&gt;) if it hasn&#39;t already been created and it
will be saved to the &lt;strong&gt;bs.alert&lt;/strong&gt; key:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;bs.alert&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Finally, you may have noticed that the plugin function accepts an &lt;code&gt;options&lt;/code&gt;
argument.  This is a common jQuery plugin pattern. There aren&#39;t any actual
options for the &lt;code&gt;Alert&lt;/code&gt; class, but &lt;code&gt;options&lt;/code&gt; can also be a string with the name
of a method that you want to invoke on the &lt;code&gt;Alert&lt;/code&gt; instance.  That&#39;s what is
being done here. &lt;code&gt;data&lt;/code&gt;, remember, is a reference to the &lt;code&gt;Alert&lt;/code&gt; instance.
&lt;code&gt;data[option]&lt;/code&gt; therefore refers to a function on the &lt;code&gt;Alert&lt;/code&gt; instance. It is
called with &lt;code&gt;$this&lt;/code&gt; as the context (that is, within the method invoked by
&lt;code&gt;call&lt;/code&gt;, &lt;code&gt;this&lt;/code&gt; will refer to &lt;code&gt;$this&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Also, as a jQuery plugin best practice, the result of calling &lt;code&gt;this.each&lt;/code&gt; is
returned to enable chaining of jQuery function calls.&lt;/p&gt;
&lt;p&gt;The other thing we haven&#39;t talked about yet is this line:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Constructor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Alert&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;See &lt;a href=&quot;http://stackoverflow.com/a/10526115/1419499&quot;&gt;this StackOverflow answer for a long
explanation&lt;/a&gt;.  but, basically, if
we don&#39;t do this then the &lt;code&gt;Alert&lt;/code&gt; constructor remains &lt;em&gt;private&lt;/em&gt; to the closure
in which we defined it.  By creating the &lt;code&gt;Constructor&lt;/code&gt; reference, other code can
directly instantiate an &lt;code&gt;Alert&lt;/code&gt; instance without needing to invoke it indirectly
through the jQuery API.&lt;/p&gt;
&lt;h4&gt;Alert &lt;code&gt;noConflict&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Now we&#39;re at the &lt;code&gt;noConflict&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;noConflict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;old&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is a simple convention for handling the situation that there is another
jQuery plugin also called &lt;code&gt;alert&lt;/code&gt;.  This function sets &lt;code&gt;$.fn.alert&lt;/code&gt; to its old
value and returns &lt;code&gt;this&lt;/code&gt; which refers to the &lt;code&gt;$.fn.alert&lt;/code&gt; function defined
above.&lt;/p&gt;
&lt;h4&gt;Alert Data API&lt;/h4&gt;
&lt;p&gt;Finally we get to the Data API. This allows for purely declarative use of the
Alert plugin, no JavaScript calls necessary.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;click.bs.alert.data-api&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dismiss&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This binds the &#39;click&#39; event for any DOM element in the page matching the
&lt;code&gt;dismiss&lt;/code&gt; selector to &lt;code&gt;Alert&lt;/code&gt;&#39;s &lt;code&gt;close&lt;/code&gt; method.  Recall that the &lt;code&gt;dismiss&lt;/code&gt;
selector was defined as &lt;code&gt;[data-dismiss=&quot;alert&quot;]&lt;/code&gt;.  So any clickable element in
the page that has the attribute &lt;code&gt;data-dismiss&lt;/code&gt; with value &lt;strong&gt;alert&lt;/strong&gt; will have
its &lt;em&gt;click&lt;/em&gt; event handled by &lt;code&gt;Alert&lt;/code&gt;&#39;s &lt;code&gt;close&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;The difference with the Data API is that there is no actual &lt;code&gt;Alert&lt;/code&gt; instance
created. Instead &lt;code&gt;Alert.prototype.close&lt;/code&gt; method is used directly, as a pure
function. The way &lt;code&gt;close&lt;/code&gt; will be invoked in this case is basically identical to
how it will be invoked via the binding we see in the &lt;code&gt;Alert&lt;/code&gt; constructor:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dismiss&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Additional Resources&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions?redirectlocale=en-US&amp;amp;redirectslug=CSS%2FTutorials%2FUsing_CSS_transitions&quot;&gt;Using CSS Transitions&lt;/a&gt; - at Mozilla Developer Network&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Reference/Events/transitionend&quot;&gt;transitionend&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7828109877306646259/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/7828109877306646259' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7828109877306646259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7828109877306646259'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/04/bootstraps-alertjs-plugin-line-by-line.html' title='Bootstrap&#39;s Alert.js Plugin, line by line'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-339763148562399283</id><published>2014-03-22T13:13:00.001-04:00</published><updated>2014-03-22T13:13:41.048-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="scala"/><title type='text'>Scala: Object equality and the canEqual method</title><content type='html'>&lt;!--
Scala: Object equality and canEqual
--&gt;

&lt;p&gt;This week I&#39;m in chapter 30 of &lt;a href=&quot;http://www.artima.com/shop/programming_in_scala_2ed&quot;&gt;Programming in Scala, 2nd ed.&lt;/a&gt;, the chapter titled &lt;em&gt;Object Equality&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;Getting Object Equality Right&lt;/h4&gt;
&lt;p&gt;This chapter is about how hard it is to properly implement a class&#39; &lt;code&gt;equals&lt;/code&gt;
method. There is good advice here on the pitfalls to avoid and recipes to write
good &lt;code&gt;equals&lt;/code&gt; and &lt;code&gt;hashCode&lt;/code&gt; methods. Most of this chapter is present in the
article &lt;a href=&quot;http://www.artima.com/lejava/articles/equality.html&quot;&gt;How to Write an Equality Method in Java&lt;/a&gt; except that the examples in the article use Java instead of Scala.&lt;/p&gt;
&lt;h4&gt;What is the &lt;code&gt;canEqual&lt;/code&gt; method?&lt;/h4&gt;
&lt;p&gt;One of the strategies in this chapter is to introduce a &lt;code&gt;canEqual&lt;/code&gt; method for
non-final classes.  This allows subclasses to override &lt;code&gt;canEqual&lt;/code&gt; if they want
to not allow being equal to the parent class or sibling classes.&lt;/p&gt;
&lt;p&gt;The example in the chapter is this. You start with a &lt;code&gt;Point&lt;/code&gt; class, which has
&lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinate members.  Then you have a &lt;code&gt;ColoredPoint&lt;/code&gt; class that
subclasses &lt;code&gt;Point&lt;/code&gt; and overrides &lt;code&gt;equals&lt;/code&gt; to make it so that &lt;code&gt;ColoredPoint&lt;/code&gt;s
aren&#39;t equal to &lt;code&gt;Point&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;Here&#39;s the definition of &lt;code&gt;Point&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And the naive implementation of &lt;code&gt;ColoredPoint&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ColoredPoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Color.Value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ColoredPoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; 
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;where &lt;code&gt;Color&lt;/code&gt; is:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Enumeration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Red&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Orange&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Yellow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Green&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Blue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Indigo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Violet&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Value&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The problem with this is that &lt;code&gt;equals&lt;/code&gt; is not symmetric. It is possible for a
&lt;code&gt;Point&lt;/code&gt; to be equal to a &lt;code&gt;ColoredPoint&lt;/code&gt;, but the &lt;code&gt;ColoredPoint&lt;/code&gt; wouldn&#39;t be equal to
the &lt;code&gt;Point&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is a little better, but still not transitive:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ColoredPoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Color.Value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ColoredPoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To see how this doesn&#39;t work, consider a red ColoredPoint with x and y
coordinates of 1,2 and a blue ColoredPoint with the same coordinates.  The
red ColoredPoint is equal to a &lt;code&gt;Point(1, 2)&lt;/code&gt; and the &lt;code&gt;Point(1, 2)&lt;/code&gt; is equal to
the blue ColoredPoint, but the red and blue ColoredPoint are not equal to each
other.&lt;/p&gt;
&lt;p&gt;The solution proposed in the chapter is to introduce a new method, &lt;code&gt;canEqual&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canEqual&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Point&lt;/code&gt; would then be defined as such (including &lt;code&gt;hashCode&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hashCode&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canEqual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
            &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canEqual&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isInstanceOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And &lt;code&gt;ColoredPoint&lt;/code&gt; is defined like so&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ColoredPoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Color.Value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hashCode&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hashCode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hashCode&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ColoredPoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canEqual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canEqual&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isInstanceOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ColoredPoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now &lt;code&gt;Point&lt;/code&gt; instances cannot be equal to &lt;code&gt;ColoredPoint&lt;/code&gt; instances since the
first check that &lt;code&gt;Point.equals&lt;/code&gt; will make is to call
&lt;code&gt;ColoredPoint.canEqual(Point)&lt;/code&gt; which will return false.  &lt;strong&gt;It&#39;s vitally
important that the &lt;code&gt;canEqual&lt;/code&gt; method be call on &lt;code&gt;that&lt;/code&gt; with &lt;code&gt;this&lt;/code&gt; as the
argument&lt;/strong&gt;.  &lt;code&gt;canEqual&lt;/code&gt; is a way for classes to define what they can be equal
to.  In &lt;code&gt;Point&lt;/code&gt; and &lt;code&gt;ColoredPoint&lt;/code&gt; the match expression has been used to make
sure that &lt;code&gt;that&lt;/code&gt; is the right type, so now we can call &lt;code&gt;canEqual&lt;/code&gt; on &lt;code&gt;that&lt;/code&gt; to
make sure that equality is possible in the reverse direction: that &lt;code&gt;that
canEqual this&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Does &lt;code&gt;canEqual&lt;/code&gt; violate the Liskov Substitution Principle?&lt;/h4&gt;
&lt;p&gt;One criticism of the &lt;code&gt;canEqual&lt;/code&gt; approach is that it violates the &lt;a href=&quot;http://en.wikipedia.org/wiki/Liskov_substitution_principle&quot;&gt;Liskov
Substitution Principle&lt;/a&gt; which, according to Wikipedia, states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;if S is a subtype of T, then objects of type T may be replaced with objects of
type S (i.e., objects of type S may substitute objects of type T) without
altering any of the desirable properties of that program (correctness, task
performed, etc.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The authors of the book make the argument that Liskov Substitution Principle is
not violated because, although the behavior of subclasses is different than the
parent class, the contract itself, that &lt;code&gt;equals&lt;/code&gt; return a boolean value, is not
changed.&lt;/p&gt;
&lt;p&gt;My intuition though is that this is a violation.  From the perspective of the
&lt;code&gt;Point&lt;/code&gt; class, any two &lt;code&gt;Point&lt;/code&gt; instances at the same x and y coordinates are
equal. A subclass changing that definition has violated the contract in a way
that makes a subclass not substitutable with a parent class.  Let&#39;s look at an
example of where substitution is violated.&lt;/p&gt;
&lt;p&gt;Consider a &lt;code&gt;distance&lt;/code&gt; method in &lt;code&gt;Point&lt;/code&gt; that calculates the distance between two
&lt;code&gt;Point&lt;/code&gt;s.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This method is taking a shortcut: if the two points are equal, then just return 0.
This shortcut won&#39;t work if applied to a &lt;code&gt;ColoredPoint&lt;/code&gt; even though it could be
if &lt;code&gt;ColoredPoint&lt;/code&gt; hadn&#39;t overridden the &lt;code&gt;equals&lt;/code&gt; method. To me this is an
example of a case where substitutability is violated because this method is
expecting that it &lt;em&gt;can&lt;/em&gt; take this shortcut for any &lt;code&gt;Point&lt;/code&gt; instance.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;canEqual&lt;/code&gt; is a code smell&lt;/h4&gt;
&lt;p&gt;In general I think that &lt;code&gt;canEqual&lt;/code&gt; is a code smell.  When you look at just the
problem of defining &lt;code&gt;equals&lt;/code&gt; it might seem reasonable to introduce &lt;code&gt;canEqual&lt;/code&gt;.
But think about the impact on other methods. For example, consider if we had
extended &lt;code&gt;Point&lt;/code&gt; with a new &lt;code&gt;3DPoint&lt;/code&gt; class.  Then we would have to completely
change the &lt;code&gt;distance&lt;/code&gt; method. So not only can &lt;code&gt;3DPoint&lt;/code&gt; instances not equal
&lt;code&gt;Point&lt;/code&gt; instances, but we can&#39;t calculate the distance between &lt;code&gt;3DPoint&lt;/code&gt;s and
&lt;code&gt;Point&lt;/code&gt;s. This is clearly a &lt;em&gt;Liskov Substitution Principle&lt;/em&gt; violation.&lt;/p&gt;
&lt;p&gt;So if you are thinking of using &lt;code&gt;canEqual&lt;/code&gt; because you want subclasses to not be
equal to parent classes, it seems likely to me that if your subclasses can&#39;t
equal the parent class then that probably affects other methods too.&lt;/p&gt;
&lt;p&gt;As an alternative, consider using composition instead of inheritance. For
example, we could define the ColoredPoint like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ColoredPoint2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Color.Value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;point&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hashCode&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hashCode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hashCode&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ColoredPoint2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Additional Resources&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.artima.com/lejava/articles/equality.html&quot;&gt;How to Write an Equality Method in Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://booksites.artima.com/programming_in_scala_2ed/examples/html/ch30.html&quot;&gt;Code examples from chapter 30&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/339763148562399283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/339763148562399283' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/339763148562399283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/339763148562399283'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/03/scala-object-equality-and-canequal.html' title='Scala: Object equality and the canEqual method'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7032734989629005459</id><published>2014-03-09T09:23:00.003-04:00</published><updated>2014-03-09T09:26:17.729-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cake-pattern"/><category scheme="http://www.blogger.com/atom/ns#" term="scala"/><category scheme="http://www.blogger.com/atom/ns#" term="traits"/><title type='text'>Scala: Understanding the self type annotation and how it relates to the Cake Pattern</title><content type='html'>&lt;!--

# Scala: Understanding the self type annotation and how it relates to the Cake Pattern

--&gt;

&lt;p&gt;I&#39;m currently working through the book &lt;a href=&quot;http://www.artima.com/shop/programming_in_scala_2ed&quot;&gt;Programming in Scala, 2nd
ed.&lt;/a&gt;.  I&#39;m in chapter 29
which is on &lt;em&gt;Modular Programming Using Objects&lt;/em&gt;. What is covered in the chapter
has also been referred to as the Cake Pattern.  The chapter takes the approach
of building up to the Cake Pattern through an example that helps illustrate the
kind of problems that the Cake Pattern solves. To understand the Cake Pattern
you have to understand how the &lt;em&gt;self type&lt;/em&gt; annotation works. So I&#39;m going to
take a slightly different approach and start with how the &lt;em&gt;self type&lt;/em&gt; annotation
works since it is so crucial.&lt;/p&gt;
&lt;h4&gt;What is the &lt;em&gt;self type&lt;/em&gt; annotation?&lt;/h4&gt;
&lt;p&gt;In brief, the &lt;em&gt;self type&lt;/em&gt; annotation allows you to split a trait in two but still refer to
things on the second trait as though they are defined in the first trait,
basically assuming (well, requiring) that they are mixed in together.  For
example, the following trait simply prints a greeting at a prompt:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Prompter1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;gt; &amp;quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;printGreeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompter1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Prompter1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;prompter1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printGreeting&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now suppose you want to split out the &lt;code&gt;greeting&lt;/code&gt; part, maybe so that you can
provide greetings for different languages. You could do this:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Prompter2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// the self type annotation&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GreetingProvider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;gt; &amp;quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;printGreeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Next line would work too. &amp;#39;this&amp;#39; can refer to things within this trait or&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// the declared self type trait&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//println(this.prompt + this.greeting)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GreetingProvider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompter2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Prompter2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GreetingProvider&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;prompter2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printGreeting&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The code in Prompter2 is exactly the same as in Prompter1 except that there is
now a &lt;em&gt;self type&lt;/em&gt; annotation which says that &lt;code&gt;this&lt;/code&gt; can also refer to
&lt;code&gt;GreetingProvider&lt;/code&gt;. Also the &lt;code&gt;greeting&lt;/code&gt; has moved to a separate trait,
&lt;code&gt;GreetingProvider&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Do you need the &lt;em&gt;self type&lt;/em&gt; annotation if you take care to always mix in the
two traits together?  No, because &lt;code&gt;Prompter2&lt;/code&gt; won&#39;t even compile and you get
this error:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;console&amp;gt;&lt;/span&gt;:37: error: not found: value greeting
                println(prompt + greeting)
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;What happens if you tried to create a new Object and only mixed in Prompter2?&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Prompter2&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Prompter2&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;illegal&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inheritance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;-type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Prompter2&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;does&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;conform&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Prompter2&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;s selftype Prompter2 with GreetingProvider&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;            new Object with Prompter2&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;                            ^&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Does order matter?  It doesn&#39;t appear to. The following works just fine:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prompter2backwards&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GreetingProvider&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Prompter2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;prompter2backwards&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printGreeting&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you have a &lt;em&gt;self type&lt;/em&gt; annotation, does &lt;code&gt;this&lt;/code&gt; &lt;strong&gt;only&lt;/strong&gt; refer to that type?
Apparently not.  We could just as well have defined &lt;code&gt;Prompter2.printGreeting&lt;/code&gt;
like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;printGreeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// &amp;#39;this&amp;#39; can refer to things within this trait or the declared self type trait&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So the &lt;em&gt;self type&lt;/em&gt; annotation appears to extend what &lt;code&gt;this&lt;/code&gt; can refer to.&lt;/p&gt;
&lt;p&gt;You can also have multiple traits mixed in for your &lt;em&gt;self type&lt;/em&gt; annotation:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;this:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bar&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Baz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So what does this have to do with the &lt;em&gt;Cake Pattern&lt;/em&gt;? We&#39;ll get there but for
now hopefully you can see that the &lt;em&gt;self type&lt;/em&gt; annotation allows you to express
a dependency within a trait, a dependency that when satisfied allows one trait
to make use of code defined in a separate trait.  The &lt;em&gt;Cake Pattern&lt;/em&gt; is a
&lt;em&gt;Dependency Injection&lt;/em&gt; technique that uses &lt;em&gt;self type&lt;/em&gt; annotations to express
and ultimately fulfill the dependencies between traits.&lt;/p&gt;
&lt;h4&gt;Applying the &lt;em&gt;Cake Pattern&lt;/em&gt; to the examples in chapter 29&lt;/h4&gt;
&lt;p&gt;Chapter 29 doesn&#39;t mention the &lt;em&gt;Cake Pattern&lt;/em&gt; and doesn&#39;t really apply it. It
goes as far as introducing the &lt;em&gt;self type&lt;/em&gt; annotation and showing how you can
use to refactor a large trait and split it up into several smaller traits.&lt;/p&gt;
&lt;p&gt;The chapter presents a &lt;code&gt;Database&lt;/code&gt; class that abstracts getting &lt;code&gt;Food&lt;/code&gt; and
&lt;code&gt;Recipe&lt;/code&gt; instances from some sort of backing store.  The &lt;code&gt;Database&lt;/code&gt; is then
split up into three traits: one for &lt;code&gt;FoodCategory&lt;/code&gt; methods, one for &lt;code&gt;Food&lt;/code&gt;
methods and one for &lt;code&gt;Recipe&lt;/code&gt; methods.  It&#39;s not all spelled out in the chapter
but you would end up with something that looks like the following:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Apple&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Apple&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Orange&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Orange&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Cream&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Cream&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sugar&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Sugar&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ingredients&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instructions&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foods&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allCategories&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FoodCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allFoods&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foodNamed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;allFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allRecipes&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Recipe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Database&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategories&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The book then proceeds to implement &lt;code&gt;Foods&lt;/code&gt; and &lt;code&gt;Recipes&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFoods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pear&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Pear&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allFoods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Apple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allCategories&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Nil&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRecipes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Does not compile&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FruitSalad&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;fruit salad&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Apple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Uh oh&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;Mix it all together.&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allRecipes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;FruitSalad&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The problem is that &lt;code&gt;SimpleRecipes&lt;/code&gt; has a dependency on &lt;code&gt;SimpleFoods&lt;/code&gt;. As such
&lt;code&gt;Pear&lt;/code&gt; is no longer in scope. &lt;em&gt;Self type&lt;/em&gt; annotation to the rescue!&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRecipes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleFoods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FruitSalad&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;fruit salad&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Apple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;Mix it all together.&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allRecipes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;FruitSalad&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This all works well enough for such a short example, but in the real world, when
you have a database abstraction that has hundreds (or thousands?) of methods for
retrieving objects from the database, would this suffice?  Because the problem
becomes that you will end up mixing all of those methods into the local
namespace of your &lt;code&gt;Database&lt;/code&gt; class.  For example, instead of having a
&lt;code&gt;Foods.getAll&lt;/code&gt; method even this simple example compels us to having the method
called &lt;code&gt;Foods.allFoods&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is where the &lt;em&gt;Cake Pattern&lt;/em&gt; comes in.  With the &lt;em&gt;Cake Pattern&lt;/em&gt; you wrap
your trait in a &quot;component&quot; trait. For example, the &lt;code&gt;FoodCategories&lt;/code&gt; trait gets
wrapped like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategoriesComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foodCategories&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FoodCategories&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foods&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allCategories&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FoodCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Likewise for &lt;code&gt;Foods&lt;/code&gt; and &lt;code&gt;Recipes&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodsComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foods&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Foods&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allFoods&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foodNamed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;allFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RecipesComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recipes&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Recipes&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allRecipes&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Recipe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now I&#39;ll create a &lt;code&gt;SimpleFoodsComponent&lt;/code&gt; that implements &lt;code&gt;Foods&lt;/code&gt; and
&lt;code&gt;FoodCategories&lt;/code&gt; (the book implements them together too):&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;// Implement Foods and FoodCategories at once&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFoodsComponent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodsComponent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategoriesComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFoods&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foodCategories&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foods&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFoods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pear&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Pear&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allFoods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Apple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allCategories&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Nil&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And now time for the &lt;code&gt;SimpleRecipesComponent&lt;/code&gt;.  This one will depend on
&lt;code&gt;SimpleFoodsComponent&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRecipesComponent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RecipesComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleFoodsComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recipes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRecipes&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRecipes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FruitSalad&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;quot;fruit salad&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Apple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Pear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;quot;Mix it all together.&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allRecipes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;FruitSalad&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;But this time the &lt;em&gt;self type&lt;/em&gt; annotation brings &lt;code&gt;foods&lt;/code&gt; into scope. So instead
of bringing the &lt;code&gt;Foods&lt;/code&gt; methods into scope we&#39;re just bringing the &lt;code&gt;foods&lt;/code&gt;
reference (which implements &lt;code&gt;Foods&lt;/code&gt;) into scope.  I like this since it keeps
type members in separate namespaces.&lt;/p&gt;
&lt;p&gt;Does it make sense to have a &lt;code&gt;Database&lt;/code&gt; abstraction any longer?  I&#39;m not sure,
but, for completeness, here&#39;s how I implemented it.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DatabaseComponent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategoriesComponent&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodsComponent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RecipesComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Database&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Database&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoodCategories&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Recipes&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleDatabaseComponent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DatabaseComponent&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFoodsComponent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRecipesComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Database&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFoods&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRecipes&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I haven&#39;t yet talked about the other main piece of the chapter&#39;s example, the
&lt;code&gt;Browser&lt;/code&gt;.  As a component it would be defined like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BrowserComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DatabaseComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;browser&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Browser&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Browser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recipesUsing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;food&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;displayCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;database.FoodCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And then it could be implemented with a dependency on the
&lt;code&gt;SimpleDatabaseComponent&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleBrowserComponent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BrowserComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleDatabaseComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;browser&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleBrowser&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleBrowser&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Browser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recipesUsing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;food&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;allRecipes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recipe&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;recipe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ingredients&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;food&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;displayCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;database.FoodCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If the &lt;code&gt;Browser&lt;/code&gt; is the top level component then you could define it more
simply, kind of like how the book does it.&lt;/p&gt;
&lt;p&gt;For more information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/&quot;&gt;http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Explains the cake pattern along with alternative approaches, very nice.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cakesolutions.net/teamblogs/2011/12/19/cake-pattern-in-depth/&quot;&gt;http://www.cakesolutions.net/teamblogs/2011/12/19/cake-pattern-in-depth/&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;A more real world example of the cake pattern&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7032734989629005459/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/7032734989629005459' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7032734989629005459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7032734989629005459'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/03/scala-understanding-self-type.html' title='Scala: Understanding the self type annotation and how it relates to the Cake Pattern'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4664100440857921862</id><published>2014-03-02T13:22:00.002-05:00</published><updated>2014-03-02T13:24:43.742-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="scala"/><title type='text'>Scala: Extractors</title><content type='html'>&lt;!--

# Scala: Extractors

--&gt;

&lt;p&gt;I&#39;m currently working through the book &lt;a href=&quot;http://www.artima.com/shop/programming_in_scala_2ed&quot;&gt;Programming in Scala, 2nd
ed.&lt;/a&gt;.  I&#39;m in chapter 26
which is on &lt;em&gt;Extractors&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;What are Extractors?&lt;/h4&gt;
&lt;p&gt;Earlier in the book case classes were introduced.  One of the things you can do
with case classes is use them in pattern matching expressions. For example, you
might have an &lt;code&gt;Email&lt;/code&gt; case class to describe an email address:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isEmail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;But what if you are dealing with values that aren&#39;t case classes?  Extractors
allow you to basically define arbitrary match expressions without needing to set
up case classes.&lt;/p&gt;
&lt;p&gt;To understand extractors I find it helpful to understand their inverse,
&lt;em&gt;injections&lt;/em&gt;, first.  Injections take inputs and produce an output of some type,
not unlike a case class constructor.  Injections have an &lt;code&gt;apply&lt;/code&gt; method.  So
instead of our &lt;code&gt;Email&lt;/code&gt; case class above, we could define a somewhat similar
injection like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;@&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;(This is basically the example given in the book.)&lt;/p&gt;
&lt;p&gt;An &lt;em&gt;extractor&lt;/em&gt; on the other hand works in the reverse direction.  In this case
it defines an &lt;code&gt;unapply&lt;/code&gt; method that would take a candidate string and, if it is
an email address, will return the parts which would correspond to the arguments
to the &lt;code&gt;apply&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;@&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unapply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aplit&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;@&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;An &lt;em&gt;extractor&lt;/em&gt; requires the &lt;code&gt;unapply&lt;/code&gt; method, the &lt;code&gt;apply&lt;/code&gt; method is optional.
Also note that the &lt;code&gt;unapply&lt;/code&gt; method returns an &lt;code&gt;Option&lt;/code&gt; and will return &lt;code&gt;None&lt;/code&gt;
if the string is not an email address.&lt;/p&gt;
&lt;p&gt;For more details see &lt;a href=&quot;http://docs.scala-lang.org/tutorials/tour/extractor-objects.html&quot;&gt;Extractor Objects&lt;/a&gt;. For example, you can have an unapply method that returns a &lt;code&gt;Boolean&lt;/code&gt;, and there is the &lt;code&gt;unapplySeq&lt;/code&gt; method for handling variable number of arguments to an extractor.&lt;/p&gt;
&lt;h4&gt;When to use extractors vs case classes?&lt;/h4&gt;
&lt;p&gt;So extractors let you define match expression patterns in much the same way as
can be achieved with case classes. When do you use extractors instead of case
classes?&lt;/p&gt;
&lt;p&gt;The advantage that extractors have over case classes is that case classes expose
the implementation type of an API&#39;s data model.  Using an extractor allows you
to hide the implementation type(s) of the API&#39;s data model and change it without
requiring client code to change as well.&lt;/p&gt;
&lt;p&gt;For example, we can use our &lt;code&gt;Email&lt;/code&gt; extractor with a non-case class email class
like so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EmailImpl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;@&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unapply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;@&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Case classes do have advantages though. They are simpler, can be optimized
better by the Scala compiler and with &lt;code&gt;sealed&lt;/code&gt; case class hierarchies the
compiler can also catch missed cases.&lt;/p&gt;
&lt;p&gt;You can always start with case classes and then switch to extractors once there
is a need to change the data model&#39;s concrete representation type.&lt;/p&gt;
&lt;h4&gt;An example: Date&lt;/h4&gt;
&lt;p&gt;Extractors seem like a great way of working with unstructured data and APIs
where you don&#39;t have control over the source code. As an example consider the
following extractor for getting the individual time values out of a
&lt;code&gt;java.util.Date&lt;/code&gt; instance:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Calendar&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unapply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;JDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getInstance&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setTime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;YEAR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MONTH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DAY_OF_MONTH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;HOUR_OF_DAY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MINUTE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SECOND&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JCal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MILLISECOND&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This allows you write match expression against &lt;code&gt;java.util.Date&lt;/code&gt; instances, like
so:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isFebruary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;JDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can also just use them to unpack values:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hour&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minutes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;milliseconds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JDate&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now you have a much simpler way to work with Java date instances.&lt;/p&gt;
&lt;h4&gt;Final thoughts&lt;/h4&gt;
&lt;p&gt;Extractors are kind of hard to think about because you have to think in terms of
turning output backwards into inputs. Also, it&#39;s not always obvious what would
be useful for &lt;code&gt;unapply&lt;/code&gt; to return.  When working through the examples and making
up some of my own I found it useful to think of how I would implement the
&lt;em&gt;injection&lt;/em&gt; (i.e., the &lt;code&gt;apply&lt;/code&gt; method) first.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4664100440857921862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/4664100440857921862' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4664100440857921862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4664100440857921862'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/03/scala-extractors.html' title='Scala: Extractors'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-8038249739221311632</id><published>2014-02-23T10:01:00.000-05:00</published><updated>2014-03-02T09:24:06.466-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="scala"/><title type='text'>Scala: Encoded Polyline, an Example in Implementing a Custom Collection Type</title><content type='html'>

&lt;p&gt;This week I&#39;m in chapter 25 of &lt;a href=&quot;http://www.artima.com/shop/programming_in_scala_2ed&quot;&gt;Programming in Scala, 2nd ed.&lt;/a&gt;, the chapter titled &lt;em&gt;The Architecture of Scala Collections&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As an exercise, I decided I&#39;d implement a custom collection for encoded
latitude/longitude points using Google&#39;s encoding method &lt;a href=&quot;https://developers.google.com/maps/documentation/utilities/polylinealgorithm?csw=1&quot;&gt;described
here&lt;/a&gt;
if you&#39;re interested. I&#39;ve written some encoding/decoding code for this format
for the &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.fuelmyroute.android.app&quot;&gt;FuelMyRoute Android
app&lt;/a&gt;
I&#39;ve been working on, so I&#39;m fairly familiar with it.  The example the authors
implement in the book is a RNA collection where the bases are stored as bits in
an &lt;code&gt;Array&lt;/code&gt; of &lt;code&gt;Ints&lt;/code&gt;. In trying to come up with a different data structure to
implement I likewise thought of one where the data is stored in a different and
more compact format.&lt;/p&gt;
&lt;p&gt;So I started by creating a case class to represent a latitude/longitude point,
&lt;code&gt;LatLng&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lat&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lng&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then I created a &lt;code&gt;Polyline&lt;/code&gt; class that extends &lt;code&gt;LinearSeq&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initLatLng&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearSeq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Why a &lt;code&gt;LinearSeq&lt;/code&gt;?  Well, the polyline encoding format works like this. You
encode the value of the first latitude and longitude point as a character
string. For the second point, you encode the &lt;em&gt;difference&lt;/em&gt; from the first point.
For the third point, you encode the difference from the second point, and so on.
So there is no efficient random access possible.  Getting the first point
(&lt;code&gt;head&lt;/code&gt;) is fine, but in general getting a point at some index will take time
proportional to the length of polyline.  This all strongly suggests LinearSeq as
the right abstraction for an encoded polyline.  Scala&#39;s &lt;code&gt;List&lt;/code&gt; has the same
performance characteristics, for example, and is also a &lt;code&gt;LinearSeq&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are two abstract methods that must be implemented by subclasses of
&lt;code&gt;LinearSeq&lt;/code&gt;: &lt;code&gt;apply&lt;/code&gt; and &lt;code&gt;length&lt;/code&gt;. Unfortunately, again, these will take time
proportional to the length of the polyline. I&#39;m implementing them here based on
the iterator:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latlng&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latlng&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IndexOutOfBoundsException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;No LatLng at index &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;But for a &lt;code&gt;LinearSeq&lt;/code&gt;, what you want to do is provide efficient implementations
of &lt;code&gt;isEmpty&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt;. The private constructor for &lt;code&gt;Polyline&lt;/code&gt; is given
the &lt;code&gt;encoding&lt;/code&gt; as a &lt;code&gt;String&lt;/code&gt;, as well as the initial values for latitude and
longitude, which are 0 for starting from an encoded polyline string.  So for
&lt;code&gt;isEmpty&lt;/code&gt; we can simply check the length of the &lt;code&gt;encoding&lt;/code&gt; string:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;head&lt;/code&gt; will lazily convert the first latitude/longitude point and return it.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NoSuchElementException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Collection is empty.&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;computeFirstLatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;firstLatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;computeFirstLatLng&lt;/code&gt; sets &lt;code&gt;firstLatLng&lt;/code&gt;, which is of type &lt;code&gt;Option[LatLng]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The way &lt;code&gt;tail&lt;/code&gt; will work is this: it will get the first latitude/longitude point
and the remainder of the encoded string and then create a new &lt;code&gt;Polyline&lt;/code&gt;
instance from those values. Recall that when a &lt;code&gt;Polyline&lt;/code&gt; is created it is given
an initial value for the first latitude/longitude point. We can pass the first
LatLng as the initial value to use for the &lt;code&gt;Polyline&lt;/code&gt; that includes the
substring of the encoded polyline from the second point on.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UnsupportedOperationException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Collection is empty.&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;computeFirstLatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstLatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Where did &lt;code&gt;index&lt;/code&gt; come from? That&#39;s a private &lt;code&gt;var&lt;/code&gt; in class &lt;code&gt;Polyline&lt;/code&gt; that
keeps track of the position within the &lt;code&gt;Polyline&lt;/code&gt;. It really only ever points to
first point (index=0) or the second point, since traversing this Polyline will
consist of calling &lt;code&gt;head&lt;/code&gt; then &lt;code&gt;tail&lt;/code&gt; then &lt;code&gt;head&lt;/code&gt; and so on until the returned
&lt;code&gt;tail&lt;/code&gt; &lt;code&gt;isEmpty&lt;/code&gt;. Here&#39;s how &lt;code&gt;index&lt;/code&gt; is used and how &lt;code&gt;computeFirstLatLng&lt;/code&gt; is
implemented:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeFirstLatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;firstLatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEmpty&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lat&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initLatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getNextNumber&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lng&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initLatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lng&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getNextNumber&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;firstLatLng&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getNextNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shift&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;charAt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;63&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x1f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shift&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;shift&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e5&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now to create a companion object that can construct a &lt;code&gt;Polyline&lt;/code&gt; instance:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromEncoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromSeq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;latlngs&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// TODO: implement encoding LatLngs into a polyline string&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now we can create and iterate over a &lt;code&gt;Polyline&lt;/code&gt; instance:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromEncoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;_p~iF~ps|U_ulLnnqC_mqNvxq`@&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pl&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;38.5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;120.2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;40.7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;120.95&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;43.252&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;126.453&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Builders&lt;/h4&gt;
&lt;p&gt;This all works well enough, but what happens if you apply methods like &lt;code&gt;take&lt;/code&gt; or
&lt;code&gt;filter&lt;/code&gt;?&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;take&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;res0&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;scala.collection.LinearSeq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;38.5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;120.2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;40.7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;120.95&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The type of the result is &lt;code&gt;List&lt;/code&gt;, not &lt;code&gt;Polyline&lt;/code&gt; as we would like. To have your
custom Collection type return results in the same type you need to provide a
&lt;code&gt;Builder&lt;/code&gt; that can construct instances of your custom collection type.&lt;/p&gt;
&lt;p&gt;What&#39;s a &lt;code&gt;Builder&lt;/code&gt;?  A &lt;code&gt;Builder&lt;/code&gt; can add elements to a particular kind of
collection type.  Also useful is that a &lt;code&gt;Builder&lt;/code&gt; provides a &lt;code&gt;mapResult&lt;/code&gt; method
that allows you to map from the output of one &lt;code&gt;Builder&lt;/code&gt; to a different
collection type.  Here&#39;s a simplified interface:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;-Elem&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;+To&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Elem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;this.type&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;To&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapResult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;To&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NewTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Elem&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;NewTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The power of &lt;code&gt;mapResult&lt;/code&gt; is we can use an existing &lt;code&gt;Builder&lt;/code&gt; to create a
collection of one type and then map it to the &lt;code&gt;Polyline&lt;/code&gt; collection type.  In
our case we&#39;ll use &lt;code&gt;ArrayBuffer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So what do you need to do to supply a custom &lt;code&gt;Builder&lt;/code&gt;?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Extend the &quot;&lt;code&gt;Like&lt;/code&gt;&quot; trait and supply the result type of your custom collection
   as the second type parameter of the trait. Every Seq type has a corresponding
   &quot;&lt;code&gt;Like&lt;/code&gt;&quot; type that contains all of the implementation. For example,
   &lt;code&gt;LinearSeq&lt;/code&gt;&#39;s Like type is &lt;code&gt;LinearSeqLike&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Override &lt;code&gt;newBuilder&lt;/code&gt; to return a &lt;code&gt;Builder&lt;/code&gt; that can construct instances of
   your custom collection type.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For &lt;code&gt;Polyline&lt;/code&gt; it would work like this:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initLatLng&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearSeq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearSeqLike&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newBuilder&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapResult&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromSeq&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note: I&#39;d need to actually implement &lt;code&gt;Polyline.fromSeq&lt;/code&gt; for this to work. I ran
out of time, but hopefully you can see how the Builder would work and actually
implementing &lt;code&gt;fromSeq&lt;/code&gt; is just a detail at this point.&lt;/p&gt;
&lt;h4&gt;CanBuildFrom&lt;/h4&gt;
&lt;p&gt;Overriding &lt;code&gt;newBuilder&lt;/code&gt; isn&#39;t quite enough for our custom collection type to
always return the same collection type (at least when it is possible to return
the same collection type).  For example, the collection concatenation operator,
&lt;code&gt;++&lt;/code&gt;, needs to be able to return a sequence where the element type of the
sequence is the most specific superclass of the right hand side and left hand
side collections.  It does this via an implicit parameter of type
&lt;code&gt;CanBuildFrom&lt;/code&gt;.  The signature of &lt;code&gt;++&lt;/code&gt; is:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;++[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;That&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GenTraversableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bf&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CanBuildFrom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LinearSeq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;That&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;That&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;CanBuildFrom&lt;/code&gt; is a trait defined as such:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CanBuildFrom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;-From&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;-Elem&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;+To&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;From&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Elem&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Elem&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So basically the Scala compiler will try to bind the most specific implicit
&lt;code&gt;CanBuildFrom&lt;/code&gt; that it can match the types of the arguments.  &lt;code&gt;LinearSeq&lt;/code&gt;
defines a very general &lt;code&gt;CanBuildFrom&lt;/code&gt; that can be used for any types.  To have
&lt;code&gt;++&lt;/code&gt; concatenate two &lt;code&gt;Polyline&lt;/code&gt;s and return a &lt;code&gt;Polyline&lt;/code&gt; instance we have to
define a specific &lt;code&gt;CanBuildFrom&lt;/code&gt;, which can be done in the companion object:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//...&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// We&amp;#39;ll move the newBuilder method to the companion object and the&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Polyline class will reference this one&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newBuilder&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapResult&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromSeq&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canBuildFrom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CanBuildFrom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newBuilder&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LatLng&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Polyline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newBuilder&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Resources&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The polyline decoding code was largely inspired by &lt;a href=&quot;http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java&quot;&gt;http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Looks like most of chapter 25 of &lt;em&gt;Programming in Scala&lt;/em&gt; is online: &lt;a href=&quot;http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html&quot;&gt;http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/8038249739221311632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/8038249739221311632' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/8038249739221311632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/8038249739221311632'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/02/scala-encoded-polyline-example-in.html' title='Scala: Encoded Polyline, an Example in Implementing a Custom Collection Type'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-5422532606356201834</id><published>2014-02-17T12:49:00.000-05:00</published><updated>2014-02-17T12:50:02.625-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="scala"/><title type='text'>Scala: What&#39;s the difference between Traversable and Iterable?</title><content type='html'>&lt;!--

# Scala: What&#39;s the difference between Traversable and Iterable?

--&gt;

&lt;p&gt;I&#39;m currently working through the book &lt;a href=&quot;http://www.artima.com/shop/programming_in_scala_2ed&quot;&gt;Programming in Scala, 2nd
ed.&lt;/a&gt;.  I&#39;m in chapter 24
and reading about the &lt;code&gt;Traversable&lt;/code&gt; and &lt;code&gt;Iterable&lt;/code&gt; traits and the difference
between them.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Traversable&lt;/code&gt; is a trait with one abstract method, &lt;code&gt;foreach&lt;/code&gt;.  It&#39;s signature is&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Elem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Defining this one method for a &lt;code&gt;Traversable&lt;/code&gt; allows your collection class to
gain several useful methods like&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;map&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flatMap&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;take&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;drop&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;filter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;foldLeft&lt;/code&gt;, &lt;code&gt;foldRight&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.scala-lang.org/api/current/index.html#scala.collection.Traversable&quot;&gt;etc.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Iterable&lt;/code&gt; is a trait that extends &lt;code&gt;Traversable&lt;/code&gt; and also has one abstract
method, &lt;code&gt;iterator&lt;/code&gt;. It&#39;s signature is&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Iterable&lt;/code&gt; defines &lt;code&gt;foreach&lt;/code&gt; in terms of this &lt;code&gt;iterator&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Elem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If we can implement &lt;code&gt;foreach&lt;/code&gt; in terms of &lt;code&gt;iterator&lt;/code&gt;, why have &lt;code&gt;Traversable&lt;/code&gt; as
a separate trait?&lt;/p&gt;
&lt;p&gt;The book provides one reason: &lt;strong&gt;that for some collections, implementing
&lt;code&gt;iterator&lt;/code&gt; may not be easy or may not be efficient&lt;/strong&gt;. To illustrate this the
book uses a &lt;code&gt;Tree&lt;/code&gt; data structure as an example.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Tree&lt;/code&gt; data structure is defined as a case class hierarchy:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;sealed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I&#39;m a Scala newbie so I couldn&#39;t get &lt;a href=&quot;http://booksites.artima.com/programming_in_scala_2ed/examples/html/ch24.html#sec3&quot;&gt;their &lt;code&gt;Traversable&lt;/code&gt; &lt;code&gt;Tree&lt;/code&gt; code
example&lt;/a&gt;
to work. Instead I came up with this:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;sealed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Traversable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For the &lt;code&gt;Iterable&lt;/code&gt; version I came up with this:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;sealed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Iterable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;single&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Both fairly straightforward. The problem with the &lt;code&gt;Iterable&lt;/code&gt; version is
with the efficiency of visiting nodes in the tree. In particular, the
implementation of &lt;code&gt;++&lt;/code&gt; is such that it has to do an extra indirection at every
call to &lt;code&gt;next&lt;/code&gt; to determine whether to pull from the left or the right iterator.&lt;/p&gt;
&lt;p&gt;I think it helps to see what a naive implementation of &lt;code&gt;++&lt;/code&gt; would look like:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Every call to &lt;code&gt;next&lt;/code&gt; has to first check &lt;code&gt;left.hasNext&lt;/code&gt; before returning a value.
In a balanced binary tree with N leaf nodes, the depth of the tree is
approximately log(N). So to reach a leaf via this added iterator would require
an extra log(N) calls to &lt;code&gt;left.hasNext&lt;/code&gt;.  Therefore, visiting all of the leaf
nodes using the iterator would take O(N*log(N)).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;But&lt;/em&gt;, that&#39;s with the naive implementation of &lt;code&gt;++&lt;/code&gt;. The &lt;a href=&quot;https://github.com/scala/scala/blob/v2.10.3/src/library/scala/collection/Iterator.scala#L341&quot;&gt;actual
implementation&lt;/a&gt;,
shown below, optimizes by keeping a reference, &lt;code&gt;cur&lt;/code&gt;, to the current &lt;code&gt;Iterator&lt;/code&gt;.
This allows it to avoid needing to check &lt;code&gt;hasNext&lt;/code&gt; on the first &lt;code&gt;Iterator&lt;/code&gt; on
each call to &lt;code&gt;next&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GenTraversableOnce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AbstractIterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// optimize a little bit to prevent n log n behavior.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cur&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selfExhausted&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// since that is by-name, make sure it&amp;#39;s only referenced once -&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// if &amp;quot;val it = that&amp;quot; is inside the block, then hasNext on an empty&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// iterator will continually reevaluate it. (ticket #3269)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toIterator&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// the eq check is to avoid an infinite loop on &amp;quot;x ++ x&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selfExhausted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cur&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;selfExhausted&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasNext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So, to a certain degree, this example with the &lt;code&gt;Tree&lt;/code&gt; is a little artificial.
It&#39;s just as easy to implement &lt;code&gt;Tree&lt;/code&gt; as an &lt;code&gt;Iterable&lt;/code&gt; as it is to implement it
as a &lt;code&gt;Traversable&lt;/code&gt; and there is no fundamental reason why the performance of
visiting all of the leaf nodes needs to be worse than a &lt;code&gt;Traversable&lt;/code&gt;
implementation.&lt;/p&gt;
&lt;p&gt;I think it is reasonable to assume that there might be data structures where
implementing an &lt;code&gt;Iterator&lt;/code&gt; over their elements could be challenging (either
fundamentally so or with regards to efficiency). I just wish I could think of a
more compelling example.&lt;/p&gt;
&lt;p&gt;Further resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/2602379/in-scala-2-8-collections-why-was-the-traversable-type-added-above-iterable&quot;&gt;http://stackoverflow.com/questions/2602379/in-scala-2-8-collections-why-was-the-traversable-type-added-above-iterable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.schauderhaft.de/2010/12/19/the-scala-collection-api-sucks-or-is-it-a-work-of-beauty/&quot;&gt;http://blog.schauderhaft.de/2010/12/19/the-scala-collection-api-sucks-or-is-it-a-work-of-beauty/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/5422532606356201834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/5422532606356201834' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5422532606356201834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5422532606356201834'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2014/02/scala-whats-difference-between.html' title='Scala: What&#39;s the difference between Traversable and Iterable?'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7078733966312264460</id><published>2013-03-29T21:32:00.000-04:00</published><updated>2013-03-29T21:32:14.833-04:00</updated><title type='text'>Learning Design: An Initial Curriculum</title><content type='html'>&lt;!--
vim: ts=4 sw=4 et ai tw=80:
# Learning Design: An Initial Curriculum
--&gt;

&lt;p&gt;I&#39;m a programmer, not a designer. And in the past, I&#39;ve been fine with that.
I&#39;ll do the programming, let the designers do the designing. But now I want to
learn how to design. And by design I mean just about everything that design can
mean, both things like visual, graphic design and things like usability and
information architecture.&lt;/p&gt;
&lt;p&gt;Why? What&#39;s changed? I would say two things really. First, I think I can learn
design (I think anyone can learn just about anything if motivated). I used to
think that it just wasn&#39;t my talent. I would tell myself that &quot;I can make things
work, I just can&#39;t make them pretty.&quot; Second, I&#39;m curious. I want to learn
design now. I have come to appreciate that design isn&#39;t just &quot;making things
pretty&quot;.  I think that design is about solving the human side of a problem.
Being a programmer means I can solve the technological side of a problem, but
that is only half of it. The best code in the world that actually solves a real
problem won&#39;t do anyone good if it isn&#39;t usable. And the more that the user
interface to a system &lt;em&gt;delights&lt;/em&gt; users the more impact that solution will have
in the real world.&lt;/p&gt;
&lt;p&gt;I also think that learning design is a better career move than, for example,
learning functional programming or how to write event-driven, non-blocking web
server code, or whatever the new hotness is.  I don&#39;t expect to become a great
designer, only a decent one.  I expect I will still need to work with a &quot;real&quot;
designer on at least some of my projects, maybe all.  But being able to put
together good looking prototypes, being able to communicate better with
web/graphic designers, being able to produce decent initial working versions of
software, being able to layout and organize displays of information in ways that
are helpful and appealing, all of that makes me better able to deliver software
solutions and hence make me more valuable to potential employers. Perhaps most
importantly to me, as an wannabe bootstrapped entrepreneur, it means I can
create more compelling applications and that I can more fully realize the
applications that I see in my imagination.&lt;/p&gt;
&lt;p&gt;So here&#39;s what I&#39;m looking at now as resources for learning design.&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;http://teamtreehouse.com/learning-adventures/become-a-web-designer&quot;&gt;Treehouse: Become a Web Designer Adventure&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I like the idea of an online course. I think it will be easier to consume and
stay on track.  I also like that Treehouse covers theory (although maybe a
little light on it by the looks of the curriculum) and also practice, how to use
the tools of the trade. (But man is Photoshop expensive!)&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;http://www.amazon.com/Non-Designers-Design-Book-Robin-Williams/dp/0321193857/ref=la_B000APA7OO_1_1?ie=UTF8&amp;amp;qid=1364604565&amp;amp;sr=1-1&quot;&gt;Non-Designer&#39;s Design Book by Robin Williams&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I&#39;ve seen this book recommended on Hacker News and elsewhere more times than I
can count.  I&#39;m including it with the hopes it will give me a good foundation in
the basics of design theory (and practice).&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;http://www.amazon.com/Dont-Make-Me-Think-Usability/dp/0321344758/ref=la_B001KHCFUU_1_1?ie=UTF8&amp;amp;qid=1364604618&amp;amp;sr=1-1&quot;&gt;Don&#39;t Make Me Think by Steve Krug&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Another book that comes highly recommended. I realize this list is a little
light on HCI type topics and perhaps I can add some more useability/user
experience resources to this list, but I think &lt;em&gt;Don&#39;t Make Me Think&lt;/em&gt; is a good
place to start.&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;http://www.amazon.com/Drawing-Right-Side-Brain-Definitive/dp/1585429201/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1364604750&amp;amp;sr=1-1&quot;&gt;Drawing on the Right Side of the Brain by Betty Edwards&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I don&#39;t think drawing will directly help me with web design, but I do think it
will get the artistic juices flowing. One of the things I&#39;ve read about this
book is that it doesn&#39;t so much teach you how to draw as much as it teaches you
how to really &lt;em&gt;see&lt;/em&gt;.  That ability to see clearly will help me to see what is
good in other&#39;s design and perhaps also help me see how to make my designs
better.&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;http://www.amazon.com/Design-Everyday-Things-Donald-Norman/dp/0465067107/ref=la_B000APP96A_1_1?ie=UTF8&amp;amp;qid=1364605106&amp;amp;sr=1-1&quot;&gt;Design of Everyday Things by Donald Norman&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Another highly recommended book, but I haven&#39;t read much about it. Looking
forward to reading it.&lt;/p&gt;
&lt;h4&gt;Copying good designs&lt;/h4&gt;
&lt;p&gt;What&#39;s the saying, &lt;em&gt;good artists create, great artists steal?&lt;/em&gt;. As part of my
curriculum I&#39;ll study and copy design that I find appealing. Why do they work so
well?  How do they implement those designs?&lt;/p&gt;
&lt;p&gt;I&#39;ve done something like this before when I was working on learning CSS. I took
a screenshot of &lt;a href=&quot;http://www.csszengarden.com&quot;&gt;csszengarden.com&lt;/a&gt;, copied the HTML
and images and wrote the CSS from scratch to match the screenshot.  It was a
good learning exercise, not just in that I exercised applying what I had learned
about CSS but after I was done I also compared what I had done to the
csszengarden.com&#39;s CSS code and learned from the approaches they had taken.&lt;/p&gt;
&lt;h4&gt;Notable Mention&lt;/h4&gt;
&lt;p&gt;In my research, these resources looked interesting and I might use them, but I
don&#39;t have enough time to do everything.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/1119998956&quot;&gt;Design for Hackers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://designingfortheweb.co.uk/book/index.php&quot;&gt;Designing for the Web&lt;/a&gt; - This
  is a free resource&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://hackdesign.org/&quot;&gt;HACKDESIGN&lt;/a&gt; - free course by email. Actually I think
  I will sign up for this one. Looks interesting and I&#39;ve never done a course by
  email.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sachagreif.com/ebook/&quot;&gt;Step by Step UI Design&lt;/a&gt; - Step by Step UI
  Design. Looks really good as a resource for learning more about the actual
  practice of web design.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.coursera.org/course/hci&quot;&gt;HCI course on Coursera&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7078733966312264460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/7078733966312264460' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7078733966312264460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7078733966312264460'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2013/03/learning-design-initial-curriculum.html' title='Learning Design: An Initial Curriculum'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-269170701630410057</id><published>2013-03-17T10:33:00.000-04:00</published><updated>2013-03-17T10:33:20.424-04:00</updated><title type='text'>Using Codea and Khan Academy to teach computer programming to my daughter</title><content type='html'>&lt;!--
vim: ts=4 sw=4 et ai tw=80:
# Using Codea and Khan Academy to teach computer programming to my daughter
--&gt;

&lt;p&gt;I&#39;ve been teaching computer programming to my oldest daughter (who is turning 11
soon) for the past couple of years or so. We started out with Scratch and she
had a blast with that. After completing a simple game that she designed and
developed herself, I asked her what she wanted to do next. She said, &quot;I want to
do what you do&quot;. She knew from watching me work that the visual programming
environment in Scratch is not how &quot;real&quot; programmers work.&lt;/p&gt;
&lt;p&gt;So our next step was to give Python programming a try. We got the book &lt;a href=&quot;http://inventwithpython.com/&quot;&gt;Invent
Your Own Computer Games with Python&lt;/a&gt; and started
working through it. Unfortunately, jumping into Python from Scratch was probably
a little too tough and the fact that the programs she
was creating in Python were completely textual meant that it was less engaging.
So I started thinking about what we could do next.&lt;/p&gt;
&lt;h5&gt;Getting nostalgic for my Atari 800XL&lt;/h5&gt;
&lt;p&gt;I thought about what computing meant for me when I was her age. Growing up I had
an &lt;a href=&quot;http://en.wikipedia.org/wiki/File:Atari-800XL.jpg&quot;&gt;Atari 800XL&lt;/a&gt;.  What a
marvelously simple device compared to what we have available to us today.  There
were two things that made the Atari 800XL a great first computer for a kid:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;No internet.&lt;/li&gt;
&lt;li&gt;Simple programming environments (BASIC and Turtle graphics).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That first one is a big deal. We don&#39;t let our children use computers unattended
because of the inherent dangers of the world wide web.  I&#39;m sure my parents
never had any such concerns because my Atari 800XL was never networked at all.
Because of that I spent a lot of time just playing around on my computer.  I
remember hours upon hours spent meticulously typing in computer programs from
magazines such as &lt;a href=&quot;http://en.wikipedia.org/wiki/Compute!&quot;&gt;Compute!&lt;/a&gt; into my
800XL.&lt;/p&gt;
&lt;p&gt;The second one, simple programming environments, is important too, but there are
plenty of those to be had. Turtle graphics was particularly good because I could
get the gratification of generating a visual effect of some sort. Probably the
most advanced turtle graphics program I wrote (which wasn&#39;t very advanced, but I
was proud of it at the time) was one where I animated a simple line drawing of a
bird flapping its wings. I could control the bird&#39;s position on the screen by
using a joystick.  That was a lot of fun.&lt;/p&gt;
&lt;p&gt;So this got me to thinking. Could I set up a computing environment for my
daughter that would be easy for us to monitor, allow her to just waste time
playing around with different ideas and approaches, and allow her to create
graphical programs?&lt;/p&gt;
&lt;h5&gt;Enter Codea&lt;/h5&gt;
&lt;p&gt;I thought, what if she could have a turtle graphics like program on our iPad?
She (like everyone in the family) just adores our iPad.  If she could create
graphical programs on the iPad, especially if they could respond to touch and
what not, I thought she would get a big kick out of that.&lt;/p&gt;
&lt;p&gt;The iPad still suffers from the problem of having unfettered access to the
internet, but an app that serves as a self-contained environment would minimize
the chance that she would ever even end up in Safari.  Also, it&#39;s not too hard
to keep an eye on her using the iPad while in the same room with her.&lt;/p&gt;
&lt;p&gt;While Codea is a great programming environment, it&#39;s not the the best learning
environment. I tried coming up with my own lessons, and I also found some Codea
tutorials online, but nothing was really clicking. She did spend some time just
exploring and playing with Codea, but that only goes so far.&lt;/p&gt;
&lt;h5&gt;And then we found Khan Academy&lt;/h5&gt;
&lt;p&gt;Khan Academy has video lessons and an integrated code editor.  Like Codea, it
offers a &lt;a href=&quot;http://processing.org/&quot;&gt;Processing&lt;/a&gt; like API.  There are a few nice
things about Khan Academy.&lt;/p&gt;
&lt;p&gt;First, they have a series of tutorials that my daughter is able to watch and
progress through at her own pace. The tutorials are in sync with actions in the
code editor, so she can pause the tutorial and experiment with the code at any
point.  Also nice, the video tutorials are narrated by a woman. It might seem
like a minor thing but I&#39;ve noticed that my daughter has picked up on the fact
that the computer programmer profession is male-dominated, so any reinforcements
that, &lt;em&gt;yes, girls program too&lt;/em&gt;, is always nice.&lt;/p&gt;
&lt;p&gt;Second, the code editor and the graphical display are side by side. You can see
the effect of your code changes as you type them.  Codea requires you flip
between code editing and running your code.&lt;/p&gt;
&lt;p&gt;Third, Khan Academy has gamification!  You can earn achievements and badges. You
can create a &quot;spin-off&quot; of one of the example programs, make it cooler, and then
other Khan Academy users can vote on them.  Turns out this is very cool for an
11 year old!&lt;/p&gt;
&lt;p&gt;So far, Khan Academy seems to be the most perfect environment to learn computer
programming that we&#39;ve found yet.&lt;/p&gt;
&lt;p&gt;Since Khan Academy and Codea both use the Processing API, we&#39;ve experimented
with moving code between the two environments.  There are some slight syntactic
differences between JavaScript (Khan Academy) and Lua (Codea) of course. Codea
also has the vertical axis flipped compared to Khan Academy. Khan Academy names
some things differently and has some different API methods like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;strokeWeight&lt;/code&gt; instead of &lt;code&gt;strokeWidth&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;point(x ,y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;triangle(x1, y1, x2, y2, x3, y3)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&#39;s an example of how I translated the &lt;a href=&quot;http://www.khanacademy.org/cs/intro-to-animation/830742281&quot;&gt;Intro to
Animation&lt;/a&gt; lesson
into Codea (&lt;code&gt;point&lt;/code&gt; and &lt;code&gt;triangle&lt;/code&gt; aren&#39;t used below, but they are used in some
Khan Academy programs so I&#39;m including them here just for illustrative purposes):&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;-- KA-Intro to Animation&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- vim: set ts=4 sw=4 et ai filetype=lua:&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Hello World!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;strokeWeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;strokeWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;triangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;myMesh&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mesh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;myMesh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vec2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vec2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vec2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;myMesh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initKhan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- Khan Academy setup&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- set a default stroke &amp;quot;weight&amp;quot; (codea calls this width) and color&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;strokeWeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;-- translate and scale into Khan Academy coordinate system&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;initKhan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- this is the draw loop! everything inside this&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- function will be run over and over again.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;252&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;214&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;noStroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;-- position of the car&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;-- draw the car body&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;115&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;178&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;-- draw the wheels&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;77&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;66&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;66&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ellipse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;221&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ellipse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;75&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;221&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So that&#39;s where we are so far. I&#39;m hoping we can work toward a project this
year, like making a mobile app game or something.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/269170701630410057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/269170701630410057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/269170701630410057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/269170701630410057'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2013/03/using-codea-and-khan-academy-to-teach.html' title='Using Codea and Khan Academy to teach computer programming to my daughter'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-2142413703684127453</id><published>2013-03-09T21:37:00.001-05:00</published><updated>2013-03-09T21:37:57.415-05:00</updated><title type='text'>How do you set up for multi package Python development?</title><content type='html'>&lt;!--
vim: ts=4 sw=4 et ai tw=80:
# How do you set up for multi package Python development?

--&gt;

&lt;style&gt;
.codehilite .hll { background-color: #ffffcc }
.codehilite  { background: #f8f8f8; }
.codehilite .c { color: #408080; font-style: italic } /* Comment */
.codehilite .err { border: 1px solid #FF0000 } /* Error */
.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
.codehilite .o { color: #666666 } /* Operator */
.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
.codehilite .gd { color: #A00000 } /* Generic.Deleted */
.codehilite .ge { font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #FF0000 } /* Generic.Error */
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.codehilite .gi { color: #00A000 } /* Generic.Inserted */
.codehilite .go { color: #888888 } /* Generic.Output */
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.codehilite .gs { font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.codehilite .gt { color: #0044DD } /* Generic.Traceback */
.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #B00040 } /* Keyword.Type */
.codehilite .m { color: #666666 } /* Literal.Number */
.codehilite .s { color: #BA2121 } /* Literal.String */
.codehilite .na { color: #7D9029 } /* Name.Attribute */
.codehilite .nb { color: #008000 } /* Name.Builtin */
.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.codehilite .no { color: #880000 } /* Name.Constant */
.codehilite .nd { color: #AA22FF } /* Name.Decorator */
.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #0000FF } /* Name.Function */
.codehilite .nl { color: #A0A000 } /* Name.Label */
.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
.codehilite .nv { color: #19177C } /* Name.Variable */
.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
.codehilite .mf { color: #666666 } /* Literal.Number.Float */
.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.codehilite .sx { color: #008000 } /* Literal.String.Other */
.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
.codehilite .vc { color: #19177C } /* Name.Variable.Class */
.codehilite .vg { color: #19177C } /* Name.Variable.Global */
.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
&lt;/style&gt;

&lt;h5&gt;Or, how do I use my models outside of a Pyramid application?&lt;/h5&gt;
&lt;p&gt;I&#39;ve developed a little Pyramid app as a mobile backend version of
&lt;a href=&quot;http://fuelmyroute.com&quot;&gt;FuelMyRoute.com&lt;/a&gt;.  As natural, I&#39;ve defined the
database models inside the application.  But, now I want to develop a new gas
price data importer piece of code that will live outside of the Pyramid web
application.  This importer will need to make use of the same models as defined
in the Pyramid app. So what to do?&lt;/p&gt;
&lt;p&gt;Well, ideally I would have the models defined outside of the Pyramid app in its
own package.  So I would end up with three packages: the Pyramid app is a package,
the models are a package, making the importer code a third package.  The importer
package would depend on the models package, just like the Pyramid app.&lt;/p&gt;
&lt;p&gt;Now, in Python there are lots of mechanisms to pull this off. First we could
just manipulate the &lt;code&gt;sys.path&lt;/code&gt; in each package to pull in the needed
dependencies.  Second we could set a &lt;code&gt;PYTHONPATH&lt;/code&gt; to pull in the other packages.
But the way I decided to do it was to install the packages into a virtual
environment. I got this idea from the Pyramid tutorial/documentation where it
has you do a &lt;code&gt;python setup.py develop&lt;/code&gt; into the virtual environment for the app.
&lt;code&gt;python setup.py develop&lt;/code&gt; is basically a way to symlink in your package into the
system path of the virtual environment.&lt;/p&gt;
&lt;p&gt;Here are the three packages. Each package name is prefixed with &lt;code&gt;gptp-&lt;/code&gt;, which is just
an codename for an earlier version of FuelMyRoute.com.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;gptp-models&lt;/code&gt; - Defines the SQLAlchemy models&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gptp-pyramid&lt;/code&gt; - The Pyramid application, depends on &lt;code&gt;gptp-models&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gptp-importer&lt;/code&gt; - Gas price data importer code, depends on &lt;code&gt;gptp-models&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&#39;s the &lt;code&gt;setup.py&lt;/code&gt; file for the &lt;code&gt;gptp-models&lt;/code&gt; package:&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;setuptools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find_packages&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# http://pythonhosted.org/distribute/setuptools.html#basic-use&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;gptp-models&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;0.1dev&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;packages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;install_requires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# &amp;lt;0.8 includes stupid stuff like 0.8b2, so have to defensively prevent&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# alphas, betas etc. http://stackoverflow.com/a/14405269/1419499&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;SQLAlchemy&amp;lt;0.7.99&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;#... additional dependecies&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This is just about as barebones as it can get for a &lt;code&gt;setup.py&lt;/code&gt;. I believe that
only &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt; and &lt;code&gt;packages&lt;/code&gt; are required.  This package depends on
SQLAlchmey, amongst other things, so I&#39;ve included that to illustrate how to
declare dependencies.&lt;/p&gt;
&lt;p&gt;Here&#39;s the setup.py for &lt;code&gt;gptp-pyramid&lt;/code&gt;:&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;setuptools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find_packages&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;here&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abspath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__file__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;README&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;here&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;README.txt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;CHANGES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;here&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;CHANGES.txt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;pyramid&amp;lt;=1.3.99&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;SQLAlchemy&amp;lt;=0.7.99&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;transaction&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;pyramid_tm&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;pyramid_debugtoolbar&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;zope.sqlalchemy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;waitress&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;gptp-models&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# .. more dependencies ..&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;gptp&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;0.0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;gptp&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;long_description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;README&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;CHANGES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;classifiers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;Programming Language :: Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;Framework :: Pylons&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;Topic :: Internet :: WWW/HTTP&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;Topic :: Internet :: WWW/HTTP :: WSGI :: Application&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;author_email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;web wsgi bfg pylons pyramid&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;packages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;include_package_data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;zip_safe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;test_suite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;gptp&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;install_requires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;entry_points&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      [paste.app_factory]&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      main = gptp:main&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      [console_scripts]&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      initialize_gptp_db = gptp.scripts.initializedb:main&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;There&#39;s more going on here, but most of the extra stuff is stuff that was
auto-generated by Pyramid. The important thing is that on about line 18 the
package &lt;code&gt;gptp-models&lt;/code&gt; is listed as a required dependency.&lt;/p&gt;
&lt;p&gt;Finally we have &lt;code&gt;gptp-importer&lt;/code&gt;&#39;s setup.py:&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;setuptools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find_packages&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# http://pythonhosted.org/distribute/setuptools.html#basic-use&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;gptp-importer&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;0.1dev&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;packages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;install_requires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;gptp-models&amp;#39;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;About what you might expect at this point.&lt;/p&gt;
&lt;p&gt;So now with my three packages set up, I can proceed with setting up a virtual
environment.   I&#39;m using Python 3.3 so I set up the virtual environment with the
built in pyvenv command and install distribute and pip into it, using this
script, named &lt;code&gt;bootstrap-pyvenv&lt;/code&gt;:&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Create Python virtual environment&lt;/span&gt;
pyvenv &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# install distribute and pip&lt;/span&gt;
curl -O http://python-distribute.org/distribute_setup.py
&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;/bin/python distribute_setup.py
&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;/bin/easy_install pip

&lt;span class=&quot;c&quot;&gt;# Clean up&lt;/span&gt;
rm distribute*
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;So I run:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;bootstrap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyvenv&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gptpenv&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then, activate the environment and run &lt;code&gt;python setup.py develop&lt;/code&gt; in each
package, starting with &lt;code&gt;gptp-models&lt;/code&gt; of course:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gptpenv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activate&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gptp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;develop&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gptp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;importer&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;develop&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gptp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyramid&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;develop&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Okay, so that&#39;s set up. But how do I get Pyramid to use my models that are
defined in a separate package? Here&#39;s what my models.py looked like before I
made my changes:&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sqlalchemy&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ForeignKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sqlalchemy.ext.declarative&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;declarative_base&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;relationship&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;scoped_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sessionmaker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;zope.sqlalchemy&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ZopeTransactionExtension&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;datetime&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;shapely.wkb&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unpack&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;geo.proj&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProjectedPoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utm_projector&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;DBSession&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scoped_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sessionmaker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ZopeTransactionExtension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;declarative_base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# ... start defining my models here ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;I moved my models into &lt;code&gt;gptp-models/models.py&lt;/code&gt; and updated the pyramid models.py
to be:&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;models&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;scoped_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sessionmaker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;zope.sqlalchemy&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ZopeTransactionExtension&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;DBSession&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scoped_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sessionmaker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ZopeTransactionExtension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The &lt;code&gt;import models&lt;/code&gt; imports my models from the &lt;code&gt;gptp-models&lt;/code&gt; package (could
probably be namespaced better, but this suffices for now). The line&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;is just a convenience so that I can continue to import &lt;code&gt;Base&lt;/code&gt; from the Pyramid
models.py.&lt;/p&gt;
&lt;p&gt;That&#39;s basically it. I just need to update the imports elsewhere in the app. For
example, in my &lt;code&gt;views.py&lt;/code&gt; I had&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt;1
2
3
4
5
6
7&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;DBSession&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;GasStation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;GasPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;which becomes:&lt;/p&gt;
&lt;table class=&quot;codehilitetable&quot;&gt;&lt;tr&gt;&lt;td class=&quot;linenos&quot;&gt;&lt;div class=&quot;linenodiv&quot;&gt;&lt;pre&gt;1
2
3
4
5
6
7
8
9&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;DBSession&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;GasStation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;GasPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;h4&gt;Other Approaches to the Multiple Python Packages Problem&lt;/h4&gt;
&lt;p&gt;I asked about what people do in this situation on Twitter:&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p&gt;Developing on multiple python projects that depend on each other? Make a virtual env and &#39;python setup.py develop&#39; in each project&lt;/p&gt;&amp;mdash; marcus_christie (@marcus_christie) &lt;a href=&quot;https://twitter.com/marcus_christie/status/308413997164670976&quot;&gt;March 4, 2013&lt;/a&gt;&lt;/blockquote&gt;

&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;Pradeep Gowda replied with&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-conversation=&quot;none&quot;&gt;&lt;p&gt;@&lt;a href=&quot;https://twitter.com/marcus_christie&quot;&gt;marcus_christie&lt;/a&gt; package each project &amp;amp; push to a local python package index (pypi). Use pip --index-url to install in virtualenv&lt;/p&gt;&amp;mdash; btbytes (@btbytes) &lt;a href=&quot;https://twitter.com/btbytes/status/308421728399400960&quot;&gt;March 4, 2013&lt;/a&gt;&lt;/blockquote&gt;

&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;I think that would probably be the better way to go for a larger project and
multiple developers. For what I&#39;m doing, since it&#39;s just me and a side project,
the setup described above is sufficient.&lt;/p&gt;
&lt;p&gt;Pradeep shared the following benefit of going the local pypi approach:&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-conversation=&quot;none&quot;&gt;&lt;p&gt;@&lt;a href=&quot;https://twitter.com/marcus_christie&quot;&gt;marcus_christie&lt;/a&gt; having packages versioned and on a repo opens up new workflow opportunities (eg: vagrant/chef automation). Many +ves.&lt;/p&gt;&amp;mdash; btbytes (@btbytes) &lt;a href=&quot;https://twitter.com/btbytes/status/308426138391289858&quot;&gt;March 4, 2013&lt;/a&gt;&lt;/blockquote&gt;

&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;He also shared &lt;a href=&quot;http://ziade.org/2008/03/20/how-to-run-your-own-private-pypi-cheeseshop-server/&quot;&gt;this link on how to set up a local
PyPI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So that&#39;s another option that is worth considering too.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/2142413703684127453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/2142413703684127453' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2142413703684127453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2142413703684127453'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2013/03/how-do-you-set-up-for-multi-package.html' title='How do you set up for multi package Python development?'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-6297381763271495308</id><published>2013-02-10T21:13:00.001-05:00</published><updated>2013-02-10T21:13:34.612-05:00</updated><title type='text'>CodeMash 2013 Part II: Sessions</title><content type='html'>&lt;!--
vim: ts=4 sw=4 et ai tw=80:
# CodeMash 2013 Part II: Sessions
--&gt;

&lt;p&gt;In my previous post, &lt;a href=&quot;http://marcus-christie.blogspot.com/2013/01/codemash-2013-part-i-precompilers.html&quot;&gt;CodeMash 2013 Part
I&lt;/a&gt;,
I covered the &quot;precompilers&quot; (that&#39;s CodeMash-ese for &quot;tutorial&quot; or &quot;workshop&quot;)
that I attended. The last two days of CodeMash, Thursday and Friday, are devoted
to technical talks and presentations (although there&#39;s a lot more going on than
just technical talks like open spaces, KidzMash (for the younger geeks), the
&lt;a href=&quot;http://www.flickr.com/photos/lsirtosky/6691276793/&quot;&gt;bacon bar&lt;/a&gt;, etc.).&lt;/p&gt;
&lt;p&gt;Continuing with my plan from the first two days I decided to mostly focus on&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Mobile web development/PhoneGap&lt;/li&gt;
&lt;li&gt;Javascript MVC Frameworks/Single page applications&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Thursday 9:45 AM: Performance, Productivity. Pick Two with Dart&lt;/h2&gt;
&lt;p&gt;Seth Ladd gave a talk on Dart. It&#39;s an ambitious project to create a new way of
building web applications. At the heart of it is Dart, a optionally statically
typed language that is reminiscent of Java and that can compile down to
JavaScript.&lt;/p&gt;
&lt;p&gt;My overall impression is that Dart is a lot to chew off.  Seth showed what the
JavaScript code looks like that Dart can compile to. I found it rather bizarre
looking, not at all like the nice output you get with CoffeeScript. One question
I had going in is if you can call third party JavaScript libraries. You &lt;em&gt;can&lt;/em&gt;
but you have to use some sort of bridge to do so (which he didn&#39;t have time to
show). With CoffeeScript, it&#39;s trivial to call third party libraries.&lt;/p&gt;
&lt;p&gt;So it&#39;s interesting and the tooling is pretty cool, it just feels like you&#39;d end
up cutting yourself off from a big chunk of the web community going with Dart.&lt;/p&gt;
&lt;h2&gt;Thursday 11:00 AM: Machine Learning - Understanding the Past&lt;/h2&gt;
&lt;p&gt;This was a fantastic talk by &lt;a href=&quot;https://twitter.com/@sethjuarez&quot;&gt;Seth Juarez&lt;/a&gt; on
using machine learning techniques to help make sense of your data. He went over
&lt;em&gt;unsupervised&lt;/em&gt; learning methods like K-means clustering and principal component
analysis.  He&#39;s put &lt;a href=&quot;http://numl.net/blog/codemash-2.0.1.3&quot;&gt;his slides up here&lt;/a&gt;
in case you&#39;re interested.&lt;/p&gt;
&lt;h2&gt;Thursday 1:45 PM: HTML 5 and the Great Mobile Debate&lt;/h2&gt;
&lt;p&gt;This was a great talk about the current state of developing cross platform
mobile applications and whether it makes sense to develop those apps using HTML
5.  &lt;a href=&quot;http://twitter.com/@aglover&quot;&gt;Andy Glover&lt;/a&gt; gave this talk; he &lt;a href=&quot;http://www.app47.com/2013/01/24/the-codemash-consensus-best-conference-ever/&quot;&gt;wrote up a
blog
post&lt;/a&gt;
covering his main points.&lt;/p&gt;
&lt;p&gt;In summary, Andy suggests not using HTML 5 and if you want to target multiple
mobile platforms with a single codebase, he suggests you look at one of the
cross platform frameworks such as Appcelerator, Xamarin, Corona or Unity.  The
main points of his argument are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mobile browsers are even more fragmented than native APIs. Here he pointed out
  how even the most advanced mobile browsers don&#39;t support all of HTML 5 (he
  used conformance testing tools like &lt;a href=&quot;http://rng.io&quot;&gt;rng.io&lt;/a&gt; and
  &lt;a href=&quot;http://fmbip.com&quot;&gt;fmbip.com&lt;/a&gt;).  I&#39;m not sure I agree on this point; there&#39;s
  an awful lot in HTML 5 and a browser doesn&#39;t need to support all of it to be
  perfectly fine to target with a mobile web app. But he does have a point that
  simply making a mobile web app doesn&#39;t mean you don&#39;t have to deal with
  fragmentation issues.&lt;/li&gt;
&lt;li&gt;HTML rules on the desktop because it&#39;s easier to distribute an app as a web
  application than as a native blob of bits.  The web&#39;s strength on the desktop
  doesn&#39;t matter on mobile because on mobile the software distribution problem
  is a solved problem.&lt;/li&gt;
&lt;li&gt;Consumer apps with a great user experience (examples he used were Flipboard
  and Angry Birds) have set the bar really high for the UI quality of a mobile
  app.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The talk was very thought provoking, although I think HTML 5 and PhoneGap are
perfectly fine for an app in the enterprise or B2B space.  I don&#39;t think I would
use HTML 5 to make a game or a consumer app (well, maybe as a kind of prototype
of a consumer app), but I do think it has a place in the enterprise.&lt;/p&gt;
&lt;h2&gt;Thursday 3:35 PM: Lessons from Two Years of Backbone.js&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/@superchris&quot;&gt;Chris Nelson&lt;/a&gt; presented on lessons learned
using Backbone.js.  This was a packed talk that I was unfortunately late to so I
didn&#39;t take the greatest notes.  I also can&#39;t find his slides online.  Wish I
could find them because he had some interesting material on stuff like how to do
composite views in Backbone.js. Lesson learned: show up early to get a good seat
:)&lt;/p&gt;
&lt;h2&gt;Thursday 4:50 PM: Client/Server Apps with HTML5, Play, CoffeeScript, and More&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jamesward.com/&quot;&gt;James Ward&lt;/a&gt; gave a whirlwind tour of a very modern
web application development stack using Play, CoffeeScript, Bootstrap and more.
He tore through the slides but 1 hour just wasn&#39;t enough time to complete the
whole thing.&lt;/p&gt;
&lt;h2&gt;Friday 10:45 AM: The Native/Mobile Web: Beyond the Basics with PhoneGap&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/@thegrubbsian&quot;&gt;JC Grubbs&lt;/a&gt; gave a talk on some of the real
world concerns with building a PhoneGap app, like how to deal with performance
issues or how to create a build process to target multiple mobile platforms.
&lt;a href=&quot;https://speakerdeck.com/thegrubbsian/beyond-the-basics-with-phonegap&quot;&gt;His slides are
here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Structuring a project&lt;ul&gt;
&lt;li&gt;src - source code&lt;/li&gt;
&lt;li&gt;www - js and css get concatenated to this directory&lt;/li&gt;
&lt;li&gt;ios&lt;ul&gt;
&lt;li&gt;www -&amp;gt; ../www/ - symlink in the www folder to the respective container
  app&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;android&lt;ul&gt;
&lt;li&gt;www symlinked likewise&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Typical stack&lt;ul&gt;
&lt;li&gt;Zepto/JQuery&lt;/li&gt;
&lt;li&gt;backbone/underscore&lt;ul&gt;
&lt;li&gt;template rendering performance&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;moment.js / gui tools / data libs / JQuery Mobile&lt;/li&gt;
&lt;li&gt;jasmine / rake-pipeline / sass / ejs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GUI Toolkits&lt;ul&gt;
&lt;li&gt;JQuery Mobile&lt;/li&gt;
&lt;li&gt;iUI&lt;/li&gt;
&lt;li&gt;Sencha Touch&lt;/li&gt;
&lt;li&gt;Ratchet&lt;ul&gt;
&lt;li&gt;this is actually a prototyping toolkit but JC pulled out the UI stuff
  from it to create mobile web UIs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Media queries&lt;/li&gt;
&lt;li&gt;Icon Fonts&lt;ul&gt;
&lt;li&gt;scales automatically&lt;/li&gt;
&lt;li&gt;icomoon - Chrome app for browsing icon fonts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Flex box / fluid layout&lt;/li&gt;
&lt;li&gt;scrolling&lt;ul&gt;
&lt;li&gt;&lt;code&gt;webkit-overflow-scroll: touch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;avoid scrolling libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;iOS Bounce&lt;ul&gt;
&lt;li&gt;you can turn this off with a PhoneGap setting&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Local vs Remote data&lt;ul&gt;
&lt;li&gt;use Backbone sync plugins that handle saving dirty records and flush when
  online&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Debugging&lt;ul&gt;
&lt;li&gt;test in browser - there are PhoneGap shims&lt;/li&gt;
&lt;li&gt;iOS remote debugger&lt;/li&gt;
&lt;li&gt;debug.phonegap.com - weinre&lt;/li&gt;
&lt;li&gt;JSlint&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Testing&lt;ul&gt;
&lt;li&gt;Jasmine / QUnit&lt;/li&gt;
&lt;li&gt;Capybara / Cucumber&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Performance&lt;ul&gt;
&lt;li&gt;Tap vs click&lt;ul&gt;
&lt;li&gt;use touch events&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;JS vs CSS animations&lt;ul&gt;
&lt;li&gt;use CSS animations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;clean the DOM&lt;/li&gt;
&lt;li&gt;Page everything - no infinite scroll&lt;/li&gt;
&lt;li&gt;Web workers (iOS 5.1+)&lt;/li&gt;
&lt;li&gt;Plugins&lt;ul&gt;
&lt;li&gt;can use them to get native performance&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Deployment&lt;ul&gt;
&lt;li&gt;TestFlightApp&lt;/li&gt;
&lt;li&gt;PhoneGap Build&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Backbone/JQuery Mobile&lt;ul&gt;
&lt;li&gt;use JQuery Mobile for styling/UI, but disable ajax based navigation&lt;/li&gt;
&lt;li&gt;backbone router is flaky on iOS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Friday 1:45 PM: Building Rich User Experiences Without JavaScript Spaghetti&lt;/h2&gt;
&lt;p&gt;This was a talk on using some design patterns to make more maintainable
JavaScript code. The speaker &lt;a href=&quot;http://www.jaredthenerd.com/&quot;&gt;Jared Faris&lt;/a&gt; and if
you&#39;re interested, I believe the same talk is available to view online &lt;a href=&quot;http://www.infoq.com/presentations/UX-JavaScript-Spaghetti&quot;&gt;at
InfoQ&lt;/a&gt;. Here are my
notes from the talk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Decouple code that has multiple concerns&lt;/li&gt;
&lt;li&gt;Write small, discrete bits of code&lt;/li&gt;
&lt;li&gt;Think of UI components as separate JS objects&lt;/li&gt;
&lt;li&gt;put DOM stuff in separate layer&lt;/li&gt;
&lt;li&gt;Mediator pattern&lt;/li&gt;
&lt;li&gt;Observer pattern&lt;/li&gt;
&lt;li&gt;Pub/sub - Postal.js (Event routing)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.msdn.com/b/thebeebs/archive/2012/06/26/minifying.aspx&quot;&gt;Chrome has a
  de-minifier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;EJS templates&lt;/li&gt;
&lt;li&gt;JQuery doTimeout plugin - a better setTimeout&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://thomasjbradley.ca/lab/signature-pad/&quot;&gt;Signature Pad&lt;/a&gt; - capture a
  signature in a HTML5 canvas&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dev.jtsage.com/jQM-SimpleDialog/demos2/&quot;&gt;SimpleDialog2&lt;/a&gt; - better modal
  dialog for JQuery Mobile&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Friday 3:35 PM: AngularJS: The HTML of the Future&lt;/h2&gt;
&lt;p&gt;This was a very interesting talk for me because I really hadn&#39;t seen any
AngularJS before. &lt;a href=&quot;https://twitter.com/@johnlindquist&quot;&gt;John Lindquist&lt;/a&gt;
demonstrated how to create your own &lt;em&gt;directives&lt;/em&gt; which basically is a way to
create your own HTML elements.&lt;/p&gt;
&lt;h2&gt;What else?&lt;/h2&gt;
&lt;p&gt;Well there&#39;s the &lt;a href=&quot;http://www.kalahariresorts.com/oh/&quot;&gt;waterpark&lt;/a&gt;, right? You
can&#39;t go to CodeMash and not spend some time in the waterpark. The family and I
had a good time there on Thursday night.&lt;/p&gt;
&lt;p&gt;Also, there&#39;s KidzMash, a parallel conference with cool computer programming
activities for kids. I took my youngest daughter (7 years old) to one session where she
learned how to &quot;program&quot; me by creating a list of simple instructions (step,
left, right) that I would then follow on a grid that had been taped into the
floor.  My oldest daughter (10 years old) has been programming in Scratch,
Python and a little Lua and JavaScript recently, so I took her to a talk on
using a Windows Kinect device to create programs that respond to gestures.  That
was a lot of fun too (now she wants a Kinect!).&lt;/p&gt;
&lt;p&gt;All in all, it was a great conference. I learned a lot, and I expect I&#39;ll be
digging deeper into some of things I was exposed to over the next couple of
months. I hope I get to go back to it next year.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/6297381763271495308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/6297381763271495308' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6297381763271495308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6297381763271495308'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2013/02/codemash-2013-part-ii-sessions.html' title='CodeMash 2013 Part II: Sessions'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-3514903490325716861</id><published>2013-01-27T20:25:00.001-05:00</published><updated>2013-01-27T20:25:47.634-05:00</updated><title type='text'>CodeMash 2013 Part I: Precompilers</title><content type='html'>&lt;!--
vim: ts=4 sw=4 et ai tw=80:
# CodeMash 2013 Part I: Precompilers
--&gt;

&lt;p&gt;This year I went to &lt;a href=&quot;http://codemash.org/&quot;&gt;CodeMash&lt;/a&gt;, a fun, eclectic software
development conference held at the Kalahari Resort in Sandusky, OH. I learned
quite a bit and had a great time. There were so many good sessions that it was
hard to decide which ones to go to. To help me decide I decided to focus in on
two areas I&#39;m currently interested in:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Mobile web development/PhoneGap&lt;/li&gt;
&lt;li&gt;Javascript MVC Frameworks/Single page applications&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first two days of the conference, Tuesday and Wednesday, were devoted to
half and full day workshops/tutorials that CodeMash calls &lt;em&gt;Precompilers&lt;/em&gt;.  &lt;/p&gt;
&lt;h2&gt;Tuesday AM: PhoneGap tutorial&lt;/h2&gt;
&lt;p&gt;My first precompiler on Tuesday was &lt;em&gt;Developing Mobile applications with
PhoneGap&lt;/em&gt; by &lt;a href=&quot;http://www.raymondcamden.com/&quot;&gt;Ray Camden&lt;/a&gt;. You can find the
presentation and the labs &lt;a href=&quot;https://github.com/cfjedimaster/DevelopingMobileAppsWithPhoneGap&quot;&gt;on
GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The highlight of this presentation was the discussion on how to test mobile web
applications and the various tools that are available.&lt;/p&gt;
&lt;p&gt;Probably the coolest one I saw was
&lt;a href=&quot;https://github.com/blackberry/Ripple-UI&quot;&gt;Ripple&lt;/a&gt;. Ripple is a mobile web
application emulator that can run as a Chrome extension. You can simulate
different devices and different frameworks (I believe it can emulate the
PhoneGap API so you can test your code to some extent). You can change network
settings and geolocation data.  You can also fire off mobile specific events
like &lt;code&gt;deviceready&lt;/code&gt;. The &lt;a href=&quot;https://developer.blackberry.com/html5/documentation/getting_started_with_ripple_1866966_11.html&quot;&gt;user
documentation&lt;/a&gt;
is hosted on Blackberry&#39;s website Ripple is currently an Apache Incubator
project.&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxkpK5VUV_U1czGSQ8MQ46JKLIL4BVoSdFskyx0WkU4Be151t8c1z-ezRBChC6nIi6aRAKdqbp6SwfgLi8gs5ayal19bf1r6qXVTEb5ukBIxdBmtUE0-PajHHvbf5ehoUb1WY1Vw/s1600/ripple3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;220&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxkpK5VUV_U1czGSQ8MQ46JKLIL4BVoSdFskyx0WkU4Be151t8c1z-ezRBChC6nIi6aRAKdqbp6SwfgLi8gs5ayal19bf1r6qXVTEb5ukBIxdBmtUE0-PajHHvbf5ehoUb1WY1Vw/s320/ripple3.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;There were some other tools that looked interesting and were demoed but I
haven&#39;t yet played around with them. First, you can &lt;a href=&quot;http://moduscreate.com/enable-remote-web-inspector-in-ios-6/&quot;&gt;connect the desktop Safari
browser to the mobile Safari browser running in the iOS
Simulator&lt;/a&gt;. You
can use all of the normal Safari developer tools but they work with the web page
in mobile Safari.  Very cool. The second tool I&#39;ll mention is &lt;a href=&quot;http://html.adobe.com/edge/inspect/&quot;&gt;Edge
Inspect&lt;/a&gt; which takes that same idea and
extends it so you can remotely inspect mobile web code running on an actual
device. Edge Inspect is a freemium service so you can try before you buy and
perhaps get a lot of use out of it without spending a dime.&lt;/p&gt;
&lt;p&gt;Finally I&#39;ll mention
&lt;a href=&quot;http://people.apache.org/~pmuellr/weinre/docs/latest/&quot;&gt;weinre&lt;/a&gt; which wasn&#39;t
mentioned (and to be honest I&#39;ve not used it but have heard of it) but is in the
same vein and is a free and open source project.&lt;/p&gt;
&lt;h2&gt;Tuesday PM: Choose Your Own Application&lt;/h2&gt;
&lt;p&gt;From the guys at SRT Solutions comes the very fun &lt;a href=&quot;http://chooseyourownapplication.com/&quot;&gt;Choose Your Own
Application&lt;/a&gt;!.  You should &lt;strong&gt;seriously
check this out&lt;/strong&gt;. Remember those &lt;em&gt;Choose Your Own Adventure&lt;/em&gt; books from when you
were a kid? This is the same idea except you choose your software stack. You can
choose to use JavaScript or CoffeeScript, Backbone or Knockout, ASP.NET or Rails
or Node.js, and finally you can choose to deploy to Heroku or Azure.&lt;/p&gt;
&lt;p&gt;I chose to use JavaScript with Backbone with a Node.js backend, deployed to
Heroku. The app they have you create is a StackOverflow like web site where
users can submit questions and vote on them (very simplistic implementation).
One cool part of the design is that it uses &lt;a href=&quot;http://socket.io&quot;&gt;Socket.IO&lt;/a&gt; to
push updates via WebSockets (which ended up falling back to long polling on
Heroku as I recall). You can open up two browser windows, create a question in
one window and see it update in the other window. It&#39;s a good way to see the
power of a Javascript MVC framework like Backbone; the model is updated
in the background and the view immediately reflects it.&lt;/p&gt;
&lt;p&gt;If you want to see what the code looks like, I&#39;ve pushed my code to GitHub:
&lt;a href=&quot;https://github.com/machristie/chooseyourownapplication-bbjsnodeheroku&quot;&gt;https://github.com/machristie/chooseyourownapplication-bbjsnodeheroku&lt;/a&gt;.
I found Heroku ridiculously easy to get set up with and a really simple and
powerful way to deploy out a website.  The combination of GitHub and the free
usage tier of Heroku is especially nice for an exercise like this because you
can easily publish the code &lt;strong&gt;and&lt;/strong&gt; the working implementation for something you
are learning or some new approach you are trying and would like feedback on.&lt;/p&gt;
&lt;p&gt;You can see my running implemenation here
&lt;a href=&quot;http://cyoa-mchristie.herokuapp.com/&quot;&gt;http://cyoa-mchristie.herokuapp.com/&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Wednesday AM: Atomic Scala&lt;/h2&gt;
&lt;p&gt;This session was presented by Dianne Marsh and Bruce Eckel. The idea was to
present concepts in Scala one at a time (or one &quot;atom&quot; at a time). I think
they&#39;re intended audience is first time programmers or at least programmers who
don&#39;t have a Java background. In any case the pacing of the tutorial was way too
slow, especially for a session with an advertised level of intermediate. They
were kind enough to give us a pre-publish version of their book, &lt;a href=&quot;http://www.atomicscala.com&quot;&gt;Atomic
Scala&lt;/a&gt;, and going at my own pace I would probably
find it useful for learning Scala.  We&#39;ll see.&lt;/p&gt;
&lt;h2&gt;Wednesday PM: Real-world JavaScript Testing&lt;/h2&gt;
&lt;p&gt;The Atomic Scala session was actually full day but I skipped out on the second
half and went to &lt;a href=&quot;https://twitter.com/searls&quot;&gt;Justin Searls&#39;&lt;/a&gt; session on real
world JavaScript testing. This was a great session that combined presenting on
lessons learned in the wild with a fun hands on lab. His slides and the code for
the lab are &lt;a href=&quot;https://github.com/searls/codemash-jasmine-precompiler&quot;&gt;up on
GitHub&lt;/a&gt;. 
The talk started with how to use Jasmine, a JavaScript unit testing framework.
They then added to this by featuring various jasmine addons and other techniques
for making writing unit tests easier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/searls/jasmine-fixture&quot;&gt;jasmine-fixture&lt;/a&gt; for easily adding
  elements to the DOM that are expected by the tests&lt;/li&gt;
&lt;li&gt;Using Coffeescript which allows for a cleaner syntax making the tests more
  readable&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/searls/jasmine-given&quot;&gt;jasmine-given&lt;/a&gt; for &quot;Given&quot;, &quot;When&quot;,
  &quot;Then&quot; style testing.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/testdouble/lineman&quot;&gt;lineman&lt;/a&gt; is used to automatically
  compile CoffeeScript with &lt;code&gt;lineman run&lt;/code&gt; and automatically run your tests (or
  &lt;em&gt;specs&lt;/em&gt;) with &lt;code&gt;lineman spec&lt;/code&gt;. The nice thing here is that the testing
  framework was also remote driving a Chrome browser window (or headlessly) to
  re-run the tests and display the test results. This gave immediate feedback:
  write a test, save, test is run and status displayed; update production code,
  save, test is re-run. You can see what working with lineman is like by
  watching this screencast: 
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot;
  src=&quot;http://www.youtube.com/embed/BmZ4XRErYAI&quot; frameborder=&quot;0&quot;
  allowfullscreen&gt;&lt;/iframe&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was an extremely nice and productive setup. We paired up and worked on
creating a test for a fibonacci calculator web application. It was tough since I
didn&#39;t know CoffeeScript or Jasmine, but very rewarding as it helped me see how
I would actually use this to test &lt;em&gt;real&lt;/em&gt; code.  I&#39;ve posted &lt;a href=&quot;https://github.com/machristie/codemash-jasmine-precompiler&quot;&gt;my solution on
GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;TODO: I want to dive more into this setup and see how it is actually working.
There are a lot of moving parts here and I&#39;m not familiar with most of them. But
I&#39;m hoping I can use this setup or one like it for my JavaScript code.&lt;/p&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Well, the first two days were kind of mentally exhausting!  But it was fun to be
thrown into the deep end and have to figure out a bunch of stuff using
frameworks and languages that I&#39;m not familiar with. Definitely worth it to do
the Precompilers if you are going to CodeMash.&lt;/p&gt;
&lt;p&gt;Next week I&#39;ll blog about the other two days of CodeMash.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/3514903490325716861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/3514903490325716861' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3514903490325716861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3514903490325716861'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2013/01/codemash-2013-part-i-precompilers.html' title='CodeMash 2013 Part I: Precompilers'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxkpK5VUV_U1czGSQ8MQ46JKLIL4BVoSdFskyx0WkU4Be151t8c1z-ezRBChC6nIi6aRAKdqbp6SwfgLi8gs5ayal19bf1r6qXVTEb5ukBIxdBmtUE0-PajHHvbf5ehoUb1WY1Vw/s72-c/ripple3.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4287013497720648186</id><published>2012-11-11T18:32:00.000-05:00</published><updated>2012-11-11T18:32:56.390-05:00</updated><title type='text'>Pyramid, MySQL, and Python 3</title><content type='html'>
&lt;h1&gt;For the impatient&lt;/h1&gt;

&lt;p&gt;
Assuming you have Python 3 installed with distribute and virtualenv and also MySQL, create a virtualenv 
&lt;/p&gt;

&lt;pre&gt;
virtualenv --no-site-packages --distribute myenv
&lt;/pre&gt;

&lt;p&gt;
Then activate your environment
&lt;/p&gt;

&lt;pre&gt;
source myenv/bin/activate
&lt;/pre&gt;

&lt;p&gt;
Create the following requirements file (save to requirements.txt):
&lt;/p&gt;

&lt;pre&gt;
#oursql==0.9.3 but need special Python 3 build https://bugs.launchpad.net/oursql/+bug/1051512
https://launchpad.net/oursql/py3k/py3k-0.9.3/+download/oursql-0.9.3.zip
pyramid==1.3.4
&lt;/pre&gt;

&lt;p&gt;
Then run:
&lt;/p&gt;

&lt;pre&gt;
pip install -r requirements.txt
&lt;/pre&gt;


&lt;h1&gt;The longer version&lt;/h1&gt;

&lt;p&gt;
I&#39;m currently working on an Android app version of &lt;a href=&quot;http://fuelmyroute.com&quot;&gt;FuelMyRoute.com&lt;/a&gt;.  The website currently uses TurboGears (version 1.0.something I&#39;m afraid). I thought about using the website as the backend for the mobile app but wanted the freedom to experiment and potentially do things much differently in a separate mobile backend.  I also wanted to work on a more modern stack. The TurboGears team has essentially joined forces with the Pyramid team, so I took a look at Pyramid. I liked what I saw, and with version 1.3 it can run on Python 3.
&lt;/p&gt;

&lt;p&gt;
So let&#39;s see if we can get a Pyramid/SQLAlchemy/MySQL site working on Python 3.  The first thing I ran into is that it was hard to find a good Python MySQL driver that works on Python 3. For years I&#39;ve been using the trusty if somewhat antiquated MySQLdb Python module.  It looks like development has slowed to a halt on MySQLdb so I took a look at alternatives.
&lt;/p&gt;

&lt;p&gt;
First alternative I explored was &lt;a href=&quot;https://launchpad.net/myconnpy&quot;&gt;MySQL Connector/Python&lt;/a&gt;. I like that Oracle is sponsoring the development and it is a pure Python library. However, I hit upon a major bug that made it a deal breaker. I&#39;ve subsequently learned that this bug has been fixed so I&#39;ll probably give it another try in the future.
&lt;/p&gt;

&lt;p&gt;
Second alternative I looked at was OurSQL. I&#39;m not sure if it is a fork of MySQLdb, but it seems fairly similar. It does have &lt;a href=&quot;http://packages.python.org/oursql/&quot;&gt;some benefits&lt;/a&gt; over MySQLdb , not the least of which is Python 3 support.  One catch is that you can&#39;t just &quot;pip install oursql&quot; under Python 3. There is a distinct branch of code for the Python 3 support. To install the Python 3 branch of OurSQL you can use the requirements.txt file above, or for just OurSQL you can do
&lt;/p&gt;

&lt;pre&gt;
pip install https://launchpad.net/oursql/py3k/py3k-0.9.3/+download/oursql-0.9.3.zip
&lt;/pre&gt;

&lt;p&gt;
I also ran into an issue with Python 3 and one of Pyramid&#39;s dependencies, zope.interface.  That&#39;s why zope.interface is listed in the requirements.txt file with version 3.8.0. But this is fixed now &lt;a href=&quot;https://github.com/Pylons/pyramid/issues/604&quot;&gt;https://github.com/Pylons/pyramid/issues/604&lt;/a&gt;. Just make sure you get the latest 1.3 bugfix release. At the time of this writing, that is 1.3.4.
&lt;/p&gt;

&lt;p&gt;
To get started with SQLAlchemy, just run the following to create a Pyramid scaffold project using SQLAlchemy:
&lt;pre&gt;
pcreate -s alchemy MyProject
&lt;/pre&gt;
More info here: &lt;a href=&quot;http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/project.html&quot;&gt;http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/project.html&lt;/a&gt;
&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4287013497720648186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/4287013497720648186' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4287013497720648186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4287013497720648186'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2012/11/pyramid-mysql-and-python-3.html' title='Pyramid, MySQL, and Python 3'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-2429213810499808379</id><published>2011-07-09T13:20:00.006-04:00</published><updated>2011-07-09T17:39:42.324-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="technology"/><category scheme="http://www.blogger.com/atom/ns#" term="twitter"/><title type='text'>How to dynamically change the Tweet Button&#39;s tweet text</title><content type='html'>Looked around on the internet for a way to dynamically change the tweet text of the &lt;a href=&quot;http://dev.twitter.com/pages/tweet_button&quot;&gt;Tweet Button&lt;/a&gt;, but didn&#39;t find a good solution. Most of what I found involved setting the text when the page is being rendered server side or client side. But what I need for &lt;a href=&quot;http://fuelmyroute.com/&quot;&gt;FuelMyRoute.com&lt;/a&gt; is a way to dynamically update the tweet text based on the user&#39;s activity in the page after it has rendered. (Specifically, based on the route provided by the user, I want to update the tweet text to say something specific about how much the user has saved per gallon of gas.)&lt;br /&gt;&lt;br /&gt;The solution I went with uses the iframe Tweet Button, and basically you just need a bit of javascript to manipulate the URL that configures the iframe Tweet Button. I went with the iframe Tweet Button over the javascript Tweet Button because the javascript one manipulates the DOM and replaces your anchor tag with an iframe, etc. You could theoretically dynamically change the tweet text for the javascript Tweet Button but it would be a little brittle, being dependent on how the javascript Tweet Button renders itself.&lt;br /&gt;&lt;br /&gt;Enough jibber jabber, on to the code! You start by adding an iframe Tweet Button to the page:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;https://gist.github.com/1073967.js?file=gistfile1.xml&quot;&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Then you need this function which updates the text parameter of the iframe Tweet Button&#39;s query string (which of course will cause the button to reload):&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;https://gist.github.com/1073778.js?file=gistfile1.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;You can try it out right here. Click on the Tweet Button below and preview the message, which should be &quot;Replace Me&quot;:&lt;br /&gt;&lt;br /&gt;&lt;iframe id=&quot;tweet-button&quot; allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://platform.twitter.com/widgets/tweet_button.html?via=marcus_christie&amp;amp;text=Replace%20Me&amp;amp;count=horizontal&quot; style=&quot;width:110px; height:20px;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Now click on the button below which will call &lt;code&gt;updateTweetButtonText(&#39;I just dynamically updated the text of a Tweet Button!&#39;);&lt;/code&gt; and then click on the Tweet Button again to see that the preview tweet has been updated:&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;text/javascript&quot; src=&quot;https://raw.github.com/gist/1073778/f0c1148a17240a063dbbfc8983411a70e6cc99b7/gistfile1.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;input type=&quot;button&quot; value=&quot;Update text&quot; onclick=&quot;updateTweetButtonText(&#39;I just dynamically updated the text of a Tweet Button!&#39;);&quot; /&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/2429213810499808379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/31592724/2429213810499808379' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2429213810499808379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2429213810499808379'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2011/07/how-to-dynamically-change-tweet-buttons.html' title='How to dynamically change the Tweet Button&#39;s tweet text'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>