<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4822684209473355816</id><updated>2011-10-04T20:41:23.049+01:00</updated><category term='flash'/><category term='language fundamentals'/><category term='as3-signals'/><category term='timeline'/><category term='security'/><category term='robotlegs'/><category term='AIR'/><category term='TDI'/><category term='AS3'/><category term='ECMAScript'/><category term='modeller'/><category term='UML'/><category term='textmate'/><category term='aviary'/><category term='undocumented'/><category term='flex'/><category term='Google code'/><category term='PureMVC'/><category term='types'/><category term='mvc'/><category term='interface'/><category term='Model view controller'/><category term='processes'/><category term='as3 tdd testing process mocking samples wtf'/><category term='identity'/><category term='MDI'/><category term='saffron'/><category term='enterprise applications'/><category term='UML tool'/><category term='as3 tdd'/><category term='as3 tdd testing process'/><category term='actionscript'/><category term='class swatches'/><category term='as3 DRY robotlegs'/><category term='modular'/><category term='open-source'/><category term='asdoc'/><title type='text'>flAir :: flashFlexAir</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-4235567748308112390</id><published>2010-10-28T12:56:00.011+01:00</published><updated>2010-10-28T13:58:26.581+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='as3 tdd'/><title type='text'>TDD: The Starwars Answer vs The MacGyver Principle</title><content type='html'>&lt;i&gt;&lt;span class="Apple-style-span"  style="color:#666666;"&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="color:#666666;"&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;"But what if you write a bug - like a typo or something - into the test? I mean, your tests aren't going to be perfect, are they?"&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a genuine question someone - understandably - asked me earlier this week when I was introducing them to the idea of TDD.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have two answers to this question:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;1) The math answer:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If P(Error) is the probability of any line of code you write containing an error, and you write t lines of test code and tn lines of production code, where n is greater than 1, then bugs in both tests and production code can only slip through when they coincide, and you will fix tn bugs in production code for every t bugs in the tests. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And as P(A + B) = P(A) * P(B) then you vastly reduce the number of undetected bugs caused by genuine code errors - eg accidental assignment, wrong operations, wrong variable names etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you don't speak Math, the outcome is many, many fewer small bugs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;2) The Starwars Answer:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;i&gt;"These are not the bugs you are looking for."&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;No - really, typos and wrong negatives are cool to find, and do cause many wasted hours debugging, but this isn't why I do TDD.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;TDD is most powerful when it really hurts. The pain comes because you realise that you have written, or planned to write, some code that is hard to test.  TDD pokes you right in the coupling. It stabs you with your own &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;statics&lt;/b&gt;&lt;/span&gt; and shoves your crappy assumptions right...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;... you get the idea?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you write a test for a class, or a unit of functionality, you are trying to do that outside of the application. So all those hooks and shortcuts and bits of spaghetti that seem so handy inside your app swiftly start to look like what they are: problems.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But there's something TDD brings to your attention that's even harder to swallow...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;TDD goes against the MacGyver principle&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;TDD exposes to you the numerous pathways through your code. If you're testing something as simple as a form with a set of radio buttons, you have to test every possible option for that radio button selection. You imagined you were going to write half a dozen tests for this class and suddenly you've got 15. And you can still think of more special cases that aren't covered.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a head-fuck because we like to pretend, to ourselves, that what we're trying to do is much, much easier and less complex than it actually is. I suspect there are very few genuine pessimists* in programming. We are self-selected &lt;a href="http://en.wikipedia.org/wiki/MacGyver"&gt;MacGyver&lt;/a&gt; types with a tendency to see the solutions in any situation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This process relies on the confidence trick of pretending to yourself that what you're undertaking is pretty straightforward, really. We &lt;i&gt;have&lt;/i&gt; to turn a blind eye to the factorial expansion of pathways through our code presented by each new 'tiny' feature, because the alternative is lying awake at night wondering whether we've really covered every important combination of user actions, and knowing that we're never going to hit the deadline.*&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Many flash programmers are just as badass as MacGyver. They bravely code ahead, pushing to the side the concept of failure - they know they can cross between these two structures using only a coathanger and some magic strings (static) because there is no room for any other possibility.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And hell, it works out a lot of the time. We all built some awesome stuff in as1 when we didn't even have compile-time-checking or type safety. But if you're still MacGuyver coding today, I have one piece of advice: &lt;i&gt;Don't look down.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;* There are plenty of us who are cynical, but I think that's distinct from pessimism. We probably believe there are solutions to most problems, but that people are too damn stupid / greedy to allow them to be implemented.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;** In reality, nobody ever hits the deadline with MacGuyver coding, but they at least agree to the deadline, which most of the time is all the boss is looking for.  With TDD, nobody agrees to the deadline the boss was hoping for. As always, TDD just shifts that pain forward in the timeline.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-4235567748308112390?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/4235567748308112390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=4235567748308112390' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4235567748308112390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4235567748308112390'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2010/10/tdd-starwars-answer-vs-macgyver.html' title='TDD: The Starwars Answer vs The MacGyver Principle'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-6858690028484969811</id><published>2010-10-15T14:30:00.007+01:00</published><updated>2010-10-15T15:30:54.252+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='as3 DRY robotlegs'/><title type='text'>Don't dehydrate your code</title><content type='html'>&lt;b&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;DRY &lt;/b&gt;&lt;i&gt;(don't repeat yourself)&lt;/i&gt; is one of the first principles you learn as a fledgling coder.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you build your first loop, you're embracing DRY, and all the wonderful code-shrinking that comes with it. And it feels good, and we're taught to seek out repetition as a terrible code smell, and do away with it as soon as possible.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;But it's possible to be &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;i&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;too&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt; DRY - no, really, it is.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When considering repetition for refactoring, there are two different questions we can ask:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;'Are these two blocks of code the same?'&lt;/li&gt;&lt;li&gt;'Do these two blocks of code serve the same purpose?'&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The different questions can lead to different answers for the same blocks of code. If the answer to question 2 is 'no' then you potentially create another, harder, refactor down the line, when you realise that the operation needs to change for one case, and not for another.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These &lt;i&gt;&lt;b&gt;too-dry&lt;/b&gt;&lt;/i&gt; refactorings leave their own particular code smell - &lt;b&gt;optional parameters&lt;/b&gt;. They're not &lt;i&gt;always&lt;/i&gt; a sign of overly-dry code - the robotlegs context takes an useful optional parameter for 'autostartup' -  but when the optional parameter is littered through the code inside the function, it can be a sign that your code has become dehydrated and you'd be better off splitting it back out again - and either living with a little repetition or slicing the functionality up differently.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;We make a similar call when we make decisions about inheritance and interfaces. &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;ClassB might have all the same functions as ClassA, and a few extras of its own, but unless ClassB truly &lt;b&gt;"is a"&lt;/b&gt; ClassA, then there's no reason why the two should evolve together in the future. Better to tolerate the repetition because it correctly represents the cognitive model behind the application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Similarly, unless ClassA and ClassB share &lt;b&gt;obligations&lt;/b&gt;, and could potentially &lt;b&gt;stand in&lt;/b&gt; for each other without your application logic losing sense, they shouldn't implement the same interface. &lt;i&gt;Even if they have the same functions. Yes, e&lt;/i&gt;&lt;i&gt;ven if they have the same functions.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;Shut up with the "it's less code" thing&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;Of course all of this requires us to recognise that &lt;b&gt;&lt;i&gt;"&lt;/i&gt;&lt;/b&gt;&lt;i&gt;&lt;b&gt;It's less code"&lt;/b&gt;&lt;/i&gt; is never a refactoring justification in itself. Often, great refactorings create more code, not less. The objective is always to make your application easier to maintain, change and grow. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So - unless you're writing your code for a programmable calculator from the 1980s, any time you hear yourself think or say (or write, I see this a ton on the robotlegs support forum) "but it's less code this way..." just give yourself a little slap. There are often good reasons to take the fewer-classes approach, but they need to be more fleshed out than 'less code'.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The scarce resource is &lt;b&gt;&lt;i&gt;your brain&lt;/i&gt;&lt;/b&gt;. Your attention, your cognition, your working memory, your mental-models. And of course your time. An over-dry refactoring (particularly for the sake of 'less code') that requires a reversal later is expensive in terms of all these scarce resources.&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;Embrace (selective) repetition&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;A criticism of robotlegs is that you can end up with code repetition of very simple blocks of code in your Commands and Mediators, as well as a lot of custom Events. It *feels* weird to type the same code twice or three times to translate 3 different Events into the same corresponding action. But, in my mind, this is part of the power of the Command pattern.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Each Command encapsulates the logic steps required to respond to that situation - and they can freely change in future without impacting upon each other. The code repeated in your Commands is usually cheap and simple - if it's not then think about farming some of the logic out to a helper of some kind. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So don't sweat the 'glue' code having similarity between Commands and Mediators sometimes. Code that is dehydrated is just as tricky (sometimes trickier) to work with as code that needs a little DRYing off.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-6858690028484969811?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/6858690028484969811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=6858690028484969811' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6858690028484969811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6858690028484969811'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2010/10/code-repetition-its-possible-to-be-too.html' title='Don&apos;t dehydrate your code'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-6501688215610103029</id><published>2010-10-07T20:12:00.005+01:00</published><updated>2010-10-07T21:44:19.463+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='as3 tdd testing process mocking samples wtf'/><title type='text'>TDD: Make your intentions clear(er)</title><content type='html'>A habit I've got into recently is creating more and more classes specifically for the purpose of testing.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If the class extends a class which is meaningful to my application it's called &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ThingSupport&lt;/span&gt; (where Thing is the name of the Class it extends).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If the class is extending a more generic class - eg Sprite, or Command with an empty execute - then it's called &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SampleThing&lt;/span&gt;. (Again, Thing is replaced with the name of the Class it extends).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So - my source library now contains a growing number of classes like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SampleCommandA&lt;/div&gt;&lt;div&gt;SampleCommandB&lt;/div&gt;&lt;div&gt;SampleVO&lt;/div&gt;&lt;div&gt;SampleEvent&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;UserVOSupport&lt;/div&gt;&lt;div&gt;MainMenuItemSupport&lt;/div&gt;&lt;div&gt;AccountModelSupport&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;b&gt;Support&lt;/b&gt; classes tend to populate the constructor parameters.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So if the constructor of UserVO is&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;public function UserVO(key:uint, username:String, password:String, jobTitle:String etc )&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;then the constructor of UserVOSupport is&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public function UserVOSupport(key:uint = 1)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;super(key, 'username_'+String(key), 'password_'+String(key) etc)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now I can create a dozen UserVOs with distinct properties only passing an incrementing uint variable to the constructors. Lovely ... but...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;...it's not about typing less&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The ThingSupport classes do two things: they make it easier for me to instantiate the class, but also they &lt;b&gt;isolate&lt;/b&gt; my tests from changes to the constructor of the Thing classes. If I update the Thing constructor to include another param, or change the order, I don't have to touch my tests - I just make a matching change in one place - ThingSupport.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When my coder-friends protest that they find TDD tiresome because if you make changes you have to do loads of maintenance on your tests, this makes me think that they're not isolating their tests well enough. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;So what about the Sample classes?&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What's the point in creating a SampleEvent? If the class/test requires a particular class why bother to create a sample class as well?  Why not just use Event?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is the newest thing I've added to my workflow - and hey, by the end of next week I might have changed my mind - but I'm experimenting with using it to make my intentions clearer in my tests. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As in - what's *real* and what's just test scaffolding. Particularly in integration tests where multiple classes are working together. The use of Sample as a prefix is helping me keep my head straight on which elements are being tested and which are simply provided to wire things up.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That way, when I look through my code and it uses SampleCommandA I know that the SampleCommandA is not part of what's being tested - it's just fodder for the test.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;Couldn't you just use mocking?&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I do use mocking (with mockolate) a lot. Actually I tend to use stubbing / verification - via mockolate. I use it to mock interfaces for services so that I can verify that a method on that service has been run by a command with the correct treatment of the event payload, even before I've implemented the concrete service to the interface.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I also mock (for verification) framework elements - injector, CommandMap - to verify that runtime mappings have been made correctly - again, usually in Commands. It's easy to think of Commands as being so banal that they're barely worth testing, but a Command that doesn't actually run the method on the service, or doesn't manipulate the event payload correctly, or fails to make a mapping could potentially lead to hours of debugging once compiled into the wider app.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;Focus on minimising your WTFs per minute&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As &lt;a href="http://www.twitter.com/mark_star"&gt;@mark_star&lt;/a&gt; tweeted this week: "The only valid measurement of code quality is WTFs/minute" (clean code).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I believe the use of Support and Sample classes is significantly lowering my WTF rate. It &lt;i&gt;feels&lt;/i&gt; good.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm starting to think that a focus on "less typing = better" is really dangerous in a coder. I can type at 80 wpm. Can I code at 80 wpm? Can I f***!  This 'more code = slower' belief is part of what keeps people from embracing TDD. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But it's a dangerous obsession for more than one reason. The search for the perfect IDE may actually lead to an increase in the kinds of WTFs that go on for hours and even days.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.twitter.com/_ondina"&gt;@_ondina&lt;/a&gt; posted some wisdom on the robotlegs board today about the value of being intimate enough with your code that you can write it by hand. We were discussing code generation tools for robotlegs at the time - and she made the valid point that if you rely too much on code generation tools then there's a chance that small errors - [inject] vs [Inject] - creep in to your code and you have no way of diagnosing them, because you haven't built up enough experiences of what looks right for your brain's pattern recognition system to let you know what is wrong.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Food for thought.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-6501688215610103029?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/6501688215610103029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=6501688215610103029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6501688215610103029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6501688215610103029'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2010/10/tdd-make-your-intentions-clearer.html' title='TDD: Make your intentions clear(er)'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-2155530998334323493</id><published>2010-09-28T10:56:00.012+01:00</published><updated>2010-09-28T19:38:17.529+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='as3 tdd testing process'/><title type='text'>Harnessing the Drive in Test Driven Development</title><content type='html'>I had an interesting exchange with someone on twitter last night - he'd been working on some math, that kind of looked right to him now, but had no way of knowing whether it was 'right' or not.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I teased him that he should have done TDD, but he felt that TDD meant you had to know your API ahead of coding, and his situation was evolving, so that ruled out TDD.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was arguing that actually TDD is ideal for when you're not quite sure where you're headed - a view point that didn't fly with his experience - so this is an attempt to further explain that sentiment.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Your brain and body will try to resist TDD&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A common barrier to adopting TDD (this is what my colleagues and peers come back with over and over) is "I don't know enough about what I'm doing to write the test yet."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My response is that if you don't know enough about what you're doing to write the test yet, you sure as hell don't know enough to write the code yet!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Test Driven Development shifts a ton of that 'wtf am I trying to do?' pain to the front of the process. And that's hard to get used to. It exposes what you don't have clarity about - when you really just want to get on and pretend you do know where you're headed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So - how can TDD possibly help when you don't have a clear idea of your direction?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;TDD means more than one kind of test&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;I do 3 kinds of tests. End-to-end tests, integration tests and unit tests. Combining all 3 test varieties is the key to driving evolving development. (Which, IMHO, is the only kind there really is.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I write the end-to-end tests first. An end-to-end test describes &lt;a href="http://en.wikipedia.org/wiki/User_story"&gt;a user story&lt;/a&gt;. If you don't know what your user stories are then you need to get those together before you take another step. User stories will be numerous, even in the simplest app, so don't overwhelm yourself - just start with the shortest, simplest user story in your requirements.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;User story / end-to-end tests&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In a complex app, the user stories are rarely actually end-to-end (startup to shutdown) but they capture a unit of meaningful interaction with the application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is only one user story end-to-end test in each test case. Some examples from my current app include:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;LibrarySimpleSearchReturnsInvalid&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;LibrarySimpleSearchProducesNoResults&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;LibrarySimpleSearchProducesResults&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;LibraryShowAllShowsAllItems&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;LibraryAdvancedSearchProducesResultsByType&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;LibraryAdvancedSearchProducesResultsByExclusion&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;... you get the idea.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In each case, the test recreates the user experience from the moment of opening the library (which is a searchable, browsable set of resources of different types - jpg, document, video etc) until they receive their search results.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This means that it's a UI driven test. I have the test code enter text, push buttons etc, and I delve into the display list to verify that the correct items / text etc have appeared on screen at the end, and usually this is asynchronous to allow time for transitions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Integration / functional area tests&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These test a component of functionality. For example the search window, or the results viewer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Unlike unit tests they make use of real concrete instances of the classes needed to fully instantiate and work with the components being tested.  If the functional area depends on the framework to wire it together, the framework is instantiated (robotlegs in my case) in order to wire up the component.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my current app I have an integration tests for the main menu:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;NestedMenuTest&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This menu has multiple layers of nested items and has to collapse all / expand all / auto-collapse and so on in response to checkbox clicks. My integration tests check that the scrolling behaves itself when the items are being expanded/collapsed. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;test_max_scroll_then_collapseAll_resolves&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;test_mid_scroll_then_expandAll_keeps_top_visible_item_in_place_and_scales_scroller&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;and so on...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Usually, integration tests are event driven - I kick it all off by manually firing an event. Often, but not always, they require you to use the display list to verify the results.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Unit / API tests&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These test that a specific class does what it is supposed to. They test all the public (API) functions of a class, sometimes multiple times if there are errors to be thrown or alternative paths through the class itself.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is a wisdom that says test all API except for property accessors. I tend to test my property accessors as well, because there is no limit to what I can screw up and it's faster to get them right them at this point than when the error emerges later.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Instead of using concrete instances of their complex dependencies (eg services), my unit tests make use of mocks (using Drew Bourne's Mockolate) to verify that they've acted upon those classes correctly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If I was testing that a command pulled values from the event that triggered it, did some jiggery pokery with these values and then used the results in calling a method on the appropriate service, I would mock the services to verify that call, rather than try to test against the results of the call.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here, I've mocked the two services, lessonLoaderService / joinedLessonLoaderService:&lt;/div&gt;&lt;div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: scroll; width: 100%; white-space:nowrap"&gt;&lt;code&gt;public function testLoadsLessonIfRequestEventNotJoinedLesson():void{&lt;br /&gt;  var lessonLoadRequestData:ILessonLoadRequestData = new LessonLoadRequestDTO("test","testSwfPath", true, '', false);&lt;br /&gt;  var testEvent:LessonDownloadEvent = new LessonDownloadEvent(LessonDownloadEvent.LESSON_DOWNLOAD_READY, lessonLoadRequestData);&lt;br /&gt;  instance.event = testEvent;&lt;br /&gt;  instance.execute();&lt;br /&gt;                                                                       &lt;br /&gt;  verify(instance.lessonLoaderService).method("loadLesson").args(equalTo('testSwfPath'));&lt;br /&gt;  verify(instance.lessonLoaderService).method("loadLesson").once();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public function testLoadsJoinedIfRequestEventIsJoinedLesson():void{&lt;br /&gt;  var lessonLoadRequestData:ILessonLoadRequestData = new LessonLoadRequestDTO("test","testSwfPath", true, '', true);&lt;br /&gt;  var testEvent:LessonDownloadEvent = new LessonDownloadEvent(LessonDownloadEvent.LESSON_DOWNLOAD_READY, lessonLoadRequestData);&lt;br /&gt;  instance.event = testEvent;&lt;br /&gt;  instance.execute();&lt;br /&gt;                                                                       &lt;br /&gt;  verify(instance.joinedLessonLoaderService).method("loadLesson").args(equalTo('testSwfPath'));&lt;br /&gt;  verify(instance.joinedLessonLoaderService).method("loadLesson").once();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:monospace;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style="font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Putting it all together&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Often, we put applications together from the bottom up. With half an eye on the requirements, we start thinking about interfaces and event types and functional areas.  This works, but it can also result in some YAGNI code, as well as throwing code out that seemed like it was going to be relevant until you realised that the requirements weren't complete.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think there's more sanity in a work flow that runs this way:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) User story&lt;/div&gt;&lt;div&gt;2) End-to-end test that verifies this user story (or part of it - this can evolve)&lt;/div&gt;&lt;div&gt;3) Integration tests for the functional areas required to fulfil the end-to-end-test&lt;/div&gt;&lt;div&gt;4) Unit tests for the classes required to provide the functional areas&lt;/div&gt;&lt;div&gt;5) Code to pass 4, to pass 3, to pass 2, to verify against 1&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;... and when you have no fails, then add to 2, add to 3, add to 4, do 5, rinse and repeat etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Doing it this way, the consequences are:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;A lot of head scratching early in each cycle (creating end-to-end tests is hard).&lt;/li&gt;&lt;li&gt;Usually having failing tests in your test suite, until you're done adding a feature/user story.&lt;/li&gt;&lt;li&gt;Always being able to tell what the hell you were doing when you last stopped ... because your failing tests make that obvious.&lt;/li&gt;&lt;li&gt;Never writing code that doesn't actually add value to the project by contributing to the implementation of a user story.&lt;/li&gt;&lt;li&gt;Always working towards a 'shippable' goal, which is good for the client (and your cash flow if you bill against features) and also allows real user feedback to improve the work still to be done.&lt;/li&gt;&lt;li&gt;Reduced cognitive load for you at a micro level - you fix problems in the code while that part of the code is what you're focussed on.&lt;/li&gt;&lt;li&gt;Reduced cognitive load for you at a macro level - you don't have to hold the 'where am I going' part in your head, or remember to test manually, because your user story tests have that covered.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I would argue that as a consequence of those last two there's a bigger reward: being able to show up more fully for the rest of your life. A bug, or a concern about whether I've really implemented feature X correctly, impacts on my ability to be present for my family. I'm kind of not-really-there at dinner, because 90% of my brain is background processing code stuff. This still happens with TDD, but it happens a lot less.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;So, if you don't find that TDD is improving your code and your process - not just your output but also your enjoyment - then my (cheeky) suggestion is that you've not discovered what it's really about yet.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my experience, TDD is fun. Chemicals in my brain fun.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#6600CC;"&gt;PS. If you haven't already got it, this book is essential reading on harnessing the Drive in TDD: &lt;a href="http://www.growing-object-oriented-software.com/"&gt;http://www.growing-object-oriented-software.com/&lt;/a&gt;  Props to Joel Hooks for recommending it.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-2155530998334323493?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/2155530998334323493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=2155530998334323493' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2155530998334323493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2155530998334323493'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2010/09/harnessing-drive-in-test-driven.html' title='Harnessing the Drive in Test Driven Development'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-4679317755615244965</id><published>2010-09-03T22:46:00.008+01:00</published><updated>2010-09-07T12:33:49.615+01:00</updated><title type='text'>Air Swf loading anomolies</title><content type='html'>The application I do most of my work on (An AIR 1.5 app) loads swfs in 2 ways.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are modules of functionality that are loaded into the application sandbox using the secure loading method that I've blogged about here before.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are also 'lessons' which consist of multiple swfs that are loaded into the non-application sandbox. If a lesson consists of 4 swfs then they are all loaded, and then they are added to / removed from the stage as the user browses through the lesson.  When another lesson is loaded the previous lesson swfs are first unloaded.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These swfs are having code injected into their timelines, but they also contain code at timeline depth and in nested MovieClips. This is generally just simple 'show this label on MouseOver' functionality. Nothing fancy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I found a few months ago that loading the swfs serial - as you would expect to do [by waiting for one to INIT before loading the next] - caused the code in the nested MovieClips to *often* fail - on Mac or PC. I tried to track down the cause of this, and through my experiments I discovered that loading the swfs parallel seemed to solve the problem.  So, unable to discover a reason I went with the approach that worked.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now the problem has reared its ugly head again - but only on PC.  On Mac, all code works fine all the time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On PC (Windows XP), the timeline code, and the injected code, are always fine. But MovieClip code - whether done in a separate class file or just put into the MC timeline, is borked in SOME swfs, depending on what order the swfs INIT in.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So far I've discovered the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) Loading the swfs serial, MC code is frequently borked on Mac or PC.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2) Loading the swfs parallel, code borking is dependent on the INIT order.  [Might this indicate that the swf isn't fully loading when it INITs first?]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3) Whether the code is directly in the MC, or just in the MC timeline, it's just not there - even a stop() doesn't work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4) I've replicated the problem with simple assets (a 2 frame MC with diff coloured squares and a stop() on frame 1), guaranteed not to clash with any other assets in any other swf being loaded.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;5) The swfs most likely to be borked are those with the largest file size. BUT removing some assets to reduce the file size doesn't appear to help.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;6) The swfs are currently being exported from Flash Pro CS4. I'm downloading CS5 trial just incase it helps. They're FP10.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;7) Some swfs are only borked if they INIT first. Some are able to tolerate being the first to INIT without problems. Some are borked if they're first OR second (of six in that case) to load.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;8) Adding a pause after all the swfs have loaded, before I do anything else, makes no difference.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;9) Air runtime is 2.0.3&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---  EDIT - conclusion&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;I think I've found the source of the problem.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The load order and the broken movieclip code are both symptoms of the same problem: the swf has not loaded into memory correctly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;The broken swfs are usually the largest, and when they INIT ahead of much smaller swfs it's probably a sign of incomplete loading, hence the correlation with Level-1 code not running. (Level-0 is timeline, level-1 is code inside MCs on that timeline etc).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Having run the tests hundreds of times I've found that this problem occurs approximately 50% of the time in a Parallels-XP virtual PC, and occasionally on a Windows 7 machine that has been down-versioned to windows XP (and hiccups in many other areas). So far it does not happen on a Mac book pro bootcamp XP install, or a stable Vista install.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I guess it's a genuine thread crash in the Air app, most likely some sort of memory issue?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have not been able to find a way to prevent the problem from happening. Instead I have a work around:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Each swf contains a MC on the timeline on frame 1 with a line of code with the sole purpose of notifying the application (via the sandbox bridge) that level-1 code has been loaded correctly. If this notification is not received for a particular swf by the time the 'COMPLETE' event fires, the swf is deemed to have loaded incorrectly, and is unloaded from memory and loaded again.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This process is repeated until the load is correct. The files are local so the delay to the user is minimal.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-4679317755615244965?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/4679317755615244965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=4679317755615244965' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4679317755615244965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4679317755615244965'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2010/09/air-swf-loading-anomolies.html' title='Air Swf loading anomolies'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-5588814923888890730</id><published>2010-07-13T17:12:00.008+01:00</published><updated>2010-07-14T15:11:09.912+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='timeline'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='undocumented'/><title type='text'>Using actionscript 3 to inject code into the timeline</title><content type='html'>Two undocumented handy features from AS3 for working with the MovieClip timeline:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  font-weight: bold; font-family:monospace, serif;font-size:13px;"&gt;frame1();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Which runs the code on frame 1 of the timeline, with corresponding functions for any frame that contains code - &lt;span class="Apple-style-span"   style="  font-weight: bold; font-family:monospace, serif;font-size:13px;"&gt;frame99(), frame354()&lt;/span&gt; etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  font-weight: bold; font-family:monospace, serif;font-size:13px;"&gt;addFrameScript(frameNumber:int, newFrameActions:Function):void&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Which adds the code specified in newFrameActions at the frameNumber. Note that this is a zero-based frame number, yet frame1() is one-based. To add code to the first frame of an MC and then call it, you would do:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;mc.addFrameScript(0, firstFrameActions);&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; mc.&lt;/span&gt;frame1();&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;addFrameScript&lt;/b&gt;&lt;/span&gt; will overwrite any existing actions, so if you want to augment and not just replace the code that is there, you'll need to first grab the existing frame code and then include that in your new function like this:&lt;/div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;var oldFrameActions:Function = function():void {};&lt;br /&gt;&lt;br /&gt;if((mc['frame23'] != null) &amp;amp;&amp;amp; (mc['frame23'] is Function))&lt;br /&gt;{&lt;br /&gt;oldFrameActions = mc['frame23'];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var newFrameActionsFrame23:Function = function():void {&lt;br /&gt;oldFrameActions();&lt;br /&gt;// add new code here...&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Of course all of that is much better wrapped up in some portability that doesn't care whether it's frame 23 or frame 99 etc.  I'm using a class for that - &lt;a href="http://gist.github.com/474159"&gt;http://gist.github.com/474159&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You feed it a MovieClip and you'd probably want to hold a reference inside that MovieClip as well because one of the other uses is in overriding gotoAndPlay() so that it will rerun the code in the current frame without having to move the playhead  (assuming frameScriptManager is a reference to an instance of the class in the gist):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;override public function gotoAndPlay(frame:Object, scene:String = null):void&lt;br /&gt;{&lt;br /&gt;var frameNo:int = this.currentFrame;&lt;br /&gt;&lt;br /&gt;super.gotoAndPlay(frame, scene);&lt;br /&gt;&lt;br /&gt;if(this.currentFrame == frameNo)&lt;br /&gt;{    &lt;br /&gt;var frameFunction:Function = frameScriptManager.getFrameScriptAtFrame(frameNo);&lt;br /&gt;try {&lt;br /&gt;  frameFunction();&lt;br /&gt;}&lt;br /&gt;catch(e:Error)&lt;br /&gt;{&lt;br /&gt;  trace(e.getStackTrace());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The class, and in particular the &lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;getFrameScriptAtFrame()&lt;/span&gt;&lt;/b&gt; function also deals with the major gotcha: even once you've added additional code to the timeline at frame 1, the frame1() function continues to only run the actions that were present in the MovieClip (or Fla) timeline when it was published.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An alternative to rerun the current frame actions is to call Stage.invalidate() before the gotoAndPlay() - which is OK unless your content, like ours, is loaded into a sandbox that doesn't have access to Stage.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;--- ADDENDUM ---&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have now also discovered that the visibility of the frame1() function is internal - so unless the FrameScriptManager is compiled into the same package as the SWF / MovieClip base class, these will show up as undefined (annoyingly no more helpful error is thrown).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So - the workaround is that your MC to be injected should implement the following function:&lt;/div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    public function getFrameScriptAt(frameNumber:int):Function&lt;br /&gt;   {&lt;br /&gt;       return this['frame'+frameNumber];&lt;br /&gt;   }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;This is also specified in the IInjectableTimeline interface I've added to the Gist file. However, the FrameScriptManager class itself doesn't require an IInjectableTimeline, but will accept a vanilla MovieClip because the complications of ApplicationDomains for content loaded at runtime, plus variation in where the FrameScriptManager is complied (in the parent swf or in the child swf), make it tricky to roll a one-size-fits-all solution with strong typing.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So - the interface is there to help you keep yourself honest. Unfortunately there's no compiler enforcement in this case.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;--------&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;What's the point of all this? Well, in our case the swfs being targeted for timeline code injection are animated lessons. These lessons also need some code in them to address the application they run in - so that they can ask the main message window to show a title, or offer a download, or some instructions, or set the status of the play / pause button at the end of a section. Previously we did this using frame code, but this was hard to test and maintain. Instead we now specify most titles, instructions, download paths etc in an external xml file which is quick to edit.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;At runtime the xml file for each lesson is processed and the relevant actions are added to the timeline of the lesson swfs, meaning that as far as the application is concerned these new, easier to manage (for us and our client) lessons behave exactly like the old ones.&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-5588814923888890730?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/5588814923888890730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=5588814923888890730' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/5588814923888890730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/5588814923888890730'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2010/07/using-actionscript-3-to-inject-code.html' title='Using actionscript 3 to inject code into the timeline'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-8818532838307423634</id><published>2010-02-26T16:02:00.003Z</published><updated>2010-07-13T17:12:34.982+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='processes'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>Programming for the slowest processor</title><content type='html'>Last week, er... no, actually it was this week, I had a bang on the head. Black out, concussion, skull x-rays, the works.&lt;br /&gt;&lt;br /&gt;Everything is intact, but my short term memory is temporarily a bit rubbish. My concentration span is minutes at most.&lt;br /&gt;&lt;br /&gt;But it has brought into focus something I've been working on for a while - changing my processes to really concentrate on minimising the load on the slowest processor: my &lt;b&gt;brain&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The AS3 application I'm currently building is not a fast-firing game or a web-delivered viral. File size and the speed of event firing aren't a critical success factor, so I'm taking the opportunity to experiment with how I programme, to make it&lt;b&gt;&lt;i&gt; easier for me to do my job as well as I can.&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;s&gt;Over the next couple of weeks &lt;/s&gt; When I get a chance I'll be posting a series of entries on:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;1. Using the &lt;a href="http://www.robotlegs.org/"&gt;[robotlegs] framework&lt;/a&gt; to cut cognitive boilerplate (it's about thinking, not typing!)&lt;br /&gt;&lt;br /&gt;2. Reducing cognitive overhead through ultra-verbose programming.&lt;br /&gt;&lt;br /&gt;3. Getting the compiler to pull its weight - including &lt;a href="http://github.com/robertpenner/as3-signals"&gt;AS3 signals&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;4. Using end-to-end testing and the &lt;a href="http://github.com/Stray/RobotEyes"&gt;roboteyes&lt;/a&gt; tools to get more sleep.&lt;br /&gt;&lt;br /&gt;5. Employing &lt;a href="http://projectsprouts.org/"&gt;project sprouts&lt;/a&gt; to make true TDD (unit, integration and end-to-end testing) easier than falling off a log.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The emphasis is on making sure that I can do my job well, and enjoy doing it, even on days when I am much less than my best. Not because I foresee a lot of head injuries in my future, but because as a team leader, business owner, parent, partner and dog owner, there turn out to be a lot of days when I'm interrupted.&lt;br /&gt;&lt;br /&gt;I could pretend that all of this is in the interests of my clients. Sure, they benefit. But this new way of working is about the advantages to me today, and the future developers on my project (often also me) - whether that future is 10 minutes, 10 days or 10 months away.&lt;br /&gt;&lt;br /&gt;Part 1 coming this weekend.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-8818532838307423634?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/8818532838307423634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=8818532838307423634' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/8818532838307423634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/8818532838307423634'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2010/02/programming-for-slowest-processor.html' title='Programming for the slowest processor'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-6781629518176484380</id><published>2009-10-20T14:56:00.002+01:00</published><updated>2009-10-20T16:46:25.136+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='robotlegs'/><category scheme='http://www.blogger.com/atom/ns#' term='as3-signals'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><title type='text'>robotLegs meets as3-signals?</title><content type='html'>The flash event model is a bit... sucky.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Robert Penner wrote these 3 blog posts which summarise the limitations:&lt;/div&gt;&lt;div&gt;&lt;a href="http://robertpenner.com/flashblog/2009/08/my-critique-of-as3-events-part-1.html"&gt;My Critique of AS3 Events – Part 1&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://robertpenner.com/flashblog/2009/09/as3-events-7-things-ive-learned-from.html"&gt;AS3 Events – 7 things I’ve learned from community&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://robertpenner.com/flashblog/2009/09/my-critique-of-as3-events-part-2.html"&gt;My Critique of AS3 Events – Part 2&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;He's been working on an alternative known as &lt;a href="http://github.com/robertpenner/as3-signals/"&gt;as3-signals, which you'll find on git-hub&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Essentially signals seem to provide the following enhancements: (correct me if I'm wrong here)&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;A type based rather than string based registration for an event.&lt;/li&gt;&lt;li&gt;Compile time checking that you only register for relevant signals. If SomeClass doesn't have a .clicked signal then you won't be able to listen for it.&lt;/li&gt;&lt;li&gt;Centralised and handy functions for removing all listeners from an event.&lt;/li&gt;&lt;li&gt;The ability to add a listener for one time only (and have it automatically removed).&lt;/li&gt;&lt;li&gt;Useful runtime errors (if you use 'addOnce' after you've already used 'add' or the reverse you get a sensible error).&lt;/li&gt;&lt;li&gt;The option to prioritise listeners - enforcing a calling order.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;I'm currently working on this modularised rebuild of an existing piece of complex software. Inter-module communication is the thing I'm thinking about most.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also been checking out the interesting stuff over at &lt;a href="http://github.com/darscan/robotlegs-framework/"&gt;robotlegs&lt;/a&gt; - a DI driven framework which looks light and really focussed... except that Flash CS4 won't let you use the metadata required, so it seems to be Flex only for now.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, it has a nice command and event mapping model - allowing for type checking, 'one shot only' and so on.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So... I'm considering the benefits of a hybrid. Of creating a command mapped version of as3-signals.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Questions:&lt;/div&gt;&lt;div&gt;1) How to replicate the nice compile time checking that Signals provides while also supporting the decoupling of the modules via the centralised command map - so you can't register for an event that will never exist.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2) Where to put the events? Which package? Do they need to reside in a centralised area?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3) Is this a complete waste of time? Does the command map already provide sufficient decoupling? Should I simply use signals within a module and the command map between modules?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4) Could a module create a new signal 'channel' dynamically, or does that make no sense at all?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Questions... questions...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-6781629518176484380?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/6781629518176484380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=6781629518176484380' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6781629518176484380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6781629518176484380'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2009/10/robotlegs-meets-as3-signals.html' title='robotLegs meets as3-signals?'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-4420376631884186995</id><published>2009-09-16T18:20:00.005+01:00</published><updated>2009-12-14T22:53:14.376Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='enterprise applications'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='modular'/><title type='text'>A framework for Modular AIR Applications</title><content type='html'>I've finished building a framework for securely loading signed, packaged swfs into the application sandbox at runtime, while leaving others in the non-application sandbox and rejecting modules without matched signatures.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.newloop-clients.co.uk/module_resource_tests/AirModularApplication.zip"&gt;All the assets, tests, source code and documentation can be downloaded here.&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The framework fairly neatly packages the whole process.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The origin of the signature testing process is the &lt;a href="http://www.adobe.com/devnet/air/flex/quickstart/xml_signatures.html"&gt;Adobe article here&lt;/a&gt;, where you can also download a compiled code swc of the necessary flex-only classes if you're working in Flash.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#000099;"&gt;The air application I've built as proof-of-principle achieves the following:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Modules with matching signatures are loaded to the app sandbox (if requested).&lt;/li&gt;&lt;li&gt;Modules without matching signatures requesting app sandbox loading are rejected.&lt;/li&gt;&lt;li&gt;Modules can also be loaded to the non-application sandbox.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#000099;"&gt;It demonstrates:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;That app sandbox loaded modules can write to the file system (they put a directory on your desktop).&lt;/li&gt;&lt;li&gt;That non-app sandbox loaded modules are prevented from writing to the file system.&lt;/li&gt;&lt;li&gt;That both app and non-app sandbox loaded modules can pass library assets to the main application to be added to the display list.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It has a lot of user feedback / developer feedback built in. In the absence of the ability to trace in the air application itself I'm listening for this feedback and displaying it in a textarea in the main application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Currently the information about what to load and how to load it, and where to find the .zip assets on a server to install modules, is all contained in &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;moduleData.xml&lt;/span&gt; inside the applicationFlasAndCode folder. When you start the application you must browse to this file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;To use the framework:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Use &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ModuleXMLLoader&lt;/span&gt; to load an xml document containing your module information.&lt;/li&gt;&lt;li&gt;This creates a strongly typed iterator: &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ModuleDescriptionIterator&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Instantiate &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ModuleChainLoader,&lt;/span&gt; passing it that iterator.&lt;/li&gt;&lt;li&gt;Listen for the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ModuleEvent.MODULE_LOADING_COMPLETE&lt;/span&gt; event.&lt;/li&gt;&lt;li&gt;Ask the moduleChainLoader to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;startLoadingModules()&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;When you handle the loading complete event, run &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;getModuleDictionary()&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Access your modules from the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ModuleDictionary&lt;/span&gt; using &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;getModule()&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;getSandboxedModule()&lt;/span&gt;.  You pass the module's unique name to those functions. They pass back the required module.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Any questions at all, post them here or email me.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;How secure is secure?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm building an enterprise training application. It already exists in AIR, but we're moving to a modular system because our users don't have the permissions required to run the automatic updates.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Secure, for me, is secure enough not to be the preferred target for a malicious attack. Nothing is impossible, but I want to make it sufficiently difficult / tedious that anyone intending to cause trouble looks elsewhere to do it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Notes:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my own final application the xml will be a secure data stream coming from a server.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you want to keep my xml structure you can use the ModuleXMLLoader class as is, but I've kept it as a separate stage in the process so that you can make changes to this.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Some possible gotchas to avoid:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The example module flas have classes which extend ITestableModule. You'll need to point flash to the com folder in order for this interface to be found.&lt;/li&gt;&lt;li&gt;Remember that flash keeps signing with the last certificate you used. So when creating good and bad modules, and compiling the app itself, keep an eye on which certificate you're using.&lt;/li&gt;&lt;li&gt;Module .air packages need to be renamed .zip&lt;/li&gt;&lt;li&gt;You cannot test secure loading in the flash test player. You have to create the application .air file, install it and run it to test it.&lt;/li&gt;&lt;li&gt;Don't forget to grab that SignatureUtils.swc from &lt;a href="http://www.adobe.com/devnet/air/flex/quickstart/xml_signatures.html"&gt;the Adobe link&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;b&gt;Addition:&lt;/b&gt; &lt;a href="http://www.newloop-clients.co.uk/downloads/remoteModuleTester.zip"&gt;The flex source files are here. &lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-4420376631884186995?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/4420376631884186995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=4420376631884186995' title='30 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4420376631884186995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4420376631884186995'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2009/09/framework-for-modular-air-applications.html' title='A framework for Modular AIR Applications'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>30</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-3124348237424322820</id><published>2009-09-01T17:48:00.003+01:00</published><updated>2009-09-01T19:09:58.735+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Creating modular applications in Adobe AIR</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Identity is on hold at the moment, work still being too hectic. I'm hoping to really get down to it next year - I've got 3 O'Reilly books on the way out by March next year, and they're eating all my time.&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;In the meantime, the main work project I've got going on is a nice fit with what Identity needs to achieve in terms of modularity. It's an e-learning app, already running successfully as an Air application, but we're rebuilding it to achieve the following:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="color:#006600;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;1) Dynamically built modular environment. Other than the AIR shell itself, all the functionality will be loaded by the app at runtime. This allows for non-admin updates, and for user A and user B to have different logging systems / quiz engine etc.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="color:#006600;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;2) Reskinned at runtime. Different departments and sub companies of the corporate client can have a different look and feel, maybe even a different screen size requirement.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;I've already grappled with the Air security sandbox stuff within this app. The lessons themselves are dynamically loaded and using sandbox bridge for communication. The current quiz apps are also decoupled, and only simple data is passing around - mostly I'm using strings of xml for more structured data requirements.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;I've been playing with the two variations of loading content into flash:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;A) &lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The light side:&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt; use a normal loader, put your downloaded content into a sandbox where it can only access other content via the safe and secure bridge.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;B) &lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The dark side:&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt; read the file into a ByteArray and use loadBytes() with &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="color:#333333;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;allowLoadBytesCodeExecution = true on the loader context, to give your loaded content the run of the place... including the fileSystem.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="color:#006600;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The pros and cons of breaking the Air security model&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;i&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The light side:&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Events&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Events must be passed using loaderInfo.sharedEvents.  Only built-in events keep their type, but that's ok. The actual Event.type property is just a plain string anyway, so you can still make use of a custom event for compile time checking to avoid typos, as the Air shell doesn't care that it didn't know what MyCustomEvent.DOG_BARKED was - it just sees "dogBarked".  On the down side you can't pass useful extra data with your custom events.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Security&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;You can use sensible functions like storeAsset(assetPath:String) to pull in things and read / write to the file system, rather than opening up your user's computer for an attack by rogue dynamically loaded modules.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Loading grandchildren&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Loading a grandchild asset such as a png or jpg seems to be possible using loadBytes() with code execution set to false. You have to pass the byteArray as a normal array, reconstruct it to be a byteArray, and then load the content in the child module. I've only part tested this. More to follow. And it's pretty gross as a process.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Decoupling logic and events is ok&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Modularising the logic of the application doesn't actually seem to be too hard. The code was pretty nicely decoupled already, and we think we can reduce inter-module communication to a combination of vanilla events and xml (passed as string).  We'd use the Air shell as a postman to deliver messages from one module to another. There would be an unnerving amount of dynamic stuff which isn't checkable at compile time, but it's doable.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Major hurdle: providing skin assets at runtime&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;I simply can't find any way to load the actual graphics for the modules at runtime. All I want is to load a specific (dynamically selected) swf with a bunch of MCs in the library, and to be able to do stuff like "new LoginButtonUpSkin()" and whack the requested graphic into the right place.  I guess we could export all of our graphics as pngs and use the loadBytes() trick to feed them to the individual modules, but how grim is that?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The other option would be to compile variations on the modules themselves, with different look and feel. "MainMenuGreen.swf" "MainMenuBlue.swf". That feels like a huge pain in the ass when it comes to creating new skins. The designers would need access to the code library, they always ring me up wondering how to link their files to the com folder... you can see the potential headaches I'm sure...&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial, sans-serif;"&gt;&lt;span class="Apple-style-span"  style=" font-style: italic; font-weight: bold; font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The dark side:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Events: &lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Module to module event traffic is possible. Events don't lose their typing when passing from module to module.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Security: &lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;This is dangerous stuff. But all my modules are coming from a trusted server and &lt;/span&gt;&lt;a href="http://www.adobe.com/devnet/air/flash/quickstart/xml_signatures.html"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;there's a technique for verifying signatures&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;. Basically any module that wants to be loaded into the application sandbox using the loadBytes() method would have to be an Air app in itself. Then that air package gets loaded and ripped open, the signature verified and the module loaded or rejected. I've no doubt that it's not failsafe.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Will adobe continue to provide this work-around?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The adobe official documentation on &lt;/span&gt;&lt;a href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7e5a.html"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;working securely with untrusted content&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt; end with the following fear-inducing statement:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse;  line-height: 16px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span"  style=" border-collapse: collapse;  font-style: italic; line-height: 16px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family:Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span class="notetitle" style="line-height: 16px; font-weight: bold;  "&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Note: &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;In a future release of Adobe AIR, this API may change. When that occurs, you may need to recompile content that uses the&lt;/span&gt;&lt;samp class="codeph" style="line-height: 18px; font-family: 'Courier New', Courier, monospace; "&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;allowLoadBytesCodeExecution&lt;/span&gt;&lt;/samp&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt; property of the LoaderContext class.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial, sans-serif;"&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style=" font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;A future release WHEN? What? And will I need to recompile content even if it's happily running. Will Air 2.0 break my 1.5 application if I've used this?  Presumably Adobe would provide a better work around for achieving this, but my client doesn't want to do a thousand admin-requiring reinstalls... which is why we're going to use a module based system in the first place...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande', serif;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;At the moment I'm still testing, still lurching from favouring one side to the other. More to follow as it unfolds. Hopefully I can save someone the three days of googling and testing I've just been through.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-3124348237424322820?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/3124348237424322820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=3124348237424322820' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/3124348237424322820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/3124348237424322820'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2009/09/creating-modular-applications-in-adobe.html' title='Creating modular applications in Adobe AIR'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-1107573182428123502</id><published>2008-09-17T14:27:00.015+01:00</published><updated>2008-09-17T18:10:57.810+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asdoc'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='textmate'/><title type='text'>TextMate for Flash, Actionscript 3 and asdoc</title><content type='html'>The Flash IDE sucks. I never quite manage to feel at home in the eclipse interface and Flex whines about my Flash components when I try to compile documentation. Powerflasher looks good but resides within eclipse, and FlashDevelop is PC only.&lt;br /&gt;&lt;br /&gt;I love TextMate, and I wanted to sort out my workflow so I could edit .as files in TextMate, compile in Flash and also create asdoc documentation for all my code. I read up online and followed a few people's instructions but found I was still a mile away from what I needed. Having worked through those issues, here's a step-by-step guide to getting to a coherent &lt;span style="font-style: italic;"&gt;code-document-compile&lt;/span&gt; set up with TextMate and Flash.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;Note: The paths to put stuff are a good guide, you can alter them if you like later. Create any folders that don't already exist as you go. HD is a substitute for whatever you've named your main Hard Drive.&lt;/span&gt;  &lt;span style="font-style: italic;"&gt;I found that on one of my computers the folder HD/Developer/ was heavily restricted and I had to change the permissions and then apply to enclosed items to give myself write access.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:130%;"&gt; &lt;span style="font-weight: bold; color: rgb(153, 0, 0);"&gt;1) Install the Flex 3 SDK (free)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Download from : &lt;a href="http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+3"&gt;http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+3&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;I downloaded the latest &lt;span style="font-weight: bold;"&gt;milestone&lt;/span&gt; build of the Adobe Flex SDK (not the open source version) but there are also nightly build s available, and stable interim builds too.&lt;br /&gt;&lt;br /&gt;Put this folder in : &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;HD/Developer/SDKs/&lt;/span&gt; and then rename the folder to be called &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;Flex&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_to35iirdAeY/SNEZ5ynv9mI/AAAAAAAAAM4/FSJTSeJHHfY/s1600-h/Picture+10.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_to35iirdAeY/SNEZ5ynv9mI/AAAAAAAAAM4/FSJTSeJHHfY/s400/Picture+10.png" alt="" id="BLOGGER_PHOTO_ID_5247003521495070306" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(153, 0, 0);font-size:130%;" &gt;2) Download and install TextMate (free trial, then $50)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You can get the application file at : &lt;a href="http://macromates.com/"&gt;http://macromates.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A 30 day trial is available, but I'm sure you'll want to buy it. The best $50 I've ever spent on software.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(153, 0, 0);font-size:130%;" &gt;3) Get the TextMate bundles for Actionscript 3, Ant and Flex&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You can &lt;span style="font-weight: bold;"&gt;download&lt;/span&gt; the zip files of zipped stable builds from the side bar of creator Simon Gregory's blog: &lt;a href="http://blog.simongregory.com/10/textmate-actionscript-3-and-flex-bundles/"&gt;http://blog.simongregory.com/10/textmate-actionscript-3-and-flex-bundles/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The zips are in the right hand column under "Bundles".&lt;br /&gt;&lt;br /&gt;To install these, just &lt;span style="font-weight: bold;"&gt;double click&lt;/span&gt; the .tmbundle file once it has unzipped. Textmate will install them in the right place and the file will disappear from your downloads folder.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(153, 0, 0);font-size:130%;" &gt;4) Copy the Flash components .swc files to your SDKs folder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Within &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;HD/Developer/SDKs/&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;create&lt;/span&gt; a folder called AS3.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Copy&lt;/span&gt; the &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;Applications/Adobe Flash CS3/Configuration/Components/&lt;/span&gt; folder into this &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/SDKs/AS3/&lt;/span&gt; folder.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_to35iirdAeY/SNEjk2kG7GI/AAAAAAAAANA/nSyVZ0tuVo4/s1600-h/Picture+11.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_to35iirdAeY/SNEjk2kG7GI/AAAAAAAAANA/nSyVZ0tuVo4/s400/Picture+11.png" alt="" id="BLOGGER_PHOTO_ID_5247014156892564578" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;5) Set up your TextMate project.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_to35iirdAeY/SNEkx80YlmI/AAAAAAAAANI/bB1Cv_AYM88/s1600-h/Picture+12.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/_to35iirdAeY/SNEkx80YlmI/AAAAAAAAANI/bB1Cv_AYM88/s400/Picture+12.png" alt="" id="BLOGGER_PHOTO_ID_5247015481421370978" border="0" /&gt;&lt;/a&gt;I keep all my AS3 classes in one top level folder, which also then contains my asdoc building stuff and my docs folder once the documentation is created. You may want to do something different - so feel free to tweak this once you're all set up.&lt;br /&gt;&lt;br /&gt;So - my top level folder is  &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/as3_classes/&lt;/span&gt; (this name is not used anywhere so you can call it whatever you like), and it contains my top level packages - com, uk.&lt;br /&gt;&lt;br /&gt;Within this folder you should also create the subfolders &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/asdoc_ant/&lt;/span&gt;, &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/fl/&lt;/span&gt; and &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/docs/&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;In order to be able to work with files which refer to flash components, you need to fill this &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/fl/&lt;/span&gt; folder with all the fl. package classes.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_to35iirdAeY/SNEkyC3-cXI/AAAAAAAAANQ/KxGj-EA4Hd8/s1600-h/Picture+13.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://2.bp.blogspot.com/_to35iirdAeY/SNEkyC3-cXI/AAAAAAAAANQ/KxGj-EA4Hd8/s400/Picture+13.png" alt="" id="BLOGGER_PHOTO_ID_5247015483047047538" border="0" /&gt;&lt;/a&gt;You'll find these in &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;Applications/Adobe Flash CS3/Configuration/&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;There are 4 sets to copy, all of which need to go into that single &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/fl/&lt;/span&gt; folder in your top level folder. There are two sets of video package files, make sure you add one to the other and don't just overwrite the first. Be certain to copy and not just move these files or your Flash App will go crazy.&lt;br /&gt;&lt;br /&gt;Within the /Configuration/ folder above, the 4 fl folders are at:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;- /ActionScript 3.0/Classes/&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;- /Component Source/ActionScript 3.0/FLVPlayback/&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;- /Component Source/ActionScript 3.0/FLVPlaybackCaptioning/&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;- /Component Source/ActionScript 3.0/User Interface/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once you've got them all you should have a list of subfolders like the image on the left.&lt;br /&gt;&lt;br /&gt;Now, to create your project, within TextMate do &lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;File &gt; New Project&lt;/span&gt;. Simply drag your top level folder (the one I called as3_classes, which contains your packages, docs, fl and asdoc_ant) to the folder pane where it says &lt;span style="font-style: italic;"&gt;"Drag Files and Folders Here"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;6) Create your build.xml file&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_to35iirdAeY/SNEpb-atddI/AAAAAAAAANw/X3ptCEJWl2M/s1600-h/Picture+14.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_to35iirdAeY/SNEpb-atddI/AAAAAAAAANw/X3ptCEJWl2M/s400/Picture+14.png" alt="" id="BLOGGER_PHOTO_ID_5247020601451574738" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Within &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/asdoc_ant/&lt;/span&gt; create a new xml file called build.xml. Paste the following into it:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;project name="asdoc" default="asdocs"&amp;gt;&lt;br /&gt;&amp;lt;target name="asdocs"&amp;gt;&lt;br /&gt;&lt;br /&gt;   &amp;lt;!-- Clean out the contents of the doc directory, without deleting "docs" --&amp;gt;&lt;br /&gt;   &amp;lt;delete includeemptydirs="true"&amp;gt;&lt;br /&gt;       &amp;lt;fileset dir="../docs/" includes="**/*" /&amp;gt;&lt;br /&gt;   &amp;lt;/delete&amp;gt;&lt;br /&gt;&lt;br /&gt;   &amp;lt;exec executable='/Developer/SDKs/Flex/bin/asdoc' failonerror="false"&amp;gt;&lt;br /&gt;       &amp;lt;arg line='-library-path /Developer/SDKs/Flex/frameworks/libs'/&amp;gt;&lt;br /&gt;       &amp;lt;arg line='-library-path /Developer/SDKs/Flex/frameworks/libs/air'/&amp;gt;&lt;br /&gt;       &amp;lt;arg line='-library-path /Developer/SDKs/AS3/Components'/&amp;gt;&lt;br /&gt; &amp;lt;arg line='-library-path /Developer/SDKs/Flex/frameworks/locale/en_US'/&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;!-- these classes are required in your source files in order to use the flash components, but&lt;br /&gt; we really don't want to have to error check and create documentation for them --&amp;gt;&lt;br /&gt; &amp;lt;arg line='-exclude-classes fl.accessibility.AccImpl fl.accessibility.ButtonAccImpl fl.accessibility.CheckBoxAccImpl fl.accessibility.ComboBoxAccImpl fl.accessibility.DataGridAccImpl fl.accessibility.LabelButtonAccImpl fl.accessibility.ListAccImpl fl.accessibility.RadioButtonAccImpl fl.accessibility.SelectableListAccImpl fl.accessibility.TileListAccImpl fl.accessibility.UIComponentAccImpl fl.containers.BaseScrollPane fl.containers.ScrollPane fl.containers.UILoader fl.controls.BaseButton fl.controls.Button fl.controls.ButtonLabelPlacement fl.controls.CheckBox fl.controls.ColorPicker fl.controls.ComboBox fl.controls.DataGrid fl.controls.dataGridClasses.DataGridCellEditor fl.controls.dataGridClasses.DataGridColumn fl.controls.dataGridClasses.HeaderRenderer fl.controls.Label fl.controls.LabelButton fl.controls.List fl.controls.listClasses.CellRenderer fl.controls.listClasses.ICellRenderer fl.controls.listClasses.ImageCell fl.controls.listClasses.ListData fl.controls.listClasses.TileListData fl.controls.NumericStepper fl.controls.ProgressBar fl.controls.progressBarClasses.IndeterminateBar fl.controls.ProgressBarDirection fl.controls.ProgressBarMode fl.controls.RadioButton fl.controls.RadioButtonGroup fl.controls.ScrollBar fl.controls.ScrollBarDirection fl.controls.ScrollPolicy fl.controls.SelectableList fl.controls.Slider fl.controls.SliderDirection fl.controls.TextArea fl.controls.TextInput fl.controls.TileList fl.controls.UIScrollBar fl.core.InvalidationType fl.core.UIComponent fl.data.DataProvider fl.data.SimpleCollectionItem fl.data.TileListCollectionItem fl.events.ColorPickerEvent fl.events.ComponentEvent fl.events.DataChangeEvent fl.events.DataChangeType fl.events.DataGridEvent fl.events.DataGridEventReason fl.events.InteractionInputType fl.events.ListEvent fl.events.ScrollEvent fl.events.SliderEvent fl.events.SliderEventClickTarget fl.lang.Locale fl.livepreview.LivePreviewParent fl.managers.FocusManager fl.managers.IFocusManager fl.managers.IFocusManagerComponent fl.managers.IFocusManagerGroup fl.managers.StyleManager fl.motion.Animator fl.motion.BezierEase fl.motion.BezierSegment fl.motion.Color fl.motion.CustomEase fl.motion.easing.Back fl.motion.easing.Bounce fl.motion.easing.Circular fl.motion.easing.Cubic fl.motion.easing.Elastic fl.motion.easing.Exponential fl.motion.easing.Linear fl.motion.easing.Quadratic fl.motion.easing.Quartic fl.motion.easing.Quintic fl.motion.easing.Sine fl.motion.FunctionEase fl.motion.ITween fl.motion.Keyframe fl.motion.MatrixTransformer fl.motion.Motion fl.motion.MotionEvent fl.motion.RotateDirection fl.motion.SimpleEase fl.motion.Source fl.motion.Tweenables fl.transitions.Blinds fl.transitions.easing.Back fl.transitions.easing.Bounce fl.transitions.easing.Elastic fl.transitions.easing.None fl.transitions.easing.Regular fl.transitions.easing.Strong fl.transitions.Fade fl.transitions.Fly fl.transitions.Iris fl.transitions.Photo fl.transitions.PixelDissolve fl.transitions.Rotate fl.transitions.Squeeze fl.transitions.Transition fl.transitions.TransitionManager fl.transitions.Tween fl.transitions.TweenEvent fl.transitions.Wipe fl.transitions.Zoom fl.video.AutoLayoutEvent fl.video.ComponentVersion fl.video.ConnectClient fl.video.ConnectClientNative fl.video.ControlData fl.video.CuePointManager fl.video.CuePointType fl.video.FLVPlayback fl.video.flvplayback_internal fl.video.FPADManager fl.video.INCManager fl.video.IVPEvent fl.video.LayoutEvent fl.video.MetadataEvent fl.video.NCManager fl.video.NCManagerNative fl.video.ParseResults fl.video.QueuedCommand fl.video.ReconnectClient fl.video.SkinErrorEvent fl.video.SMILManager fl.video.SoundEvent fl.video.UIManager fl.video.VideoAlign fl.video.VideoError fl.video.VideoEvent fl.video.VideoPlayer fl.video.VideoPlayerClient fl.video.VideoPlayerState fl.video.VideoProgressEvent fl.video.VideoScaleMode fl.video.VideoState'/&amp;gt;&lt;br /&gt; &amp;lt;!-- the source of your code to generate docs for - I'm only doing my com folder --&amp;gt;&lt;br /&gt;       &amp;lt;arg line='-doc-sources ../com'/&amp;gt;&lt;br /&gt; &amp;lt;!-- where the documentation ends up --&amp;gt;&lt;br /&gt;       &amp;lt;arg line='-output ../docs'/&amp;gt;&lt;br /&gt;       &amp;lt;arg line='-templates-path /Developer/SDKs/Flex/asdoc/templates'/&amp;gt;&lt;br /&gt; &amp;lt;!-- where to look for top level packages - eg the fl package --&amp;gt;&lt;br /&gt;       &amp;lt;arg line='-source-path ../'/&amp;gt;&lt;br /&gt; &amp;lt;!-- edit this to include your own footer --&amp;gt;&lt;br /&gt;       &amp;lt;arg line='-footer newloop'/&amp;gt;&lt;br /&gt;   &amp;lt;/exec&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Thanks to many other bloggers I've borrowed sections of that xml from, it was hugely appreciated when I was struggling to get my own version set up.&lt;br /&gt;&lt;br /&gt;If you've set up exactly as I've described above then you shouldn't need to edit that file. If you've used other locations then you'll need to edit your file paths to match. It doesn't like paths with spaces in.&lt;br /&gt;&lt;br /&gt;You'll notice that the list of excluded classes is pretty long and basically contains all the flash component and base classes, so that you're not compiling documentation on those.&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(153, 0, 0);font-size:130%;" &gt;&lt;br /&gt;&lt;br /&gt;7) Do your FIRST (of many) test documentation build.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These next steps are basically a cycle of building, failing, fixing something, building and failing a bit better and so on until you finally have documentation.&lt;br /&gt;&lt;br /&gt;With the build.xml file open in TextMate, press Apple-B to build, or go to &lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;bundles &gt; ant &gt; Build.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_to35iirdAeY/SNEkyZMSazI/AAAAAAAAANg/ej65Ia80Dz8/s1600-h/Picture+5.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_to35iirdAeY/SNEkyZMSazI/AAAAAAAAANg/ej65Ia80Dz8/s400/Picture+5.png" alt="" id="BLOGGER_PHOTO_ID_5247015489037822770" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Most likely you will a list of over 100 errors. It seems to stop and fail at around 115 or so. This doesn't mean that you only have 115, but that it has given up.&lt;br /&gt;&lt;br /&gt;Weirdly it then also says "&lt;span style="font-family:verdana;"&gt;BUILD SUCCESSFUL&lt;/span&gt;". This is nonsense - your build did not work. Don't panic, that's totally normal. Some of those errors can be reduced by changing the flex config settings to be less strict. Personally I worked with the least strict config possible until I knew that I could build SOME documentation. Then I reintroduced the strictness and debugged as I went.&lt;br /&gt;&lt;br /&gt;To alter the strictness of your flex config open&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;HD/Developer/SDKs/Flex/frameworks/flex-config.xml&lt;/span&gt; in TextMate.&lt;br /&gt;&lt;br /&gt;Set the following:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;show-actionscript-warnings&amp;gt;false&amp;lt;/show-actionscript-warnings&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;strict&amp;gt;false&amp;lt;/strict&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;Save&lt;/span&gt; the flex-config.xml file.&lt;br /&gt;&lt;br /&gt;Build again. Fail again. See the next step for tips for debugging.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold; color: rgb(153, 0, 0);"&gt;8) Fixing your code to get rid of those errors ...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was a long process, but the types of errors in my classes that I had to sort out may help you on your way:&lt;br /&gt;&lt;br /&gt;a) If you have errors like &lt;span style="font-family:courier new;"&gt;"Error: Type was not found or was not a compile-time constant: TextInput."&lt;/span&gt; where you recognise that the type not found is a flash component then check that you've definitely put the flash component swc files in your SDKs folder and the fl files in your top level directory.&lt;br /&gt;&lt;br /&gt;b) Historical stuff related to old unit tests / files not now required. Mostly I just binned those. They gave me errors like "Interface not properly implemented" - which is true as I had stopped developing those test files and continued with the interface.&lt;br /&gt;&lt;br /&gt;c)  Flash Library issues - eg &lt;span style="font-family:courier new;"&gt;"24 Error: Type was not found or was not a compile-time constant: TestClip.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[exec]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[exec]         private var testArea:TestClip;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Where TestClip was a movieclip inside the library of a Fla, exported with the name "TestClip". You know when the flash IDE says "Don't worry, I'll create this class at runtime ... " well, that's no good for ASDocs.&lt;br /&gt;&lt;br /&gt;As tedious as it was, my only option was to create actual classes for all those linked in MCs. And of course I then need to go back to the Fla files and change the export linkage of those symbols in the library to match the final class path. Dull. There may be a way around this but I wasn't able to find one.&lt;br /&gt;&lt;br /&gt;d) Issues with 3rd Party frameworks such as Yahoo astra components.&lt;br /&gt;&lt;br /&gt;I consistently got the following error:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;/Volumes/loopShop/as3_classes/com/yahoo/astra/animation/Animation.as(85): col: 21 Error: Type was not found or was not a compile-time constant: Animation.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[exec]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[exec]             var oldAnimation:Animation = Animation.targetsToAnimation[target];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the end I just dumped from my library the Animation class and everything that depended upon it. Which was OK as I wasn't actually using it. If you are using it then you might have to approach yahoo for a solution - they have their own documentation which must be coping with this error, so perhaps they can help.&lt;br /&gt;&lt;br /&gt;e) Issues with Adobe Flash components / core classes.&lt;br /&gt;&lt;br /&gt;The only one I found was:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[exec] /Volumes/loopShop/as3_classes/fl/core/UIComponent.as(968): col: 63 Error: Parameter initializer unknown or is not a compile-time constant.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[exec]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[exec]         public function invalidate(property:String=InvalidationType.ALL,callLater:Boolean=true):void {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It basically didn't like the use of the &lt;span style="font-family:courier new;"&gt;InvalidationType.ALL&lt;/span&gt; constant. Instead I changed it to &lt;span style="font-family:courier new;"&gt;"all"&lt;/span&gt;, which is the value from the InvalidationType class, and it works ok.&lt;br /&gt;&lt;br /&gt;You should be able to work through the errors you get, removing classes that are causing problems and aren't needed, fixing pathing issues (I had a few classes where I'd moved them outside their original package accidentally) and creating real class paths for classes which were previously created by flash at runtime.&lt;br /&gt;&lt;br /&gt;With any luck your error numbers are reducing, and eventually you get the prize - it generates some documentation in your &lt;span style="font-weight: bold; color: rgb(102, 0, 204);font-family:courier new;" &gt;/docs/&lt;/span&gt; folder!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;9) Reinstate some of the compiler strictness&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next you can switch your flex-config back to show warnings:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;show-actionscript-warnings&amp;gt;true&amp;lt;/show-actionscript-warnings&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;there are a bunch of different things you can warn about, but the really interesting one is this (nearer the bottom):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;warn-no-type-decl&amp;gt;true&amp;lt;/warn-no-type-decl&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;This one was a real eye opener to me. I had no idea how often I created a variable without specifying a type. I remember probably 90% of the time, but those 10% are a real liability. It created a huge list for me to fix but I think it was worth it as now I can fix them as I go, simply by running my asdoc build before I finish for the day and spotting them regularly.&lt;br /&gt;&lt;br /&gt;If you use automatic stage variable declaration in flash then you'll be unable to switch back to strict mode. It will freak out about you using &lt;span style="font-family:courier new;"&gt;this.myTextField&lt;/span&gt; in the middle of a class when &lt;span style="font-family:courier new;"&gt;myTextField&lt;/span&gt; isn't declared as a variable at the top.&lt;br /&gt;&lt;br /&gt;So, you need to use:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;strict&amp;gt;false&amp;lt;/strict&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;If you don't have a bunch of legacy stuff with stage variables being used without being found then you can switch back to strict = true.&lt;br /&gt;&lt;br /&gt;When I finally got my docs to compile (a wonderful moment) the ant build also threw a ton of warnings about fl package files that were being excluded and that it couldn't find them. I know I should care about this, but it hasn't caused me any problems so far. My guess is that these are entries in the excluded classes which don't have a corresponding .swc file, but if you've got a better idea let me know.&lt;br /&gt;&lt;br /&gt;I have quite a large code library and it takes about four minutes to build my documentation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(153, 0, 0);"&gt;10) Edit the ActionScript 3 bundle to use apple-enter to compile your Fla&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;TextMate top menu &lt;span style="font-weight: bold;font-family:trebuchet ms;" &gt;&gt; Bundles &gt; Bundle Editor&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Unfold the ActionScript 3 bundle on the left.&lt;br /&gt;&lt;br /&gt;Click the + button and select "New Command". I called mine "Test in Flash".&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_to35iirdAeY/SNEs4J-gCFI/AAAAAAAAAN4/widCaLt0obE/s1600-h/Picture+8.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_to35iirdAeY/SNEs4J-gCFI/AAAAAAAAAN4/widCaLt0obE/s400/Picture+8.png" alt="" id="BLOGGER_PHOTO_ID_5247024384125700178" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Save &gt; &lt;span style="font-family:trebuchet ms;"&gt;All Files in Project&lt;/span&gt;&lt;br /&gt;Commands : &lt;blockquote&gt;&lt;pre&gt;echo "document.testMovie();" &gt; /tmp/fc.jsfl&lt;br /&gt;open /tmp/fc.jsfl -a "Applications/Adobe Flash CS3/Adobe Flash CS3.app"&lt;/pre&gt;&lt;/blockquote&gt;Input &gt; &lt;span style="font-family:trebuchet ms;"&gt;None&lt;/span&gt;&lt;br /&gt;Output &gt; &lt;span style="font-family:trebuchet ms;"&gt;Discard&lt;/span&gt;&lt;br /&gt;Activation &gt; &lt;span style="font-family:trebuchet ms;"&gt;Key Equivalent&lt;/span&gt;   (I made mine apple-enter as that's my reflex)&lt;br /&gt;Scope Selector: leave blank&lt;br /&gt;&lt;br /&gt;To compile a fla you need to have the fla open in flash. Then from TextMate just press your activation key (apple-enter is mine) and it switches to flash and does the deed.&lt;br /&gt;&lt;br /&gt;You can also edit the bundle editor to suit your own for loop style etc. The tab completion stuff is fab.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;You're all set (hopefully).&lt;br /&gt;&lt;br /&gt;Let me know if you have any questions, good luck!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-1107573182428123502?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/1107573182428123502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=1107573182428123502' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/1107573182428123502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/1107573182428123502'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/09/textmate-for-flash-actionscript-3-and.html' title='TextMate for Flash, Actionscript 3 and asdoc'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_to35iirdAeY/SNEZ5ynv9mI/AAAAAAAAAM4/FSJTSeJHHfY/s72-c/Picture+10.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-976461044900245964</id><published>2008-09-05T10:41:00.003+01:00</published><updated>2008-09-05T10:48:58.051+01:00</updated><title type='text'>Quick update</title><content type='html'>Eek! I've been so slack at keeping this updated. Apologies. My housemate / work partner broke her ankle a few weeks back and life is slightly more complex than usual until she has the use of that leg again - hence no time to really devote to Identity. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Photo evidence is available on my personal house-blog if you're into that sort of thing.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Life resumes (hopefully) on the 25th September when the cast comes off and simple tasks such as carrying a cup of tea to the place where she wants to drink it become possible again.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-976461044900245964?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/976461044900245964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=976461044900245964' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/976461044900245964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/976461044900245964'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/09/quick-update.html' title='Quick update'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-4078071615873612873</id><published>2008-07-16T10:49:00.004+01:00</published><updated>2008-07-16T11:04:39.778+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='textmate'/><title type='text'>Still here, and loving TextMate for AS3</title><content type='html'>Just a quick note to say that I haven't abandoned Identity and / or fallen under a bus.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The book I'm writing at the moment is in the final intense stages, so spare time is non-existent.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll try to reply today to anyone who has emailed me and not heard back. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As an aside - last week I finally completed configuring &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; to edit all my AS3 projects, and use ant to produce asdocs. I'm mostly working in Flash rather than Flex so it took a bit of wiggling to get the fl. package stuff to stop complaining.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Clearly if you're on Windows then you've got the option of &lt;a href="http://www.flashdevelop.org/"&gt;FlashDevelop&lt;/a&gt;, but on Mac I've tried Flex, Eclipse with &lt;a href="http://fdt.powerflasher.com/"&gt;Powerflasher FDT&lt;/a&gt;, &lt;a href="http://www.jedit.org/"&gt;jEdit&lt;/a&gt;, &lt;a href="http://www.panic.com/coda/"&gt;coda&lt;/a&gt; (which I'm still using for everything except AS3) and of course the good ol' Flash IDE, but I've finally settled on &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; and I'm really happy with it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'd been using TextMate as a 'power editor' to do extensive find / replace type tasks when refactoring for a while, but had come across multiple problems that stopped me from switching to it for all my AS3 and asdocs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll post a complete run down of how I've finally got it set up next week. Google code group and this blog should be active again from the end of next week onwards. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-4078071615873612873?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/4078071615873612873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=4078071615873612873' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4078071615873612873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4078071615873612873'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/07/still-here-and-loving-textmate-for-as3.html' title='Still here, and loving TextMate for AS3'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-3663561826274697030</id><published>2008-06-21T17:17:00.001+01:00</published><updated>2008-06-21T17:18:50.641+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='aviary'/><title type='text'>Aviary invites</title><content type='html'>I've got 5 &lt;a href="http://a.viary.com/blog"&gt;aviary&lt;/a&gt; invites to give away.&lt;div&gt;&lt;br /&gt;&lt;div&gt;Let me know if you're interested.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-3663561826274697030?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/3663561826274697030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=3663561826274697030' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/3663561826274697030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/3663561826274697030'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/06/aviary-invites.html' title='Aviary invites'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-1123981111651010689</id><published>2008-06-03T15:34:00.003+01:00</published><updated>2008-06-03T16:35:07.145+01:00</updated><title type='text'>What if Sam releases Saffron?</title><content type='html'>I've been asked the question "What happens to Identity if Sam releases Saffron?" a couple of times recently, so I thought it might be a good idea to address it here, as I'm sure more people are wondering it.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The answer is that I don't know (mostly because it won't be up to me). At the moment Sam's website continues to be offline, and all anybody 'knows' about Saffron UML is based on a handful of screenshots and whole bunch of rumours.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If Sam does release Saffron and it turns out to be as good a tool as people are anticipating then either Identity will cease to be something that is worth developing, and we'll just get on with using Saffron (and be glad about it!) or Identity will still look like it delivers something sufficiently different from Saffron to continue working on it. We may even use Saffron for later stages of development, and/or perhaps refactor some of the Identity features to work as Saffron plugins. In any case, the best feature of open source development is the fact that it won't be my decision. If anybody sees value in continuing development then they can go right ahead and do that!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In using the PureMVC framework we're aiming to create some of the functionality we're going to need as add-ons to the framework which should also have use in other projects. We're going to need a set of lightweight components too, and we'll either be using existing open-source code or developing our own for those - which will also continue to have value regardless of what happens with Identity.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm personally building Identity because I really want to use it! As someone who used to be a manufacturing engineer I'm also really interested in production processes, and I'm excited about the solutions that we might develop in delivering truly integrated planning / modeling / documentation / stub-code. I've got no urge to be a big name in the flash community, though if Identity does come to fruition I quite fancy the idea of writing a book about joined up processes in AS3. Or something. Probably AS4 by then ;)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oddly I'm using CRC and UML to structure the book I'm writing at the moment about Global Climate Change. My chapters are like objects, having responsibilities, collaborations, methods and properties. One of the things that I dream about for Identity is the ability to plug-in alternative tools for organising our thinking. Stuff that hasn't been dreamt up yet ...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-1123981111651010689?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/1123981111651010689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=1123981111651010689' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/1123981111651010689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/1123981111651010689'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/06/what-if-sam-releases-saffron.html' title='What if Sam releases Saffron?'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-4163410343458808595</id><published>2008-05-29T15:18:00.005+01:00</published><updated>2008-08-27T23:58:38.270+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='UML tool'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='modeller'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>Snapshots</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_to35iirdAeY/SD7DB3U9Z6I/AAAAAAAAALo/7IbGeh9hT6A/s1600-h/identity_snapshots.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_to35iirdAeY/SD7DB3U9Z6I/AAAAAAAAALo/7IbGeh9hT6A/s400/identity_snapshots.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5205812656086017954" /&gt;&lt;/a&gt;&lt;br /&gt;Last week I was doing UML diagrams for a colleague to use in building his part of a large application. It occurred to me that the information he actually needed was quite a lot less than what was on the diagram, but as we were doing some test led development, and the model was continuously evolving to reflect the results of our tests, it was too annoying (and unreliable) to have two separate versions of the model to update.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think the answer to this problem would be for each Identity Project to be able to have multiple 'Snapshots' - as roughly visualised in the pic above. In different Snapshots the state (CRC / Full class element / Collapsed class element) of each element could be different, but making a change to the model would update it overall, and the changes would be reflected in each snapshot. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also been thinking about 'visibility filters' for the snapshots. Being able to toggle on and off all public / private / protected / package attributes and operations in the whole diagram would be useful too - I often find myself running 2 copies of a model, one with the entire structure and one to give to a collaborator which only includes the public stuff.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Apologies if this stuff is already present in existing UML tools - at the moment I've decided to not do any research into what's already out there until the first draft of the Identity spec is written up. At that point I think it'd be useful to compare what we've come up with to what's already available, but I'm trying to keep my thinking coming from 'what do we want this to do?' at the moment rather than 'what do other tools do?', knowing that we can pick the status quo up later.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-4163410343458808595?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/4163410343458808595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=4163410343458808595' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4163410343458808595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/4163410343458808595'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/snapshots.html' title='Snapshots'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_to35iirdAeY/SD7DB3U9Z6I/AAAAAAAAALo/7IbGeh9hT6A/s72-c/identity_snapshots.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-8654737879161583074</id><published>2008-05-23T18:59:00.002+01:00</published><updated>2008-05-23T19:11:06.846+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Google code'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='modeller'/><category scheme='http://www.blogger.com/atom/ns#' term='Model view controller'/><category scheme='http://www.blogger.com/atom/ns#' term='PureMVC'/><title type='text'>Google code sign-up info</title><content type='html'>&lt;a href="http://code.google.com/p/identity-modeller/"&gt;Join the Identity Modeller project at Google Code here.&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also resolved the single-core / multi-core puzzle I think.  A multi-core version of &lt;a href="http://www.puremvc.org"&gt;PureMVC&lt;/a&gt; is going to be appropriate for a modules based application whether the app has one or many project windows.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Each module can run its own mini-version of the PureMVC framework.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The recommended strategy for modular PureMVC - presenting an interface to the module - is the only option available within the AIR security model anyway, so the multiCore AS3 port of PureMVC looks like a perfect fit.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm hoping that we can develop some of our functionality as PureMVC plug-ins.  For example - stuff around history / undo / redo across different modules is going to be a fairly generic solution. The saving of application state (something I love love love about Coda) so that when you start up next time it's just as you left it is also a framework solution that might be of use to other PureMVC users.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've been thinking about the roadmap and time frame. A couple of people who have expressed interest in being involved are just hitting an intense period of exams and thesis submissions for the next month or so. I think that's potentially a good thing - I believe it takes a while for an idea as complex as this to settle and emerge. My objective then is to remain in planning until the end of June, and work towards a more and more precise definition of the project in that time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Work begins in earnest at the beginning of July. I'd very much like to get to Alpha in October / November and release the first Beta in time for christmas. Wouldn't that be nice?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-8654737879161583074?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/8654737879161583074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=8654737879161583074' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/8654737879161583074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/8654737879161583074'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/google-code-sign-up-info.html' title='Google code sign-up info'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-6394189187457384530</id><published>2008-05-21T09:47:00.004+01:00</published><updated>2008-05-21T10:20:29.043+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TDI'/><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='MDI'/><category scheme='http://www.blogger.com/atom/ns#' term='interface'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='Model view controller'/><category scheme='http://www.blogger.com/atom/ns#' term='PureMVC'/><title type='text'>PureMVC, and the MDI / TDI quandry.</title><content type='html'>CarnageBlood recommended I &lt;a href="http://puremvc.org/index.php?option=com_frontpage&amp;amp;Itemid=1"&gt;check out PureMVC&lt;/a&gt; as a framework, and I'm really grateful for the suggestion because it looks excellent.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have no doubt that using PureMVC is a good move - it's opensource and we can develop any generically useful extensions as plug ins that will be useful to other PureMVC users.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The big question I have is single-core or multi-core?  How do these relate to interface possibilities?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My favourite applications appear to be a hybrid of &lt;a href="http://en.wikipedia.org/wiki/Tabbed_document_interface"&gt;TDI&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Multiple_document_interface"&gt;MDI&lt;/a&gt;.  &lt;a href="http://www.panic.com/coda/"&gt;Coda&lt;/a&gt; is an amazing one-window-web-development tool that has tabbed browsing of files open in each window - one window referring to a 'site'.  Having multiple windows open means I can entirely separate my work by project / client / server.  I love it.  Each window has its own interface - file browser, search tool, activity etc.  A couple of windows - such as 'clips' - a code snippets tool - are shared across the app as floating panels.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.omnigroup.com/applications/omnigraffle/"&gt;Omnigraffle 5&lt;/a&gt; works in a very similar way. Lots of the interface is wrapped directly around the document, but formatting panels etc are floating shared windows.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've done plenty of standard MVC development but never a multi-core app.  I'm not even sure that what I'm describing is truely multicore?  Whilst there would be many models, views and controllers, the actual basis of the application is perhaps still a single core?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;More reading to be done - and possibly the best way forward is to plan version 1 as single window (apart from interface floaters) tabbed documents style, with the multiple project windows version as a major update.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-6394189187457384530?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/6394189187457384530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=6394189187457384530' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6394189187457384530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6394189187457384530'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/puremvc-and-mdi-tdi-quandry.html' title='PureMVC, and the MDI / TDI quandry.'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-8307638496238379890</id><published>2008-05-20T20:05:00.003+01:00</published><updated>2008-05-20T20:26:33.205+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='UML tool'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='modeller'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>Identity modeller roadmap</title><content type='html'>&lt;span class="Apple-style-span" style="font-style: italic;"&gt;If you build it, they will come ... &lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;That's my mantra at the moment anyway. At times I wonder whether I'll get enough active contribution to this project to make it worth doing open source ... and then I tell myself to shut up, because open source is something I &lt;span class="Apple-style-span" style="font-style: italic;"&gt;believe&lt;/span&gt; in.  Wikinomics, etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have a genuine passion about this project. I guess it's my old production engineer background coming out - I want to fix the process, regardless of the product. In the last year or so I've begun to feel incredibly frustrated by a lot of the work I do, by the sheer pointlessness of it to be honest.  But I still have friends who do OO coding who don't feel able to use UML, or CRC, and I still find I'm having to talk myself into doing it sometimes, and I know that if I had the tool that Identity aims to become I would be a much better coder and technical manager. I know that sharing good code would be easier for starters.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm fortunate to be involved in a couple of really, genuinely worthwhile projects - the biggest of which is a training application that runs in AIR. Apart from a really good usable GUI, the AIR-ness means that this app can manage its own updates in a wonderfully smooth way, something which has allowed us to get it out to users much earlier in the process than with a conventional app, where releasing updates might be problematic.  We can get a bug report from the client, engineer a fix and release the new update to all users within hours.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Based on that experience, the Identity modeller roadmap aims to release as early as possible. I'm also a fan of getting the risky bits out of the way as early as you can, so we start up with the data side, and work towards graphics at the end. To begin with it won't be pretty, but it will be working.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.newloop-clients.co.uk/downloads/identity_roadmap.pdf"&gt;You can download the roadmap here. (pdf, 1.4 MB)&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've no idea what the timeframe is, which will depend partly on how many people get involved and how their schedules are playing out. If you want to have input into the big picture, in particular the scope of the model and the way data is saved, speak up now.  Thanks to all those already chipping in on email and chat!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you're not able to contribute in terms of coding or design but would like to do unit testing or alpha / beta testing I'm already taking names for those ... don't be shy.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-8307638496238379890?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/8307638496238379890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=8307638496238379890' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/8307638496238379890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/8307638496238379890'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/identity-modeller-roadmap.html' title='Identity modeller roadmap'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-2215595218039568099</id><published>2008-05-17T18:38:00.004+01:00</published><updated>2008-08-27T23:58:40.006+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='modeller'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>Identity modeller overview documents</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_to35iirdAeY/SC8irDUO7YI/AAAAAAAAALg/cc_ExCpi1RM/s1600-h/identity_overview.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_to35iirdAeY/SC8irDUO7YI/AAAAAAAAALg/cc_ExCpi1RM/s400/identity_overview.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5201414217656102274" /&gt;&lt;/a&gt;&lt;br /&gt;I've gathered together some of the thinking and ideas I've been bouncing around with Jeroen and Weyert, and chucked everything into a 7 page friendly pdf : &lt;a href="http://www.newloop-clients.co.uk/downloads/identity_overview.pdf"&gt;download it here&lt;/a&gt; (1.6MB).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As always, feedback, input, thoughts etc are all very much welcome.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also been looking at alternatives to osFlash as they're closed to new submissions it seems.  I think probably Google Code is the right choice - if anyone has direct experience of using it please let me know what you'd advise.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think the next step is a road map of proof-of-principle steps.  And later, identifying the bridge API requirements for the various plug-ins and components will be a big exercise - so the more brains the merrier!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-2215595218039568099?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/2215595218039568099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=2215595218039568099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2215595218039568099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2215595218039568099'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/identity-modeller-overview-documents.html' title='Identity modeller overview documents'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_to35iirdAeY/SC8irDUO7YI/AAAAAAAAALg/cc_ExCpi1RM/s72-c/identity_overview.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-8704745181698166683</id><published>2008-05-07T17:50:00.005+01:00</published><updated>2008-05-07T20:07:21.737+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='open-source'/><category scheme='http://www.blogger.com/atom/ns#' term='UML tool'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><title type='text'>Interested in testing or influencing development?</title><content type='html'>There are a few different ways in which you could get involved in this project if you're interested.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The easiest is just by reading this blog and chipping in with a few comments here and there.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm also going to build some mailing lists, so please drop me an email if you'd like to get involved in any of the following ways:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Top level design team - reading through the specification for the app, contributing brain power to solving the big problems and specifying unit tests.&lt;/li&gt;&lt;li&gt;Coding team - writing classes to unit test for the main app.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Plug-in team - creating swfs to add functionality using the plug-in APIs.&lt;/li&gt;&lt;li&gt;Graphic design team - determining how this thing should look.&lt;/li&gt;&lt;li&gt;Language team - drawing up xml files for AS3 / AS2 etc.&lt;/li&gt;&lt;li&gt;Unit-testing team - testing parts of the app (obviously we'll do as much as possible with automated unit tests, but sometimes you really do need a human to bash things!)&lt;/li&gt;&lt;li&gt;Alpha-testing team - testing the first usable release of the app.&lt;/li&gt;&lt;li&gt;Beta-testing team - does what it says on the tin.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I know this kind of project is potentially a bit daunting, but if you feel like there is a particular task that you'd be interested in, let me know.  Maybe you've already got some experience that might be useful - perhaps you're a regex junkie who'd relish the prospect of churning through AS3 files to strip out the data required for reverse generation of models?  Or perhaps you're just really good at breaking stuff, and would be an ideal candidate for the unit-testing team :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Maybe you're up to your neck in actual work but would like to read through the proposals to make sure we're building something that meets your needs as well as our own?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Don't be shy ...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(102, 102, 102);"&gt;[edit : It's been suggested that we put the project up on osflash.org - a really good idea, but when I tried to do it I found that the sign up page has the following message : &lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(102, 102, 102);"&gt;&lt;span class="Apple-style-span" style="font-style: italic; "&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic; "&gt;&lt;span class="Apple-style-span" style="color: rgb(102, 102, 102);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic; "&gt;&lt;span class="Apple-style-span" style="color: rgb(102, 102, 102);"&gt;New project signups are currently on hold as we transition to an automatic system. The old manual system just isn’t working out as neither John nor I (Aral) have time to go through the submissions and that’s not fair for you guys. &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(102, 102, 102);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(102, 102, 102);"&gt;If anyone has another suggestion please let me know, otherwise I'll stick to the blog for now and set up a svn repository as soon as it's going to be useful. ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-8704745181698166683?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/8704745181698166683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=8704745181698166683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/8704745181698166683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/8704745181698166683'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/interested-in-testing-or-influencing.html' title='Interested in testing or influencing development?'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-6378631717080360267</id><published>2008-05-07T11:21:00.006+01:00</published><updated>2008-08-27T23:58:39.242+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><category scheme='http://www.blogger.com/atom/ns#' term='Model view controller'/><title type='text'>Combining MVC with the AIR sandbox</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_to35iirdAeY/SCGSlw4tg7I/AAAAAAAAALY/ePgJoXVA8zw/s1600-h/indentity_components_api.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_to35iirdAeY/SCGSlw4tg7I/AAAAAAAAALY/ePgJoXVA8zw/s400/indentity_components_api.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5197596622437843890" /&gt;&lt;/a&gt;&lt;br /&gt;Identity seems to be an ideal candidate for the &lt;a href="http://en.wikipedia.org/wiki/Model-view-controller"&gt;Model-View-Controller&lt;/a&gt; design pattern.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;I recently converted a large application into an Air app and had to grapple with the differences in how loaded content can access the loader Air file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are lengthy and comprehensive white-papers available from Adobe, and they &lt;span class="Apple-style-span" style="font-style: italic;"&gt;do&lt;/span&gt; explain the new model very comprehensively, but I feel quite strongly that the 'What's new in AIR?' overview stuff for flash developers should have had the following simple point:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 0, 153);"&gt;In order for a loaded swf to be able to communicate with the parent AIR file you must create an API class with public functions within the AIR application and assign this to the loaded swf as a bridge.  The only data which can pass between the parent AIR file and the loaded swf is simple type data : Number, String, Boolean. You cannot pass complex typed data between a loaded swf and a parent AIR file.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The implementation of this into our application was initially a bit painful.  The application is a training environment.  The main AIR app loads external swfs of individual lessons and quizzes. The app GUI has all the interface and the loaded swfs basically only contain a timeline with a voice over and animations and a small amount of functionality.  There is quite a lot of communication between the two however - with the loaded swf prompting the GUI to update all sorts of things - messages on screen, navigation state, icons indicating the availability of other resources.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We had previously achieved a lot of decoupling by using events.  In the new model it was no longer possible for a typed object, such as an event, to pass between the swf and the AIR app. Of course it took a whole bunch of testing and digging through various white-papers to realise that this was the issue ... but we got there in the end.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The result is an even more cleanly decoupled app, with less requirement for the animators to put code into their lessons, and the AIR app is at far less risk of being broken by anything they do.  At the moment there is a small loss in compile-time error checking, though I suppose we could define constants within the local lesson to get back what we had with the events.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So - I am thinking about what the AIR security sandbox will mean for Identity.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It makes sense to have a number of the core functions held in separately compiled swfs, so that they can be extended / swapped easily.  This also gives a lot of protection to the core application as it means that only expected data can pass through.  We can check and place limits on this data before it is used within the app.  Lovely.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example - the ECMAScript-based parser should be able to handle AS2, AS3, AS4 and probably PHP5 and 6, but I haven't a clue what other languages people might find this useful for.  The logic for creating / stripping an AS3 file is quite clear to me - you need a file that defines how a class is built and then you do some regexy things and some iteration through the properties and functions.  How universal that logic is I don't know.  How much customisation you can do without editing the parser, I don't know.  How much benefit coders might get out of editing the parser to suit a specific need, I don't know.  So - if the parser is an externally loaded swf then you can select a parser to use and introduce a layer of flexibility.  You can even build your own.  People can experiment easily with their parser and make public 'improved' ones maybe.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[I'd love to see a parser that simultaneously builds your asDoc html, for example ... not sure how this would be possible right now, but it doesn't feel completely unrealistic, if the parser simply called file writing functionality within the API].&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can assign a specific API to each loaded swf, but you can only assign one.  So, that API needs to deal with all relevant aspects of Model, View and Controller in one class, though of course it's just a gateway through which simple-typed data passes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Application-sandbox loaded components do have a lot more potential for interaction with the parent AIR app, but I think the outside-the-app model offers a much more secure and controlled environment for plug-ins, so this seems like the best route.  Identifying the kinds of functionality each of the plug-in API classes needs to have is a pretty big task in itself ... doing the planning for this project is making me more certain that I need this piece of software though!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(For mac users, if you don't already have it then you should check out &lt;a href="http://www.omnigroup.com/applications/omnigraffle/pro/"&gt;Omnigraffle Pro 5&lt;/a&gt; - the best piece of software I've ever used just got a whole load better.)&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-6378631717080360267?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/6378631717080360267/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=6378631717080360267' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6378631717080360267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/6378631717080360267'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/combining-mvc-with-air-sandbox.html' title='Combining MVC with the AIR sandbox'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_to35iirdAeY/SCGSlw4tg7I/AAAAAAAAALY/ePgJoXVA8zw/s72-c/indentity_components_api.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-7417594971530925782</id><published>2008-05-05T20:30:00.002+01:00</published><updated>2008-05-05T20:41:36.003+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='class swatches'/><category scheme='http://www.blogger.com/atom/ns#' term='modeller'/><title type='text'>Project language spaces &amp; class interchange</title><content type='html'>I'm definitely hooked on the idea of being able to model once and export stub code in multiple languages.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The potential benefits in terms of providing shared 'Class swatches' are pretty attractive.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So far what I'm imagining is that when you start a new project you select a language space for that project.  You would then be able to drag previously defined classes from a classes swatch thingy (best to be specific about the lack of definition here!) into that project - and the app would translate unsupported types according to the type mapping spec for that language. Swatch classes would only be able to be edited within the language space they were defined in - so you couldn't start adding MovieClip types to a class which you've created in ECMAScript.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You would also be able to create a new class 'based on' an existing class in your class swatches - this would import the class types into your project language and allow editing within that language.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Making sense?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-7417594971530925782?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/7417594971530925782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=7417594971530925782' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/7417594971530925782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/7417594971530925782'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/project-language-spaces-class.html' title='Project language spaces &amp; class interchange'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-2570512599265311947</id><published>2008-05-05T15:21:00.005+01:00</published><updated>2008-05-05T15:33:58.661+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='UML tool'/><category scheme='http://www.blogger.com/atom/ns#' term='identity'/><category scheme='http://www.blogger.com/atom/ns#' term='modeller'/><title type='text'>Introducing identity modeller</title><content type='html'>&lt;div&gt;Dauntless pointed out on email that I can't keep calling it "Air UML tool thing" ... and I thought coming up with a half-decent name would take ages, but here I am already, introducing &lt;span class="Apple-style-span" style="font-style: italic;"&gt;Identity modeller&lt;/span&gt;.  Whadya think?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I wanted it to convey the fact that the code and the model are intended to stay in step with each other ... and 'congruent' isn't exactly catchy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Plus, like all good math-geeks, I'm a long term fan of Euler. Couldn't resist ... sorry!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-2570512599265311947?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/2570512599265311947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=2570512599265311947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2570512599265311947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2570512599265311947'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/introducing-identity-modeller.html' title='Introducing identity modeller'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-2786578050372522781</id><published>2008-05-04T20:21:00.006+01:00</published><updated>2008-08-27T23:58:40.894+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='UML tool'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>Air UML Tool : File formats and more on typing</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_to35iirdAeY/SB4TBGBO1gI/AAAAAAAAAK4/sbBilKxe2DU/s1600-h/Picture+1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_to35iirdAeY/SB4TBGBO1gI/AAAAAAAAAK4/sbBilKxe2DU/s400/Picture+1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5196611929548707330" /&gt;&lt;/a&gt;I've been trying to wrap my head around the xmi specification for describing UML models using xml.  The purpose of the spec is obviously to allow models to be imported / exported and switched between different UML tools.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It has given me a focus for the core functionality of the application - to be able to read and write both xmi models and language specific class files.  The application would then also have the ability to write extended xmi files, containing the compliant xmi model stuff but also the project data relating to everything else - non uml stuff to do with getter/setters, positioning, etc etc. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The language specific element will be provided by external xml configs - one to describe how a class file is structured, and one to map generic types to language specific types.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've been having a bit of useful exchange with Dauntless on the types issue.  The thinking I have at the moment is that some classes are clearly language specific - anything using or extending MovieClip for example is only useful in Actionscript - whilst other classes might be much more generic, in which case it would be nice to be able to move them across different language projects.  I have a few utility type classes which I use in both AS3 and php5.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The most basic type set is that provided by UML itself: boolean, integer, float and string.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then there is the set provided by ECMAScript 4 - discussed in the previous post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As Dauntless pointed out, Java has useful stuff like Enum. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think I've almost reached a clear enough understanding of the multiple-languages issues to be able to post more detail of that tomorrow.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As always - the more the merrier - please chip in if you're interested in contributing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Meantime - if anyone can think of a good name for this baby ... Dauntless has rightly pointed out that AIR UML Tool is getting a bit dull ...!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-2786578050372522781?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/2786578050372522781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=2786578050372522781' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2786578050372522781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2786578050372522781'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/air-uml-tool-file-formats-and-more-on.html' title='Air UML Tool : File formats and more on typing'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_to35iirdAeY/SB4TBGBO1gI/AAAAAAAAAK4/sbBilKxe2DU/s72-c/Picture+1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-7743918765510384948</id><published>2008-05-02T19:37:00.006+01:00</published><updated>2008-05-02T20:53:26.280+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='UML tool'/><category scheme='http://www.blogger.com/atom/ns#' term='ECMAScript'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>AIR UML tool : Working with types across different languages</title><content type='html'>One of the most obvious changes when switching between AS2 and AS3 is the difference in built-in types.&lt;br /&gt;&lt;br /&gt;I'm talking &lt;span style="font-family:courier new;"&gt;Number&lt;/span&gt; vs &lt;span style="font-family:courier new;"&gt;int&lt;/span&gt; / &lt;span style="font-family:courier new;"&gt;uint&lt;/span&gt;.  &lt;span style="font-family:courier new;"&gt;Void&lt;/span&gt; vs &lt;span style="font-family:courier new;"&gt;void&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;From time to time I plan something that I want to execute in more than one language - in php5 or Actionscript 3 ... I've been fortunate to be able to leave AS2 behind but I know a lot of people are working on legacy projects.&lt;br /&gt;&lt;br /&gt;With &lt;a href="http://moock.org/lectures/newInECMAScript4/"&gt;Colin Moock already talking about Actionscript 4&lt;/a&gt;, the focus for future-proofing seems to be on ECMAScript 4.&lt;br /&gt;&lt;br /&gt;The release data for the new spec isn't til December 2008, but I'm guessing the end of the year will be upon us in no time.&lt;br /&gt;&lt;br /&gt;Reading through the &lt;a href="http://www.ecmascript.org/es4/spec/overview.pdf"&gt;ECMAScript 4 Overview&lt;/a&gt;, it's struck me that building with this spec in mind will force us to include the kind of flexibility that will make it easier to extend this app to other languages.&lt;br /&gt;&lt;br /&gt;For example - some of the &lt;span style="font-family:courier new;"&gt;Number&lt;/span&gt; types proposed - &lt;span style="font-family:courier new;"&gt;byte, int, uint, double&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;decimal&lt;/span&gt; - may not make it into the final spec, and we may continue to have the current AS3 set: &lt;span style="font-family:courier new;"&gt;int, uint&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;Number&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;If each language contains a type mapping spec for the core types then AS3 can map &lt;span style="font-family:courier new;"&gt;byte, double&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;decimal&lt;/span&gt; to &lt;span style="font-family:courier new;"&gt;Number&lt;/span&gt;, and if AS4 supports them then they can be supported.&lt;br /&gt;&lt;br /&gt;eg:&lt;br /&gt;&lt;br /&gt;translations/as2/typeMapping.xml :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;typeMapping&amp;gt;&lt;br /&gt;&amp;lt;type_byte&amp;gt;Number&amp;lt;/type_byte&amp;gt;&lt;br /&gt;&amp;lt;type_int&amp;gt;int&amp;lt;/type_int&amp;gt;&lt;br /&gt;&amp;lt;type_uint&amp;gt;uint&amp;lt;/type_uint&amp;gt;&lt;br /&gt;&amp;lt;type_double&amp;gt;double&amp;lt;/type_double&amp;gt;&lt;br /&gt;&amp;lt;type_decimal&amp;gt;decimal&amp;lt;/type_decimal&amp;gt;&lt;br /&gt;&amp;lt;type_Number&amp;gt;Number&amp;lt;/type_Number&amp;gt;&lt;br /&gt;&amp;lt;/typeMapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;translations/as3/typeMapping.xml :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;typeMapping&amp;gt;&lt;br /&gt;&amp;lt;type_byte&amp;gt;uint&amp;lt;/type_byte&amp;gt;&lt;br /&gt;&amp;lt;type_int&amp;gt;int&amp;lt;/type_int&amp;gt;&lt;br /&gt;&amp;lt;type_uint&amp;gt;uint&amp;lt;/type_uint&amp;gt;&lt;br /&gt;&amp;lt;type_double&amp;gt;Number&amp;lt;/type_double&amp;gt;&lt;br /&gt;&amp;lt;type_decimal&amp;gt;Number&amp;lt;/type_decimal&amp;gt;&lt;br /&gt;&amp;lt;type_Number&amp;gt;Number&amp;lt;/type_Number&amp;gt;&lt;br /&gt;&amp;lt;/typeMapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;translations/as4/typeMapping.xml :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;typeMapping&amp;gt;&lt;br /&gt;&amp;lt;type_byte&amp;gt;byte&amp;lt;/type_byte&amp;gt;&lt;br /&gt;&amp;lt;type_int&amp;gt;int&amp;lt;/type_int&amp;gt;&lt;br /&gt;&amp;lt;type_uint&amp;gt;uint&amp;lt;/type_uint&amp;gt;&lt;br /&gt;&amp;lt;type_double&amp;gt;double&amp;lt;/type_double&amp;gt;&lt;br /&gt;&amp;lt;type_decimal&amp;gt;decimal&amp;lt;/type_decimal&amp;gt;&lt;br /&gt;&amp;lt;type_Number&amp;gt;Number&amp;lt;/type_Number&amp;gt;&lt;br /&gt;&amp;lt;/typeMapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So far, the types I can identify in the ECMAScript 4 list are:&lt;br /&gt;&lt;pre style="color: rgb(51, 51, 255);"&gt;null, undefined, void&lt;br /&gt;&lt;br /&gt;Object&lt;br /&gt;&lt;br /&gt;Number, byte, int, uint, double, decimal&lt;br /&gt;&lt;br /&gt;Boolean, boolean&lt;br /&gt;&lt;br /&gt;String, string&lt;br /&gt;&lt;br /&gt;Array&lt;br /&gt;&lt;br /&gt;Vector (a strictly typed array?)&lt;br /&gt;&lt;br /&gt;Function&lt;br /&gt;&lt;br /&gt;Map (binary relations)&lt;br /&gt;&lt;br /&gt;Date&lt;br /&gt;&lt;br /&gt;RegExp&lt;br /&gt;&lt;br /&gt;Name, Namespace, NamespaceSet, NamespaceSetList&lt;br /&gt;&lt;br /&gt;Error, EncodingError, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, UndefinedError, URIError&lt;br /&gt;&lt;br /&gt;AnyString = (string,String)&lt;br /&gt;AnyBoolean = (boolean,Boolean)&lt;br /&gt;AnyNumber = (byte,int,uint,double,decimal,Number)&lt;br /&gt;FloatNumber = (double,decimal)&lt;br /&gt;&lt;br /&gt;XML, XMLList, AttributeName, AnyName&lt;br /&gt;&lt;br /&gt;IterableType, IteratorType&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I've also spotted a few more in the documentation - &lt;span style="font-family:courier new;"&gt;FieldIterator&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;ControlInspector&lt;/span&gt; perhaps?&lt;br /&gt;&lt;br /&gt;Either way - this strategy allows us to be highly specific in our documentation, and then water that precision down for each language.  Of course, coming back the other way it's trickier.  Do we want reverse engineering to simply pick the most generic type, or do we need a special comment that can specify how types are backward translated?  Something like ... (for AS3)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// *strictType:decimal //&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public var salary:Number;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Obviously the app also needs to support types from your own library.&lt;br /&gt;&lt;br /&gt;Something else I've noticed is the support for ! ? notation to specify that an object can / can't be null.  Eg&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;// "!" indicates that v can't be assigned null&lt;br /&gt;var v : MyType!&lt;br /&gt;&lt;br /&gt;// "?" indicates that v can be assigned null&lt;br /&gt;var v : MyType?&lt;br /&gt;&lt;br /&gt;// "!" indicates that this whole class is non-nullable&lt;br /&gt;class MyClass! { ...&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The idea is that this will allow earlier detection of null-pointer errors - ideally at compile-time rather than run-time.  That would make me very very happy!&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;It's a pain that ECMAScript 4 is still six and a bit months from completion, but I think the rigour that having to build for an almost-complete standard gives us is probably a good thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-7743918765510384948?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/7743918765510384948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=7743918765510384948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/7743918765510384948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/7743918765510384948'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/air-uml-tool-working-with-types-across.html' title='AIR UML tool : Working with types across different languages'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-7376016835916870427</id><published>2008-05-01T19:16:00.005+01:00</published><updated>2008-05-02T12:19:05.904+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='language fundamentals'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>AIR UML Tool : Defining the UML scope</title><content type='html'>UML 2.0 is pretty vast.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is an attempt to summarise the parts of the UML that need to be available within the tool. My current thinking is that different languages will have an xml spec file that maps these UML Language elements to the translated element for that language.  We should begin with AS3 as a primary goal, but ensure we support parts of the UML which aren't yet available to actionscript but might be included in &lt;a href="http://bitfilm.net/2007/12/09/unofficial-php-6-changelog/"&gt;PHP6&lt;/a&gt; or &lt;a href="http://www.zeuslabs.us/2007/10/28/discover-ecmascript-4-the-future-of-actionscript/"&gt;AS4&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example - AS3 doesn't support 'private' or 'protected' on a constructor, so the AS3 xml config might map it to 'public' in this case.  AS3 also doesn't support 'abstract', so that would be skipped when constructing the stub AS3 code.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The list below is probably incomplete but it's a really good place to begin.  Strict UML terms are given in (brackets).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Stuff&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;package&lt;br /&gt;&lt;/li&gt;&lt;li&gt;class&lt;br /&gt;&lt;/li&gt;&lt;li&gt;interface&lt;br /&gt;&lt;/li&gt;&lt;li&gt;property&lt;br /&gt;&lt;/li&gt;&lt;li&gt;function (operation)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Visibility&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;public&lt;br /&gt;&lt;/li&gt;&lt;li&gt;protected&lt;br /&gt;&lt;/li&gt;&lt;li&gt;private&lt;br /&gt;&lt;/li&gt;&lt;li&gt;internal (package)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Scope / implementation modifiers&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;static&lt;br /&gt;&lt;/li&gt;&lt;li&gt;abstract (unsupported in AS3 but we can hope and at least add to comments)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;const (readOnly)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;binds&lt;br /&gt;&lt;/li&gt;&lt;li&gt;dynamic (not sure this has a strict UML equivalent?)&lt;/li&gt;&lt;li&gt;overrides &lt;span class="Apple-style-span"  style="font-size:small;"&gt;[thanks dauntless]&lt;/span&gt;&lt;/li&gt;&lt;li&gt;final &lt;span class="Apple-style-span"  style="font-size:small;"&gt;[thanks dauntless]&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Class relationships&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;extends  (generalizes)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;implements (realizes)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Any glaring errors?  If you're out there following this and it makes sense to you please do speak up, encouragement, questions, interrogation and the pointing out of obvious fundamental flaws are all appreciated.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[edit]: Dauntless has also mentioned composition, which is definitely required within the laying out of diagrams / relationships, but doesn't really map to an AS3 file other than by declaring a property of that type - or am I missing something?  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We'll also need to represent the Aggregation / one-to-many : many-to-many : many-to-one type relationships as well, and also event listener lollipop etc, but again I don't think they map into the final exported AS3 files.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Dauntless also brought up the issue of types - something I've been thinking a lot about and hope to post some ideas for a strategy later today.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-7376016835916870427?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/7376016835916870427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=7376016835916870427' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/7376016835916870427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/7376016835916870427'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/air-uml-tool-defining-in-uml-scope.html' title='AIR UML Tool : Defining the UML scope'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-7785595217451329741</id><published>2008-05-01T18:38:00.009+01:00</published><updated>2008-08-27T23:58:41.640+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML tool'/><category scheme='http://www.blogger.com/atom/ns#' term='interface'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>AIR UML tool : A clearer concept</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_to35iirdAeY/SBoA_GBO1eI/AAAAAAAAAKo/WK6SO_x_msM/s1600-h/flairUml.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_to35iirdAeY/SBoA_GBO1eI/AAAAAAAAAKo/WK6SO_x_msM/s400/flairUml.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5195466204072826338" /&gt;&lt;/a&gt;&lt;br /&gt;To save any confusion - this is just a graphic, a jpg exported from a flash file which has absolutely no functionality and is purely intended to help rough out an interface concept.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I started thinking in more depth about what I personally needed this tool to be able to do, given that I'm pretty happy with my current working strategy but it just feels like there's a fair bit of friction in the system in terms of duplicating work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, I went right back to basics - my current process, which I'm sure is not unique, is to use index file cards for a fair bit of my modeling.  On one side I scribble the CRC stuff (&lt;a href="http://en.wikipedia.org/wiki/Class-Responsibility-Collaboration_card"&gt;Class Responsibilities and Collaborations&lt;/a&gt;).  On the other I outline the most important public properties and functions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_to35iirdAeY/SBoDQGBO1fI/AAAAAAAAAKw/jpvSypaa10Y/s1600-h/uml_omnigraffle.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_to35iirdAeY/SBoDQGBO1fI/AAAAAAAAAKw/jpvSypaa10Y/s400/uml_omnigraffle.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5195468695153858034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At a later stage I do a more formal UML diagram in Omnigraffle, using the UML-General template.  Then, once I'm satisfied that it's close enough to what I'll finally need, I create skeleton AS3 classes in Flash or Flex, and then write in skeleton asDoc comments ... both of which are rather tedious.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Inevitably the coding process throws up unforeseen stuff and functions, structure or even the whole model can be subject to changes.  Unless I am feeling particularly disciplined, many of these changes go mostly undocumented, usually only being written up if the code is then applied to a new project or handed over to a new developer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I no longer work as part of a large team of developers, so I've only my own experience to call upon, but if there's one thing I've learned in my time as an engineer (in both the physical and the software world) it is to begin by making a product that a single concrete person needs, and not a product that doesn't actually satisfactorily meet the needs of any of a whole bunch of abstract people :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Where I've landed is that this tool should be like a digital version of my index file card box, which integrates my workflow all the way through from creating CRCs to assembling them into a project, to defining public interfaces on the flip side, to drawing that up in a UML sketching tool, to defining private functionality, to adding comments to explain usage, to generating AS3 skeleton functions with asDoc compatible comments and getter / setter functions where desired ... it has to take care of that whole shebang.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That process has to be 2 way, preferably with 'intelligent' (the magic word for 'haven't defined the rules for this yet') syncing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Returning to my dodgy graphic at the top - I'm no designer, so will be looking to get some major input on that side - the concept is that you have a bunch of index cards on screen, you click the little arrow in the top right corner to flip 'em round.  They expand and contract to give enough space for the properties / functions.  All the standard spec of UML 2 is available to you and they also have a neat interface (represented by the G S on the right of the properties) for requesting that Getter / Setter functions be created for those properties. &lt;/div&gt;&lt;br /&gt;I'm sure there will be other, sexier, less geeky skins that people want to add later but this one seems like a great one to kick off with because it focusses the mind on what we're trying to do - take the friction out of a tried-and-tested way of working, not revolutionise the whole process!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-7785595217451329741?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/7785595217451329741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=7785595217451329741' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/7785595217451329741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/7785595217451329741'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/05/air-uml-tool-clearer-concept.html' title='AIR UML tool : A clearer concept'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_to35iirdAeY/SBoA_GBO1eI/AAAAAAAAAKo/WK6SO_x_msM/s72-c/flairUml.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-2697091494009230057</id><published>2008-04-08T15:23:00.004+01:00</published><updated>2008-08-27T23:58:42.516+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='flex'/><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><title type='text'>AIR UML thingy overview</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_to35iirdAeY/R_uCMMbk9aI/AAAAAAAAAKg/wmtMtOflxXw/s1600-h/flAir_overview.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_to35iirdAeY/R_uCMMbk9aI/AAAAAAAAAKg/wmtMtOflxXw/s400/flAir_overview.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5186882541854193058" /&gt;&lt;/a&gt;&lt;br /&gt;So ... here's the overview of the project.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The green box contains the most basic possible release of the software - no real whistles and bells beyond getting something useful that we can start using / testing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The boxes above that are the language / saved file format stuff.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The blue boxes are things for versions 2 to 100 ... &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All saved data / parameters / language specs etc will be in xml.  The entire app will be written in AS3 only - nothing specific to Flex or Flash.  No assets ... well, maybe a png library later, but it should be possible to compile the project from either an empty FLA or a simple Flex project without requiring any assets.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So - with the whole project written in pure AS3, anyone who uses the software will also be able to modify / adapt / enhance / reskin it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In terms of UML elements, I think we should start with the most commonly used elements and then add further ones later.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As far as interface / usability goes, my 2 favourite pieces of software are &lt;a href="http://www.panic.com/coda/"&gt;coda, by panic&lt;/a&gt;, and &lt;a href="http://www.omnigroup.com"&gt;omnigraffle by omnigroup&lt;/a&gt;.  If we get anywhere near to something as beautifully usable as those two I'll be a very very happy bunny.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The 'class swatches' add on is something I'm kind of excited about myself.  It would allow you to have templates for classes / design patterns that you drop in and edit.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll expand more on the diagram above as soon as I get a chance, and it's by no means a concrete solution, just the one that I've come to so far - all feedback / ideas gratefully received.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-2697091494009230057?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/2697091494009230057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=2697091494009230057' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2697091494009230057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/2697091494009230057'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/04/air-uml-thingy-overview.html' title='AIR UML thingy overview'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_to35iirdAeY/R_uCMMbk9aI/AAAAAAAAAKg/wmtMtOflxXw/s72-c/flAir_overview.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4822684209473355816.post-757186351579251025</id><published>2008-04-04T12:07:00.000+01:00</published><updated>2008-04-04T13:37:27.172+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open-source'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='saffron'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='actionscript'/><title type='text'>Open-source Saffron-like UML tool</title><content type='html'>&lt;div&gt;&lt;a href="http://www.levelofindustry.com/journal"&gt;Saffron&lt;/a&gt; is / was an AIR-based UML tool that promised great things, but so far has yet to deliver even an Alpha.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Like many others I've binned my own UML tool project believing that Saffron was just around the corner and far exceeded my own project's limited capabilities.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The AS3 community's response to Saffron has been overwhelming - we want this tool. Badly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Whatever the reasons for Sam's non-delivery on Saffron - and frankly it's not like he owes us as all we've invested is our hope - I’ve given up on Saffron appearing anytime soon.&lt;/div&gt;&lt;br /&gt;Leaving behind the rumours, Saffron would be a fantastic tool and Sam has clearly solved a few of the usability issues that bug me about other UML tools.  Whether or not he has been able to execute it, his concept is seriously good.&lt;br /&gt;&lt;br /&gt;If a bunch of us got together I believe we could do this open-source quite rapidly. If there is interest I’m prepared to get the ball rolling - if we all want Saffron so badly then we need to deliver it ourselves!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I am looking to gather together contributors to work on the project, taking this (scaled down) vision as a starting point:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Project scope:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The tool will run on AIR in multiple windows.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It will allow you to generate AS3 stub code + asdoc comments from your diagrams.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It will allow you to generate diagrams from AS3 code (with asdoc comments).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It will allow you to add additional commenting to classes / functions.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It will stick as closely to UML 2 as is feasible and support the core OO concepts.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The API will be built with expansion for other languages in mind - all they would require is a new parser logic.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There will be autocomplete / prompting for classes already included in the project diagram.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Data / projects / configs will be held in XML files.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Ethos&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;There will be a focus on releasing usable builds as early and as often as possible - even if they are ugly!  Provided we maintain backward compatibility it's more valuable to have a tool that helps us do some of what we need than nothing.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;All project components / specs etc will be open-source and public.  &lt;br /&gt;&lt;/li&gt;&lt;li&gt;All development will be test driven - tests written before code.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Refactoring will be encouraged.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;No effort is too small - write just one class that solidly delivers and passes its unit test and your contribution is valuable.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The project will be cross platform Flex / Flash to maximise the number of possible participants.  (Yes, it's a pain, but I think it's worth it).&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;If you're interested please say so below ... with the right approach and the right numbers of people this thing could fly quite quickly, don't you think?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4822684209473355816-757186351579251025?l=flair-flash-flex-air.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flair-flash-flex-air.blogspot.com/feeds/757186351579251025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4822684209473355816&amp;postID=757186351579251025' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/757186351579251025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4822684209473355816/posts/default/757186351579251025'/><link rel='alternate' type='text/html' href='http://flair-flash-flex-air.blogspot.com/2008/04/open-source-saffron-like-uml-tool.html' title='Open-source Saffron-like UML tool'/><author><name>Stray</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp2.blogger.com/_to35iirdAeY/Rf71yRwJo8I/AAAAAAAAACw/kB83g33z3Yc/s320/stray_southpark.jpg'/></author><thr:total>12</thr:total></entry></feed>
