Search This Blog

Monday, February 7, 2011

Comma-Separated-Value Strings As Static Const Collections

Have you ever wanted to define a constant set of specific values in ActionScript 3 or JavaScript? In ActionScript 3, you could of course use a private Array variable within a class definition, implementing external access to it as a read-only getter. In JavaScript, you could implement a closure within your object structure that would return the set of values as an Array object. However, both of these implementations have a number of holes, assuming you want your set of values to truly be constant.

The Array objects in both variants of ECMAScript-262 are mutable, meaning that they are subject to change at runtime. Additionally they are objects and thus are passed as pointers to their place in memory, meaning that any changes made on the arrays will ripple throughout your code, affecting any code storing a reference to your "constants".

Immutability
When you truly want something to be constant, you want that something to not only never change but be impossible to change at runtime. Collections in ActionScript and JavaScript are mutable by their very nature: they are designed to change. Collections are sorted, the keys and values are shifted, pushed, and deleted, etc. Sure, you can define a variable like the following:



const MY_COLLECTION = [1,2,3,"bob"];



However, at runtime, any references to MY_COLLECTION can move 2 before 1, delete "bob", etc. Not good if you intended the collection to be constant, and not good if you don't want the changes in the collection to ripple throughout your code base.

How do we achieve the intended results? By using an immutable type to store the value.

Strings
So we need an immutable type. Strings are immutable. This means that they do not change. You might be asking, "Wait a second. I can change a string. I can call substr(), push new characters on the string, concatenate it, etc. Strings can change." Actually they can't.

Strings are not only value types, but are also immutable. When you update a string by concatenating another string to it, you are actually creating a new string from the two concatenated substrings. This substring is then placed in memory at the location of the old string, making it appear that the string has changed. The string itself has not changed, it has been replaced.

This means they make effective constants. You use string constants all the time in ActionScript: Event.EVENT is one common example, used in event addition and handling. Defining a usable collection constant is very easy as well: use a string.

Using Data Transfer Formats As String Constants
A simple string can't act like a collection can it? Ever heard of CSV? It stands for comma separated value, and it is a data transfer format. Data transfer formats are useful formats for encoding objects into a transportable form. In the case of a collection, we're talking about encoding a list of values into a string.

For simple collections of value primitives, CSV formatted strings work quite well:


const MY_COLLECTION = "1,2,3,'bob'";


A CSV doesn't have to be comma-separated, though. If you want your values to be strings that contain commas, you can use spaces, tabs, underscores, exclamation marks, separator tokens ("%sep%"), special unicode characters (\u10225), etc.  As long as you separate each string with the same token, all you need to do to turn the string into an array when you want to use it is to call split() on the string, passing your separator token as the parameter. This will return the collection.

I particularly like using CSV constants when I need an enumeration of a few values, like "cat", "dog" or "turtle" for a list of possible pets.

const PETS = "cat,dog,turtle";


This type of enumeration comes in handy when I'm validating entries in setters. For this example, I want to make sure that the value for the pet setter is either dog, cat, or turtle. Wouldn't want any rats or roaches for pets.

public static const PETS = "cat,dog,turtle";
private var _pet:String;
public function set pet(value:String):void{
    if(PETS.indexOf(value) !== -1){
        _pet = value;
    }
}


You can use any of the String object methods on your collection constant. Here I used the indexOf() method to check to make sure the value was valid.

CSVs may not cut it if you are using more complex objects. In those cases you can use other data transfer formats, like XML, JSON, or YAML. Just be sure to use the string notation of these formats, so that they are immutable. These types of constants can be rehydrated throughout your applications and libraries where they need to be used, and the resulting objects can even be changed, without affecting other portions of your application that use the same constant.


Happy coding!









Friday, February 4, 2011

RE: You Must Learn JavaScript

If you are already a .js Ninja then you know about many of the things I'm going say in this post, so you can skip it. This post is a response to a post on theNerdary post "You Must Learn JavaScript." In the post, Kenny Meyers insists that the single most important language to learn is JavaScript, because 99% of companies will have need for it. Some comments on the post stipulated that JavaScript is important for the web developer only. This used to be true, but is no longer the case.


JavaScript: Not Just For Web Developers
For many years, JavaScript was a simple way to do really bad things to your Geocities page. Marquee scrollers, biplane banner-like mouse cursors, auto-scrolling text, pop-up bombs, etc. Then it became a way to show and hide elements by manipulating css properties. Then came Ajax, and with it, the Ajax Revolution that has recently led to the whole HTML5 vs. Flash debate.


While all of this was happening, some were trying to push JavaScript into new arenas – embeds in Java applications, server-side code, and even desktop APIs. Rhino was one of the first server-side JavaScript implementations I can remember. The Windows Media SDK used it as the scripting language when Windows Media Player was embedded in desktop applications.


None of these efforts were really taken as serious applications built on JavaScript, and today it remains largely a DOM manipulation and asynchronous request language. However, the future is coming, and that future probably is JavaScript.


Why? JavaScript engines have become fast and robust. This means JavaScript can do more in less time and do it more reliably. I liken it to the performance improvements made to the JVM that pushed Java into being the single most important language on the planet circa 2000. Another similarity with Java is that, for the most part, JavaScript is the write-once-deploy-everywhere language Java was supposed to be.


In addition, the language is ubiquitous. Nearly every web-site in the world has at least some JavaScript, and nearly every web developer knows at least some JavaScript. This means that there already exists an enormous pool of talented js developers for businesses to draw from to create great applications. The adoption rate of a language is a huge contributing factor to a language's success. Smalltalk is a great language. It influenced nearly every modern OO programming language. Hardly anybody uses it. Haskell is great too, however it mainly remains relegated to academia. JavaScript, on the other hand, is used by nearly every major corporation and every major web enterprise worldwide.


These two developments, talent pool and performance, have created a pressure for JavaScript to move beyond the browser.


Node.js
Node is an evented IO framework built on V8, Google Chrome's JavaScript engine. What can you do
with Node? How about a highly scalable http or XMPP server. How about a database? JavaScript has invaded the server with a vengeance. Check out some of the modules available for Node. Want to build that next great thing but don't know .net, PHP, Java, or Ruby, but do know js? Give Node a try.


Appcelerator's Titanium
Titanium brings JavaScript to the desktop (and mobile) world. Why make a desktop app when you can make a web app? Because the interaction is richer and the runtime experience is constant. When you make a commercial web application you have to take into account the wide variation of platforms and bandwidths your users have access to: Windows XP/Vista/7, Linux, Mac, Safari, Chrome, Opera, IE<9, IE 9 beta, conqueror, etc. More often than not, you have to tame down your feature set, or support a number of different feature sets, HTML markups, and CSS presentations to reach all of your available audience. Titanium allows you to use all the new HTML5 markup and CSS3 presentation technologies without having to worry if your target audience only has access to IE6 on Windows XP. It is able to do this because it uses the WebKit rendering engine as its presentation layer. It also exposes file I/O, OS integrated drag and drop, and many of the other features that are not easily accessible to a web application. It also means that you don't need to know Flash/Flex/Air, the .net Application Framework, GTK, or Cocoa to build desktop applications that can run offline and synchronize with the cloud when connected.


Mobile
Like it or not, the world now holds the computing power of the Playstation 2 in the palm of it's hand. If you thought developing for the fragmented desktop or web world was difficult, mobile is a whole new ballgame. Android is fractured, requiring you to know every version of the framework, iPhone suffers from less prevalent fracturing, BlackBerry is still behind those in functionality, and all use different languages for their app runtimes. Though iPhone rules the mobile market, no one OS dominates the market enough to simply ignore the other mobile operating systems. The one thing that permeates all of the major players is the web, and JavaScript is the only scripting language that runs in browsers, making it the only language capable of reaching users on all platforms.


Conclusion
JavaScript is the future. If you want to be a profitable 21st century software firm or a successful developer in the 21st century, you need to know JavaScript. You need to know JavaScript because it is everywhere, from the database to the iPhone. It's influence is growing. You must learn JavaScript because it is becoming this century's version of the C programming language: ubiquitous and used everywhere.


As always comments are welcome.







Wednesday, February 2, 2011

Flash Builder 4 -dump-config Additional Compiler Options Documentation Bug

According to the Adobe Online Documentation for Flash Builder 4, when you want to dump the config file of a project you have to use the absolute path to define where you want the config file to be. This is incorrect.

To dump a config, open Project->Properties->Flex (Library) Compiler and add the following to additional compiler options: -dump-config {pathRelativeToProjectSrcFolder}/{configFileName}.xml. For me, {pathRelativeToProjectSrcFolder} is ../ANT as I store my configs for automated builds on Hudson inside each project under the project root in ANT. I usually name my config file the name of the project with -config.xml. So for an imaginary project called Dump, the file structure looks like this:


  • Dump
    • src/
      • Default Package/
        • Dump.mxml
    • libs/
    • bin-debug/
    • ANT/
      • dump-config.xml
In the Dump project, the additional compiler args to add are: -dump-config ../ANT/dump-config.xml.