<?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>kuwamoto.org &#187; flex</title>
	<atom:link href="http://kuwamoto.org/category/flex/feed/" rel="self" type="application/rss+xml" />
	<link>http://kuwamoto.org</link>
	<description>music, technology, interfaces, people</description>
	<lastBuildDate>Mon, 19 Jul 2010 20:21:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>The dark side of software as a service</title>
		<link>http://kuwamoto.org/2007/10/18/the-dark-side-of-software-as-a-service/</link>
		<comments>http://kuwamoto.org/2007/10/18/the-dark-side-of-software-as-a-service/#comments</comments>
		<pubDate>Thu, 18 Oct 2007 19:19:19 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/10/18/the-dark-side-of-software-as-a-service/</guid>
		<description><![CDATA[During the 80s, Sun developed a networked filesystem and it became kind of a fad to use dumb-ish Unix workstations with all of your information stored on the network. At the time, I remember someone describing this trend by saying &#8220;it&#8217;s like using a normal computer, except that every once in a while, a server [...]]]></description>
			<content:encoded><![CDATA[<p>During the 80s, Sun developed a networked filesystem and it became kind of a fad to use dumb-ish Unix workstations with all of your information stored on the network. At the time, I remember someone describing this trend by saying &#8220;it&#8217;s like using a normal computer, except that every once in a while, a server you&#8217;ve never heard of goes down, and you can&#8217;t access your files anymore&#8221;.</p>
<p>Fast forward to 2007. I happen to have multiple computers at home, so I&#8217;ve been using Google Docs to store some of my critical information so that I don&#8217;t have to worry about which computer I&#8217;m using. And.. guess what? Google Docs is completely hosed right now (at least for me).</p>
<p>It&#8217;s a weird feeling to not be able to access my own data until someone else fixes their problem. Maybe I should have thought about that before putting my data in the cloud&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/10/18/the-dark-side-of-software-as-a-service/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Quick analysis of Adobe and Buzzword</title>
		<link>http://kuwamoto.org/2007/10/01/quick-analysis-of-adobe-and-buzzword/</link>
		<comments>http://kuwamoto.org/2007/10/01/quick-analysis-of-adobe-and-buzzword/#comments</comments>
		<pubDate>Mon, 01 Oct 2007 18:02:07 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/10/01/quick-analysis-of-adobe-and-buzzword/</guid>
		<description><![CDATA[You may have already heard about Adobe&#8217;s acquisition of Virtual Ubiquity, the company that makes Buzzword. Being an Adobe fan and shareholder, I am excited. Rick Treitman and his gang are a smart, experienced group, and the software is simply amazing. That having been said, I have a number of concerns. Maybe concerns is too [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://scobleizer.com/2007/09/30/adobe-joins-rest-of-industry-in-going-for-microsofts-throat/">You may</a> <a href="http://radar.oreilly.com/archives/2007/09/adobe_acquires_buzzword.html">have already</a> <a href="http://blog.wired.com/business/2007/10/virtual-ubiquit.html">heard</a> about Adobe&#8217;s acquisition of <a href="http://www.virtub.com/">Virtual Ubiquity</a>, the company that makes Buzzword. Being an Adobe fan and shareholder, I am excited. Rick Treitman and his gang are a smart, experienced group, and the software is simply amazing.</p>
<p>That having been said, I have a number of concerns. Maybe concerns is too strong. Let&#8217;s put it this way. I have some hopes about how Adobe goes about this.</p>
<p><strong>I hope they find a way to make Buzzword available freely to everyone instead of just trying to sell to corporations.</strong> There was a bank robber by the name of Willie Sutton, who when asked why he robbed banks, replied: &#8220;That&#8217;s where the money is.&#8221; In a sense, this is why companies try to sell software to large corporations.</p>
<p>The most likely scenario that I can imagine is that they try to put Buzzword together with Acrobat and their newly announced Share product into a sort of office suite that they sell at relatively low cost (~5k?) to corporations. Why do I worry about this?</p>
<ol>
<li>Online applications are a potentially disruptive technology, but only when combined with easy availability. Look at the inroads that Google docs has already made. That application looks like a toy compared with Buzzword (no offense to Sam and Steve and the rest of the Google docs gang). But if Buzzword becomes a behind-the-firewall application that only large enterprises purchase, it won&#8217;t get the momentum it needs to move forward.</li>
<li>In the enterprise, a better product is not necessarily the most important thing, and Adobe is not yet a company that has a proven track record of selling to enterprises. That&#8217;s not to say that Adobe couldn&#8217;t get there someday, but it&#8217;s hard.</li>
<li>I&#8217;m just speculating about pricing, but a mid-priced (5k?) product is a very difficult product to sell. It&#8217;s not expensive enough to warrant a salesforce, but it&#8217;s too expensive for people to try out and adopt virally.</li>
</ol>
<p>In general, I am usually skeptical of freemium models, but in this case, I think it&#8217;s the right one. (free product + premium offerings + expensive software sales for enterprises).</p>
<p><strong>I hope Adobe doesn&#8217;t stretch itself too thin by trying to do too many things.</strong> Let&#8217;s count the fundamental shifts that Adobe is trying to undergo, all at the same time:</p>
<ol>
<li>Become a platform company.</li>
<li>Become a technology provider to the mobile industry.</li>
<li>Become an enterprise software company.</li>
<li>Become a company that delivers software as a service.</li>
</ol>
<p>Any one of these is potentially transformative, and very difficult to achieve. Trying to do it all is very scary. Maybe Adobe will pull it off, but I would feel more comfortable if the company was trying to do fewer things.</p>
<p><strong>I hope Adobe finds a way for the Virtual Ubiquity guys to continue working as if they were at a startup.</strong> Even when everyone is doing everything right, organizational dynamics tend to change when a smaller company is absorbed inside of a larger one. And this space right now is going to get so competitive that I would rather bet on a small startup than a large company. Or better yet, I hope they can harness the power of both.</p>
<h2 class="separator">~</h2>
<p>So those are my hopes. Overall, I am very bullish. Buzzword is an amazing piece of software, and the Virtual Ubiquity team is outstanding. Adobe leadership is smart and determined. The space is undeniably exciting. I am 100% sure that in 10 years, the way that people use productivity software will have completely changed. So Adobe is getting into a very exciting game with a great product. There is a lot of competition out there, and Adobe has a number of challenges ahead. I hope they come out on top.</p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/10/01/quick-analysis-of-adobe-and-buzzword/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Leaving Adobe</title>
		<link>http://kuwamoto.org/2007/09/17/leaving-adobe/</link>
		<comments>http://kuwamoto.org/2007/09/17/leaving-adobe/#comments</comments>
		<pubDate>Mon, 17 Sep 2007 17:29:31 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/09/17/leaving-adobe/</guid>
		<description><![CDATA[Hi folks. As it turns out, I have decided to leave Adobe. The reasons are complicated, but my decision was somewhat sudden and unexpected, so I am not quite sure what I&#8217;ll be doing next. If you have any ideas for me, let me know! For the time being, I won&#8217;t be posting much until [...]]]></description>
			<content:encoded><![CDATA[<p>Hi folks.</p>
<p>As it turns out, I have decided to leave Adobe. </p>
<p>The reasons are complicated, but my decision was somewhat sudden and unexpected, so I am not quite sure what I&#8217;ll be doing next. If you have any ideas for me, let me know! For the time being, I won&#8217;t be posting much until I figure out what I&#8217;ll be doing.</p>
<p>Thanks to all the great people I met along the way. It has been tremendous fun. I will be rooting for Flex from the sidelines.</p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/09/17/leaving-adobe/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Introducing the FlexibleContainer component (aka Advanced ActionScript Refactoring &#8211; Step 3)</title>
		<link>http://kuwamoto.org/2007/05/17/introducing-the-flexiblecontainer-component-aka-advanced-actionscript-refactoring-step-3/</link>
		<comments>http://kuwamoto.org/2007/05/17/introducing-the-flexiblecontainer-component-aka-advanced-actionscript-refactoring-step-3/#comments</comments>
		<pubDate>Thu, 17 May 2007 18:55:11 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/05/17/introducing-the-flexiblecontainer-component-aka-advanced-actionscript-refactoring-step-3/</guid>
		<description><![CDATA[We&#8217;re now ready for our final step. We started with something that looked like this, and we are going to end up with something that looks like this. As you can see, the layout of the container is assignable at runtime. After step 2, there was very little refactoring to do. I removed the DragTile [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re now ready for our final step. We started with something that looked like <a href="http://examples.kuwamoto.org/DragTile/DragTile_step0/DragDrop.html">this</a>, and we are going to end up with something that looks like <a href="http://examples.kuwamoto.org/DragTile/DragTile_step3/DragDrop.html">this</a>. As you can see, the layout of the container is assignable at runtime.</p>
<p>After <a href="http://kuwamoto.org/2007/05/16/advanced-actionscript-refactoring-step-2/">step 2</a>, there was very little refactoring to do. I removed the DragTile class once and for all, and I added styles back in. The way that the Flex styling mechanism works, you can implement styles for non UIComponents, and that&#8217;s what I did. Each Layout object can have its own styles.</p>
<p>I created another concrete layout called CircleLayout to make sure that the layout was actually assignable at runtime. This exposed a few bugs, which I fixed. I factored out the common code between TileLayout and CircleLayout into a common concrete superclass, called Layout. In the end, the inheritance hierarchy for the layout managers looks like this:</p>
<div class="figure"><img src="http://examples.kuwamoto.org/DragTile/LayoutInheritance.png"/></div>
<p>I also &#8220;fixed&#8221; some nitpicky things along the way. I&#8217;ve always thought that the drag/drop feedback was a bit confusing, so I changed the behavior in a subtle way (see if you can spot it!).</p>
<p>In the end, the true test of whether this refactoring worked is to see how easy it is to add a new layout. Whereas the original DragTile code was 600+ lines of code, the CircleLayout code is only about 100 lines of code, and all of it pertains to geometry. There is virtually no code in there to manage renderers or animators or anything like that.</p>
<pre>public class CircleLayout extends Layout
{
// ILayout interface
override public function getMeasuredSize():Point
{
	return getMaxSize();
}

override public function findItemAt(px:Number, py:Number, seamAligned:Boolean):Number
{
	// Can't execute this if we aren't attached to a container.
	if (!container || container.renderers.length == 0)
		return NaN;

	// Get the radius and center of the circle.
	var radius : Number = Math.min(unscaledContainerWidth, unscaledContainerHeight) / 2;
	var hCenter : Number = unscaledContainerWidth / 2;
	var vCenter : Number = unscaledContainerHeight / 2;

	var angle : Number = Math.atan2(py-vCenter, px-hCenter);
	if (angle &lt; 0)
		angle += 2 * Math.PI;

	// figure out the closest "item" by working backwards from the angle to the index, using floating point math.
	var result : Number = container.renderers.length * angle / (2 * Math.PI);

	// depending on whether this is seam aligned, do a ceil or round.
	result = (seamAligned) ? Math.ceil(result) : Math.round(result);

	// do a modulo op to make sure that this is within [0, length-1]. Modulo is the correct
	// operator in this case because this is a circle.
	result %= container.renderers.length;
	return result;
}

override public function generateLayout():void
{
	// Get the radius and center of the circle.
	var radius : Number = Math.min(unscaledContainerWidth, unscaledContainerHeight) / 2;
	var hCenter : Number = unscaledContainerWidth / 2;
	var vCenter : Number = unscaledContainerHeight / 2;

	// Find the max item size.
	var maxSize : Point = getMaxSize();
	var max : Number = Math.max(maxSize.x, maxSize.y);

	// Inset the radius by the max size.
	radius -= max;

	// Loop through the items and position them.
	var length : int = container.renderers.length;
	for (var idx:int = 0; idx &lt; length; idx++)
	{
		var renderer:IUIComponent = container.renderers[idx];
		var target:LayoutTarget = animator.targetFor(renderer);//targets[idx];

		// evenly space each item over 2*pi radians.
		var angle : Number = (2 * Math.PI) * idx / length;

		// position items on a circle.
		target.scaleX = target.scaleY = 1;
		target.item = renderer;
		target.unscaledWidth = renderer.getExplicitOrMeasuredWidth();
		target.unscaledHeight = renderer.getExplicitOrMeasuredHeight();
		target.x = hCenter + radius * Math.cos(angle) - target.unscaledWidth/2;
		target.y = vCenter + radius * Math.sin(angle) - target.unscaledHeight/2;
		target.animate = true;
	}

	// If there is more than one item, and if there is a drag target, nudge the items next to the drag target
	if (length &gt; 1 &amp;&amp; container.dragTargetIndex &gt;= 0 &amp;&amp; container.dragTargetIndex &lt; length)
	{
		// Find the items to the left and right of the target.
		var leftIndex : int = (container.dragTargetIndex + length - 1) % length;
		var rightIndex : int = (leftIndex + 1) % length;

		var leftTarget : LayoutTarget = animator.targetFor(container.renderers[leftIndex]);
		var rightTarget : LayoutTarget = animator.targetFor(container.renderers[rightIndex]);

		// exaggerate the difference between the two targets by a factor of maxSize/2.
		var dx : Number = rightTarget.x - leftTarget.x;
		var dy : Number = rightTarget.y - leftTarget.y;
		var distance : Number = Math.sqrt( dx*dx + dy*dy );

		leftTarget.x -= dx / distance * max/2;
		leftTarget.y -= dy / distance * max/2;
		rightTarget.x += dx / distance * max/2;
		rightTarget.y += dy / distance * max/2;
	}
}

protected function getMaxSize() : Point
{
	// Can't execute this if we aren't attached to a container.
	if (!container)
		return new Point(0, 0);

	// Find the max item size.
	var maxWidth : Number = 0;
	var maxHeight : Number = 0;

	if(container.renderers.length &gt; 0)
	{
		for(var i:int=0;i&lt;container.renderers.length;i++)
		{
			var itemRenderer:IUIComponent = container.renderers[i];
			maxWidth = Math.ceil(Math.max(maxWidth,itemRenderer.getExplicitOrMeasuredWidth()));
			maxHeight = Math.ceil(Math.max(maxHeight,itemRenderer.getExplicitOrMeasuredHeight()));
		}
	}

	return new Point(maxWidth, maxHeight);
}</pre>
<p>Could this be improved? Sure. There are still linkages between the layout and the container that we should probably get rid of. But for now, I think I&#8217;m going to stop. Maybe I&#8217;ll refactor the rest of it away later. :-)</p>
<p>Code for the final version <a href="http://examples.kuwamoto.org/DragTile/DragTile_step3.zip">can be found here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/05/17/introducing-the-flexiblecontainer-component-aka-advanced-actionscript-refactoring-step-3/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Advanced ActionScript Refactoring &#8211; Step 2</title>
		<link>http://kuwamoto.org/2007/05/16/advanced-actionscript-refactoring-step-2/</link>
		<comments>http://kuwamoto.org/2007/05/16/advanced-actionscript-refactoring-step-2/#comments</comments>
		<pubDate>Wed, 16 May 2007 19:51:57 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/05/16/advanced-actionscript-refactoring-step-2/</guid>
		<description><![CDATA[In Step 1, we created a superclass to hold the common logic for all flexible layouts. Now, let&#8217;s change the model from inheritance to composition. My goal in this step was to move all DragTile functionality into a separate helper class, leaving DragTile as just an empty shell. Until now, we have not had to [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-step-1/">Step 1,</a> we created a superclass to hold the common logic for all flexible layouts. Now, let&#8217;s change the model from inheritance to composition. My goal in this step was to move all DragTile functionality into a separate helper class, leaving DragTile as just an empty shell.</p>
<p>Until now, we have not had to worry about the contract between the container and the layout manager. All we did in step 1 was decide which methods belonged in the superclass and the subclass on a somewhat haphazard basis.</p>
<p>Now that we want to move this into a separate helper object, we need to ask ourselves how the main object (the container) needs to communicate with the helper object. A good starting point is to look at the members that the DragTile subclass defines.</p>
<div class="figure"><img src="http://examples.kuwamoto.org/DragTile/step1_DragTile_api.png" /></div>
<p>All of the properties (green dots) seem to be specific to DragTile. Meanwhile, three member functions at the bottom look truly general: measure(), findItemAt(), and generateLayout(). Let&#8217;s use these as our initial interface for ILayout. </p>
<p>Because measure() is a method defined on IUIComponent, It doesn&#8217;t make sense to just move it to a non-UIComponent object. Instead, I decided to define a helper function, getMeasuredSize(), that we call from the measure() function. And thinking through some of the other complexities that might arise, I added an attach() and detach() method so that the layout manager could do some initialization and cleanup whenever it was used. The interface now looks like this:</p>
<div class="figure"><img src="http://examples.kuwamoto.org/DragTile/step2_ILayout_api.png" /></div>
<p>I now had to make this &#8220;real&#8221; by creating a layout property of FlexibleContainer and creating a concrete implementation of ILayout called TileLayout.</p>
<p>How do we get from where we are in step 1 to where we need to get to in step 2? In step 1, DragTile is a subclass of FlexibleContainer. After step 2, we know that there won&#8217;t be a class called &#8220;DragTile&#8221; anymore. </p>
<p>This seems like a hard change to make incrementally, and the whole point of refactoring is to do these changes in small, incremental steps. Which brings me to the next tip.</p>
<p class="innerquote"><strong>Tip 5: </strong> If needed, build temporary scaffolding to make sure your code continues to &#8220;work&#8221; as you refactor.</p>
<p>In this case, I used <strong>both</strong> inheritance and delegation while I was in the middle of the refactoring. In other words, I wrote a little bit of scaffolding code to keep the DragTile class around even after I had created the TileLayout class, and slowly moved code over from one to the other.</p>
<div class="figure">
<img src="http://examples.kuwamoto.org/DragTile/scaffolding.png" /></div>
<p>For those of you who are not familiar with the ideas behind refactoring, this writing of temporary code might seem kind of insane. However, once you get used to it, you will never go back. Big changes are <strong>much</strong> easier to do successfully in small, bite-sized pieces. Sometimes this means writing a few lines of shim code to hold things up as you change things incrementally.</p>
<p>The next step was to move all the functionality out of the DragTile subclass. During this phase, I didn&#8217;t move entire methods. Instead, I dissected methods line by line and moved the correct functionality over to the appropriate class using the following simple rules:</p>
<ul>
<li>If the logic contained in the line of code was &#8220;general&#8221;, it move it to the FlexibleContainer superclass</li>
<li>If the logic contained in the line is specific to tiles, move it to the &#8220;TileLayout&#8221; class</li>
</ul>
<p>This process worked fine for most of the logic, but the styles were a different matter. TileLayout is not a UIComponent, so it doesn&#8217;t participate in the CSS system. Meanwhile, the styles that DragTile defines are specific to tiles (vGap, hGap, etc). While it is possible to have things that are not UIComponents participate in CSS, it takes a lot of work, and I didn&#8217;t feel like tackling it right then.</p>
<p>What I decided to do was to turn off the style functionality temporarily. This brings us to the next tip:</p>
<p class="innerquote"><strong>Tip 6: </strong> When temporarily disabling functionality during a big refactor, be sure to do so in a way that preserves information, ideally through stub functions.</p>
<p>One way to turn off the CSS functionality would have been to comment out the lines of code that refer to CSS and restore them later. The problem with this approach is that it is difficult to make sure that the the code inside your comments continues to be &#8220;correct&#8221; as you move your code around. </p>
<p>To help make sure that the CSS knowledge that was embedded in Ely&#8217;s code didn&#8217;t get lost, I created a stub getStyle() function that always returned NaN. This meant that all of the CSS logic in Ely&#8217;s code was still there and still functioning, but it was attached to a CSS style sheet where nothing was ever defined.</p>
<p>By keeping Ely&#8217;s code alive, it was easy to make sure that I was making the right edits to it as I refactored. As I moved code around, the compiler would remind me if I was doing something terribly wrong. This doesn&#8217;t prevent <strong>all</strong> coding errors, but it helps prevent many of them.</p>
<p>After all this, I was able to move all of the code from the DragTile code into one of the other two classes. The final version of the DragTile class looked like this:</p>
<pre>public class DragTile extends FlexibleContainer
{
	public function DragTile()
	{
		super();

		layout = new TileLayout();
	}
}</pre>
<p>We are now (obviously) at the point where we can get rid of the DragTile object. Code for step 2 <a href="http://examples.kuwamoto.org/DragTile/DragTile_step2.zip">can be found here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/05/16/advanced-actionscript-refactoring-step-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Advanced ActionScript Refactoring &#8211; Step 1</title>
		<link>http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-step-1/</link>
		<comments>http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-step-1/#comments</comments>
		<pubDate>Tue, 15 May 2007 20:02:29 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-step-1/</guid>
		<description><![CDATA[In the intro, we talked about the problem we want to tackle, which is to refactor DragTile to be more flexible. If you haven&#8217;t read it yet, you might want to check it out. Back? Ok. Now, let&#8217;s look at some code. Step 0 &#8211; the starting point The original files for my investigation can [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-intro/">the intro</a>, we talked about the problem we want to tackle, which is to refactor DragTile to be more flexible. If you haven&#8217;t read it yet, you might want to check it out.</p>
<p>Back? Ok. Now, let&#8217;s look at some code.</p>
<h3>Step 0 &#8211; the starting point</h3>
<p>The original files for my investigation can be downloaded from <a href="www.quietlyscheming.com">Ely&#8217;s site,</a> or you can get my <a href="http://examples.kuwamoto.org/DragTile/DragTile_step0.zip">slightly munged version here.</a></h3>
<h3>Step 1 &#8211; pull up the FlexibleContainer superclass</h3>
<p>Even though we said we were going to use composition instead of inheritance to separate these classes, we do this as a first step because it is easier than pulling out a helper class. </p>
<p class="innerquote"><strong>Tip 3:</strong> Always refactor in small steps that leave the external behavior unchanged</p>
<p>The basic procedure is to create a superclass (which I called &#8220;FlexibleContainer&#8221;) and to walk through the DragTile code method by method and property by property to move things to the superclass if it seems appropriate. </p>
<p>I started by moving all of the local variables that seemed &#8220;general&#8221; to the superclass. This included the _items array, the renderers array, and so forth. The variables that seemed specific to the Tile layout were left in the DragTile class. </p>
<p>Because most of these variables were private, moving them to the superclass caused a lot of compile errors, most of which I fixed by moving the appropriate methods to the superclass. </p>
<p>In one case (dragTargetIndex) I needed to create a protected accessor so that the subclass could get at this information. If you want to be a stickler about it, making a private member protected requires some thought. Is this the right way for a subclass to get information from its superclass? In this case, it&#8217;s probably not the right thing. The &#8220;right&#8221; thing is probably to pass the drag information as a parameter during the drag operation. This brings us to the next tip:</p>
<p class="innerquote"><strong>Tip 4:</strong> When refactoring, don&#8217;t try to make it &#8220;perfect&#8221;. Just strive to incrementally improve the code each time you touch it.</p>
<p>Creating a protected accessor here was the quickest way to separate these two classes without overcomplicating the design. We can come back and fix this later after the dust has settled.</p>
<p><span id="more-115"></span></p>
<p>At this point, the FlexibleContainer class and the DragTile class have been completely separated. The outlines look like this.</p>
<p>Original API:</p>
<div class="figure">
<img src="http://examples.kuwamoto.org/DragTile/step0_api.png" />
</div>
<p>After the first refactoring, the new API looks like this. Remember that our goal here is to put all the logic that is specific to a specific layout (Tile) into one class, leaving as much of the general code in the superclass as possible. The DragTile class should be as small as possible (but no smaller!) :</p>
<div class="figure">
<img src="http://examples.kuwamoto.org/DragTile/step1_api.png" />
</div>
<p>Source code for step 1 can be <a href="http://examples.kuwamoto.org/DragTile/DragTile_step1.zip">found here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-step-1/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Making the world better via refactoring &#8211; Intro</title>
		<link>http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-intro/</link>
		<comments>http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-intro/#comments</comments>
		<pubDate>Tue, 15 May 2007 19:02:01 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-intro/</guid>
		<description><![CDATA[I love Ely&#8217;s DragTile component (demo). However, I have always wished that it were easier to extend its behavior to encompass different layouts. To me, that immediately suggests a (big) refactoring. For those of you who have never done refactoring or who don&#8217;t refactor as often as you should, I thought it might be fun [...]]]></description>
			<content:encoded><![CDATA[<p>I <strong>love</strong> Ely&#8217;s <a href="http://www.quietlyscheming.com/blog/components/animated-dragtile-component/">DragTile</a> component <a href="http://demo.quietlyscheming.com/DragTile/DragDrop.html">(demo)</a>. However, I have always wished that it were easier to extend its behavior to encompass different layouts. To me, that immediately suggests a (big) refactoring. For those of you who have never done refactoring or who don&#8217;t refactor as often as you should, I thought it might be fun to walk through this step by step.</p>
<div class="figure">
<a href="http://demo.quietlyscheming.com/DragTile/DragDrop.html"><img src="http://examples.kuwamoto.org/DragTile/DragTile.png" border="0" /></a></div>
<h3>What is refactoring?</h3>
<p><a href="http://c2.com/cgi/wiki?WhatIsRefactoring">Refactoring</a> is the process of incrementally changing the structure of your code without changing the outward functionality. It may seem silly to focus on <strong>not</strong> changing the functionality, but it is actually pretty important.</p>
<p>The idea is that there are two distinct phases of work: coding and refactoring. During coding, you add new functionality. During refactoring, you restructure your code while making sure that it continues to work properly. <strong>Not</strong> changing functionality during refactoring gives you a strong reference point as you make lots of iterative changes to the structure. You know your refactoring was successful if the new code still does what the old code did. </p>
<h3>Refactoring for better reuse</h3>
<p>Usually, you refactor code so that it can be more flexible or more reusable that it currently is. Sometimes, the change that is required is obvious. In other cases, you have to think a little before figuring out how to transform your code. </p>
<p>In this particular case, we want to make it easier to change layouts. Looking at the DragTile code, there is quite a bit that would be the same no matter what the layout is, and relatively little that needs to change with each new layout algorithm. Because the layout algorithm is something that is likely to change in various use cases, it is probably a good idea to isolate this functionality into a separate class.</p>
<p class="innerquote"><strong>Tip 1:</strong> Cleanly separate out the code that you think will need to change often into a separate class.</p>
<p>The most obvious way to divide up the DragTile layout code from the rest of the DragTile code is through inheritance:</p>
<div class="figure">
<img src="http://examples.kuwamoto.org/DragTile/DragTileInherit.png" />
</div>
<p>Splitting things up in this way allows us to create a new subclass with a different layout (say, a circle) while reusing the logic that might be common to both, such as the code to talk to item renderers and do animation.</p>
<p>The other main way to split things up is through composition:</p>
<div class="figure">
<img src="http://examples.kuwamoto.org/DragTile/DragTileComposition.png" />
</div>
<p>In this case, the container delegates to another object in order to do layout. There are a number of advantages to this approach:</p>
<ol>
<li>Using delegates often makes it possible to modify behavior at runtime. After we are finished with this particular refactoring, we should be able to change the layout of one of our containers without reparenting. Woohoo!!</li>
<li>Decomposing larger classes into smaller classes can make it easier to evolve different parts of the system separately as needs change. For example, let&#8217;s say we later decide to split up FlexibleContainer into two classes: one that is lightweight for easy download, and another that is robust, to handle caching, localization, etc. Should &#8220;DragTile&#8221; inherit from the light one or the robust one? If layout is handled through delegation, you may not need to choose.</li>
<li>Composition often allows for greater decoupling. For example, let&#8217;s say you are building a photo organizer module. With the inheritance approach above, it would be difficult to create the module in such a way that the photo module knows absolutely nothing about the layout. With the composition approach, you could provide a default layout (say, Tile), while allowing the user of the module to pass in a different layout if needed.</li>
</ol>
<p>All of this leads to the next tip, which is:</p>
<p class="innerquote"><strong>Tip 2:</strong> Think hard before using inheritance. Composition is almost always a better way to separate out the flexible part of a class from the invariant part.</p>
<p>So now we have a general idea of what we want to separate out, and how we want to do it. We&#8217;ll start digging into actual code in the next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/05/15/making-the-world-better-via-refactoring-intro/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>More thoughts on open source Flex and community</title>
		<link>http://kuwamoto.org/2007/04/25/more-thoughts-on-open-source-flex-and-community/</link>
		<comments>http://kuwamoto.org/2007/04/25/more-thoughts-on-open-source-flex-and-community/#comments</comments>
		<pubDate>Thu, 26 Apr 2007 06:05:30 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/04/25/more-thoughts-on-open-source-flex-and-community/</guid>
		<description><![CDATA[It&#8217;s been interesting reading reactions from folks like Ted Leung and Ryan Stewart on the Flex open source announcement. I imagine that more interesting discussions are going to happen as people slowly digest the news and start digging deeper into what this all means and how it will all work. One of my concerns around [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been interesting reading reactions from folks like <a href="http://www.sauria.com/blog/2007/04/25/adobe-open-sources-flex/">Ted Leung</a> and <a href="http://blogs.zdnet.com/Stewart/?p=353">Ryan Stewart</a> on the Flex open source announcement. I imagine that more interesting discussions are going to happen as people slowly digest the news and start digging deeper into what this all means and how it will all work.</p>
<p>One of my concerns around open sourcing Flex is around how we stay disciplined about what goes into the framework. As it stands, it is quite difficult for the Flex engineers to balance between the things they would like to add to the framework versus practical considerations like download size and runtime performance. We are going to make sure we don&#8217;t get bogged down in feature-itis or &#8220;design by committee&#8221;.</p>
<p>One thing that I think could help is a clearly articulated philosophy about what Flex is, what Flex is not, and how it should evolve going forward. One community that has done a particularly good job at this is the <a href="http://microformats.org/about/">microformats community</a>. In many ways, the microformats movement grew up as a reaction to some of the more ambitious movements around adding semantics to the web. Because of this reactionary nature, the value of practical, small, incremental steps was greatly appreciated by everyone in that community.</p>
<p>As we open up Flex development to the world, my hope is that we can build a strong, core philosophy around Flex that is similarly grounded in keeping things practical, small, and focused. </p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/04/25/more-thoughts-on-open-source-flex-and-community/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flex SDK being open sourced</title>
		<link>http://kuwamoto.org/2007/04/25/flex-sdk-being-open-sourced/</link>
		<comments>http://kuwamoto.org/2007/04/25/flex-sdk-being-open-sourced/#comments</comments>
		<pubDate>Thu, 26 Apr 2007 04:06:30 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/04/25/flex-sdk-being-open-sourced/</guid>
		<description><![CDATA[I don&#8217;t usually glom onto these news postings, on the theory that you already have plenty of blog sources for this kind of stuff. However, this is a topic that is near and dear to my heart, so I thought I&#8217;d write a little about it. Today, we announced that we are going to open [...]]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t usually glom onto these news postings, on the theory that you already have plenty of blog sources for this kind of stuff. However, this is a topic that is near and dear to my heart, so I thought I&#8217;d write a little about it.</p>
<p>Today, we announced that we are going to open source the Flex SDK under the Mozilla public license. in my mind, this is just another step in our continued push to open up our platform to make sure that our community can feel confident in building their applications (and in many cases, their businesses!) on top of it.</p>
<p>I&#8217;m obviously pretty excited about this, which begs the question: should we have open sourced it earlier? I don&#8217;t think so. We have gone through quite a bit of change between Flex 1.0 to where we are now (remember ActionScript 2? remember the old pricing model? remember the huge API shift from 1.5 to 2.0?) and IMHO, it might have been more difficult to make some of the radical changes we did if we were following a completely open process.</p>
<p>Now, the situation is quite different. The Flex community has reached critical mass and is growing daily. The Flex SDK codebase has had most of the rough edges smoothed off of it, and we are at a point where we no longer expect huge API changes in our existing core API. Most importantly, it feels like the right time to invite the community to become part of defining what Flex is.</p>
<p>We are still working out the details, but I think this is pretty exciting. More details can be found <a href="http://www.adobe.com/go/opensourceflex">here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/04/25/flex-sdk-being-open-sourced/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Asynchronous calls explained</title>
		<link>http://kuwamoto.org/2007/04/25/asynchronous-calls-explained/</link>
		<comments>http://kuwamoto.org/2007/04/25/asynchronous-calls-explained/#comments</comments>
		<pubDate>Wed, 25 Apr 2007 17:23:42 +0000</pubDate>
		<dc:creator>sho</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://kuwamoto.org/2007/04/25/asynchronous-calls-explained/</guid>
		<description><![CDATA[Someone emailed me recently to ask about a case of asynchronous calls that I think is fairly common. At the risk of opening up the floodgates (no, you cannot email me every time you have a Flex question!!!), I think it&#8217;s worth answering publicly because it probably trips a lot of people up. Note that [...]]]></description>
			<content:encoded><![CDATA[<p>Someone emailed me recently to ask about a case of asynchronous calls that I think is fairly common. At the risk of opening up the floodgates (no, you cannot email me every time you have a Flex question!!!), I think it&#8217;s worth answering publicly because it probably trips a lot of people up. </p>
<p>Note that this is a more basic (and common?) case than the stuff I was talking about earlier. For more advanced solutions, see <a href="http://kuwamoto.org/2006/05/16/dealing-with-asynchronous-events-part-1/">here,</a> <a href="http://kuwamoto.org/2006/05/16/dealing-with-asynchronous-events-part-2/">here</a> and <a href="http://kuwamoto.org/2006/05/19/dealing-with-asynchronous-events-part-3/">here.</a></p>
<blockquote><p>From: XXXX@XXXXXXXXX</p>
<p>I have two loops.  One grabs an Xml file that contains a list of a bunch of Xml files I use to layout data to print.  (What I am doing is printing a set of documents).</p>
<p>So, as I loop through each, I call the URLRequest to grab the Xml to process and register the Complete event (which takes care of processing the Xml).</p>
<p>So if I have 20 documents, I find only the last one gets handled, the rest are ignored.  I am guessing this is because the thread does not stop.  I am thinking synchronous events are not an option either.</p>
<p>What I want to happen is one fires, it lets me do what I want to do, then the next one fires.  Or alternatively, one is processed, then the next one is processed.</p>
<p>Am I making sense?</p></blockquote>
<p>Yes, it does make sense, and I bet a lot of people get stuck on this. So here&#8217;s the answer.</p>
<p><span id="more-110"></span></p>
<h2 class="separator">~</h2>
<h3>The problem</h3>
<p>Let&#8217;s take a look at the following (simplified version) of the code that was sent to me:</p>
<pre>var loader : URLLoader = new URLLoader();
public function loadItAll(tree: XML)
{
    for each (var elem:XML in tree.elements())
    {
        loader.load(new URLRequest(elem.text().toString()));
        loader.addEventListener(Event.COMPLETE, onComplete);
    }
}

public function onComplete(event: Event)
{
    myXMLResult = new XML( loader.data );
    // handle the URL request here
}
</pre>
<p>The expectation here was that onComplete() would be called n times, one for each URL request. As it turned out, onComplete() was only called once.</p>
<p>So what&#8217;s happening?</p>
<p>Flash network calls are asynchronous, which means that the loader.load() call doesn&#8217;t happen right away. In fact, <strong>all the code in the for loop runs</strong> before any of the network calls happen.</p>
<p>To understand the order of events, it might be easier to use a physical analogy, like asking a valet to go get a car. (It&#8217;s easier for me, anyway. I think it&#8217;s because of the way human brains have evolved &#8212; it&#8217;s a lot easier for me to think about physical things like people and vehicles, not network calls and data packets!)</p>
<p>Imagine the following pseudocode.</p>
<pre>public function doItAll()
{
    for each (person in line)
    {
        ask the valet to go get the person's car.
        ask the valet to say "car ready" when the car is ready.
    }
}

public function carReady(car: Car)
{
    get in the car and drive home.
}
</pre>
<p>Remember that all of the ActionScript code has to finish running before the asynchronous methods start executing. In the above psuedocode, the valet takes all the requests for all the people in line <b>before</b> going to get a single car. </p>
<p>As it turns out, this valet is only capable of returning one car at a time (not surprising) and more importantly, can only remember one request at a time. Ack! So when we went through the line of people and asked each one of them for their ticket, he only remembered the last request! This is the reason that only one car is returned.</p>
<p>There are a few ways to fix this problem:<br />
1) Hire lots of valets (one for each person in line).<br />
2) Don&#8217;t ask for the next car until the first car is back.<br />
3) Teach the valet to remember multiple requests.</p>
<p>Let&#8217;s stop our analogy right here and get back to our original psuedocode for each of these three strategies.</p>
<h3>Strategy 1: Hire lots of valets</h3>
<p>This is probably the simplest strategy, but it doesn&#8217;t work in all cases. Here is the pseudocode:</p>
<pre>public function loadItAll(tree: XML)
{
    for each (var elem:XML in tree.elements())
    {
        var loader : URLLoader = new URLLoader();
        loader.load(new URLRequest(elem.text().toString()));
        loader.addEventListener(Event.COMPLETE, onComplete);
    }
}

public function onComplete(event: Event)
{
    var loader = URLLoader(event.target);
    loader.removeEventListener(Event.COMPLETE, OnComplete);

    myXMLResult = new XML( loader.data );
    // handle the URL request here
}
</pre>
<p>Notice that every time through the loop, we are creating a new URLLoader. Because of this, we have to make sure we are referring to the correct URLLoader during the onComplete() method. We do this by getting the URLLoader from the target of the complete event that was fired.</p>
<p>It&#8217;s probably also a good idea to remove the event listener to avoid having lots and lots of URLLoader objects created without being destroyed. </p>
<p>This strategy will not work if you need to have items loaded in a certain order, or if spawning lots and lots of URLLoaders will cause a performance problem. (In this case, I think this is throttled by the network stack, so I think you are OK. In other cases, it might not be OK).</p>
<h3>Strategy 2: Don&#8217;t ask for the next car until the first car is back</h3>
<p>This is probably the next simplest strategy.</p>
<pre>var loader : URLLoader = new URLLoader();
var list : XMLList;
var i : int;

public function loadItAll(tree: XML)
{
    loader.addEventListener(Event.COMPLETE, onComplete);
    list = tree.elements();
    i = 0;
    loadNext();
}

public function loadNext()
{
    if (i < list.length())
    {
        var elem: XML = list[i++];
        loader.load(new URLRequest(elem.text().toString()));
    }
}

public function onComplete(event: Event)
{
    myXMLResult = new XML( loader.data );
    // handle the URL request here

    loadNext();
}
</pre>
<p>The cons of this method are that none of the network operations are happening in parallel, which can be a performance problem. Also, the logic to walk through the list of entires is scattered throughout multiple methods. You can clean this up using state objects or other strategies, but you quickly get to strategy three, which is:</p>
<h3>Strategy 3: Teach the valet to remember multiple requests</h3>
<p>This is the most work, and you can make this as complex as you like. The benefits are that it centralizes the handling of this loop into a single place.</p>
<pre>class MyLoader extends URLLoader()
{
   override public function load(string: URL)
   {
       // put stuff on a queue
       // if there are no pending requests, call loadNext();
   }

   private function loadNext()
   {
       // remove one thing from the queue and load it
   }

   private function onComplete()
   {
       // dispatch the COMPLETE event
       // initiate the next load
   }
}</pre>
<pre>var loader : MyLoader = new MyLoader();
public function loadItAll(tree: XML)
{
    loader.addEventListener(Event.COMPLETE, onComplete);

    for each (var elem:XML in tree.elements())
    {
        loader.load(new URLRequest(elem.text().toString()));
    }
}

public function onComplete(event: Event)
{
    myXMLResult = new XML( loader.data );
    // handle the URL request here
}
</pre>
<p>There are a number of things to worry about here, such as whether it is OK to be returning data in loader.data, given that the same object is being reused for multiple requests. Probably the right thing to do is to create a token object (using the AsyncToken class?) that holds all the information and to pass that to the user. And then you can start building callback mechanisms into that AsyncToken. And then... well, it gets more and more complicated.</p>
<p>Details of some more advanced solutions around this can be found <a href="http://kuwamoto.org/2006/05/16/dealing-with-asynchronous-events-part-1/">here,</a> <a href="http://kuwamoto.org/2006/05/16/dealing-with-asynchronous-events-part-2/">here</a> and <a href="http://kuwamoto.org/2006/05/19/dealing-with-asynchronous-events-part-3/">here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kuwamoto.org/2007/04/25/asynchronous-calls-explained/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
	</channel>
</rss>
