Showing posts with label AS3. Show all posts
Showing posts with label AS3. Show all posts

Tuesday, 13 July 2010

Using actionscript 3 to inject code into the timeline

Two undocumented handy features from AS3 for working with the MovieClip timeline:

frame1();

Which runs the code on frame 1 of the timeline, with corresponding functions for any frame that contains code - frame99(), frame354() etc.

addFrameScript(frameNumber:int, newFrameActions:Function):void

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:

mc.addFrameScript(0, firstFrameActions);
mc.frame1();

addFrameScript 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:
var oldFrameActions:Function = function():void {};

if((mc['frame23'] != null) && (mc['frame23'] is Function))
{
oldFrameActions = mc['frame23'];
}

var newFrameActionsFrame23:Function = function():void {
oldFrameActions();
// add new code here...
}
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 - http://gist.github.com/474159

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):

override public function gotoAndPlay(frame:Object, scene:String = null):void
{
var frameNo:int = this.currentFrame;

super.gotoAndPlay(frame, scene);

if(this.currentFrame == frameNo)
{
var frameFunction:Function = frameScriptManager.getFrameScriptAtFrame(frameNo);
try {
frameFunction();
}
catch(e:Error)
{
trace(e.getStackTrace());
}

}

}

The class, and in particular the getFrameScriptAtFrame() 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.

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.

--- ADDENDUM ---

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).

So - the workaround is that your MC to be injected should implement the following function:
    public function getFrameScriptAt(frameNumber:int):Function
{
return this['frame'+frameNumber];
}

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.

So - the interface is there to help you keep yourself honest. Unfortunately there's no compiler enforcement in this case.

--------


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.

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.


Friday, 26 February 2010

Programming for the slowest processor

Last week, er... no, actually it was this week, I had a bang on the head. Black out, concussion, skull x-rays, the works.

Everything is intact, but my short term memory is temporarily a bit rubbish. My concentration span is minutes at most.

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 brain.

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 easier for me to do my job as well as I can.

Over the next couple of weeks When I get a chance I'll be posting a series of entries on:

1. Using the [robotlegs] framework to cut cognitive boilerplate (it's about thinking, not typing!)

2. Reducing cognitive overhead through ultra-verbose programming.

3. Getting the compiler to pull its weight - including AS3 signals.

4. Using end-to-end testing and the roboteyes tools to get more sleep.

5. Employing project sprouts to make true TDD (unit, integration and end-to-end testing) easier than falling off a log.



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.

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.

Part 1 coming this weekend.

Tuesday, 20 October 2009

robotLegs meets as3-signals?

The flash event model is a bit... sucky.

Robert Penner wrote these 3 blog posts which summarise the limitations:

He's been working on an alternative known as as3-signals, which you'll find on git-hub.

Essentially signals seem to provide the following enhancements: (correct me if I'm wrong here)
  1. A type based rather than string based registration for an event.
  2. 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.
  3. Centralised and handy functions for removing all listeners from an event.
  4. The ability to add a listener for one time only (and have it automatically removed).
  5. Useful runtime errors (if you use 'addOnce' after you've already used 'add' or the reverse you get a sensible error).
  6. The option to prioritise listeners - enforcing a calling order.
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.

I've also been checking out the interesting stuff over at robotlegs - 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.

However, it has a nice command and event mapping model - allowing for type checking, 'one shot only' and so on.

So... I'm considering the benefits of a hybrid. Of creating a command mapped version of as3-signals.

Questions:
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.

2) Where to put the events? Which package? Do they need to reside in a centralised area?

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?

4) Could a module create a new signal 'channel' dynamically, or does that make no sense at all?

Questions... questions...

Wednesday, 16 September 2009

A framework for Modular AIR Applications

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.


The framework fairly neatly packages the whole process.

The origin of the signature testing process is the Adobe article here, where you can also download a compiled code swc of the necessary flex-only classes if you're working in Flash.

The air application I've built as proof-of-principle achieves the following:
  • Modules with matching signatures are loaded to the app sandbox (if requested).
  • Modules without matching signatures requesting app sandbox loading are rejected.
  • Modules can also be loaded to the non-application sandbox.

It demonstrates:
  • That app sandbox loaded modules can write to the file system (they put a directory on your desktop).
  • That non-app sandbox loaded modules are prevented from writing to the file system.
  • That both app and non-app sandbox loaded modules can pass library assets to the main application to be added to the display list.

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.

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 moduleData.xml inside the applicationFlasAndCode folder. When you start the application you must browse to this file.

To use the framework:
  1. Use ModuleXMLLoader to load an xml document containing your module information.
  2. This creates a strongly typed iterator: ModuleDescriptionIterator.
  3. Instantiate ModuleChainLoader, passing it that iterator.
  4. Listen for the ModuleEvent.MODULE_LOADING_COMPLETE event.
  5. Ask the moduleChainLoader to startLoadingModules().
  6. When you handle the loading complete event, run getModuleDictionary().
  7. Access your modules from the ModuleDictionary using getModule() and getSandboxedModule(). You pass the module's unique name to those functions. They pass back the required module.

Any questions at all, post them here or email me.


How secure is secure?

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.

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.


Notes:

In my own final application the xml will be a secure data stream coming from a server.

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.


Some possible gotchas to avoid:
  • 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.
  • 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.
  • Module .air packages need to be renamed .zip
  • 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.
  • Don't forget to grab that SignatureUtils.swc from the Adobe link.

Wednesday, 17 September 2008

TextMate for Flash, Actionscript 3 and asdoc

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.

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 code-document-compile set up with TextMate and Flash.

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. 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.

1) Install the Flex 3 SDK (free)

Download from : http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+3

I downloaded the latest milestone build of the Adobe Flex SDK (not the open source version) but there are also nightly build s available, and stable interim builds too.

Put this folder in : HD/Developer/SDKs/ and then rename the folder to be called Flex.




2) Download and install TextMate (free trial, then $50)

You can get the application file at : http://macromates.com/

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.


3) Get the TextMate bundles for Actionscript 3, Ant and Flex

You can download the zip files of zipped stable builds from the side bar of creator Simon Gregory's blog: http://blog.simongregory.com/10/textmate-actionscript-3-and-flex-bundles/

The zips are in the right hand column under "Bundles".

To install these, just double click the .tmbundle file once it has unzipped. Textmate will install them in the right place and the file will disappear from your downloads folder.


4) Copy the Flash components .swc files to your SDKs folder

Within HD/Developer/SDKs/ create a folder called AS3.

Copy the Applications/Adobe Flash CS3/Configuration/Components/ folder into this /SDKs/AS3/ folder.



5) Set up your TextMate project.

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.

So - my top level folder is /as3_classes/ (this name is not used anywhere so you can call it whatever you like), and it contains my top level packages - com, uk.

Within this folder you should also create the subfolders /asdoc_ant/, /fl/ and /docs/.

In order to be able to work with files which refer to flash components, you need to fill this /fl/ folder with all the fl. package classes.

You'll find these in Applications/Adobe Flash CS3/Configuration/.

There are 4 sets to copy, all of which need to go into that single /fl/ 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.

Within the /Configuration/ folder above, the 4 fl folders are at:

- /ActionScript 3.0/Classes/
- /Component Source/ActionScript 3.0/FLVPlayback/
- /Component Source/ActionScript 3.0/FLVPlaybackCaptioning/
- /Component Source/ActionScript 3.0/User Interface/

Once you've got them all you should have a list of subfolders like the image on the left.

Now, to create your project, within TextMate do File > New Project. 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 "Drag Files and Folders Here".


6) Create your build.xml file


Within /asdoc_ant/ create a new xml file called build.xml. Paste the following into it:
<project name="asdoc" default="asdocs">
<target name="asdocs">

<!-- Clean out the contents of the doc directory, without deleting "docs" -->
<delete includeemptydirs="true">
<fileset dir="../docs/" includes="**/*" />
</delete>

<exec executable='/Developer/SDKs/Flex/bin/asdoc' failonerror="false">
<arg line='-library-path /Developer/SDKs/Flex/frameworks/libs'/>
<arg line='-library-path /Developer/SDKs/Flex/frameworks/libs/air'/>
<arg line='-library-path /Developer/SDKs/AS3/Components'/>
<arg line='-library-path /Developer/SDKs/Flex/frameworks/locale/en_US'/>

<!-- these classes are required in your source files in order to use the flash components, but
we really don't want to have to error check and create documentation for them -->
<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'/>
<!-- the source of your code to generate docs for - I'm only doing my com folder -->
<arg line='-doc-sources ../com'/>
<!-- where the documentation ends up -->
<arg line='-output ../docs'/>
<arg line='-templates-path /Developer/SDKs/Flex/asdoc/templates'/>
<!-- where to look for top level packages - eg the fl package -->
<arg line='-source-path ../'/>
<!-- edit this to include your own footer -->
<arg line='-footer newloop'/>
</exec>
</target>
</project>
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.

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.

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.


7) Do your FIRST (of many) test documentation build.


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.

With the build.xml file open in TextMate, press Apple-B to build, or go to bundles > ant > Build.



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.

Weirdly it then also says "BUILD SUCCESSFUL". 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.

To alter the strictness of your flex config open

HD/Developer/SDKs/Flex/frameworks/flex-config.xml in TextMate.

Set the following:
<show-actionscript-warnings>false</show-actionscript-warnings>

<strict>false</strict>
Save the flex-config.xml file.

Build again. Fail again. See the next step for tips for debugging.


8) Fixing your code to get rid of those errors ...

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:

a) If you have errors like "Error: Type was not found or was not a compile-time constant: TextInput." 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.

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.

c) Flash Library issues - eg "24 Error: Type was not found or was not a compile-time constant: TestClip.
[exec]
[exec] private var testArea:TestClip;"

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.

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.

d) Issues with 3rd Party frameworks such as Yahoo astra components.

I consistently got the following error:

/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.
[exec]
[exec] var oldAnimation:Animation = Animation.targetsToAnimation[target];

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.

e) Issues with Adobe Flash components / core classes.

The only one I found was:

[exec] /Volumes/loopShop/as3_classes/fl/core/UIComponent.as(968): col: 63 Error: Parameter initializer unknown or is not a compile-time constant.
[exec]
[exec] public function invalidate(property:String=InvalidationType.ALL,callLater:Boolean=true):void {

It basically didn't like the use of the InvalidationType.ALL constant. Instead I changed it to "all", which is the value from the InvalidationType class, and it works ok.

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.

With any luck your error numbers are reducing, and eventually you get the prize - it generates some documentation in your /docs/ folder!


9) Reinstate some of the compiler strictness

Next you can switch your flex-config back to show warnings:

<show-actionscript-warnings>true</show-actionscript-warnings>
there are a bunch of different things you can warn about, but the really interesting one is this (nearer the bottom):

<warn-no-type-decl>true</warn-no-type-decl>
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.

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 this.myTextField in the middle of a class when myTextField isn't declared as a variable at the top.

So, you need to use:
<strict>false</strict>
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.

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.

I have quite a large code library and it takes about four minutes to build my documentation.


10) Edit the ActionScript 3 bundle to use apple-enter to compile your Fla


TextMate top menu > Bundles > Bundle Editor

Unfold the ActionScript 3 bundle on the left.

Click the + button and select "New Command". I called mine "Test in Flash".


Save > All Files in Project
Commands :
echo "document.testMovie();" > /tmp/fc.jsfl
open /tmp/fc.jsfl -a "Applications/Adobe Flash CS3/Adobe Flash CS3.app"
Input > None
Output > Discard
Activation > Key Equivalent (I made mine apple-enter as that's my reflex)
Scope Selector: leave blank

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.

You can also edit the bundle editor to suit your own for loop style etc. The tab completion stuff is fab.

---

You're all set (hopefully).

Let me know if you have any questions, good luck!

Wednesday, 16 July 2008

Still here, and loving TextMate for AS3

Just a quick note to say that I haven't abandoned Identity and / or fallen under a bus.

The book I'm writing at the moment is in the final intense stages, so spare time is non-existent.

I'll try to reply today to anyone who has emailed me and not heard back. 

As an aside - last week I finally completed configuring TextMate 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.

Clearly if you're on Windows then you've got the option of FlashDevelop, but on Mac I've tried Flex, Eclipse with Powerflasher FDT, jEdit, coda (which I'm still using for everything except AS3) and of course the good ol' Flash IDE, but I've finally settled on TextMate and I'm really happy with it.

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.

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. 

 

Thursday, 29 May 2008

Snapshots


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.

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. 

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.

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.

Tuesday, 20 May 2008

Identity modeller roadmap

If you build it, they will come ... 

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 believe in.  Wikinomics, etc.

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.

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.

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.


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!

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.

Wednesday, 7 May 2008

Combining MVC with the AIR sandbox


Identity seems to be an ideal candidate for the Model-View-Controller design pattern.

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.

There are lengthy and comprehensive white-papers available from Adobe, and they do 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:

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.

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.

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.

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.

So - I am thinking about what the AIR security sandbox will mean for Identity.

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.

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.  

[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].

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.

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!

(For mac users, if you don't already have it then you should check out Omnigraffle Pro 5 - the best piece of software I've ever used just got a whole load better.)

Thursday, 1 May 2008

AIR UML Tool : Defining the UML scope

UML 2.0 is pretty vast.

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 PHP6 or AS4.

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.  

The list below is probably incomplete but it's a really good place to begin.  Strict UML terms are given in (brackets).

Stuff
  • package
  • class
  • interface
  • property
  • function (operation)

Visibility
  • public
  • protected
  • private
  • internal (package)

Scope / implementation modifiers
  • static
  • abstract (unsupported in AS3 but we can hope and at least add to comments)
  • const (readOnly)
  • binds
  • dynamic (not sure this has a strict UML equivalent?)
  • overrides [thanks dauntless]
  • final [thanks dauntless]

Class relationships
  • extends  (generalizes)
  • implements (realizes)

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.

[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?  

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.

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.

AIR UML tool : A clearer concept


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.

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.

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 (Class Responsibilities and Collaborations).  On the other I outline the most important public properties and functions.


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.

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.

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 :)

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.

That process has to be 2 way, preferably with 'intelligent' (the magic word for 'haven't defined the rules for this yet') syncing.

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. 

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!

Tuesday, 8 April 2008

AIR UML thingy overview


So ... here's the overview of the project.

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.

The boxes above that are the language / saved file format stuff.

The blue boxes are things for versions 2 to 100 ... 

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.

So - with the whole project written in pure AS3, anyone who uses the software will also be able to modify / adapt / enhance / reskin it.

In terms of UML elements, I think we should start with the most commonly used elements and then add further ones later.  

As far as interface / usability goes, my 2 favourite pieces of software are coda, by panic, and omnigraffle by omnigroup.  If we get anywhere near to something as beautifully usable as those two I'll be a very very happy bunny.

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.  

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.

Friday, 4 April 2008

Open-source Saffron-like UML tool

Saffron is / was an AIR-based UML tool that promised great things, but so far has yet to deliver even an Alpha.

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.

The AS3 community's response to Saffron has been overwhelming - we want this tool. Badly.

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.

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.

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!

I am looking to gather together contributors to work on the project, taking this (scaled down) vision as a starting point:


Project scope:

  • The tool will run on AIR in multiple windows.
  • It will allow you to generate AS3 stub code + asdoc comments from your diagrams.
  • It will allow you to generate diagrams from AS3 code (with asdoc comments).
  • It will allow you to add additional commenting to classes / functions.
  • It will stick as closely to UML 2 as is feasible and support the core OO concepts.
  • The API will be built with expansion for other languages in mind - all they would require is a new parser logic.
  • There will be autocomplete / prompting for classes already included in the project diagram.
  • Data / projects / configs will be held in XML files.

Ethos

  • 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.
  • All project components / specs etc will be open-source and public.  
  • All development will be test driven - tests written before code.
  • Refactoring will be encouraged.
  • No effort is too small - write just one class that solidly delivers and passes its unit test and your contribution is valuable.
  • 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).
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?