Ensemble Tofino: Flex/Actionscript in Visual Studio

For as long as I can remember (please, no snide comments from the peanut gallery - yes, mom, I mean you), I’ve wished for Actionscript support in Visual Studio. Fed up with the Flash IDE’s inability to keep up with the capabilities of other modern IDEs, over the years I’ve turned to various external editors for AS coding joy; I used to swear by SE|PY, and more recently have been known to shout the pleasure that is using FlashDevelop from the proverbial (and virtual) rooftops. So you can imagine my excitement on seeing Jon Dowdell’s tweet about Tofino, a Visual Studio plugin adding support for Flex and Actionscript development directly in Visual Studio.

This is, I have to say, cool as hell. I love working in FlashDevelop, but as good as it is (and it is freakin’ good), Visual Studio (imnsho) takes the cake as far as IDE’s go. It’s powerful, fast, makes a developer’s life easier, etc (yes, FD does all that as well, just not quite to the same extent). It’s particularly cool in that people are seeing the benefits of working inside of Visual Studio, particularly for projects that have a .NET based back-end layer. So of course I had to download and install the beta.

Off I go, and, with beta’ed breath (ewww), fire up VS and create a new project. Lovely options - Flex App, Flex Library, or Actionscript Application. I can feel the love. Being more of an AS junkie than Flex-able, I create a new Actionscript project. I like the default project layout (though it would be nice if it asked for a default namespace); it includes a src directory, bin directory, and an html template directory (which, though I haven’t tried yet, appears to be editable and allows one to customize the html generated on publish/compile). Quickly open up the default .as file, which contains a class that lovingly extends Sprite. I hop into the constructor to add a call to super() and…

Type s and press CTRL+Space. Bam. The nothingness I am greeted with rattles my teeth. What’s this, I think to myself. No code hints/intellisense? Hrm. Maybe they’ve only got that for MXML at this point. Ok, I’ll try a Flex project. Open the default MXML, try adding an opening chevron and hitting CTRL+Space; again, nahda. Add an mx: and try again? Still no love.

Ok, it’s a beta. I try simply compiling the app (Flex now as the default project), which works beautifully, opening up Firefox and showing the “Hello, World” label. Well, that was fun.

I’m not trying to detract from what they’ve done - this is a huge step forward for the Flash (and .NET/Visual Studio) community. It will be even nicer as it continues to evolve and adds things like Intellisense support, unit testing (to be fair, it might have that now, haven’t tried it, though), a visual mxml editor, integration with the Flex ISAPI filter for IIS, etc. But to me it’s more of an alpha than a beta (ok, it purports to support debugging, which alone makes it a beta, but from a pure “writing code” perspective, there’s a lot to come.

My wishlist, in no particular or practical order:

  • Integrated ASDoc or XML Documentation (eg: it reads the documentation and includes it in a tooltip when relevant, for example when showing Intellisense or hovering over a method/class/property)
  • Actionscript Intellisense (for both intrinsic/flash and custom classes)
  • MXML Intellisense
  • Support for non .swc references (eg: reference a folder structure containing .as without bringing it into the folder structure of the project)
  • Visual MXML editor
  • Use SwfObject as the default embed methodology (or allow a choice, either global or on a project-by-project basis)

There’s probably more, but that’s my ask for today. And though my initial review may seem a bit lukewarm, I’m really, really, really excited about this. I’ll be following proress on Tofino’s development very closely.

Get it for yourself @ ensemble.com.

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

Why Constants Just Do Not Replace Enums

(Or, one of the many things that ticks me off about Actionscript 3...)

Seems like every time I talk about Actionscript, I'm ranting about something or other that's just ticking me off. I have to start posting about the things I love about it. [ed. I started this post a long time ago and haven't gotten around to finishing it until now. sue me.]

Well, not tonight [ed. today]. Soon, though, I promise.

One of the cool additions to AS 3 is the const keyword. Compile time constants are a beautiful thing. And right off the bat, Adobe started using constants all over the place. In many places, as simulated enums. This is cool, this is good, very excellent.

The big problem is that it misses the point. Enums aren't simply a way of ensuring that you don't make a type-o, letting the compiler throw an error at you because you once again incorrectly spelled "eneterFrema" (yes, I know you spell "spelled" s-p-e-l-l-e-d, I'm employing some sort of literary device, can't remember which, deal with it). Enums are there to make you code a) easier to read and b) easier to write.

I'll illustrate with an example:

GradientGlowFilter (well, actually, you can go with pretty much any bitmap filter on this one, but I'm going to use GGF for a few reasons: firstly, it doesn't include BitmapFilter in it's name, secondly, it's the one I ran into this particular issue with, so there).

The gradient glow filter constructor has the following prototype:

  1. GradientGlowFilter(distance:Number = 4.0, angle:Number = 45,
  2.      colors:Array = null, alphas:Array = null, ratios:Array = null,
  3.      blurX:Number = 4.0, blurY:Number = 4.0, strength:Number = 1,
  4.      quality:int = 1, type:String = "inner", knockout:Boolean = false)

Specifically, I'm looking at the "type" parameter. It's typed as a string, but it only has three possible values, namely, BitmapFilterType.FULL, BitmapFilterType.INNER, or BitmapFilterType.OUTER. You'll notice the default value for the parameter in the constructor above is the string literal "inner". That should have been, at the least, BitmapFilterType.INNER. That would get across (in applications like FlashDevelop and, yes, even in the Flash IDE [ed. you don't actually use the Flash IDE to write code, do you? Seriously...]) that, even though it's using constants and not enums, the value must be one of the constants on the BitmapFilterType class. Same holds true for the quality parameter. It's typed as number, default value is 1, and it needs to be a member of the BitmapFilterQuality class.

Moving to enums would solve this in two ways. For starters, it would be type-safe (eg: if you tried to pass a string, it would break at compile time). And it would be self-documenting, in that by looking at the method prototype you would immediately know what your possible values are and where to find the enum. (Never mind that naming the parameter "type" is ridiculously unhelpful...at least naming it bitmapFilterType would have cleared up what the parameter is there for.)

The truth is, these aren't huge issues, and one could argue that the additional overhead of using an enum-type of class (a la my examples posted previously) adds overhead that isn't absolutely necessary, in the form of properties, etc), but for my money the developer ease of use and clarity far outweighs that (I can't imagine there would be a huge performance bottleneck by having constants that are instances of a class instead of raw strings).

To me, the constructor prototype for this should have been:

  1. GradientGlowFilter(distance:Number = 4.0, angle:Number = 45,
  2.      colors:Array = null, alphas:Array = null, ratios:Array = null,
  3.      blurX:Number = 4.0, blurY:Number = 4.0, strength:Number = 1,
  4.      quality:int = BitmapFilterQuality.LOW, bitmapFilterType:String = BitmapFilterType.INNER,
  5.      knockout:Boolean = false)

Sure, I can look at the documentation and get the answer in seconds, but that's still seconds where I'm second guessing myself.

The other example I was going to bring up was event types (eg: new Event( Event.ENTER_FRAME ) - I finally saw an example last week of using string names for events where it actually made sense to use strings, as opposed to a fully-typed event model, but never mind that). My biggest problem with the implementation, truth be told, is the lack of consistency with where the event type constants are housed (eg. where are the packages for event types? why is ACTIVATED a constant on the Event class, but ACTIVITY is a constant on the ActivityEvent class? Why aren't ADDED and ADDED_TO_STAGE on the DisplayEvent class (which doesn't exist, ttbomk)? why are they all over the place? the list goes on...).

My point with all this is that time and time again, the Actionscript BCL does developers gross injustice by not implementing API's that are consistent and usable. Adobe should make it mandatory that every developer on the team have a copy of Framework Design Guidelines sitting on their desks.

I should probably say, again, that I really do love Flash and where it's going (and where it's been), but as it matures, these are the issues that are going to differentiate it from the other offerings (Silverlight? maybe, I don't know...they do really come at it from different angles, but hey...). And that's not me saying the Silverlight API's are perfect (truth be told, I haven't done much with them, so I can't really offer an opinion there).

Allright. Enough of a rant. Next time, I'm going to scream about the Sound API. Argh. Lovely capabilities. Scary API. Seriously. Scary.

Seeya next time, on J's Bitchings About Things Not Many Other People Care About (But, In His Opinion, They Should).

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

Simple .NET Multiple File Downloader

Jeff Atwood has completely taken over my life.

Well, perhaps not completely, but for whatever reason over the past week or so I've been reading a whole lot of posts from his archive (and by "a whole lot" I mean "every single") whenever I'm waiting for my computer to do something else. For a VB.NET developer (ha, take that, Jeff), he's pretty cool.

In any case, in one of his posts he linked to the (freely) downloadable version of the Graphics Programming Black Book by Michael Abrash, which I'm somewhat interested in poking through (as time allows). So I innocently click and am promptly presented with 70+ links to the individual pdf for each chapter.

Oh. Joy.

As you can imagine, I wasn't particularly interested in point-and-click downloading that many files (can you say RSS?), so I whipped up a quick little console app to download all the files, using Jeff Key's abso-f*&king-lutely genius Snippet Compiler (dotnet 2.x). Which, if you program in .NET (C#, that is), I suggest you download. Now. Before caring about anything I do or don't have to say.

Code for the downloader (Snippet Compiler's default helper methods included). Because I like sharing.

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Net;
  5.  
  6. public class MyClass
  7. {
  8.         public static void Main()
  9.         {
  10.                 string urlTemplate = "http://www.byte.com/abrash/chapters/gpbb{0}.pdf";
  11.                 string saveLocation = @"C:\\Graphics Programming Black Book\Chapter_{0}.pdf";
  12.                
  13.                 int fileCount = 70;
  14.                 WebClient client = new WebClient();
  15.                 for( int i = 1; i < = fileCount; i++ )
  16.                 {
  17.                         Console.Write( "downloading chapter {0}", i );
  18.                        
  19.                         string url = String.Format( urlTemplate, i );
  20.                         string filePath = String.Format( saveLocation, i );
  21.                         try
  22.                         {
  23.                                 client.DownloadFile( url, filePath );
  24.                                 Console.WriteLine( " => done." );
  25.                         }
  26.                         catch( Exception e )
  27.                         {
  28.                                 Console.WriteLine( " => error: {0}", e.Message );
  29.                         }
  30.                 }
  31.                 Console.WriteLine( "all done" );       
  32.        
  33.                 RL();
  34.         }
  35.        
  36.         #region Helper methods
  37.  
  38.         private static void WL(object text, params object[] args)
  39.         {
  40.                 Console.WriteLine(text.ToString(), args);       
  41.         }
  42.        
  43.         private static void RL()
  44.         {
  45.                 Console.ReadLine();     
  46.         }
  47.        
  48.         private static void Break()
  49.         {
  50.                 System.Diagnostics.Debugger.Break();
  51.         }
  52.  
  53.         #endregion
  54. }

Yes, I know there are probably Firefox plugins that would've done this (not to mention download managers), but I couldn't be bothered to try and find one. Besides, this way was more fun.
And yes, I know that this code is completely custom for downloading this particular series of files, but it could be easily and quickly modded to handle multiple scenarios (have the user enter a format, use a text file full of urls, etc, etc). The point here was fast.
And no, there's no progress indication. Deal with it. I did.

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

SCOPE_IDENTITY vs. @@IDENTITY

I stumbled across some extremely handy information today, looking for something completely different.

The deal is such:

When writing your CRUD operations, often-times you'll find yourself writing SQL that looks something like this:

  1. CREATE PROCEDURE dbo.app_CreateSomeDataPlease
  2. (
  3.         @someData nvarchar( 1024 ),
  4.         @moreData nvarchar( 2048 ),
  5.         @irrelevantNumber int = 42
  6. )
  7. AS
  8. BEGIN
  9.         INSERT INTO
  10.                 MyTable
  11.                 (
  12.                         SomeData,
  13.                         SomeMoreData,
  14.                         IrrelevantNumberForNoGoodReason
  15.                 )
  16.                 VALUES
  17.                 (
  18.                         @someData,
  19.                         @moreData,
  20.                         @irrelevantNumber
  21.                 );
  22.                
  23.         SELECT @@IDENTITY AS NewDataId;
  24. END
  25. GO

Which is all good and well (obviously a contrived and simple example). You expect to get back the new ID for the item you just created, right?

Maybe not.

Y'see, there are these things called "Triggers". You've heard of them, maybe played with them, whatever. Basically, a Trigger is SQL that gets "triggered" when something happens, like, perhaps, an INSERT, UPDATE or DELETE.

Now, I'm not going to debate whether Triggers are good, bad, or Satan in disguise (they're not). The point here is that, uh-oh - if you have an INSERT trigger on the table you're creating your data in, and that Trigger creates a row (or rows) in another table (or tables), your @@IDENTITY is not going to do what you think it's going to do.

Why not? Hang on, we'll get there.

There's another method of retrieving the last identity value, and that is the SCOPE_IDENTITY function. And the very, very subtle difference between SCOPE_IDENTITY() and @@IDENTITY is enough to trip you up for hours on end (if you hadn't read this post, of course - bear with me, we'll get there).

So what is the difference between SCOPE_IDENTITY() and @@IDENTITY?

Scope.

And I don't mean the mouthwash.

To quote the MSDN documentation:

SCOPE_IDENTITY and @@IDENTITY return the last identity values that are generated in any table in the current session. However, SCOPE_IDENTITY returns values inserted only within the current scope; @@IDENTITY is not limited to a specific scope.

A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.

What that means is that if have a trigger that fires on INSERT (into Table1) and INSERTs into another table (let's call that Table2), returning @@IDENTITY will return the new identity value from Table2, not Table1.

Maybe that's what you want, but probably not.

To make a long story short, to be safe, you're probably better off using SCOPE_IDENTITY to protect yourself in the event that a Trigger you don't know about* is firing and inserting somewhere else. And if you know about the Trigger and you want the ID from that, use @@IDENTITY.

Read a bit more about SCOPE_IDENTITY at the MSDN.

* - In all unfairness, you should know which triggers (if any) are firing, but...hey...someone else on your team may add one later on and suddenly your app breaks...now you'll know why and how to fix it...

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

FITC, and, What Is So Bad About Hungarian Notation?

Another year, another rockin' festival, for some another 3 (or 4) hangovers. FITC was, yet again, incredible. Highlights for me included John Maeda (who is a very quirky and engaging speaker...a low key presence with a whole lot of personality), North Kingdom, and Danny Stillion of IDEO. Not to mention meeting (and re-meeting) people, including - Paul Ortchanian, Gary Stasiuk, Evert Pot, Kristin Henry, and loads of other people (and by loads I mean not too many, but anyway...).

Of course, being mistaken for Justin Everett-Church was fun, for no particular reason.

Which, surprisingly, brings me to my point - what is it that is just so unbelievably bad about Hungarian Notation? (Or, rather, why do so many people seem to just hate it?)

I was chatting with Paul Ortchanian after his talk (we'd met at FITC last year, briefly, which is apparently why he mistook me for Justin), and I mentioned that I thought his presentation was great, but his use of Hungarian was killing me - oCamera in particular. In a flight of genius, I even showed him the Framework Design Guidelines book (yes, I'm that big a geek that I carry it around with me), expressing the opinion that it is perhaps the most important book for the Flash community - we're very good at solving problems and writing code that works, but writing solid, usable APIs seems to be beyond all of us (I include those writing the Flash equivalent of the BCL - come on: stage.stageHeight, for crying out loud? what were you thinking??).

Back to the point - what is so bad about Hungarian Notation? You know, naming things like oMyObject, iTreeSize, bIsThisTrue?

You may even see the problem right there.
(more...)

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

Extension Methods Are Swell

Really.

They are the difference between writing code that looks like this:

  1. string email = Request.QueryString["email"];
  2. if( EmailValidator.IsValid( email ) ) { ... }

and writing code that looks like this:

  1. string email = Request.QueryString["email"];
  2. if( email.IsValidEmailAddress() ) { ... }

And a whole lot more...

I am, however, far too tired, frustrated and various other not so glamorous things, so I will leave it to you to hop on over and read Scott Guthrie's insanely detailed post on the subject.

Oh, yeah - read it here.

Andre, Jon - this was for you. Everyone else, thank them.

Note: the code samples above were shamefully ripped from Scott. No sense reinventing the wheel, right?

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati