Friday, February 3, 2012

JS: Why not just use [fill in name] framework?

I get this question when I discuss why I'm working on my own JS framework.

There's a lot of great frameworks out there nowadays; MooTools seems to be the emerging favorite. The PureMVC port uses it, all kinds of other component sets and whatnot seem to find it useful, so you end up installing it along with certain libraries, and so forth. Prototype, Backbone, YUI, and any number of other ones that are the thing du jour, are cropping up and so on.

I've been in development for about 20 years now. In that time, I've seen a LOT of frameworks, many of which no longer exist, and many that caused a lot of headaches in the long run, especially if community support or interest in them fizzled out.

To that end, I've decided, as a developer:

- Frameworks are a good thing as far as consistency, integration of developers into a codebase, and so forth. In fact, I have seen this benefit realized so absolutely, that there is no doubt in my mind that your typical project will benefit from at least some degree of plumbing framework.
- Frameworks can become a problematic thing if developers are allowed to work around, or abandon, the framework.
- Frameworks can be a horrible thing if you picked the wrong one, and/or your developers just stop using it because they think it's unnecessary.
- Frameworks should be unobtrusive; you should barely even know it's there if you're not using it, and it should add very little bulk to your codebase.

As a qualifier, I'm not talking about component frameworks. I'm talking about architectural frameworks.

So, I've come to believe, that along with a framework, comes the responsibility of educating your developers in it's use, and ensuring they use it. This means reviewing their code and making sure they're not cheating (e.g. instead of using a notification and/or event to exchange info, they are accessing "parent"...you see this ALL the time, "because it's easier/less/code/some-other-rookie-reason").

What's my point?

At this time, the notion of the "real" JavaScript developer, is still fairly immature. Crockford's book pretty much rules the roost as far as how to "think" in terms of JavaScript. This statement may not seem true to the Sencha engineers or Yahoo guys. But for your typical developer out there, particularly transitioning from the world of ActionScript, the path to writing solid, consistent code, and what tools to use, is unclear. Aside from JQuery for DOM manipulation, nothing is certain.

The biggest problem appears to be, the nature of JavaScript itself. It's about using functions as objects, and dynamically altering those objects to be useful in the context you need it for. Duck typing, shallow hierarchies, and such are what JavaScript is all about.

But...most developers aren't used to that, and many frameworks attempt to hide this way of thinking in favor of providing an artificial structure that "programmers" are more comfortable with, that being, classes, inheritance, interfaces, and so forth.

At this point in time, I think that's a mistake. We need to learn to think in JavaScript first, and find out how we can avoid mistakes we've made in the past with things like AS1 (excessive prototype manipulation, being dynamic to the point of being unable to tell one object from another without extensive duck typing and/or "flag programming", abuse of globals, etc.) while at the same time evolving the known patterns we're all familiar with to take advantage of strengths JavaScript offers, particularly, what exactly the power of "functions as first class", and the differences in how JavaScript resolves scope, means.

So to that end, I'm writing my own framework, with what I know about UI development and what I've observed over the years works (and doesn't), without losing site of the fundamental nature of ECMAScript development, which is different than classic OOP. Call it FOP (Function Oriented Programming), or what have you. But don't try to turn it into something it's not.

If you've concluded at this point that I'm some kind of framework hater, you're wrong. I have used PureMVC and RobotLegs extensively, have background in Cairngorm (which was never a good idea for UI dev imho) and experimented with many others. I like RobotLegs the best for one main reason; it is unobtrusive. It can live in your app and you can use it, or not use it, and easily combine it with other libraries. And it use EXTREMELY useful, and EXTREMELY powerful. This is in contrast to say, JSExt, which basically requires that you become a JSExt developer. Again, I have worked with JSExt a bit, and it's powerful and useful. If you're project is right for it, the benefit will be great. But it's hardly unobtrusive.

My indicators of success for my own framework will be:

- It should not require any other library unless that library has been proven stable for years and is in massive adoption by the community and the enterprise (e.g. JQuery, which my framework uses).
- It should be small. Very small. Hopefully, a handful of utility classes and possible a couple of prototype mods, but that's it.
- It should be powerful.
- It should foster decoupling and encapsulation of concerns.
- It should be repeatable and consistent.
- It should not hide the fundamental nature of javascript, which has nothing to do with classes as we know them.
- Other developers should find the paradigm familiar, e.g. more-or-less MVC.

So far, so good. I'm working on a very large project, currently in AS, and helping the company develop the strategy to go to JS/HTML (what many incorrectly call "an HTML5 app", which has the same meaning to me that the "Web 2.0" moniker had).

As always, thanks for visiting.

Friday, January 27, 2012

If using JQuery, Careful adding Methods to Object

This was tricky one. I've been writing a JavaScript framework based on "The Teaching of Crockford". That is, no deep heirarchies, functional inheritance, etc.

One of Crockford's utilities is this:

// enables a form of "super"
Object.method ( 'superior', function ( name ) {
var that = this, method = that [ name ];
return function ( ) {
return method.apply ( that, arguments );
};
} );

This is a way of invoking a "super" method on the 'object' that you have inherited from. I don't actually use it; I just included it as a "well, I'll probably want to do that sooner or later" sort of thing (so I slapped it in a utils.js file for the time being).

My jquery ajax calls suddenly wouldn't work. I kept getting this message:

Uncaught TypeError: Object function ( name ) {
var that = this, method = that [ name ];
return function ( ) {
return method.apply ( that, arguments );
};
} has no method 'test'

Umm...wtf? So, I had to delve deeper into it...and in the unminified version of jquery, I found on line 7763, a loop that checks for the content type of the ajax response (so the call was being made, and the response returning...it was the processing of the response that was breaking).

The function is:

// Check if we're dealing with a known content-type
if ( ct ) {
for ( type in contents ) {
alert ( type + " >> " + contents [ type ] );
if ( contents[ type ] && contents[ type ].test( ct ) ) {
dataTypes.unshift( type );
break;
}
}
}

Because I had added a function "superior" to Object, "superior" now became part of the items that the response type was being tested against. It failed ("superior" did not contain a function "test", which is in the ECMAScript.js2 file, not the jquery one, click on "test" in WebStorm and you'll see). So the ajax call failed.

Solution: initially, remove the modification to Object, which I wasn't using anyway. While I understand that I could add code to JQuery to ignore this sort of thing, modifying jquery is an iffy practice, because you may have to upgrade it, etc.

A better solution would probably be to make JQuery handle the error in the event it runs into this sort of thing.

As always, thanks for visiting.

Wednesday, January 25, 2012

JSBase Javascript Framework

So...I've undertaken the task of creating a JS framework that is:

- Based on best practices as defined by some of the luminaries I've been researching (things like modules, shallow heirarchies, etc.).
- Does not insulate the user from JS itself by providing an entirely different model for development. I guess I'd call it "unobtrusive framework" design.
- Has easy to understand, well defined domains of concern (model, view, controller, command, renderer, page...that's it, at least for now).
- "Feels" familiar to your average UI developer (meaning, employs general principals of MVC).
- Makes hierarchies explicit (as opposed to making them implied when using them). I'm probably wording that poorly, but you'll see what I mean soon.
- Can be used for typical web apps (for instance, not as massive as Ext JS, not as structureless as just scripting with JQuery).
- Uses JQuery (I mean why not. JQuery is awesome).
- And so forth.

Why go about this? I've been a UI dev for a long time, and I generally find that the lighter the framework, and the closer it is to the technology you are actually working with, the better. It's why I like things like RobotLegs in the AS world; aside from the context setup and mapping, it feels like I'm working in plain old AS 90% of the time, but there is no denying that the loosely coupled notification model it provides makes it easier to build an app that is more self documenting, modular, and maintainable. I see no reason why these concepts can't be more rigidly applied in the JS world to the same beneficial ends.

So...simple and lightweight, easily extendable, and always feels like JS, which is meant to be flexible and useful with a relatively short learning curve.

I'll post a first iteration of the basics soon.

As always, thanks for visiting.

Thursday, December 1, 2011

Google App Engine Easy crossdomain.xml Pattern

Been struggling to figure out how to put a crossdomain.xml file in a GAE app? Static files dirs and all that getting in the way?

Fear not; the requirement for a crossdomain.xml file is only that it be available as a text/xml response type at the root address of your application.

It does NOT have to actually be a physical file (that's the trick).

So, in your GAE app (assuming you are using Python and that you know the basics of setting one up...)

Add this class to your main.py script (this is the script spec'd in your yaml file as the main execution script).


class SendCrossDomain ( webapp.RequestHandler ):

def get ( self ):

crossdomain = '<?xml version="1.0"?>'
crossdomain = crossdomain + '<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">'
crossdomain = crossdomain + '<cross-domain-policy>'
crossdomain = crossdomain + '<site-control permitted-cross-domain-policies="all"/>'
crossdomain = crossdomain + '<allow-access-from domain="*" to-ports="*" secure="false"/>'
crossdomain = crossdomain + '<allow-http-request-headers-from domain="*" headers="*" secure="false"/>'
crossdomain = crossdomain + '</cross-domain-policy>'

self.response.headers [ 'Content-Type' ] = 'text/xml'
self.response.out.write ( crossdomain )


Now, later in your main.py file, in your "main" method typically, where you spec url endpoint handlers, make sure you have an entry for crossdomain.xml.


application_paths = [ ( '/crossdomain.xml', SendCrossDomain ) ]


Now when a user hits the url /yourappid.appengine.com/crossdomain.xml, the SendCrossDomain class will respond to the GET request with XML data sent as text/xml, which satisfies the requirement for the Flash player.

As always, thanks for visiting.

Wednesday, November 9, 2011

Host a static Flash app in the Google Application Engine

Sometimes the short posts are the winners.

I've seen more info on this than you'd believe, and for the most part, it just all seems wrong and/or overly complex. I've even read the GAE book and it's not there.

So I went through the config app.yaml options one by one, trying everything. This is all there is to it:

- Create a directory on your machine; this is the deploy target for when you run appcfg.py upload.

For instance, create a directory at the root of your hard drive (mac or PC), "deploy".

- In that directory, create a subfolder, call it, "flashapp".

- In that subfolder, put your flash/flex stuff stuff (swfs, swcs, etc.).

- Put an app.yaml file in there, config'd like this:

handlers:
- url: /(.*)
static_files: flashapp/\1
upload: flashapp/(.*)

Run the appcfg.py upload command, pointing at the deploy directory (NOT the flashapp directory).

Done it several times, works fine. No main.py etc. files required.

Thanks for visiting.

Monday, October 24, 2011

Using PyAMF in the Google Application Engine (Python AMF gateway for Flash Player apps)

Just an update on a prior blog I wrote; I'm using PyAMF in my latest GAE project, and it's working quite successfully. I haven't put it into production yet, but I see no reason why it wouldn't proceed successfully.

PyAMF provides a Google module that makes integrating with a standard GAE startup class very easy. Adding and altering services is just a matter of adding an entry to the services object, and writing the class or method to back it. I use a command pattern, so my service entries look like { 'myservicename' : MyServiceNameClass.execute ( ) }

You can find more about PyAMF (AMF for Python) at their website, www.pyamf.com

As always, thanks for visiting.

Wednesday, October 12, 2011

PyDev and PyAMF; force them to play nice

Short one: I use PyDev for my google GAE efforts.

I used PyAMF as detailed in the PyAMF Google App Engine tutorial (which is braindead easy; just copy the pyamf directory into the base of your GAE project). When added to a vanilla GAE project created with the GAE SDK tool, it worked fine.

But then I created a project in Eclipse with PyDev; it's always worked. But I dumped in the pyamf directory and, although auto complete worked and I could "click into" the pyamf classes after importing, the app wouldn't run; import errors (no such module). I knew it was a pythonpath problem of some kind, but I couldn't figure it out, and I tried everything.

I eventually did this, and it worked; I retried it several times, it seems to be the fix for this sort of thing, possibly any such issue related to using a PyDev project.

Create project in PyDev, but do NOT configure python path (use the "configure later" option), and do NOT configure src directory; just use the base project path. Do all other configs as normal (your GOOGLE_APP_ENGINE config and so on, as if you were doing a usual project).

Then drop your PyAMF directory into the root of your PyDev project folder (remember, you don't have a src directory), doctor up your main.py to use the WebAppGateway and so on, and it finally sees all the imports and works as expected.

No idea what's going on, I'd say there's something going on in the way PyDev interprets paths vs. the way many libraries like PyAmf are set up to do their imports. I'm sure there is an elaborate answer to this involving site-directories and so on, but all I wanted was for my PyDev project to see my PyAMF modules properly, and the above steps, which simplify the PyDev project config drastically, seems to work.

Hope that saves sombody some effort, it killed half a day for me.