6Aug
There are 2 problems with creating classes in JavaScript. 1) if you create classes in separate files you may need some system to tie the files up together for speed purposes. 2) typically your might lose your function names while you debug if you aren’t careful. In other words, you might be seeing tons of anonymous functions when you debug. There is a balancing act that goes on here.
How to define a class and methods typically:
Method 1:
function MyClass() {
}
MyClass.prototype.myfunc = function(){
}
Method 2:
function MyClass() {
   this.myfunc = function(){
   }
}
Method 3:
var MyClass = {
   myfunc : function() {
   }
}
In all 3 of these techniques you lose the name of the function in the debugger. Why? Well because your functions are technically anonymous.
function() {}
vs
function bob(){}
So how can we make this happen? Well… how about this:
MyClass.prototype.myfunc = function myfunc(){}
Yea, that actually won’t work everywhere unfortunately, but this will:
function MyClass{
   function MyClass_myFunc(){
   }
   this.myFunc = MyClass_myFunc;
}
It is a bit repetitive, but this will help you find where issues are occurring in a debugger. You debugger will now state the issue came from MyClass_myFunc() instead of (?). I believe some modern browsers do actually convert the (?) to the right function, but I believe it stops at some point in the call stack. So this is great!
Well you might also wonder how to namespace? What is a namespace in javascript anyways? Well a namespace like anything other than a “primitive” in javascript is an Object. It is defined:
var mynamespace = mynamespace || {};
This will either define a namespace named “mynamespace” as a new object literal OR it will use the existing mynamespace object in the current scope. So to add a class to our namespace we would just add our class to it:
function MyClass{
   function MyClass_myFunc(){}
   this.myFunc = MyClass_myFunc;
   mynamespace.MyClass = MyClass;
}
The problem with this is that we have both: MyClass the global defined and mynamespace.MyClass. To prevent this from occurring we wrap everything up like this:
var mynamespace = mynamespace || {};
(function() {
   function MyClass{
      function MyClass_myFunc(){
      }
      this.myFunc = MyClass_myFunc;</span></div>
      mynamespace.MyClass = MyClass;
}})();
Using the power of closures we have limited our globals to 1. We ONLY have mynamespace exposed globally. Nowwwww, we got 1 other thought that we should think about. What happens if our class depends on other classes? I’ve been looking at a good way to mimic Node.JS’s commonjs library client side. I think require.js will work well for this. How we might want to define our files with require.js:
var mynamespace = mynamespace || {};
require(["jquery"], function($) {
   function MyClass{
      function MyClass_myFunc(){
      }
      this.myFunc = MyClass_myFunc;
      mynamespace.MyClass = MyClass;
}});
Maybe? I think this looks good. It mimics the functionality we had earlier by limiting our global usage. You might be wondering what require is doing. Well, basically it is acting like a map. You specify where jquery is located and if it isn’t include it will get included. You can do this with all your classes in the app.build.js file defined by require. Note, that this does to some degree break from our notion of joining files together to optimize a website. While I am still investigating this, it seems that once a dependency is loaded requirejs will not load it again. This means that require might actually test for the existence of the dependency and if it isn’t around THEN load that file. This should allow you to use require’s optimizer to pull in various portions of a project at load then the rest later. Still reading, but this seems like the most optimal setup! 🙂
By the way, using backbone.js also forces you to adhere to the above conventions!
Sources:
Share/Save
15Jul

Ok, so it has been a while since I’ve posted. It has been a busy last couple of years! I’ve been working at NetApp but just gave notice to start working somewhere new. I had a few abandoned side projects and I am now embarking on a brand new one. I’ve learned a ton. Mostly, I’ve learned what might make a project successful and what makes it fall apart. Today I am going to talk about a little game project we are putting on hold.

There was a project a few of my friends were working on where we decided merge music and gaming together. We had this epic plotline, with awesome episodic content in mind, and various other great concepts. We even had a working prototype of the game engine with some programmer art and some actual artist content. We had plenty of concepts, but when it came time to tying things together and defining deadlines everything would fall apart. We ended up in endless development time for various animations. Promises of “it will take 4 hours” turned magically into 4 months later. When it came down to it was too hard for a half committed team to execute, and definitely too hard for some of the team’s first game.

I stepped back. I know we had a talented team, but I really wanted to make a big impact at a smaller scope so I went back to the drawing board. We needed to get our little team to start thinking smaller/simpler so I threw out the idea of putting our current project off in favor of something more easy to execute. I proposed a standard shoot’em with a few twists.

The other thing I realized is that our team was missing a dedicated game designer. Someone who would really drive the game mechanics and be a champion for awesome level/game design. I reached out to one of my old friends from the Game Development Club at SJSU. He grilled me initially (mostly about how I didn’t think the iPhone was all that special when it came out to which he scoffed), but I think he liked the new premise for the game. I proposed a simple shoot’em up targeted at the OUYA with timed music elements for combos and such. The convo took a life of its own. We both proposed extremely stupid things and expanded on them to make them great. We thought making this a purely cooperative type game. We instantly considered latency issues and how that might impact the gameplay mechanics. We decided to go back and do some research and mock some things up. I immediately opt’d to get an early developer OUYA, which should be coming in by the end of the year some time and in the meantime start developing a simple engine to get us started!

Starting over is somewhat disheartening, but I think it can be refreshing and freeing as well. I am not considering anything a failure. They were all good ideas and could all potentially become something with the right direction. They all taught me a little something though and aided in focusing and explicitly defining my intentions. There is a concept in software development called “coding by coincidence”, it occurs when you achieve your desired outcome but aren’t quite sure why it occurred. I now think that this rule could by altered for the business world as well. You should always be deliberate when designing a product. Magical spurts of popularity do occur, but you should know exactly why and how they occurred. It is possible to “get” lucky, but I believe intent will deliver more guaranteed results.

12Jan

So, I read this article a couple days ago: http://mark-story.com/posts/view/testing-cakephp-controllers-the-hard-way . As a result I started pulling my hair out. I decided that is too much work. Perhaps CakePHP 1.3 fixed some of the issues mentioned in that document, but no one has really documented anything. In any case, it took a few days of experimentation, but I got a nice template going. I see a ton of people interested in testing now a days, one thing to remember when you are starting out is that we are only testing controllers, and as such should only test what THIS controller is doing. Controllers in this sense only transfer data from one place to another, add a little bit of data, and really function as  glue between models, views, components, utility classes etc. SOOO you should not be testing auth methods or if data is saved (thats what the tests for those classes are for. Furthermore, don’t test cake internal functions.

A couple more notes before the code…
– You need to set your debug level to 3
– This was a test straight from a CakeTestCase I started working on
– I tried a few ways to get access to auth/session data. This seemed to be the easiest way to do this. Simply login to your site with the user level that you’d like to test (or stay logged out). I tried to manually set the session data. I think cake doesn’t like that, and kills your session as a result.

<?php
/**
* @author parris
*/
class LrapackagesControllerTest extends CakeTestCase{
    /**
    * These should go somewhere more global
    */
    private function genRandomString() {
        $length = 10;
        $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
        $string = '';
        for ($p = 0; $p < $length; $p++) {
            $string .= $characters[mt_rand(0, strlen($characters)-1)];
        }
        return $string;
    }

    private function genRandomDouble() {
        srand((double)microtime()*1000000);
        $randomnumber = rand(0,5);
        return $randomnumber;
    }

    function startCase(){
        echo "<h1>Starting LrapackagesController Test Case</h1>";
        $this->path = APP_PATH.'/lrabuilder/lrapackages/';
        $this->testPackage = array(
            'Lrapackage'=>array(
                'name'=>$this->genRandomString(),
                'part_number'=>$this->genRandomString(),
                'version'=>$this->genRandomDouble()
            ));
    }

    function endCase(){
        echo "<h1>Ending LrapackagesController Test Case</h1>";
    }

    function startTest($method){
        echo '<h3>Starting method '.$method.'</h3>';
    }

    function endTest($method){
        echo '<hr/>';
    }

    function testAdd(){
		$result = $this->testAction($this->path.'add',array('data'=>$this->testPackage,'method'=>'post','return'=>'vars'));
		if($_SESSION['Auth']['User']['role_id']==1 || $_SESSION['Auth']['User']['role_id']==2)
		  $this->tAddLoggedInUser($result['cakeDebug']->data['Lrapackage']);
		else
		  tAddPublicUser($result);
	}

    function tAddLoggedInUser($data){
        $this->assertEqual($data['name'],$this->testPackage['Lrapackage']['name']);
        $this->assertEqual($data['part_number'],$this->testPackage['Lrapackage']['part_number']);
        //I would assertWithinMargin, but since the data needs to be identical, I don't need that.
        $this->assertEqual($data['version'],$this->testPackage['Lrapackage']['version']);
        //1000 is selected arbitrarily, but I dont care about real accuracy here.
        $this->assertWithinMargin(strtotime($data['created']),strtotime(date('Y-m-d H:i:s')),1000);
        $this->assertEqual($data['user_id'],$_SESSION['Auth']['User']['id']);
    }

    function tAddPublicUser(){
    	//echo($result); the only bad thing about this method is that you need to decide what the return var is before you
    	//have the session info... however, assuming you have properly setup your acl you shouldn't even need this test...
        //let the acl tests confirm that logged out users dont have access to logged in areas!!
    }

    function testIndex(){
        $result = $this->testAction($this->path.'index');
        //debug($result); this results in an overwhelming amount of data, be selective of the output!!
    }
}

Questions?

Go forth and unit test :)!

Some useful docs:

http://simpletest.org/api/SimpleTest/

http://simpletest.org/api/SimpleTest/Extensions/PHPUnit_TestCase.html

http://simpletest.org/api/SimpleTest/UnitTester/UnitTestCase.htm

http://book.cakephp.org/view/1210/Testing-controllers

16Sep

credits: http://www.tipb.com/2010/03/03/google-comments-apple-htc-patent-lawsuit/

First of, sorry for not posting a ton lately everyone. Been busy with letswoosh.com, rockin with Doomsday Machines, and making cool stuff at NetApp. In any case, if you are on this page, you have probably been searching endlessly for a way to get flash on your iP[ad|hone]. At work, we had a request straight from the VP of our department that ended up on my desk. “We would like to get about 200+ sales people to view training through mobile devices, namely the iPad,” was essentially the gist of the request. Well it just so happens that all of our training is done in Flash,  and around here they don’t seem to be big fans of going back to javascript. They asked me to come up with solutions.

There are essentially three ways I found that differ vastly from on another.

  • Jailbreak, then “un-jailbreak” once you install flash (I am not going to go into all of that)
  • Use smokescreen (source), a javascript version of the flash plugin, but it does not seem to work for interactive flash apps.
  • Provide a browser through a “VM”. That is host an app through some software server in the cloud.

Jailbreaking is out. We are not about to go to war with apple (although someone should). Smokescreen won’t really work out, plus it is not very “corporate ready,” which leaves us with the VM/cloud/SaaS solution. So via iPhone/iTouch I found an app called Cloud Browse. This is pretty nifty it is essentially Firefox hosted up in the cloud. It works, but there are some pitfalls. First of all, its unsupportable. If one of our clients says “ITS NOT WORKING” angrily all we can say is try again later? Also, it could potentially cost a ton, and its not a fixed cost. That is we need to buy subscriptions for each person who wants to use the app so they don’t end up on the generic/anonymous connection pool that may or may not get a connection depending on popularity at that moment in time. Do I need to mention that if you are going through some VPN service you are essentially exposing all your delicious corporate secrets? Lastly, it looks like crap on the iPad.

I mentioned the VM solution to my manager, and he said “OH, that kinda sounds like something Citrix probably does.” I did some research and found 2 must have apps and a pretty rockin video that explains a few things.

Step One (setup a server that doesn’t quite work yet for practice and experimentation):

Time to take down a fighter jet... Credits to: http://www.graphicsdb.com/img77239.htm

First thing you should do is follow the steps in the video below to get your Amazon cloud account all setup with XenApp 5.0. The AMI mentioned in the video doesn’t work with the iP[hone|ad]. I believe the AMI mentioned in the last link will work out though.

Next, log in and open up your “desktop” app, which may take up to 10 minutes even if it says “running” in amazon, server error means its still starting up. You will see all sorts of warnings about XenApp not having licenses, logins failing, terminal services needing licenses, but this is all normal and if you can open internet explorer you are doing just fine. At this point you may want to try adding apps into Citrix Access Manager, which is extremely easy (if you have a question about it feel free to ask in the comment section). I installed Firefox, Adobe Reader, Flash and AIR. I then installed an AIR application and was able to create apps in the manager tool. I used Firefox, the air application, and adobe reader.

Step Two (configure apps and reconfigure iP[ad|hone] and try it out):

You may want to add a new user. We will use this user to connect to the server via the iPad. The cool thing about having individual accounts is the same as doing so on a normal machine. Users can save their own settings and preferences. The same is applicable here.

Now go through App Store on the iPad. You can just download the Citrix Receiver for free. Go ahead and use your IP address as both the address and domain. You need have your username in the format: ComputerName\Username. If you are now able to open your web browser and launch it. Everything is working fine. Go to youtube.com and open up a video. There should be some choppiness as is expected, but hell it works. It may not be 24->30fps, but it gets the job done, and its supportable/secure.

Pricing:

At an enterprise level. This is extremely affordable. You only pay for XenApp once. The receiver is free. You may need to purchase Windows Server 2008 if you are doing this internally. Then for about 60 concurrent users we are looking at around 5 grand total. This is much more affordable than redeveloping a ton of software. One thing to note though. You should assess how much interest there actually is around all of this. The last thing you want to do is have a person dedicate about a week of their time trying to set this thing up and have no one ever use it.

Disclaimer:

Finally, let me put up a little disclaimer. I know nothing of these sorts of things. I just had a business need and tried my best to figure out how to get this to work. Questions shouldn’t necessarily be directed at me. Honestly I am not a subject matter expert for XenApp, Citrix, Windows Servers or iP[ad|hone]. Most of this stuff was pulled from best guesses and gleaned information. I will do my best to answer questions if I do receive them. In any case, I hope this was helpful to someone :)! Now I open the forum… Any other ideas?

https://www.citrix.com/English/ss/downloads/details.asp?downloadId=1864025&productId=186
23Apr

This week has been a bit intense. I am currently sitting at the San Jose Airport waiting for my flight to DC. Can’t wait to get on the plane because it is the first time I will have had a chance to sleep in the past 36 hours. (There are not enough hours in the day…)

Between binging on coffee and binging on energy drinks Andy and myself got a significant amount of work done, including but not limited to: having our program becoming autonomous and killing off Visual Studios, staring at code for about 2 hours before realizing it just needs to be pluralized to make it work, and of course a celebrator breaking of chair after I realized yet again that the letter “s” has ruined another  2 hours of my life! WOO!

Not only did we break chairs, but we also got an awesome GUI going and I migrated the original Tesla app into a plugin for Croogo. This allowed for Access Control, Auth, and an awesome template system. It also allowed for making Tesla modular enough to be run on any server!

I got 2 more features to wrap up before tomorrow night though :(. So there may be 1 more all nighter in my future for this contest. But hey, this is what I live for! It feels like 4 years ago when I was getting on stage for my first “big” concert. Lovin’ the pressure :-D!