Saturday, May 22, 2010

Google, Pacman, and the Enemies of Fun

You might think Google dropped a bomb on some small country or fed small kittens to snakes. Today, there is a lot of noise about Google's method of celebrating the anniversary of Namco's Pacman, which today turned 30.



I'm glad I don't work with all of the naysayers and complainers and whiners on the Internet who obstinately declare that they're now changing their search engine to Bing! What's funny is that deep down inside in the depths of their subconscious, they've had this burning desire to do so all along.

Microsoft has really been beating Bing into our skulls. Whenever I turn on the television, I see references to it in pop culture. On Vampire Diaries, Supernatural, and other television programs on the CW, the main characters made several references to it and even used "Bing" as a verb. This is what savvy marketing people refer to as "brand awareness" while in reality it's just brainwashing.

You people that are complaining about Google putting up an interactive widget aren't really angry at Google. You're angry at yourselves for being too stupid to understand how to use a computer, and as any psychologist will tell you, you're using displacement to redirect your anger at yourself onto Google for actually thinking that something that was meant to bring joy was a virus. You're using this moment as the excuse you've been looking for to run to Bing.

Brainwash successful!

To the complainers out there, the world isn't going to wait for you. It's moving on with or without you. I'm warning you now, you'd better catch up or you'll be standing in the unemployment line in 10 to 20 years, complaining about how your job went to India or China or someone much younger and with more drive than you, and you'll be bitching about how both your life and the the government both suck.


I am really exited to hear if the grass really is greener on the other side in Bingland. As for me, I'm sticking with Google. I'm staying on the cutting edge where life is more exciting. Why, because you can't please all of the people all of the time. If you want to be spoon fed and treated like the whiny infant that you sound like, then go to AOL or Bing. Good riddens, I say! Google's products and services will only get better if they market them to people with open minds who are willing to experiment. They're better off without you.

As for anyone coming out of college or anyone looking for a job, here is some unsolicited advice:


  • You can tell a lot about an employer by looking at the tools they use. If they support Google and openness and get really excited about new technologies, chances are you're really going to enjoy the environment and the people you work with. In that organization, you'll be important, and you'll make a difference in the world. Most importantly, you'll have a lot of fun while you do it.


  • Now, if they support Microsoft or ban a specific technology because of some ridiculous moment of hypoglycemia, lack of sleep, and confusion, then I suggest you run the other way. Well, unless you are the enemy of fun and like working with a bunch of stiffs who get hypertension because they spent money on virus software today instead of spending it on taking a computer class like they should have years ago.



In summary, I really enjoyed the Friday break. So did many of my coworkers. I feel really sorry for all of the people who were offended by something so non-offensive. Go back to your stone knives and bearskins.

Saturday, June 13, 2009

Revolutionary Testing Tools for AJAX Applications

Revolutionary Testing Tools for AJAX Applications

http://blog.browsermob.com/2008/12/faq-how-do-you-compare-to-selenium/

A few years ago, we used JMeter to try and load test a chat application we were building. Since the chat application used Comet and AJAX, I knew that the JMeter test was going to be grossly inaccurate. However, we did the best we could with tools that clearly weren't right for the job, as nothing was out there that could simulate an AJAX or Comet load test.

A few weeks ago, while working with some other consultants on a project, we discussed the use of Selenium to run some functional testing on a Firefox Extension that inserts signatures into an email. We needed a tool that could automatically send an email using Gmail, Yahoo, and Hotmail, and verify that the signature was still injecting. From my days writing HTML Reply Signatures for Gmail, I knew that this was indeed important, as any change by these third parties could have a drastic effect on the tool's ability to insert a signature.

Today, one consultant and I worked to try to insert an email address into the "To" field of the Gmail Compose window using Selenium. I've done this already in the Firefox extension, and anyone who has ever written a Greasemonkey script or Firefox extension that works with Gmail 2 can attest that this is not always an easy task if you are working outside of the API exposed by Gmail. Google engineers have put lots of effort in writing server-side code that ensures that all the id attributes in the Gmail application randomly change each session. Their creativity has sparked our creativity, and we have solved this problem. With enough time and patience, any problem can be solved.

Anyway, with Selenium, one must locate elements in the HTML of a web application by using XPATH queries. Armed with my trusty Firebug tool, I inspected the element in question and worked my way up the tree one element at a time, writing down the element tag names and positions at each step. Like a complex code, we ended up with long XPATH queries, a seemingly endless series of div[1]/div[2]/div[1]/div[1]. Although I would have preferred to just use JavaScript and a good for loop or regular expression to locate what I wanted, being a code cracker and approaching this problem from another angle was an eye-opener, XPATH is perhaps the way to go!

So that's a little background on my experience so far with testing tools. Selenium isn't a load testing tool of course, but it's a great tool to automate functional testing. It's almost like a macro recorder, similar to iMacros. Our plan is to set our test up on a VMWare image and configure this to run automatically every day. We'll get emails with our signature if it's successful, and broken or no email if it's not successful. We're also configuring it to be really loud and obnoxious if it does detect that something is amiss, just so we don't gloss over the automated emails.

Selenium can do functional testing, but what about load testing? Sure, Selenium can do load testing as well! Selenium uses real web browsers in testing, but it's up to the person doing the tests to go out and purchase the hardware to run the tests. In other words, if you want to do a 100 user load test with Selenium, you need to have 100 computers in your lab and 100 people to all click "Run" at the same time.

This is analogous to a symphony with you as the conductor who tells everyone exactly when to click "Run Test".

Of course, coordinating such an event can be costly, so one of the developers of Selenium Remote Control founded BrowserMob. BrowserMob solves this issue by providing the hardware. They claim to load test your web application using Selenium scripts and N number of real web browsers! I would be really interested to know how this was accomplished and how the costs have been kept so low.

To start, they probably use VMWare and Linux, which is one way to reduce the amount of physical hardware while still trying to simulate real hardware. They say they use Firefox 3.0, which is available on Linux. Finally, if Selenium Remote Control launches Firefox browsers to simulate functional tests, then my guess is BrowserMob is controlling a series of Selenium Remote Control instances, all running on VMWare Linux machines, and allowing BrowserMob to monitor the load.

While there are some costs associated with BrowserMob, I imagine one could use Selenium Remote Control installed on several VMWare images to run a small load test. If anyone has experience with either Selenium Remote Control or BrowserMob, I'd love to hear your thoughts on the two products!

Wednesday, December 17, 2008

Break out the Country Crock

I read an intriguingly funny article tonight. The reason it's so funny is that it's very applicable to me at the moment. My brother and I have been burning firewood for heat this winter in Portland, Oregon. We've actually obtained our fire wood from many different Craigslist advertisements, such as the one featured in this article's screen shot, and we have made some extra income selling our surpluses to people who are either in need of heat or just want the ambiance provided by a nice warm fire.

Seasoned wood does not in fact refer to seasoning the wood with pepper and salt and Italian spices although the idea does create some interesting mental pictures. For those who don't know, seasoned wood is wood that has been aged and naturally dried so that it will burn well. In order to be seasoned, most firewood must be aged for at least 1 to 2 years.

Although seasoned wood isn't seasoned in terms of teeming with lemon-pepper or garlic and oregano, burning the many different kinds of wood does indeed produce a plethora of different uniquely enticing and delicious smells. Black walnut is perhaps my favorite. Sit a piece in front of your fireplace just inches from the transfer of potential to kinetic energy. Watch the blue flames emanating from a few well-seasoned, dry chunks of maple as the walnut slowly heats up. After awhile, it smells like freshly baked bread and makes you want to go break out the Country Crock and dig in. We did that one night and the wood smelled so good I felt I could almost take a bite out of it!

With a fireplace, who needs Dish Network. It's all the entertainment I need.

Sunday, September 21, 2008

Dreamhost Hosting Special

I work with a client who uses Dreamhost as the hosting provider for a new web application. My client works with several other contractors besides myself. Some have been only temporary contracts while others have been more long-term. For the initial phase of development, all development was done on local servers, and there was only one hostname for the website.

One of the newest consultants spent just a small portion of his time in setting up some tools that would not only make development more efficient; but also, these tools will help prevent catastrophic mistakes that oftentimes can occur. Manual, repeated tasks are prone to error, and it's not a matter of if a failure occurs, but when will the failure occur.

The consultant set up several domain names for us to use in the deployment process. Previously, the site was deployed to the server under the www subdomain. While this is fine for code that has been tested on the hosting platform, it's not fine when deploying live. We now have a "testing" subdomain and a "stage" subdomain where "testing" is where untested code can be tested using a separate build of the website. "Stage", of course, mirrors whatever is deployed live and acts as a staging ground for final tests of changes to ensure that they are indeed production ready.

The consultant also set up Trac, which is an open-source wiki, bug tracking package, and project management platform all rolled into one web application. It integrates with the Subversion repository, which the consultant also setup and configured using Dreamhost's web panel.

Dreamhost offers these features as part of the standard hosting package, all for the low cost of $5.95 per month, depending on the length of your committment. Of all of the hosting providers that I've looked at, Dreamhost is the best for new startups looking to establish a web presence using PHP, Perl, Ruby, and some other popular programming languages. You'll never have to worry about running out of databases, as Dreamhost will supply you with an endless supply of MySql databases!

Some of the things that really stood out to me were things like the Jabber Chat server, a full Unix shell, the Debian Linux operating system, and IMAP access so you can download your email to a mail client. There is a one-click install feature for installing many popular packages, such as Wordpress, Moodle, and Joomla. In addition, through the shell you can install other applications, such as Trac!

To make this deal even sweeter, you can get unlimited disk space and unlimited bandwidth if you sign up now by clicking on the link in the left section on my website! This leaves lots of room for growth, and this perhaps may be the last hosting package you'll ever need!

The only catch, there are only 1111 slots left open for unlimited disk space and bandwidth, so sign up today!

Click here to learn more



Monday, September 1, 2008

Google Chrome Browser

While most of us spent our Labor Day weekend camping, barbecuing, or in my case, moving into a new home, the marketing team at Google was laboring away releasing marketing materials on what seems to be the next evolution of the web!

Google Chrome, a fully open source multi-process web browser, addresses many of the woes that most web surfers encounter on a daily basis. Instead of being concerned with browser lock ups and ensuring that we don't go over 35 to 40 tabs in Firefox for fear of the dreaded browser crash, we can rest assured knowing that the most we will ever have to worry about is a "tab crash".

What is a tab crash? According to the Google Chrome Comic book, each tab is launched as a separate process. What this means is that if there are N tabs open, there will be N JavaScript threads running, N copies of the global data structures, and a significantly reduced chance that a rogue JavaScript function will bring a user's web experience to a grinding halt.

Both Firefox and IE run as a single process. While IE does tout the advantage of running each tab in a different thread, the memory is still shared; and all tabs are still susceptible to crashes. In either case, the result is the same.

However, I am very interested to see this new browser in action. How impervious to crashes is it going to be? What is this going to mean for web development? Will we need more CSS and HTML magicians to step forward and deal with yet another browser hack? Or will Google Chrome follow web standards and allow the same ease of web application development as Firefox and Safari do?

One question that I have is in regards to add-ons. Will this new browser be as extensible as Firefox? Is there or will there eventually be a market for Google Chrome add-ons?

More importantly, is this the first step towards the Google Operating System?

I guess tomorrow we will find out.

Monday, July 21, 2008

JavaScript and Java are Pass By Value

Proof that JavaScript and Java are Pass By Value



Pass by value and pass by reference can be daunting at times, and I too have been confused and frustrated at all of the babbling about whether or not Java is one or the other, that is, until I saw an article featuring the Litmus test. I've seen the Litmus test in college, but it didn't make sense completely until reading Scott Stanchfield's "Dammit" article.

Today I was reading Jeff Cogswell's article asserting that JavaScript is pass by value. The blog author is indeed correct in his assertions; however, there were many comments rebutting his arguments. I thought it would be best to support his arguments by applying the Litmus test to JavaScript to prove once and for all whether or not JavaScript is pass by value or pass by reference.

Java is clearly pass by value. Scott Stanchfield's statement says it best: "Objects are not passed by reference. A correct statement would be Object references are passed by value."


The JavaScript Litmus Test



I decided to apply the Litmus test to JavaScript and see what the results are. Here is what I have so far:


function doLitmusTest() {
     var a1 = 5;
     var a2 = 7;
     swap(a1,a2);
     alert(a1 + ","+a2);
}

function swap(a,b) {
    var temp = a;
    a = b;
    b = temp;
}

window.addEventListener("load",function() { doLitmusTest(); },true);



The output is as follows:

5,7

The values were not swapped. JavaScript fails the Litmus test, as Java did. This means that JavaScript is also pass by value.

In Java, there is a workaround to being able to implement the swap function, and it also works in JavaScript:


function anotherTest() {
     var obj1 = { value: 5 }; // JSON notation
     var obj2 = { value: 7 }; // JSON notation
     swapValue(obj1,obj2);
     alert(obj1.value + "," + obj2.value);
}

function swapValue(objA,objB) {
     var temp = objA.value;
     objA.value = objB.value;
     objB.value = temp;
}

window.addEventListener("load",function() { anotherTest(); },true);



The output is:
7,5

In Java, data can be "wrapped" in an object to allow the value to be changed. JavaScript behaves in the same manner. All values, both primitives and object references are passed by value. With primitives, changes we make to one copy of a variable do not affect changes to another copy.

The rule is the same with Object references. Objects are not passed in as parameters in Java or JavaScript, object references are passed as parameters. References point to a specific location in memory. Three references can all point to the same location, so if the data located at that spot in memory is changed, the change will be reflected for all of the references that point to that spot.

However, changes to the reference itself are not reflected. A rule of thumb to remember is that when implementing the swap method, you can only change data by calling setter and getter methods, or by accessing public properties. However, making changes to the object reference instruct the object reference to point to a different location. This is why swapValue worked as expected while swap did not.

Below is a sequence of "visual art" to demonstrate the concepts visually:


new operator uses new memory space

Object A and Object B are instantiated and new memory is allocated on the heap.



using new on object A creates new space in memory

Object A is assigned a reference to new memory space because the "new" keyword was used.



using setter changes value in memory location

The value of the object referenced by B is changed to a new value, but the object reference still points to the same location in memory.

For A, the "new" operator created new space in memory and instantiates a new object. The "12" is located in a different spot in memory.

B, on the other hand, has a value that was set using a setter method. Thus, the value has changed from "7" to "2" without destroying the original object.



multiple objects reference the same memory space
Objects A, C, and D all point to the same place in memory. If a setter method is called on one of the object references, the value is changed in all 3 object references because they all point to the same location in memory.

A good analogy to use to explain this concept is "nicknames". For instance, my name is James, but people also refer to me by Jim. Additionally, I've been called "Mort" before as well. All three names point to the same object, me! In the example I've shown you, A, C, and D are all names of the same object.

Sunday, July 13, 2008

XSLT Transformations with XML Namespaces

As of the date of this article, there are currently not a lot of resources on the Internet regarding how to transform XML that contains namespaces. Yahoo's Weather Web Services API returns data in the form of RSS, and this data is formatted not only with elements and attributes, but also with namespaces.

I'm experimenting with the Yahoo Weather API for a potential project I may work on. Considering that there may be other Weather API's used, it makes more sense from an architectural design standpoint to tranform Yahoo's data into my own XML data structure. This ensures that if the client decides that he/she likes Google's Weather API, or the Fox News API, all we need to do is create a new XSLT stylesheet to convert the data into the format recognized by our server.

Here is part of the Yahoo Weather Data, taken from here.:


<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
<channel>

<title>Yahoo! Weather - Portland, OR</title>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Portland__OR/*http://weather.yahoo.com/forecast/97206_f.html</link>
<description>Yahoo! Weather for Portland, OR</description>
<language>en-us</language>
<lastBuildDate>Sat, 28 Jun 2008 4:53 pm PDT</lastBuildDate>
<ttl>60</ttl>
<yweather:location city="Portland" region="OR" country="US"/>

<yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/>
<yweather:wind chill="101" direction="300" speed="10" />
<yweather:atmosphere humidity="22" visibility="10" pressure="29.82" rising="2" />
<yweather:astronomy sunrise="5:24 am" sunset="9:03 pm"/>
<image>
<title>Yahoo! Weather</title>
<width>142</width>
<height>18</height>
<link>http://weather.yahoo.com</link>
<url>http://l.yimg.com/us.yimg.com/i/us/nws/th/main_142b.gif</url>
</image>
<item>

<title>Conditions for Portland, OR at 4:53 pm PDT</title>
<geo:lat>45.52</geo:lat>
<geo:long>-122.68</geo:long>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Portland__OR/*http://weather.yahoo.com/forecast/97206_f.html</link>
<pubDate>Sat, 28 Jun 2008 4:53 pm PDT</pubDate>
<yweather:condition text="Fair" code="34" temp="101" date="Sat, 28 Jun 2008 4:53 pm PDT" />
<description><![CDATA[
<img src="http://l.yimg.com/us.yimg.com/i/us/we/52/34.gif"/><br />
<b>Current Conditions:</b><br />
Fair, 101 F<BR />
<BR /><b>Forecast:</b><BR />
Sat - Mostly Clear. High: 97 Low: 65<br />
Sun - Mostly Sunny. High: 91 Low: 66<br />
<br />
<a href="http://us.rd.yahoo.com/dailynews/rss/weather/Portland__OR/*http://weather.yahoo.com/forecast/USOR0275_f.html">Full Forecast at Yahoo! Weather</a><BR/>
(provided by The Weather Channel)<br/>
]]></description>
<yweather:forecast day="Sat" date="28 Jun 2008" low="65" high="97" text="Mostly Clear" code="33" />
<yweather:forecast day="Sun" date="29 Jun 2008" low="66" high="91" text="Mostly Sunny" code="34" />
<guid isPermaLink="false">97206_2008_06_28_16_53_PDT</guid>
</item>

</channel>
</rss><!-- api1.weather.sp1.yahoo.com compressed/chunked Sat Jun 28 17:19:32 PDT 2008 -->



Note that the temperature and other weather data is stored within elements that are part of the yweather namespace. The XSLT stylesheet below demonstrates how to obtain the temp attribute from the yweather:condition element:


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0">

<xsl:template match="/">
<html>
<body>
<h2>Weather</h2>
<table border="1">
<xsl:for-each select="rss/channel">
<tr>
<td>title</td>
<td class="title"><xsl:value-of select="title" /></td>
</tr>
<tr>
<td>link</td>
<td class="link"><xsl:value-of select="link" /></td>
</tr>
<tr>
<td>curCond</td>
<td class="curCond">
<xsl:value-of select="//yweather:condition/@text" />
</td>
</tr>
<tr>
<td>curTemp</td>
<td class="curTemp">
<xsl:value-of select="//yweather:condition/@temp" />
</td>
<td id="curTemp">
<xsl:value-of select="//yweather:condition/@temp" />
</td>
</tr>
<xsl:for-each select="//yweather:forecast">
<tr>
<td>forecast</td><td class="day">day: <xsl:value-of select="@day" /></td>
</tr>
<tr>
<td></td><td class="date">date: <xsl:value-of select="@date" /></td>
</tr>
<tr>
<td></td><td class="low">low: <xsl:value-of select="@low" /></td>
</tr>
<tr>
<td></td><td class="high">high: <xsl:value-of select="@high" /></td>




On another note, I've done XML conversions before the hard way: By parsing the XML with PHP or JSP and dynamically rebuilding the XML! While this would also work to solve my problem, using XSLT will allow me to keep the transformation layer separate from the business logic.

Although this was somewhat time consuming getting started with XSLT and converting XML with namespaces, I can already feel the weight being lifted off my mind knowing that changing my data sources won't involve troubleshooting PHP errors!
Google