If you don’t have it, you’re in trouble…

I bumped into a friend of mine on the way into work this morning. I’d heard that she’d recently started a new job (really, I’m a Facebook stalker…much easier to keep up with friends like that - no need to actually have a conversation…), and I was curious how it was going. Her reply (paraphrased):

“It’s been a switch moving to an [Advertising] agency. They don’t even have source control! And I only have one monitor - it’s killing my productivity!”
Name withheld to protect the innocent…

Let that be a lesson to you.

Really, if you aren’t using some form of source control, you’re in trouble. And do not make the mistake of confusing source control with backup: the intent of backup is to ensure that you always have a certain entity, be it a file, a set of files, perhaps an (il)legally downloaded music collection. Source control isn’t concerned with the whole, final product; its intent is to capture change. Hopefully, as a developer or designer or hybrid, you see the value in that. If not, if you haven’t been bitten by this particular dog, I’d recommend you start using source control and avoid it entirely.

You see, developing a product, be it a website, mashup, game, desktop app, what-evah, is an iterative process. You go from A to B to C to D. You’re always in flux, always moving, incorporating new ideas, recalibrating, learning and relearning. And one day you’re going to break something that worked fine yesterday. Or have a client tell you they liked it the old way. Hell, you might like it the old way yourself! And then, boom - your ever-overwriting backup strategy goes to hell. You’re stuck going back to figure out what the hell you did to have it work the way it did before. With source control, you can simply roll back or merge the old with the new (well, hopefully simply…).

Now stop being selfish and thinking only about yourself. Most of us don’t live or work in a vacuum, after all. You’ve got multiple people working on the same set of files. To quote the Big Bang Theory, “I believe the appropriate metaphor here involves a river of excrement and a Native American water vessel with out any means of propulsion.” Overwriting other team member’s changes, losing your own changes, it’s a nightmare.

Really. I’ve been there.

So do yourself a favour: set yourself up with source control. First day at the new job, and they don’t have it? Set it up. Quit if they don’t let you. What to use? Lucky for you, you’ve got lots of choices. Microsoft shop? Use VSS. (Ok, that’s a joke…if you can afford it, and really have the need, pick up Team System.) Set your team up with SVN (and, if you’re on Windows, grab Tortoise - you’ll thank me). Find a plugin for your IDE of choice (you do use an IDE, right? sadly, there’s no SVN plugin for FlashDevelop that I know of - yet - but working with Tortoise makes it relatively easy). Go to town. Don’t have your own server or infrastructure to install on? Use unfuddled.com - an excellent project management and collaboration tool that includes both SVN and GIT, along with a suite of other tools for you and your team.

So there you have it. Many have said it more eloquently before me, and many more will say it better (Jeff Atwood of StackOverflow.com fame, for one). But if you’re reading this, forget about how horrific my prose is this evening and get yourself some source control.

(Don’t even get me started about how bad email is for communication…set yourself up on a collaboration platform and get the important crap out of your inbox…)

(Ok, I really think I’ve put off doing my timesheets long enough…bags…)

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

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

flash.media.SoundMixer: All your sound belong to us

Seems the SoundMixer class is a singleton. And a big one - it exists across multiple swfs and domains. Which leads to a bit of a problem.

For example, open the following urls in separate tabs in Firefox (allow the first to fully load before opening the second):

AFC Components: Reflection
Joe Satriani

That’s what I did, and (assuming you’ve got the Flash 9.0.115 player installed) you should see the same thing I did: a big security error stating that:

SoundMixer.computeSpectrum: http://www.satriani.com/2004/SatrianiPlayer4.swf cannot access http://www.afcomponents.com/flv/vid/sample.flv.

Seems to be a bit of a problem. Really, you would expect that SoundMixer would isolate itself to sound playing in the current .swf, or at least on the domain. Or, if it is going to grab the sound data from all swfs playing, it should do it without worrying about security and domain boundaries…

Incidentally, this security error doesn’t occur only when it’s cross-domain. I had the same problem when putting two swfs on a page that both attempted to grab computeSpectrum data.

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

Silence is Golden (and a little ImageMagick)

Man. It has been too long.

Been busy. Obviously. New kid, new job, new haircut. Another new year, another birthday (hit the big time this year, too…wow).

This is me getting back into the swing of things. Lots to blog about. Hurrah!

Bet you’re all excited.

This post’s fun involves a simple ImageMagick command to convert an animated gif into a sequence of png’s. Simple, I know. But as I originally did this on Monday and had to do it again today and neglected to document how I did it on Monday, I thought I’d take this opportunity to store it here, on my much-neglected blog, for posterity.

At the command line:

convert <IMAGE NAME HERE>.gif +adjoin <IMAGE SEQUENCE NAME HERE>_%03d.png

Obviously, you’d be replacing and with actual values. And you will need to download and install ImageMagick.

Ah. It’s good to be back. Ta ta for now…

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