<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Words, punctuated &#187; Articles by Paul</title>
	<atom:link href="http://probertson.com/articles/category/articles-by-paul/feed/" rel="self" type="application/rss+xml" />
	<link>http://probertson.com</link>
	<description>Thoughts on web development, user-centered design, code, etc. by Paul Robertson</description>
	<lastBuildDate>Tue, 20 Jul 2010 21:29:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Simple ActionScript 3 animation examples</title>
		<link>http://probertson.com/articles/2010/07/20/simple-actionscript-3-animation-examples/</link>
		<comments>http://probertson.com/articles/2010/07/20/simple-actionscript-3-animation-examples/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 16:20:34 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AS3]]></category>
		<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=449</guid>
		<description><![CDATA[Last week I spent a little time teaching some of the newer developers in our office about scripted animation in ActionScript 3. I put together a few simple demos for them, and I thought I might as well share them with the world.
Note that these are basic demos so if you know pretty much anything [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I spent a little time teaching some of the newer developers in our office about scripted animation in ActionScript 3. I put together a few simple demos for them, and I thought I might as well share them with the world.</p>
<p>Note that these are basic demos so if you know pretty much anything about animation in ActionScript, these may not teach you anything.</p>
<p>All these scripts do pretty much the same thing. They draw a square on the stage. When you click on it, it moves horizontally from x=100 to x=400. Each of these is a class that you can run as the main class of an AS3 application.</p>
<h2>1. The wrong way</h2>
<p>The wrong way, of course, is to use a for loop:</p>
<pre class="brush:actionscript3">package
{
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.display.Sprite;
    public class BasicAnimation extends Sprite
    {
        // ------- Constructor -------

        public function BasicAnimation()
        {
            _createChildren();
        }

        // ------- Child display objects -------

        private var _rect:Sprite;

        // ------- Private constants -------

        private const START:int = 100;
        private const END:int = 400;

        // ------- Private methods -------

        private function _createChildren():void
        {
            _rect = new Sprite();
            _rect.graphics.beginFill(0xff0000, 1);
            _rect.graphics.drawRect(0, 0, 100, 100);
            _rect.graphics.endFill();
            _rect.x = START;
            addChild(_rect);
            _rect.addEventListener(MouseEvent.CLICK, _rect_click);
        }

        // ------- Event handling -------

        private function _rect_click(event:MouseEvent):void
        {
            // wrong way:
            _rect.x = START;
            while (_rect.x < END)
            {
                _rect.x++;
            }
        }
    }
}</pre>
<h2>The right way (most basic)</h2>
<p>Of course, this one runs very slow since it&#8217;s moving at a rate of 1 pixel per frame.</p>
<pre class="brush:actionscript3">package
{
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.display.Sprite;
    public class BasicAnimation extends Sprite
    {
        // ------- Constructor -------

        public function BasicAnimation()
        {
            _createChildren();
        }

        // ------- Child display objects -------

        private var _rect:Sprite;

        // ------- Private constants -------

        private const START:int = 100;
        private const END:int = 400;

        // ------- Private methods -------

        private function _createChildren():void
        {
            _rect = new Sprite();
            _rect.graphics.beginFill(0xff0000, 1);
            _rect.graphics.drawRect(0, 0, 100, 100);
            _rect.graphics.endFill();
            _rect.x = START;
            addChild(_rect);
            _rect.addEventListener(MouseEvent.CLICK, _rect_click);
        }

        // ------- Event handling -------

        private function _rect_click(event:MouseEvent):void
        {
            // right way (very basic):
            addEventListener(Event.ENTER_FRAME, _enterFrameBasic);
        }

        private function _enterFrameBasic(event:Event):void
        {
            if (_rect.x < END)
            {
                _rect.x++;
            }
            else
            {
                removeEventListener(Event.ENTER_FRAME, _enterFrameBasic);
            }
        }
    }
}</pre>
<h2>Adding velocity as a variable</h2>
<p>The solution to the slowness is to add a velocity variable. The value (in units of pixels per frame) will determine how quickly the animation moves. Basically you just try different values until you&#8217;re happy with something. Like the previous example, this is a purely linear animation &#8212; the velocity stays constant.</p>
<pre class="brush:actionscript3">package
{
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.display.Sprite;
    public class BasicAnimation extends Sprite
    {
        // ------- Constructor -------

        public function BasicAnimation()
        {
            _createChildren();
        }

        // ------- Child display objects -------

        private var _rect:Sprite;

        // ------- Private constants -------

        private const START:int = 100;
        private const END:int = 400;

        // ------- Private methods -------

        private function _createChildren():void
        {
            _rect = new Sprite();
            _rect.graphics.beginFill(0xff0000, 1);
            _rect.graphics.drawRect(0, 0, 100, 100);
            _rect.graphics.endFill();
            _rect.x = START;
            addChild(_rect);
            _rect.addEventListener(MouseEvent.CLICK, _rect_click);
        }

        // ------- Event handling -------

        private function _rect_click(event:MouseEvent):void
        {
            // right way (very basic):
            addEventListener(Event.ENTER_FRAME, _enterFrameBasic);
        }

        private function _enterFrameBasic(event:Event):void
        {
            if (_rect.x < END)
            {
                var velocity:int = 5;
                _rect.x += velocity;
            }
            else
            {
                removeEventListener(Event.ENTER_FRAME, _enterFrameBasic);
            }
        }
    }
}</pre>
<h2>Adding acceleration</h2>
<p>Once you&#8217;ve separated out velocity, it becomes easy to make the animation non-linear by adding an acceleration value that causes the velocity to change over time. We&#8217;re just stepping back one level of complexity &#8212; the acceleration is now linear instead of the velocity.</p>
<pre class="brush:actionscript3">package
{
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.display.Sprite;
    public class BasicAnimation extends Sprite
    {
        // ------- Constructor -------

        public function BasicAnimation()
        {
            _createChildren();
        }

        // ------- Child display objects -------

        private var _rect:Sprite;

        // ------- Private constants -------

        private const START:int = 100;
        private const END:int = 400;

        // ------- Private methods -------

        private function _createChildren():void
        {
            _rect = new Sprite();
            _rect.graphics.beginFill(0xff0000, 1);
            _rect.graphics.drawRect(0, 0, 100, 100);
            _rect.graphics.endFill();
            _rect.x = START;
            addChild(_rect);
            _rect.addEventListener(MouseEvent.CLICK, _rect_click);
        }

        // ------- Event handling -------

        private function _rect_click(event:MouseEvent):void
        {
            // right way (very basic):
            addEventListener(Event.ENTER_FRAME, _enterFrameBasic);
        }

        private var _velocity:int = 0;

        private function _enterFrameBasic(event:Event):void
        {
            if (_rect.x < END)
            {
                var accel:int = 3;
                _velocity += accel;
                _rect.x += _velocity;
            }
            else
            {
                removeEventListener(Event.ENTER_FRAME, _enterFrameBasic);
            }
        }
    }
}
</pre>
<h2>Interpolating values over time</h2>
<p>This next example doesn&#8217;t build on the previous ones but instead takes a completely separate approach to creating animation. This animation is time-driven rather than frame-driven. Instead of adding a particular number of pixels to the x value each frame, it calculates how much time has elapsed since the start and what the x value should be at that moment in time, then sets the x property to that value. A consequence of this approach is that regardless of the frame rate of the SWF, the animation will always last the same amount of time.</p>
<pre class="brush:actionscript3">package
{
    import flash.utils.getTimer;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.display.Sprite;
    public class AnimationIntermediate extends Sprite
    {
        // ------- Constructor -------

        public function AnimationIntermediate()
        {
            _createChildren();
        }

        // ------- Child display objects -------

        private var _rect:Sprite;

        // ------- Private constants -------

        private const START:int = 100;
        private const END:int = 400;
        private const TOTAL_TIME:int = 5000;

        // ------- Private methods -------

        private function _createChildren():void
        {
            _rect = new Sprite();
            _rect.graphics.beginFill(0xff0000, 1);
            _rect.graphics.drawRect(0, 0, 100, 100);
            _rect.graphics.endFill();
            _rect.x = START;
            addChild(_rect);
            _rect.addEventListener(MouseEvent.CLICK, _rect_click);
        }

        // ------- Event handling -------

        private var _startTime:int = 0;

        private function _rect_click(event:MouseEvent):void
        {
            // right way (intermediate):
            _startTime = getTimer();
            addEventListener(Event.ENTER_FRAME, _enterFrameIntermediate);
        }

        private function _enterFrameIntermediate(event:Event):void
        {
            var elapsedTime:int = getTimer() - _startTime;
            var fractionComplete:Number = elapsedTime / TOTAL_TIME;

            if (fractionComplete < 1)
            {
                var totalDistance:int = END - START;
                var offset:int = Math.round(fractionComplete * totalDistance);
                _rect.x = START + offset;
            }
            else
            {
                _rect.x = END;
                removeEventListener(Event.ENTER_FRAME, _enterFrameIntermediate);
            }
        }
    }
}</pre>
<p>The main point of this example is to demonstrate the idea that you can plug in an algorithm that calculates position given time, and by varying the algorithm you can vary the animation. This is a direct lead-in to the idea of using tweening functions to vary an animation, as demonstrated in the next example.</p>
<h2>Using an animation library</h2>
<p>This example shows the use of a third-party animation library (in this case Grant Skinner&#8217;s <a href="http://www.gskinner.com/libraries/gtween/">GTween</a> library). The commented-out lines demonstrate how a library makes it easy to synchronize animation and vary the animation. Note that this is only meant as a very basic demonstration of the concept of using a library for animation &#8212; GTween and the many other animation libraries that are out there all provide many additional features.</p>
<pre class="brush:actionscript3">package
{
    import com.gskinner.motion.easing.Bounce;
    import com.gskinner.motion.easing.Sine;
    import com.gskinner.motion.GTween;
    import flash.events.MouseEvent;
    import flash.display.Sprite;
    public class AnimationTween extends Sprite
    {
        // ------- Constructor -------

        public function AnimationTween()
        {
            _createChildren();
        }

        // ------- Child display objects -------

        private var _rect:Sprite;

        // ------- Private constants -------

        private const START:int = 100;
        private const END:int = 400;
        private const TOTAL_TIME:int = 5;

        // ------- Private methods -------

        private function _createChildren():void
        {
            _rect = new Sprite();
            _rect.graphics.beginFill(0xff0000, 1);
            _rect.graphics.drawRect(0, 0, 100, 100);
            _rect.graphics.endFill();
            _rect.x = START;
            addChild(_rect);
            _rect.addEventListener(MouseEvent.CLICK, _rect_click);
        }

        // ------- Event handling -------

        private function _rect_click(event:MouseEvent):void
        {
            var tween:GTween = new GTween(_rect, TOTAL_TIME);
            tween.setValue("x", END);
//            tween.setValue("alpha", .5);
//            tween.ease = Sine.easeInOut;
//            tween.ease = Bounce.easeOut;
        }
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2010/07/20/simple-actionscript-3-animation-examples/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Changes</title>
		<link>http://probertson.com/articles/2010/05/13/changes/</link>
		<comments>http://probertson.com/articles/2010/05/13/changes/#comments</comments>
		<pubDate>Thu, 13 May 2010 08:48:32 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Life at Adobe]]></category>
		<category><![CDATA[Opinions]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=445</guid>
		<description><![CDATA[Unfortunately I can&#8217;t give this topic the time it deserves right now, but for those of you who are interested I wanted to let you know of some &#8220;significant life changes&#8221; that are happening to me.
Summary
New job. New city. New house. Moving tomorrow. Offline for a week or two. Don&#8217;t say anything important while I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>Unfortunately I can&#8217;t give this topic the time it deserves right now, but for those of you who are interested I wanted to let you know of some &#8220;significant life changes&#8221; that are happening to me.</p>
<h2>Summary</h2>
<p>New job. New city. New house. Moving tomorrow. Offline for a week or two. Don&#8217;t say anything important while I&#8217;m gone. (Sorry <a href="http://flashandthecity.com/">FATC</a>, especially <a href="http://reflex.io/">Reflex</a>: no breaking announcements or innovation allowed. =)</p>
<h2>1. Job</h2>
<p>I am now no longer working for Adobe. I have started a new job with <a href="http://dedoinc.com/">Dedo Interactive, Inc.</a>, as a Flash/Flex/ActionScript/AIR developer and also as an active collaborator with the UX design group. As <a href="http://www.danieldura.com/archive/my-last-week-at-adobe">Danny</a> and <a href="http://unitedmindset.com/jonbcampos/2010/04/30/new-position-in-dedo-inc/">Jonathan</a> have already described, this is an exciting opportunity with a group that&#8217;s pushing the boundaries of hardware and software solutions. It&#8217;s also exciting for me to be a &#8220;regular developer&#8221; like everyone I hang out with and pretend to fit in with at conferences. Of course that&#8217;s where my roots are &#8212; in being a Macromedia/Adobe customer first before being an Adobe employee &#8212; so I&#8217;m just going back to the place that I&#8217;ve tried my best not to leave anyway.</p>
<h2>2. Location</h2>
<p>Since Dedo is located in Plano (N. Dallas) Texas, naturally it seems that I need to be located there too. Danny has been really great about letting me start as a remote employee. Nevertheless, I am typing this while mostly surrounded by cardboard boxes, as well as a few too many things that I should have already packed into cardboard boxes. In approximately 32 hours a moving truck will pull up to my house and load everything up. Then I&#8217;ll pack my family into a minivan and drive for many hours and days until we get to our new house. (Just signed the mortgage papers today &#8212; ack!)</p>
<h2>3. Family</h2>
<p>Fortunately, my family has agreed to accompany me on this crazy journey. I feel sad for my three young children. They&#8217;re obviously not happy to leave their friends and school and the life that they&#8217;ve known for the last three years. (My youngest doesn&#8217;t remember anything before California, and my middle child barely remembers anything else, in spite of the fact that they were both born in Indiana.) I&#8217;m grateful to have a wonderful wife and special children who make the hard times worth it, and who make the good times good.</p>
<h2>4. Blog, Twitter, open source projects, conferences, etc.</h2>
<p>Frankly, I have no plans to change what I&#8217;ve been doing with any of those. I&#8217;ve never been the most regular blogger or twitterer, and my projects don&#8217;t get updated as often as I&#8217;d like. That probably isn&#8217;t going to change with a new job and a new city. But the vast majority of my work on them has been on my own time anyway, so the fact that I&#8217;m no longer an Adobe employee shouldn&#8217;t make that situation any worse. In fact, the owners of Dedo said that they&#8217;re pleased with my community involvement, and want it to continue. I&#8217;m definitely still using AIR, ActionScript, and SQLite in my work, so I keep finding new things and ways to improve my projects.</p>
<h2>5. Blah blah sentimental stuff</h2>
<p>Adobe is a great employer, and a great company. In spite of all the negativity and mud-slinging that&#8217;s happening right now, I can say that I never felt bad or guilty about working for Adobe. On the contrary, I am proud to have worked for Adobe. I feel like Adobe is a good, ethical company that tries to make business decisions that lead to mutual benefit for partners and customers. (Don&#8217;t bother sharing your experiences to the contrary. I&#8217;m sure I could tell you plenty too. In spite of that, this is my opinion of the company and employees overall.)</p>
<p>In addition to my great employer, living and working and associating with the community in the San Francisco bay area has been a tremendous experience, and I consider myself very fortunate for it. I&#8217;m definitely sorry to leave, especially because of the great opportunities (being near Adobe HQ), the great community (I&#8217;m looking at you <a href="http://www.meetup.com/silvafug/">SilvaFUG</a>), and the great weather =)</p>
<p>To all of you who I&#8217;ve met and become friends with over the last 3 years, farewell, and I look forward to seeing you online and at conferences of the future. I only regret that I didn&#8217;t get to come to one last meeting and tell you goodbye in person.</p>
<p>Meanwhile, I&#8217;ve been amazed to learn how many talented and community-oriented developers call the Dallas-Fort Worth area home. I&#8217;ve already attended one users&#8217; group meeting and plan to attend many more. I look forward to getting to know you better.</p>
<p>As I&#8217;ve been preparing to move, I&#8217;ve been trying to go through my many boxes that I haven&#8217;t touched since the last time I moved across the country. I was a little astounded to find so many of my college (and even a few high school) notes, papers, textbooks, etc. among my possessions. I&#8217;m getting older and more cynical now, plus we have to pay the movers by the pound, so I tried to get rid of as much as I could bear. I was amazed at how much I&#8217;ve forgotten from what I once knew. (Some of my academic papers were quite impressive to me &#8212; and it was astounding to find my 2nd year Hebrew notebook and later my calculus notes, and consider the fact that I wrote all the scribblings in there. =) I also couldn&#8217;t help but think over the many people I&#8217;ve met and known and worked with in Houston (where I grew up), Salt Lake City (where I did my undergraduate), Bloomington Indiana (grad school and my first &#8220;real&#8221; job), and of course most recently the bay area. It&#8217;s quite astounding to consider the path that life has led me on, and how I&#8217;ve ended up where I am today.</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2010/05/13/changes/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Data &#8220;paging&#8221; in AIR SQLite</title>
		<link>http://probertson.com/articles/2010/04/07/data-paging-in-air-sqlite/</link>
		<comments>http://probertson.com/articles/2010/04/07/data-paging-in-air-sqlite/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 19:25:10 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[local SQL database]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=435</guid>
		<description><![CDATA[I got an interesting question a few days ago that I thought I&#8217;d share:
My application has thousands of records in one particular table that I need to populate the display with. I was wondering if I can implement paging to speed up the retrieval of those records?
In fact he specifically wanted to know if it [...]]]></description>
			<content:encoded><![CDATA[<p>I got an interesting question a few days ago that I thought I&#8217;d share:</p>
<blockquote><p>My application has thousands of records in one particular table that I need to populate the display with. I was wondering if I can implement paging to speed up the retrieval of those records?</p></blockquote>
<p class="editornote">In fact he specifically wanted to know if it was possible to do data paging with the SQLRunner class in my <a href="/projects/air-sqlite/">air-sqlite library</a>. The answer is yes it works, without even needing any changes to the library. See below for how to do that.</p>
<p>The easiest way to implement data paging (in other words, getting only a subset of a query&#8217;s results at a time) in a <code>SELECT</code> statement is to use the <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/localDatabaseSQLSupport.html#select"><code>LIMIT..OFFSET</code> clause</a> in the <code>SELECT</code> statement.</p>
<p>In summary, you can put a <code>LIMIT</code> clause at the end of a <code>SELECT</code> statement and the result set will only include the specified number of rows:</p>
<pre class="brush:sql">SELECT * FROM myTable
LIMIT 3</pre>
<p>Then to get the next 3 rows, you add an <code>OFFSET</code> value:</p>
<pre class="brush:sql">SELECT * FROM myTable
LIMIT 3 OFFSET 3</pre>
<p>Fortunately, you can use statement parameters for the LIMIT and OFFSET values (although the docs don&#8217;t mention this &#8212; shame on me!):</p>
<pre class="brush:sql">SELECT * FROM myTable
LIMIT :limit OFFSET :offset</pre>
<p>Then you just specify values for those parameters and you&#8217;re good to go.</p>
<p>I tested this using the SQLRunner class by adding a <a href="http://github.com/probertson/air-sqlite/blob/master/tests/tests/com/probertson/data/SQLRunnerExecute.as">new set of unit tests</a> and it worked just fine without any changes to the library. (Hooray for unit tests and FlexUnit support in Flash Builder 4 &#8212; they made it nice and easy to test this out since I already had the infrastructure in place.)</p>
<p>Here is <a href="http://github.com/probertson/air-sqlite/blob/master/tests/sql/LoadRowsParameterizedLimitOffset.sql">the SQL statement I used for the unit test</a> using <code>LIMIT..OFFSET</code> with parameters:</p>
<pre class="brush:sql">SELECT colString,
colInt
FROM main.testTable
LIMIT :limit OFFSET :offset</pre>
<p>And here is <a href="http://github.com/probertson/air-sqlite/blob/master/tests/tests/com/probertson/data/SQLRunnerExecute.as#L125">the line of code that calls the statement</a> (modified slightly for readability). <code>test_result</code> is the result handler function. The parameters object specifies that I want 7 result rows, starting with row number 3 (i.e. skipping 2):</p>
<pre class="brush:actionscript3">_sqlRunner.execute(SQL, {limit:7, offset:2}, test_result);</pre>
<p class="editornote">As <a href="#comment-74422">Peter points out in the comments</a>, another approach to do something similar to data paging with AIR is to specify a number of rows to retrieve as the first argument to the <code>SQLStatement.execute()</code> method, then call the <code>SQLStatement.next()</code> method to retrieve additional rows from the same statement. This technique is <a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7d4c.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7d46">described in the documentation</a> so I won&#8217;t go into more detail about it here except to say that it does have a couple of drawbacks (mentioned in my comment below) that make it less suitable for data paging (but still very useful).</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2010/04/07/data-paging-in-air-sqlite/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>I am 360&#124;Flex (and so can you!)</title>
		<link>http://probertson.com/articles/2010/02/18/i-am-360flex-and-so-can-you/</link>
		<comments>http://probertson.com/articles/2010/02/18/i-am-360flex-and-so-can-you/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 19:41:32 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Opinions]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=399</guid>
		<description><![CDATA[The next <a href="http://360flex.com/">360&#124;Flex conference</a> is coming up quickly -- <a href="http://360flex.eventbrite.com/">March 7-10, 2010 in San Jose, California</a>. As I've been preparing for the conference and reading some of the things other people are saying about it, I've been reminiscing about past 360&#124;Flex (and other) conferences I've been to, and about how much they've impacted me professionally and personally. (Hint: a lot.)]]></description>
			<content:encoded><![CDATA[<p>(With apologies to <a href="http://www.amazon.com/Am-America-So-Can-You/dp/B0029LHWSQ/">Stephen Colbert</a> =)</p>
<p>The next <a href="http://360flex.com/">360|Flex conference</a> is coming up quickly &#8212; <a href="http://360flex.eventbrite.com/">March 7-10, 2010 in San Jose, California</a>. As I&#8217;ve been preparing for the conference and reading some of the things other people are saying about it, I&#8217;ve been reminiscing about past 360|Flex (and other) conferences I&#8217;ve been to, and about how much they&#8217;ve impacted me professionally and personally. (Hint: a lot.)</p>
<p>But I&#8217;m not here to talk about the past. (Or about <a href="/articles/2010/02/09/thoughts-on-multi-screen-context-app-development/">what I&#8217;m presenting at the conference,</a> since I&#8217;ve already mentioned that.) Instead, I&#8217;d like to talk to you about this 360|Flex, and why I&#8217;m excited to attend and what I&#8217;m looking forward to most. These fall into two categories: <a href="#sessions">Sessions I&#8217;m looking forward to</a>, and <a href="#people">people I&#8217;m excited to meet (or see again)</a>.</p>
<h2 id="sessions">The sessions (in schedule order)</h2>
<p>I combed over the whole schedule, and there is literally not a single time slot that I&#8217;m not looking forward to. Except the ones where I have to choose from two or three awesome-sounding presentations. Frankly, what I&#8217;m <em>not</em> looking forward to about 360|Flex is that I&#8217;ll have to choose not to attend some sessions that I&#8217;m really anxious to see.</p>
<h3>Sunday</h3>
<p><strong>Sunday afternoon</strong>: Joel Hooks: Hands-on development with the Robotlegs AS3 framework (I&#8217;ve mentioned I&#8217;ll be helping with this, but I&#8217;d definitely attend if I wasn&#8217;t)</p>
<h3>Monday</h3>
<p><strong>Keynote</strong>: Is this Deepa&#8217;s first keynote, now that she&#8217;s a Flex Product Manager and not an engineer anymore? She spoke to my users&#8217; group last week talking about Flex &#8220;next&#8221; (i.e. after 4). I have no idea what she&#8217;ll talk about here, but I&#8217;m looking forward to it!</p>
<p><strong>Monday 1</strong>: Already there are too many to choose&#8230;Michael Labriola (Flex components), Chase Brammer (analytics) or Richard Lord (&#8220;Designer Last&#8221; architecture)?</p>
<p><strong>Monday 2</strong>: Drew McClean and RJ Owen - Rules engine with AS3 and Hamcrest (time to find out what the buzz is about), although if I was doing more video work I&#8217;d definitely hit expert David Hassoun&#8217;s session (OSMF), or maybe I should broaden my horizons/prepare for the future with Bryce Barrand (How to find and keep top developers)</p>
<p><strong>Monday 3</strong>: Again, I can&#8217;t decide&#8230;Garth Braithwaite on skinning, or Jesse Warden on Robotlegs and Gaia?</p>
<h3>Tuesday</h3>
<p><strong>Morning panel discussion</strong> (&#8220;Principles for RIA design&#8221;): Don&#8217;t discount this because it&#8217;s early. Keith is a great facilitator (he&#8217;s a co-manager of my local users&#8217; group) and from the things I&#8217;ve heard, there will be lots of great ideas shared in this session.</p>
<p><strong>Tuesday 1</strong>: Alas, I&#8217;m speaking in this slot so I&#8217;ll miss Deepa&#8217;s Flex 4 talk <em>and</em> Aaron Pedersen and James Polanco&#8217;s Flex 4 lifecycle talk. Will anyone notice if I just skip out and go to their sessions instead?</p>
<p><strong>Tuesday 2</strong>: Jacob and Tyler Wright (and Ben Stucki, I think!): &#8220;Reflex: Rethinking Component Design.&#8221; I got to hear about the ideas behind this component/layout framework in conversations at the last 360|Flex conference, and I&#8217;ve been dying to try it out since then. Revolutionary stuff will appear here!</p>
<p><strong>Tuesday 3</strong>: Yet another tough choice: Elad Elrom on TDD, Randy Troppman and Adrew Westberg on GPS in Flex, or Aaron Hardy on Queue and Cache?</p>
<h3>Wednesday</h3>
<p><strong>Keynote</strong>: always fun and informative &#8212; hear the behind-the-scenes of the conference, and win prizes too!</p>
<p><strong>Wednesday 1</strong>: Why do they have to make it so hard to choose! Renaun Erickson (&#8220;AS tips for iPhone games&#8221;), Jeff Tapper (don&#8217;t even know but always extremely valuable), or Sim Bateman (&#8220;Getting Git&#8221;)?</p>
<p><strong>Wednesday 2</strong>: I think I may go to the dark side for a bit, and learn more about Silverlight from Jun Heider. But Nate Beck&#8217;s &#8220;Flexible games&#8221; looks mighty tempting too&#8230;</p>
<p><strong>Wednesday 3</strong>: Eric Fickes with Silverlight, part 2, Shashank Tiwari on multi-touch, or Andy Powell on UX? John and Tom, you&#8217;re making this so hard!</p>
<p><strong>Wednesday 4</strong>: (at least) two presentations worth sticking around for: Matt Guest on Flex text with TLF, and Huyen Tue Dao on Greenthreading</p>
<p>So yes, I&#8217;ve realized I&#8217;m going to have to make two clones of myself (at least) in order to attend all the sessions I want to see. And then I&#8217;ll have to merge them back together somehow. I&#8217;ll get back to you on how that one turns out&#8230;</p>
<h2 id="people">The people</h2>
<p><a href="http://www.richardlord.net/blog/360flex-san-jose">Richard Lord really nailed it</a> when he said that the best part of conferences, especially smaller ones like 360|Flex, is getting to meet and talk with and throw ideas around with other developers. I&#8217;ve learned some good things in the sessions at past conferences, but by far my best memories and most valued times are the ones I spent between sessions and evenings/nights kicking around ideas with others.</p>
<p>These are my &#8220;conference friends&#8221; (and a few &#8220;users&#8217; group friends) who I&#8217;ve met at conferences and always look forward to hanging out with again. I&#8217;m sure you know their names, and like me you may wonder why they&#8217;re actually willing to talk and hang out with someone like me =) But I&#8217;ve never gotten any attitude from these (or other) &#8220;superstars&#8221; that I&#8217;ve met in person at conferences. That&#8217;s reason 1 I love the Flash/Flex community &#8212; these people welcome ideas, and are just excited to meet people and share:</p>
<ul>
<li><a href="http://renaun.com/blog">Renaun Erickson</a></li>
<li><a href="http://david.realeyes.com/">David Hassoun</a></li>
<li><a href="http://www.iheartair.com/">Jun Heider</a></li>
<li><a href="http://dougmccune.com/blog/">Doug McCune</a></li>
<li>Clint Modien (C&#8217;mon Clint, you know you want to be there)</li>
<li><a href="http://lordbron.wordpress.com/">Tom Ortega</a> (his last 360|Flex as an organizer!)</li>
<li><a href="http://www.infoaccelerator.net/blog/">Andy Powell</a></li>
<li><a href="http://toddrothe.com/blog/">Todd Rothe</a></li>
<li><a href="http://blog.digitalbackcountry.com/">Ryan Stewart</a></li>
<li><a href="http://blog.benstucki.net/">Ben Stucki</a></li>
<li><a href="http://blog.mediarain.com/">Bryce Barrand</a></li>
<li><a href="http://jacwright.com/">Jac Wright</a></li>
<li><a href="http://xtyler.com/">Tyler Wright</a></li>
</ul>
<p>And these are the people who I&#8217;ve learned from whose work I&#8217;ve admired online, who I&#8217;m hoping to meet and get to know &#8220;in real life&#8221;:</p>
<ul>
<li><a href="http://blog.simb.net/">Sim Bateman</a></li>
<li><a href="http://twitter.com/garthdb">Garth Braithwaite</a></li>
<li><a href="http://joelhooks.com/">Joel Hooks</a></li>
<li><a href="http://blog.kevinhoyt.org/">Kevin Hoyt</a></li>
<li><a href="http://www.richardlord.net/">Richard Lord</a></li>
<li><a href="http://jesterxl.com/">Jesse Warden</a></li>
<li><a href="http://flexblog.faratasystems.com/">Yakov Fain</a></li>
</ul>
<p>And the best part is, there are plenty of others that I will meet, that I don&#8217;t know (or even know of) yet, but who will be on my &#8220;conference friends&#8221; list for the next 360|Flex =)</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2010/02/18/i-am-360flex-and-so-can-you/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Thoughts on multi-screen, multi-context app development</title>
		<link>http://probertson.com/articles/2010/02/09/thoughts-on-multi-screen-context-app-development/</link>
		<comments>http://probertson.com/articles/2010/02/09/thoughts-on-multi-screen-context-app-development/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 01:00:58 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Application Design]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Contextual design]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Multi-screen]]></category>
		<category><![CDATA[Opinions]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[User-centered design]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=372</guid>
		<description><![CDATA[Around 8 months ago I was asked to start thinking about the now emerging (particularly from a Flash Platform perspective) world of multi-screen application development. What are issues to consider? What guidance should we offer?
It turns out that my thinking on that topic isn&#8217;t going to become anything in the Adobe documentation. So I&#8217;ve sort [...]]]></description>
			<content:encoded><![CDATA[<p>Around 8 months ago I was asked to start thinking about the now emerging (particularly from a Flash Platform perspective) world of multi-screen application development. What are issues to consider? What guidance should we offer?</p>
<p>It turns out that my thinking on that topic isn&#8217;t going to become anything in the Adobe documentation. So I&#8217;ve sort of just been sitting on my ideas with the idea that someday I&#8217;ll probably share them.</p>
<p>Which brings me to this post.</p>
<h2>Aside: upcoming presentations on multi-screen development</h2>
<p>This is really a side note to the main ideas here, but I thought I&#8217;d mention it since it&#8217;s the reason I actually stopped to write this. In one of my mind-wandering moments this morning, I realized that at the upcoming <a href="http://360flex.com/">360|Flex conference (San Jose, March 7-10)</a> I&#8217;ll be involved in two presentations that are directly related to practical aspects of building multi-screen apps:</p>
<ul>
<li>
<p>As part of the pre-conference free training, <a href="http://joelhooks.com/">Joel Hooks</a> and I are doing a four-hour training on using the <a href="http://robotlegs.org/">Robotlegs micro-architecture</a>. (Joel is the main speaker, fortunately, because he&#8217;s one of the core Robotlegs developers and the main &#8220;evangelist.&#8221; I&#8217;ll be helping out, to try and help save his voice and maybe to help find typos. =)</p>
<p>If you&#8217;re wondering what a Robotlegs session has to do with multi-screen apps&#8230;keep reading, it&#8217;s explained below.</p>
</li>
<li>On Tuesday and Wednesday, <a href="http://renaun.com/">Renaun Erickson</a> and I are giving (two separate) presentations about building iPhone apps using Flash Platform tools. My session is more of an intro into the workflow, how it&#8217;s similar to other app building, and how it&#8217;s different. (Plenty of code to look at &#8212; don&#8217;t worry!) Renaun is going to get more into specifics of building a game, as well as some more intermediate/advanced topics like performance.</li>
</ul>
<p>Funny that I never really made that connection until this morning. I guess subconsciously I knew this is a direction I want to move in, and that&#8217;s why I&#8217;ve been focusing my learning (and hence my presenting) on these topics =)</p>
<h2>Background</h2>
<p>While I was partially trying to keep my thinking abstract, from a practical perspective I centered my thoughts around developing using the Flash Platform. So conceptually, what I was thinking about was the idea of making a single &#8220;app&#8221; for multiple screens, which would mean that (in the technology of the next year or so) it could be potentially take several forms:</p>
<ul>
<li>a browser/computer app (Flash Player)</li>
<li>a browser/mobile app (Flash Player)</li>
<li>a desktop app (AIR)</li>
<li>a mobile (iPhone) app (Publisher for iPhone, similar to AIR)</li>
<li>a mobile app for other devices (AIR)</li>
<li>a TV app or widget (<a href="http://tv.adobe.com/watch/max-2009-design/flash-for-the-digital-home-flash-on-tv/">Flash for the digital home</a>)
</ul>
<p>(Obviously many of these are only out in public beta, some have only been vaguely publicly acknowledged, and others may or may not ever exist as actual Adobe products =)</p>
<h2>One app, or many?</h2>
<p>Back when I started thinking about this, there seemed to be two main camps. One group was a strong advocate for the &#8220;single source&#8221; idea: you would build one SWF or one AIR app and distribute that same app on any platforms (desktop/mobile/TV). Obviously a key element to that, especially for desktop/mobile apps rather than browser apps, would be having code that detects screen size and device capabilities and adapts the UI to the device.</p>
<p>The second group felt that it was more likely that developers who are creating an app for multiple screens would actually create multiple apps (from the perspective of the IDE). The apps would obviously share some code, visual assets, etc., but would be different enough that they&#8217;d be created separately and distributed as separate file types. (In the case of apps created for the iPhone, of necessity this has to be true, at least in terms of the publishing part.)</p>
<p>Since I try to be pragmatic about things unless I have a <em>really</em> good reason, I favored the second viewpoint. However, I acknowledge that in some circumstances the first approach might be used. As always, I think that developers are going to use a mix of approaches.</p>
<p>For example, suppose I&#8217;m building an app and I want to create a version for desktop computers, a version for the iPhone, and a version for other mobile devices. Personally I see this not just as an issue of &#8220;porting&#8221; the app from one platform to another. I think that each device has its strengths, and more importantly, each device is used for different purposes and in different contexts. If I&#8217;m building an app for a device, I should definitely be <a href="http://blog.digitalbackcountry.com/2009/10/introducing-contextual-applications/">taking that notion of context into account</a> as I&#8217;m designing the app. That pretty much rules out the possibility of using the exact same app (UI and everything) for both computers and mobile devices, unless I want it to run as a widget-type app on the desktop.</p>
<p class="editornote">Also see: <a href="http://www.adobe.com/devnet/flashplatform/context_apps/">Adobe Flash Platform contextual applications developer center</a></p>
<h2>Adaptable code to the rescue</h2>
<p>On the other hand, that doesn&#8217;t mean that developers will always create completely separate projects. For example, suppose I&#8217;m creating an app for iPhone, and another for another mobile device. Or perhaps I&#8217;m using the Publisher for iPhone to create an iPhone version of my app and an iPad version. If my app is a game where I can more freely discard the conventions of the platforms, perhaps the only platform difference I need to consider is the difference in screen dimensions and pixel density. In that case, it&#8217;s quite possible that I can <a href="http://www.adobe.com/devnet/flash/articles/authoring_for_multiple_screen_sizes.html"use the same source code and have it adapt to the different screen sizes</a>.</p>
<h2>Frameworks to the rescue</h2>
<p>Even for a more line-of-business or productivity app, one of the key ideas in <a href="http://tv.adobe.com/watch/max-2009-develop/preview-flex-for-mobile-devices/">Slider</a>, the future <a href="http://flashmobile.scottjanousek.com/2010/02/12/adobe-flex-for-mobile-whitepaper/">Flex mobile framework</a>, is to (as much as possible) abstract away platform convention differences. For example, if iPhone usually puts the back button on the top, and another platform puts it on the bottom, and another platform puts it in a menu, and another platform has it assigned to a physical button on the device, then Slider might have a &#8220;back&#8221; event that you can hook into, and you can make your app perform the necessary &#8220;back&#8221; tasks regardless of platform.</p>
<h2>Design patterns to the rescue</h2>
<p>And, of course, in some situations you&#8217;ll almost surely need to create different versions of apps for different screens. For example, suppose you&#8217;re building a desktop Twitter client and a mobile Twitter client. Chances are good you&#8217;ll put some functionality into the desktop version that doesn&#8217;t go into the mobile one &#8212; such as previewing images, or maybe Facebook integration. On the other hand, adding a feature like automatic location tagging would make lots of sense in the mobile version, but not so much in the desktop one.</p>
<p>As I was thinking, many months ago, about the idea of efficiently creating different versions of the same app for different devices, a thought hit me like a ton of bricks. This is exactly the use case that the oft-mentioned &#8220;separation of concerns&#8221; is designed for:</p>
<p>Over several years, various &#8220;micro architectures&#8221; and &#8220;application frameworks&#8221; have emerged and waxed and waned in popularity. Many of these architectures are modeled around the &#8220;<a href="http://en.wikipedia.org/wiki/Model-view-controller">Model-View-Controller</a>&#8221; design pattern (or its many variations).</p>
<p>One of the key benefits that these architectures claim is that it helps you keep the pieces of your application separate, without explicit links and dependencies between them. I&#8217;ve looked into and even tried out several of these over the years. One example that is frequently used to describe the notion of separation of concerns, which I always struggled with, goes something like this:</p>
<blockquote><p>
Suppose you&#8217;re creating an app, and you build the user interface and the other logic like server communication and data processing. If you use MVC/separation of concerns, then it&#8217;s really easy to just rip out your whole user interface layer and replace it with a new one.
</p></blockquote>
<p>They usually lost me with that one. As much as I tried, I couldn&#8217;t imagine a situation in which I&#8217;d want to build my app and then just rip out the UI and replace it with a different one <a id="note1src" class="footnote" href="#note1">note 1</a>.</p>
<p>Until now.</p>
<p>Suddenly I had discovered, for myself at least, a real-world use case for the separation-of-concerns-so-you-can-swap-out-the-UI argument. If I&#8217;m building an app for the desktop and mobile, I&#8217;d like to be able to reuse my code where I can. At the same time, some functionality is only going to apply to one app or the other, so it&#8217;d be nice to be able to plug it in cleanly. Oh and by the way, the user interfaces are going to be different, so being able to swap those out is an absolute must.</p>
<p>I&#8217;d always liked micro-architectures in general, if only because I like knowing that I&#8217;m building my app using some pattern or structure that is based on developers&#8217; real-world experience. It&#8217;s much nicer than trying to invent it myself and having to deal with all the pain points they&#8217;ve already gotten over. Now that I am imagining a world where I create multiple versions of the same app, with similar functionality but different user interfaces, suddenly micro-architecture patterns have become indispensable in my mind.</p>
<h2>Conclusion</h2>
<p>These are only just a few of my thoughts about the future world of multi-screen, contextual applications. Like Lee Brimelow, I believe that going forward <a href="http://theflashblog.com/?p=1743">building multi-screen, multi-context apps is going to be a much more common scenario</a>. From my perspective as someone who thinks a lot about user experience design, and trying to optimize tools for the task and context, I think this is one of the most exciting aspects of the current technology revolution. I&#8217;ll definitely continue to share my thoughts and ideas in the future (hopefully more practical ones, too, not just abstract ones like this =)</p>
<h2>Notes</h2>
<p class="footnote" id="note1">Note 1: Just to be clear, I&#8217;m not trying to sound negative about MVC or micro-architectures/frameworks. Most of them provide many benefits, many of which are also related to the idea of separation of concerns, such as making code easier to test, making code cleaner, reducing boilerplate code, providing structure so that teams or developers who inherit a project can get going more quickly, etc. Swapping out the view layer is just one little benefit they mention. (<a href="#note1src">back</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2010/02/09/thoughts-on-multi-screen-context-app-development/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>New project: AIR SQLite utilities</title>
		<link>http://probertson.com/articles/2010/02/03/new-project-air-sqlite-utilities/</link>
		<comments>http://probertson.com/articles/2010/02/03/new-project-air-sqlite-utilities/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 20:44:55 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[AS3]]></category>
		<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Application Design]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[local SQL database]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=367</guid>
		<description><![CDATA[I&#8217;m excited to announce that I&#8217;m &#8220;officially&#8221; releasing a new open-source project that I&#8217;ve been using on personal and work projects for over a year.
For lack of a better name, I call it my &#8220;AIR SQLite utility library&#8221;
The code currently contains one major piece of functionality (well, two different variations on one bit of functionality), [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m excited to announce that I&#8217;m &#8220;officially&#8221; releasing a new open-source project that I&#8217;ve been using on personal and work projects for over a year.</p>
<p>For lack of a better name, I call it my &#8220;<a href="/projects/air-sqlite/">AIR SQLite utility library</a>&#8221;</p>
<p>The code currently contains one major piece of functionality (well, two different variations on one bit of functionality), which is a SQL &#8220;query runner&#8221; library. This is a wrapper for the AIR SQL classes that allows you to run a SQL statement by just passing a few bits of information:</p>
<ul>
<li>The text of the SQL statement itself</li>
<li>An object containing properties with the values for any statement parameters in the SQL</li>
<li>A Function to call when the operation completes</li>
<li>A failure Function</li>
<li>(optionally) a class to use as the data type for the data returned from a <code>SELECT</code> statement</li>
</ul>
<p>The library does all the work of creating SQLStatement objects and caching prepared queries, as well as pooling SQLConnection instances so you can execute multiple statements simultaneously. It also has a variation that allows you to specify a &#8220;batch&#8221; of statements to execute, and they are executed in order in a transaction.</p>
<p>I&#8217;ve also got an additional utility to add to the library. It&#8217;s a &#8220;database copy&#8221; utility that allows you to create a &#8220;deep copy&#8221; of a database &#8212; all it&#8217;s tables, views, etc. &#8212; with or without data. The key reason why this is useful is that you can use it to create an encrypted database from an unencrypted database (and vice-versa). It&#8217;s written and tested, but I decided to modify the structure slightly before releasing it, so it&#8217;s not checked in yet.</p>
<p>I&#8217;ve put the details about how it works and why it&#8217;s designed that way in <a href="/projects/air-sqlite/">the project page</a>. In case you&#8217;ve ever wondered how I design apps, I think the examples and this library give some insight into how I actually do my database-driven AIR app development. At least, how I structure the data-access part of my apps.</p>
<p>On (another) personal note, this project is also my first project that I&#8217;ve posted to <a href="http://github.com/probertson">my Github repository</a> (as opposed to projects I&#8217;ve forked). It was actually posted-but-not-advertised on Google code for a month or so, but I decided to move to Github because the collaboration and checkin-without-network-connection features are so awesome.</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2010/02/03/new-project-air-sqlite-utilities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Multi-table INSERT using one SQL statement in AIR SQLite</title>
		<link>http://probertson.com/articles/2009/11/30/multi-table-insert-one-statement-air-sqlite/</link>
		<comments>http://probertson.com/articles/2009/11/30/multi-table-insert-one-statement-air-sqlite/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 06:00:08 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[local SQL database]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=343</guid>
		<description><![CDATA[This article describes a way that you can use a single INSERT statement to add data to multiple tables in the SQL dialect supported by the SQLite engine in Adobe AIR.
Normally in SQL, including in AIR&#8217;s built-in SQLite database engine, you can only add data to one table at a time using an INSERT statement. [...]]]></description>
			<content:encoded><![CDATA[<p>This article describes a way that you can use a single <code>INSERT</code> statement to add data to multiple tables in the SQL dialect supported by the SQLite engine in Adobe AIR.</p>
<p>Normally in SQL, including in AIR&#8217;s built-in SQLite database engine, you can only add data to one table at a time using an <code>INSERT</code> statement. In some cases, particularly when you&#8217;re doing a &#8220;bulk loading&#8221; operation such as importing data from a text file into a database, it&#8217;s convenient to be able to insert data into multiple tables using a single <code>INSERT</code> statement.</p>
<p>For example, suppose you have XML data to import into a database such as the following:</p>
<pre>&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;employees&gt;
    &lt;employee firstName=&quot;Bob&quot; lastName=&quot;Smith&quot;
        location=&quot;San Francisco&quot; country=&quot;USA&quot;/&gt;
    &lt;employee firstName=&quot;Harold&quot; lastName=&quot;Jones&quot;
        location=&quot;San Francisco&quot; country=&quot;USA&quot;/&gt;
    &lt;employee firstName=&quot;Tom&quot; lastName=&quot;Donovan&quot;
        location=&quot;Boston&quot; country=&quot;USA&quot;/&gt;
    &lt;employee firstName=&quot;Mike&quot; lastName=&quot;Wilson&quot;
        location=&quot;Calgary&quot; country=&quot;Canada&quot;/&gt;
    &lt;employee firstName=&quot;Steve&quot; lastName=&quot;Thomas&quot;
        location=&quot;London&quot; country=&quot;UK&quot;/&gt;
    &lt;employee firstName=&quot;Joe&quot; lastName=&quot;Nelson&quot;
        location=&quot;London&quot; country=&quot;UK&quot;/&gt;
    &lt;employee firstName=&quot;Juan&quot; lastName=&quot;Varga&quot;
        location=&quot;Buenos Aires&quot; country=&quot;Argentina&quot;/&gt;
    ...
&lt;/employees&gt;</pre>
<p>The XML data isn&#8217;t normalized, so there is duplicate data between the various records. We will import it into a database with the following (normalized) structure:</p>
<p><img src="/resources/2009/11/30/multi_table_insert_data_model.png" width="400" height="430" alt="Data model for the database" /></p>
<p>Assuming the data is going to be imported as a single user operation, it would be painful to need to prompt the user or throw errors for every duplicate entry.</p>
<p>Using the technique described here, you can use a single SQL statement to add an employee and if necessary any related data including office location and country. (You would still loop over the data and execute one <code>INSERT</code> statement per employee record &#8212; but you wouldn&#8217;t need to execute three <code>INSERT</code> statements per employee record, or need to check for duplicate office locations and countries for each employee record to be inserted.)</p>
<p>As mentioned above, this technique is probably only appropriate when you&#8217;re doing &#8220;bulk importing&#8221; of data. If you&#8217;re just adding a single conceptual record (even if it includes data in multiple tables) you&#8217;ll most likely want to use a series of <code>INSERT</code> statements to add the data, so that you can have more precise error checking and handling.</p>
<h2>How to do it</h2>
<p>In an attempt to &#8220;cut to the chase&#8221; I&#8217;m going to put the necessary code here. For more detailed explanations on how this works and why it&#8217;s necessary, see the &#8220;<a href="#details">details</a>&#8221; section below.</p>
<p>This technique for inserting data into multiple tables using a single SQL statement consists of three elements:</p>
<ol>
<li>A view in the database that groups the data to be inserted (from all the tables) into one &#8220;table&#8221;</li>
<li>An <code>INSERT</code> statement to add the data, using the view as the destination &#8220;table&#8221; in the <code>INSERT</code> statement. This is the <code>INSERT</code> statement that you&#8217;ll run from your application while importing the data</li>
<li>A trigger defined on the view, which runs when any <code>INSERT</code> statement is executed against the view. This trigger does the actual work of checking for existing data and inserting data into individual tables.</li>
</ol>
<p>Here&#8217;s the code for each part:</p>
<h3>A view grouping the data to insert</h3>
<p>This combines all the tables that potentially need data inserted into a single &#8220;table&#8221; for the <code>INSERT</code> statement. You run this statement once to create the view in the database.</p>
<pre>CREATE VIEW employees_for_insert AS
SELECT e.firstName,
    e.lastName,
    l.name AS locationName,
    c.name AS countryName
FROM employees e
    INNER JOIN locations l ON e.locationId = l.locationId
    INNER JOIN countries c ON l.countryId = c.countryId</pre>
<h3>An <code>INSERT</code> statement that &#8220;inserts&#8221; the data into the view</h3>
<p>This code isn&#8217;t actually run, but it passes all the data to the database engine for use in the trigger. You execute this SQL statement once for each record to add to the tables.</p>
<pre>INSERT INTO employees_for_insert
(
    firstName,
    lastName,
    locationName,
    countryName
)
VALUES
(
    :firstName,
    :lastName,
    :locationName,
    :countryName
)</pre>
<h3>An <code>INSTEAD OF</code> trigger defined on the view</h3>
<p>This is the code that actually runs when the <code>INSERT</code> statement above is executed. You run this code once to create the trigger. Then the database runs the code in the trigger body automatically. If a location or country doesn&#8217;t exist it is inserted. However, if they do exist, nothing happens (no duplicate record is created). Then the main employee record is inserted.</p>
<pre>CREATE TRIGGER insert_employees_locations_countries
INSTEAD OF INSERT
ON employees_for_insert

BEGIN

INSERT INTO countries (name)
SELECT NEW.countryName
WHERE NOT EXISTS
    (SELECT 1 FROM countries
     WHERE name = NEW.countryName);

INSERT INTO locations (name, countryId)
SELECT NEW.locationName, countries.countryId
FROM countries
WHERE countries.name = NEW.countryName
AND NOT EXISTS
    (SELECT locationId
     FROM locations
     WHERE name = NEW.locationName);

INSERT INTO employees (firstName, lastName, locationId)
SELECT NEW.firstName,
    NEW.lastName,
    locations.locationId
FROM locations
WHERE locations.name = NEW.locationName;

END</pre>
<h2 id="details">Details</h2>
<p>The SQL language is designed for working with relational databases, so in a SQL database you usually use multiple tables to represent a single piece of data. That means that in a normal scenario, if you want to add a new record to a table, you may need to add a new row of data to additional tables that the main data is related to.</p>
<p>In this example, we are using a database with the following structure:</p>
<p><img src="/resources/2009/11/30/multi_table_insert_data_model.png" width="400" height="430" alt="Data model for the database" /></p>
<p>This data represents employees in a large company that has multiple office locations, identified by records in the <code>locations</code> table. In fact, this company is an international company that has offices in different countries, including multiple offices in some countries (represented by the <code>countries</code> table.</p>
<p>Each employee is associated with their primary office location by the <code>locationId</code> field in the <code>employees</code> table, and each location is defined as being in a certain country by the <code>countryId</code> column in the <code>locations</code> table.</p>
<p>In order to add a new employee you would generally have to perform several steps:</p>
<ol>
<li>Check whether the country where the employee&#8217;s office is located exists in the <code>countries</code> table</li>
<li>If not, add it; if so, get its id to create the relationship with the <code>locations</code> table</li>
<li>Make sure the office location exists in the <code>locations</code> table</li>
<li>If necessary add the location record, and get its id to use in the employee record</li>
<li>Add the employee record to the <code>employees</code> table</li>
</ol>
<p>This is a fairly complicated process because a single SQL <code>INSERT</code> statement can only operate on one table at a time. In a simple case where you are adding a single employee record, this complexity isn&#8217;t unbearably difficult. You can execute the series of SQL statements in sequence in a single transaction. If an error occurs, you can break out of the sequence and display an error message or handle the error as desired.</p>
<p>However, if you&#8217;re importing a large set of data it&#8217;s not convenient to throw errors or display dialogs to the user. Instead, it would be nice to be able to just add any dependent data where appropriate, and insert all the data in one step.</p>
<p>The technique that&#8217;s described in this article makes use of database views and a SQLite feature known as <code>INSTEAD OF</code> triggers.</p>
<p>A <em>view</em> is a predefined <code>SELECT</code> statement that&#8217;s saved in a database so it can be used in queries as though it was a table. Because it usually includes data from multiple tables, and doesn&#8217;t necessarily include all the data from any given table, a view is generally read-only &#8212; you can use a <code>SELECT</code> statement to retrieve data from a view, but you can&#8217;t use an <code>INSERT</code>, <code>UPDATE</code>, or <code>DELETE</code> statement to modify the view data.</p>
<p>However, in SQLite (and consequently in AIR) you can define a special type of trigger that&#8217;s associated with a view known as an <code>INSTEAD OF</code> trigger. (A trigger is a set of SQL code that&#8217;s associated with a table. The code is executed when a data manipulation operation is performed on that table.) When a SQL statement attempts to perform an <code>INSERT</code>, <code>DELETE</code>, or <code>UPDATE</code> operation on the view that has an <code>INSTEAD OF</code> trigger defined for that particular operation, the trigger is executed <em>instead of</em> the specified operation. You can only define <code>INSTEAD OF</code> triggers on views (it wouldn&#8217;t make sense to use one for a table). For more information about triggers, see <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/localDatabaseSQLSupport.html#createTrigger">the Adobe AIR SQL reference documentation for the <code>CREATE TRIGGER</code> statement</a>.</p>
<p>In this example, a view is defined that includes all the data in all the tables that potentially need data inserted. When the <code>INSERT</code> statement is executed the database runs the trigger instead. The trigger contains code that checks whether related data in the locations and countries tables already exists, and adds it if necessary. Then it adds the employee record with the related key values.</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2009/11/30/multi-table-insert-one-statement-air-sqlite/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>New article &#8220;Programming with the Vector class&#8221;</title>
		<link>http://probertson.com/articles/2009/09/14/programming-with-the-vector-class/</link>
		<comments>http://probertson.com/articles/2009/09/14/programming-with-the-vector-class/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 23:40:31 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Vector (typed arrays)]]></category>
		<category><![CDATA[Writing]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=326</guid>
		<description><![CDATA[Several months ago (probably almost a year ago) I wrote an article for the Adobe Developer Connection titled &#8220;Programming with the Vector class.&#8221; As you can surely guess, the article is about the Vector class, which provides typed array functionality (an array whose elements are required to all be instances of the same data type). [...]]]></description>
			<content:encoded><![CDATA[<p>Several months ago (probably almost a year ago) I wrote an article for the Adobe Developer Connection titled &#8220;<a href="http://www.adobe.com/devnet/flash/quickstart/programming_vectors_as3/">Programming with the Vector class</a>.&#8221; As you can surely guess, the article is about the Vector class, which provides typed array functionality (an array whose elements are required to all be instances of the same data type). The Vector class was added to ActionScript in Flash Player 10 and AIR 1.5.</p>
<p>Apparently the article got lost in the shuffle, and about a week ago they found it and asked me to review their changes. I just found out that the article was published today.</p>
<p>Although it&#8217;s grouped under the &#8220;quick starts&#8221; category, it has a lot of detail. Also, it&#8217;s included in the Flash developer center but Flex developers shouldn&#8217;t be put off by that. It&#8217;s really about a core ActionScript class that&#8217;s available anywhere you&#8217;re writing ActionScript. (I&#8217;ve always found the ADC&#8217;s forced boundaries between Flash, Flex, and AIR to be too constraining for reality.)</p>
<p>I personally think the article provides a good, in-depth introduction to various aspects of working with the Vector class. In particular, it has guidance on areas that some people find problematic, such as the type parameter syntax and the fact that you have to provide your own custom sorting code (and of course the article includes examples to copy). I personally think it&#8217;s better than the developer guide documentation on the Vector class. (And I wrote them both so I&#8217;m not just showing a bias for my own work =)</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2009/09/14/programming-with-the-vector-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A paperless world?</title>
		<link>http://probertson.com/articles/2009/08/20/paperless-world/</link>
		<comments>http://probertson.com/articles/2009/08/20/paperless-world/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 21:08:46 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[Articles by Paul]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=314</guid>
		<description><![CDATA[In the spirit of the anecdote I shared last March, here&#8217;s a funny little story from my day.
My boss asked me to review a report he&#8217;s been working on. He wrote it in a wiki page. I reviewed it mostly while I was riding on the train to work this morning (without network connectivity), so [...]]]></description>
			<content:encoded><![CDATA[<p>In the spirit of <a href="/articles/2009/03/10/funny-coding-behaviors/">the anecdote I shared last March</a>, here&#8217;s a funny little story from my day.</p>
<p>My boss asked me to review a report he&#8217;s been working on. He wrote it in a wiki page. I reviewed it mostly while I was riding on the train to work this morning (without network connectivity), so I didn&#8217;t make any changes to the wiki page itself but instead wrote notes in a Word document. Once I had finished my notes, I wanted to discuss them with my boss, but I was having a bit of trouble figuring out how to do it. Although I don&#8217;t think I was explicitly thinking about it, in retrospect I think I was looking at the situation with a few requirements:</p>
<ul>
<li>I wanted to share my comments in person, rather than (for example) sending them by email.</li>
<li>I wanted to be able to share them in context, i.e. while actually looking at the report.</li>
<li>I wanted to minimize the disruption to my boss. We didn&#8217;t have a planned meeting (it wasn&#8217;t a formal review) so I planned to go to his cubicle and didn&#8217;t want to have to ask him to come back to my cubicle just to see my notes.</li>
</ul>
<p>That was the problem in a nutshell. The notes were in a Word file on my computer in my cubicle. I wanted to go to my boss&#8217;s cubicle to discuss the notes so I needed a way to bring the notes with me to his cubicle. I had pretty much resigned myself to the idea that I would need to carry my laptop over to my boss&#8217;s cubicle and read my notes from it while we looked at the report on his monitor &#8212; but I wasn&#8217;t completely happy with that idea. (I&#8217;m not <em>that</em> lazy &#8212; my laptop is just hooked into a docking station and it&#8217;s really flaky about running on battery power unless you disconnect it in just the right way, which involves putting it to sleep twice and logging back in twice, among other steps. So there was a reason I didn&#8217;t want to have to go through that process.)</p>
<p>Suddenly I thought of a straightforward solution &#8212; so basic in fact that it really struck me that it wasn&#8217;t my first instinct (whereas previously it would have been).</p>
<p>Are you ready for it?</p>
<p>Here it comes&#8230;</p>
<p>I <em>printed</em> my Word document and carried the paper in my hand to my boss&#8217;s cubicle, together with a pen for taking notes.</p>
<p>Genius! The perfect solution for my requirements! The only thing noteworthy about it is that I realized it&#8217;s so extremely rare for me to print anything that it is apparently no longer an obvious course of action for me. I guess on a personal level at least I&#8217;m getting close to a paperless world.</p>
<p>And just in case this story makes me sound really unproductive, I should point out that this whole train of thought probably took no more than a couple of seconds. I wasn&#8217;t really investing <em>that</em> much time into it =)</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2009/08/20/paperless-world/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A new (old) tool for AIR SQLite development</title>
		<link>http://probertson.com/articles/2009/04/22/a-new-old-tool-for-air-sqlite-development/</link>
		<comments>http://probertson.com/articles/2009/04/22/a-new-old-tool-for-air-sqlite-development/#comments</comments>
		<pubDate>Wed, 22 Apr 2009 22:41:33 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[local SQL database]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=272</guid>
		<description><![CDATA[This is pretty much old news by internet time standards, but I haven&#8217;t had time to write about it until now. (We&#8217;re working hard to make future Flex/AIR/ActionScript/Flash documentation more focused on how you actually use documentation, better than ever before.)
A couple of years ago, before AIR beta 1 (&#8220;Apollo&#8221;), I wrote a tool for [...]]]></description>
			<content:encoded><![CDATA[<p>This is pretty much old news by internet time standards, but I haven&#8217;t had time to write about it until now. (We&#8217;re working hard to make future Flex/AIR/ActionScript/Flash documentation more focused on how you actually use documentation, better than ever before.)</p>
<p>A couple of years ago, before AIR beta 1 (&#8220;Apollo&#8221;), I wrote a tool for testing SQL statements in AIR. Later (I can&#8217;t remember exactly when) I released it under the name &#8220;<a href="/projects/doppler-air-sql-admin-tool/">Doppler</a>.&#8221; I had plans to make it a full-fledged database management tool, but those plans never really panned out. I&#8217;ve told this story lots of times now, about how I now use (and even help develop) <a href="http://www.dehats.com/drupal/?q=node/58">David Deraedt’s “Lita” SQLite admin tool</a>.</p>
<p>However, &#8220;Doppler&#8221; in its current form served a different need than Lita &#8212; Lita is great for creating and managing database structure (you&#8217;ll never have to write a CREATE TABLE statement again), but it isn&#8217;t as strong for testing individual SQL statements. Over the past several months I&#8217;ve been doing some &#8220;serious&#8221; app development, working on an AIR app that makes heavy use of SQLite. I found my little tool to be quite handy, and also found and implemented a number of small improvements that make it much more useful.</p>
<p>Since my original intentions were never going to come to fruition, and I had new future plans for the app, I decided a new name was in order. Since it is for running SQL statements, &#8220;run&#8221; was an easy and obvious choice. So now, (several weeks after posting it), allow me to officially introduce you to the <a href="/projects/run-air-sqlite-query-testing-tool/">Run! AIR SQL query authoring and testing tool</a> &#8212; the next generation of Doppler.</p>
<p>If you look at the <a href="/projects/run-air-sqlite-query-testing-tool/#history">full feature list for the latest release</a>, you&#8217;ll see that I&#8217;ve added several types of changes. A few of the ones that I&#8217;ve found most useful in my day-to-day work are:</p>
<ul>
<li>Auto-update and badge install &#8212; no more downloading the .air file (admittedly not a big deal) and no more uninstall and reinstall each time there&#8217;s a new version (a big deal)</li>
<li>&#8220;Recent SQL files&#8221; and &#8220;Recent databases&#8221; menu items</li>
<li>Opening and saving SQL files (plus keyboard shortcuts)</li>
<li>&#8220;Row count&#8221; and &#8220;execution time&#8221; displayed for SELECT statements</li>
<li>Line numbers and auto-indent in the SQL panel</li>
</ul>
<p>And yes, I did say &#8220;day-to-day&#8221; work. On some days, Run! has been my primary IDE, as I&#8217;m writing and testing and rewriting large SQL statements. It&#8217;s been kind of strange and kind of fun building a developer tool and using it as much as I use Run!.</p>
<p>I&#8217;ve already gotten a bug report and I&#8217;m working on features for the next big release, so if you have thoughts or comments please comment on the project page!</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2009/04/22/a-new-old-tool-for-air-sqlite-development/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Funny coding behaviors</title>
		<link>http://probertson.com/articles/2009/03/10/funny-coding-behaviors/</link>
		<comments>http://probertson.com/articles/2009/03/10/funny-coding-behaviors/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 19:25:35 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Writing]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=234</guid>
		<description><![CDATA[Disclaimer: this is just a silly little note, perhaps the first such on this site although my personal site primarily consists of such little tidbits, mostly about my kids.
A few years ago I was working as a developer for a computer training department at a large midwestern university*. I also wrote and taught training courses [...]]]></description>
			<content:encoded><![CDATA[<p class="editornote">Disclaimer: this is just a silly little note, perhaps the first such on this site although my personal site primarily consists of such little tidbits, mostly about my kids.</p>
<p>A few years ago I was working as a developer for a <a href="http://ittraining.iu.edu/">computer training department</a> at a <a href="http://www.iub.edu/">large midwestern university</a><a href="#note">*</a>. I also wrote and taught training courses for them. As jobs tend to do, the work was often in cycles &#8212; sometimes I&#8217;d spend a few months doing mostly coding, then perhaps I&#8217;d be working on a new workshop so I&#8217;d spend most of my time writing for a few months.</p>
<p>At one point I was in the transition phase, moving off of a &#8220;coding&#8221; cycle and into a &#8220;writing&#8221; cycle. One day while I was writing (in Adobe Framemaker &#8212; the word processor we used) I realized that each time I reached the end of a sentence my first instinct was to type a semicolon rather than a period. Too many lines of code written, I guess!</p>
<p>Anyway, I was reminded of that today when something kind of similar took place. Nowadays of course most of my writing, whether code or documentation, is done on a computer. In fact it&#8217;s fairly common that when I reach a stopping place while writing in a web browser (such as editing a wiki page) I instinctively type Ctrl+S to &#8220;save&#8221; (even though that just opens up a dialog to save the HTML of the page, rather than actually saving my work in the wiki or whatever. Today, however, this instinctual behavior was taken to a new level.</p>
<p>I was in a meeting and I had a thought about something I&#8217;ve been brainstorming since yesterday. It&#8217;s a new project I&#8217;m starting on (a documentation architecture project, not a coding one) so I&#8217;ve started by just jotting down thoughts in a notebook as they occur to me. I pulled out my notebook and wrote down my ideas. Then I felt a sort of funny twitching in my left hand &#8212; my left pinky and middle finger were instinctively trying to perform some sort of repetitive action, and couldn&#8217;t quite figure out whether it was appropriate or not. I realized that since I had just finished writing down a thought, my hand was trying to make the gesture for Ctrl+S in an attempt to &#8220;save&#8221; my &#8220;document&#8221;. Because of this my brain was momentarily confused &#8212; like it somehow knew this action didn&#8217;t quite fit in this context (pen and paper) but couldn&#8217;t figure out exactly why that was the case. Since of course, mentally I knew I needed to hurry and save my work so that it wasn&#8217;t lost.</p>
<p>Anyway, that&#8217;s my funny story for the day. Probably for the rest of my life, at least in terms of publishing at this url. So I hope you enjoyed it =)</p>
<h2 id="note" class="footnote">* Note</h2>
<p class="footnote">My use of the term &#8220;large midwestern university&#8221; is also an attempt at humor &#8212; its an academic inside joke. I went to graduate school at Indiana University (the same &#8220;large midwestern university&#8221; where I later worked) and we students often read academic papers published by our professors or their former students. In the spirit of anonymity, when they described the participants in their research studies they never described their study participants as &#8220;students at Indiana University&#8221; or something like that. Instead they always described them as &#8220;students at a large midwestern university&#8221; although the authors&#8217; biographies would always indicate their affiliation with Indiana University, so there really wasn&#8217;t any anonymity about it at all.</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2009/03/10/funny-coding-behaviors/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Please test: updated ActionScript GZIP library with Flash Player 10 support</title>
		<link>http://probertson.com/articles/2009/02/27/actionscript-gzip-library-flash-player-10/</link>
		<comments>http://probertson.com/articles/2009/02/27/actionscript-gzip-library-flash-player-10/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 22:40:50 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AS3]]></category>
		<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=232</guid>
		<description><![CDATA[Since I first created my ActionScript GZIP library as a test of Adobe AIR&#8217;s file compression capability, the number one request I&#8217;ve received has been to add support for Flash Player-only projects. With the release of Flash Player 10 last fall, I couldn&#8217;t use the lack of player support as an excuse any more. So [...]]]></description>
			<content:encoded><![CDATA[<p>Since I first created my <a href="/projects/gzipencoder/">ActionScript GZIP library</a> as a test of Adobe AIR&#8217;s file compression capability, the number one request I&#8217;ve received has been to add support for Flash Player-only projects. With the release of Flash Player 10 last fall, I couldn&#8217;t use the lack of player support as an excuse any more. So now I&#8217;ve just been using the &#8220;not enough time&#8221; excuse&#8230;</p>
<p>But not any more. A few days ago I checked in a beta (barely tested) version of that adds support for Flash Player 10 (browser) projects. It&#8217;s not linked from the main google code project page yet, but you can get to it from the <a href="http://code.google.com/p/ascompress/downloads/list">GZIP encoder project downloads page</a>.</p>
<p>The download that adds Flash Player 10 support is &#8220;ascompress-.2.0.zip&#8221;. It now includes two SWC files:</p>
<ul>
<li>GZIPEncoder_AIR.swc is the full package, with all the same features as the previous release (.1.0.2).</li>
<li>
<p>GZIPEncoder_Flash.swc is the Flash-Player-only version. It only compresses/uncompresses ByteArrays, and doesn&#8217;t have any support for files.</p>
<p>Of course, since Flash Player 10 also adds local file opening/saving support that uses ByteArray data for the files, you could easily write your own code to prompt the user for a gzip file, or compress a file and prompt the user to save it. For an example of opening and saving files from Flash Player 10, see my quick start article: &#8220;&#8221;</p>
</li>
</ul>
<p>As I implied when I described this as &#8220;beta (barely tested)&#8221; I haven&#8217;t done a lot of testing of this code yet. I don&#8217;t actually anticipate that there will be issues &#8212; really all I did was refactor the code into two classes instead of one &#8212; but that doesn&#8217;t mean there won&#8217;t be any issues, of course. =) If you&#8217;re interested, and especially if you&#8217;re one of the people who&#8217;s asked for this support, I would love it if you try it out and let me know how it works for you. If you&#8217;re willing to test it out, I&#8217;ll be happy to quickly make any fixes necessary.</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2009/02/27/actionscript-gzip-library-flash-player-10/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>AIR 1.5 encrypted SQLite database &#8212; how to use it, best practices, and new projects</title>
		<link>http://probertson.com/articles/2008/11/18/air-1_5-encrypted-sqlite-database-how-to/</link>
		<comments>http://probertson.com/articles/2008/11/18/air-1_5-encrypted-sqlite-database-how-to/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 08:30:25 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Life at Adobe]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Writing]]></category>
		<category><![CDATA[local SQL database]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=214</guid>
		<description><![CDATA[Over a year ago I described a potential area of concern for using a SQLite database with an AIR application &#8212; because all apps use the same database engine, any AIR app can read any other app&#8217;s database (as long as it can find the database file).
As you may have heard among all the news [...]]]></description>
			<content:encoded><![CDATA[<p>Over a year ago I described <a href="/articles/2007/06/21/securing-air-sql-database/">a potential area of concern for using a SQLite database with an AIR application</a> &#8212; because all apps use the same database engine, any AIR app can read any other app&#8217;s database (as long as it can find the database file).</p>
<p>As you may have heard among all the news that&#8217;s coming out from MAX right now, <a href="http://www.adobe.com/devnet/logged_in/rchristensen_lpolanco_air_1.5.html">Adobe AIR 1.5 has just been released</a>. Most of the features of AIR 1.5 are features that were introduced with Flash Player 10. However, one new feature in AIR 1.5 that helps address the easy-to-read database issue is AIR 1.5&#8217;s new support for AES encrypted databases.</p>
<p>I&#8217;ve had the interesting and at times complex job of writing the documentation for this new feature. The bulk of the new documentation is in a new section &#8220;<a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS8AFC5E35-DC79-4082-9AD4-DE1A2B41DAAF.html">Using encryption with SQL databases</a>&#8221; in the SQL database chapter of the manual &#8220;Developing Adobe AIR Applications&#8221;.</p>
<p>It&#8217;s pretty straightforward to use an encrypted database. You have to create the database as an encrypted db. To create or open it, you call the SQLConnection class&#8217;s <code>open()</code> or <code>openAsync()</code> methods, just as you normally do, and there&#8217;s a new parameter where you provide a 16-byte ByteArray encryption key for the database. That&#8217;s all there is to it.</p>
<p>The SQLConnection class also has a new <code>reencrypt()</code> method, that you use to change the encryption key of an already encrypted database.</p>
<p>If you want to see some code examples, check out the documentation listed above, or see these quick start articles on the Adobe developer center:</p>
<ul>
<li><a href="http://www.adobe.com/devnet/air/flex/quickstart/encrypted_database.html">Working with the encrypted local SQLite database (Flex)</a></li>
<li><a href="http://www.adobe.com/devnet/air/flash/quickstart/encrypted_database_flash.html">Working with the encrypted local SQLite database (Flash)</a></li>
<li><a href="http://www.stage.adobe.com/devnet/air/ajax/quickstart/encrypted_database.html">Working with the encrypted local SQLite database (HTML/JavaScript)</a></li>
</ul>
<p>There are a couple of parts of the new documentation that I think are particularly interesting (although I&#8217;m obviously biased since I wrote it all):</p>
<ul>
<li><a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS34990ABF-C893-47ec-B813-9C9D9587A398.html">Considerations for using encryption with a database</a> talks about some of the various reasons you may want to use an encrypted database, and some of the differences in how you might architect your application to account for the desired level of security and privacy.</li>
<li>
<p><a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS61068DCE-9499-4d40-82B8-B71CC35D832C.html">Example: Generating and using an encryption key</a> goes into great depth into one technique for creating an encryption key for your database. You have to provide a ByteArray encryption key to encrypt your database. How you come up with that encryption key can have a big impact on the actual security of your app data.</p>
<p>This was definitely the most involved example I&#8217;ve written for the documentation. the techniques it uses were specified to me by security engineers at Adobe. The documentation goes into lots of detail describing how these techniques are used and why. Both the code and the text went through a series of reviews by engineers and security experts.</p>
<p>I ended up writing the example as a simple UI, plus a class that anyone can just pull into their own app (rather than having to pull apart the example and turn it into something you can use. I&#8217;m also excited to share that <a href="http://mikechambers.com/">Mike Chambers</a> and <a href="http://weblogs.macromedia.com/cantrell/">Christian Cantrell</a> decided that this &#8220;encryption key generator&#8221; class is useful enough that it&#8217;s now included in the <a href="http://code.google.com/p/as3corelib/">open-source ActionScript 3.0 core library (as3corelib) project</a>.</p>
</li>
</ul>
<p>Now that AIR 1.5 is out the door, I&#8217;ve updated my <a href="http://probertson.com/projects/doppler-air-sql-admin-tool/">AIR database admin tool</a> to support encrypted databases (when you try to open an encrypted database it prompts you for an encryption key, which you enter as a Base-64 string). I already mentioned that I wrote the encryption key generator class that&#8217;s now in as3corelib. I&#8217;ve also got at least one more new encrypted database-related open-source project that I&#8217;m about to release&#8230;but I&#8217;ll wait until the MAX &#8220;firehose&#8221; dies down a bit before I write more about that one. =)</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2008/11/18/air-1_5-encrypted-sqlite-database-how-to/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>360&#124;Flex slides for &#8220;AIR SQLite: An optimization conversation&#8221;</title>
		<link>http://probertson.com/articles/2008/08/22/360flex-slides-for-air-sqlite-optimization-conversation/</link>
		<comments>http://probertson.com/articles/2008/08/22/360flex-slides-for-air-sqlite-optimization-conversation/#comments</comments>
		<pubDate>Sat, 23 Aug 2008 00:16:24 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[local SQL database]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=188</guid>
		<description><![CDATA[Updates (Oct. 30, 2008): The video of my presentation has been posted, so I added a link to it at the bottom of this post. Also, I just learned about another AIR-based SQLite admin tool which looks interesting, so I added it to the list of resources even though it&#8217;s obviously not discussed in the [...]]]></description>
			<content:encoded><![CDATA[<p class="editornote">Updates (Oct. 30, 2008): The video of my presentation has been posted, so I added a link to it at the bottom of this post. Also, I just learned about another AIR-based SQLite admin tool which looks interesting, so I added it to the list of resources even though it&#8217;s obviously not discussed in the presentation.</p>
<p>As I mentioned briefly before, this week I presented at the 360|Flex San Jose (August 2008) conference. My presentation was titled &#8220;Adobe AIR SQLite: An optimization conversation.&#8221; As I mentioned in the presentation, the term &#8220;optimization&#8221; could mean a few different things &#8212; for example, optimization meaning improving performance, or optimization meaning improving developer productivity. While my presentation focused mostly on the first type of optimization, I included suggestions for tools, libraries, and strategies that fall in the &#8220;developer productivity&#8221; type of optimization as well.</p>
<p>Anyway, as always I&#8217;m happy to make my presentation materials available. Here are the slides (with some notes) from my presentation:</p>
<p><a href="/resources/2008/08/22/air_sqlite_optimization_slides.zip">&#8220;Adobe AIR SQLite: An optimization conversation&#8221; slides</a> (PDF in .zip - 504kb)</p>
<p>I don&#8217;t really have any specific code examples, apart from what&#8217;s in the slides, so there&#8217;s no &#8220;source code&#8221; download. However, I did link to a lot of external tools and resources (including a few of my own). To save you the trouble of digging into the PDF, here are the links:</p>
<p>Tools</p>
<ul>
<li><a href="http://coenraets.org/blog/2008/02/air-based-sqlite-admin-updated-for-beta-3/">Cristophe Coenraets&#8217; &#8220;SQLite Admin&#8221;</a></li>
<li><a href="/projects/doppler-air-sql-admin-tool/">My tool for testing queries</a></li>
<li><a href="http://www.dehats.com/drupal/?q=node/59">&#8220;Lita&#8221; by David Deraedt</a> (I learned about this one after the presentation, so it&#8217;s not discussed in my slides/video, but I thought it&#8217;d be worth mentioning anyway.)</li>
</ul>
<p>Application architecture/patterns/libraries</p>
<ul>
<li><a href="http://www.peterelst.com/blog/2008/04/07/introduction-to-sqlite-in-adobe-air/">SQLite MXML wrapper classes</a> (Peter Elst)</li>
<li><a href="http://www.brandonellis.org/?p=49">Data access layer</a> (Brandon Ellis)</li>
<li><a href="http://code.google.com/p/asqlib/">asqlib SQL statement generator</a> (Miran Loncaric)</li>
<li>&#8220;Command&#8221; classes (me) as <a href="/projects/addressbook/">demonstrated by my AddressBook sample application</a></li>
<li><a href="http://code.google.com/p/air-activerecord/">AIR ActiveRecord source</a> and <a href="http://jacwright.com/blog/79/air-activerecord-is-open-source/">blog post explaining its usage</a> (Jacob Wright)</li>
<li><a href="http://www.ericfeminella.com/blog/2008/06/22/air-cairngorm-20/">AIR SQLite Cairngorm services</a> (Eric Feminella)</li>
<li>Connection and statement pools, mentioned (with source code) in the article <a href="http://www.adobe.com/devnet/air/flex/articles/air_sql_operations.html">User experience considerations with SQLite operations</a> (Daniel Rinehart)</li>
</ul>
<p>Finally, as you may have heard, Adobe sponsored the recording of every presentation at 360|Flex, and they&#8217;re all going to be made available free of charge via a channel in Adobe Media Player. They&#8217;re rolling them out in phases, <span class="cut">and mine isn&#8217;t available yet. When it is, I&#8217;ll update this post with the video as well.</span> Update: the video is <a href="http://onflash.org/ted/2008/10/360flex-sj-2008-air-sqlite-optimization.php">now available on Ted Patrick&#8217;s blog</a> as well as in Adobe Media Player.</p>
<p>In the mean time, 360|Flex was full of awesome presentations. I wasn&#8217;t able to get to all the ones I wanted to see, due to conflicts and me trying to finish up preparation for my presentation. So I&#8217;m going to be spending some time watching many of those videos as well. If you&#8217;d like to see the videos, Ted Patrick has posted instructions on his blog:</p>
<p><a href="http://www.onflex.org/ted/2008/08/360flex-sessions-media-rss-feed.php">How to view 360|Flex San Jose 8/08 session videos in Adobe Media Player</a></p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2008/08/22/360flex-slides-for-air-sqlite-optimization-conversation/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Slides and files for &#8220;AIR, Windows, Menus, and the System Tray&#8221;</title>
		<link>http://probertson.com/articles/2008/06/04/slides-and-files-for-air-windows-menus-and-the-system-tray/</link>
		<comments>http://probertson.com/articles/2008/06/04/slides-and-files-for-air-windows-menus-and-the-system-tray/#comments</comments>
		<pubDate>Wed, 04 Jun 2008 23:24:29 +0000</pubDate>
		<dc:creator>Paul Robertson</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Articles by Paul]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://probertson.com/?p=174</guid>
		<description><![CDATA[As I&#8217;ve mentioned before, a couple of weeks ago at the Webmaniacs conference I presented a session titled &#8220;Adobe AIR: Windows, Menus, and the System Tray&#8221; (and I also presented the same material in a partially different form over the course of two SilvaFUG meetings. The presentation covers those three aspects of Adobe AIR, specifically [...]]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;ve mentioned before, a couple of weeks ago at the <a href="http://webmaniacsconference.com/">Webmaniacs conference</a> I presented a session titled &#8220;Adobe AIR: Windows, Menus, and the System Tray&#8221; (and I also presented the same material in a partially different form over the course of two <a href="http://silvafug.org/">SilvaFUG</a> meetings. The presentation covers those three aspects of Adobe AIR, specifically using Flex components when they&#8217;re available. The coverage is pretty thorough in the broad sense, plus it talks about many of the issues you might run into working with these aspects of AIR.</p>
<p>In all those presentations I promised to make my slides and code available. For those of you who attended my presentations these are a long time coming; for those who attended my session at Webmaniacs/Flexmaniacs, these are also somewhat overdue.</p>
<p>In any case, after deadlines, conference, and illness, here are the slides and files for my Webmaniacs session &#8220;Adobe AIR: Windows, Menus, and the System Tray&#8221; (and my two SilvaFUG presentations that were based on that session):</p>
<ul>
<li><a href="http://probertson.com/resources/2008/06/04/air_windows_menus_system_tray_presentation.zip">&#8220;Adobe AIR: Windows, Menus, and the System Tray&#8221; slides and files</a> (2.4 MB .zip)</li>
</ul>
<p>The .zip file contains three files and a folder:</p>
<ul>
<li>Webmaniacs 2008 Slides for presentation.pdf: PDF &#8220;notes pages&#8221; printout of my presentation &#8212; each page contains one slide plus any notes that I added.</li>
<li>Exercises.pdf: Since this is a &#8220;hands-on&#8221; presentation I created this document that contains step-by-step instructions for all the exercises. Using this plus the files below you should be able to work through all the exercises for the session.</li>
<li>Code Snippets for exercises.txt: While all the code listings for the exercises are available in the PDF, a few of them are really long. In any case, if you&#8217;d rather copy and paste instead of type as you work through the exercises you can get the code from this file.</li>
<li>Exercises_workspace_start/: A Flex Builder workspace with the &#8220;starting state&#8221; of some of the exercises for the session. Most of the exercises just start from a blank screen or continue a previous exercise, but for a few I set up the UI ahead of time to save time, and those files are in this folder.</li>
</ul>
<p>Enjoy! As always, please leave comments and feedback.</p>
]]></content:encoded>
			<wfw:commentRss>http://probertson.com/articles/2008/06/04/slides-and-files-for-air-windows-menus-and-the-system-tray/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
