Monday, November 1, 2010

UX vs IP Based Language

I start being sick of this epic fail and many famous website do this ... I am Italian, I am living in Germany, but my OS as every software or device I have is in English ( and I don't know German yet ) !

The Problem

If you live in your country and you have software in your own language, you probably never spotted what I am talking about. Actually, what you have probably appreciated instead, is the fact if you write in your url bar www.google.com you'll find directly the one translated and relative to your country ... how cool is it?
My tiny winy problem is that if I write the same right now, I am redirected to google.de .... most likely in German with all settings in German as well, even the confirm button, no matter if I managed somehow to reach that point and changed the language ...

How Difficult Is It

Every single fucking browser sends an Accept-Language header with 99.9% of the time the current browser language or, in the worst case scenario, the Operating System one.
If it's not about the server, we have the same behavior on the client via navigator.language ...
In both cases I am sending a bloody en-us string that cannot surely be confused with de-de one, isn't it? But it does not matter, in 2010 and its growing globalization, these "clever" websites still rely on IP address to define the spoken language, but how wrong is this?

Language IS Context Dependent

Let's imagine we are simply traveling ... OK? Good, We have hot spots services in the airport or we are having a coffee in some local chain with wireless connection ... OK? Now we try to visit websites we use to check from home, from our country, and never with a single problem, cookies or not .... we are in the cloud, the one we would like to use everywhere but being behind some other IP address, the cloud does not recognize us anymore ... still cool, uh?
In few words, if we are simply surfing the web there is no reason in this world to trust the current provider for our spoken language.

Location And Laws Context

There are mainly and only two reasons our IP address should be considered, a map application unable to use the W3C Geolocation API, so we are more into a fallback situation, or country laws for all those services that may works differently accordingly with current country (e.g. YouTube)

Everything Else Is UX

If the website we use on daily basis does not recognize us instantly we may feel that something went terribly wrong, isn't it? And how many could freak out the moment even few links around a search field are in a completely extraneous language?
Moreover, if I decided to use English software, rather than italian, it means I made a choice and surely I cannot really complain if websites are always in English even if I am in italy or Germany ... it's the other way round: I expect this, and I am instantly confused the moment this does not happen.

The Failing Google Chrome Attempt

The ridiculous part of this story is an evident UX conflicts inside Google teams, the search engine and the translation one.

In my case, if I start Google Chrome and I go to google.com I am:
  1. redirected into google.de, it does not matter if I explicitly typed .com
  2. the whole search engine in in German
  3. a top bar lazily informs me that the page is in German, would you like to translate?
Oh ... Really??? So the browser understands I am based on English but the server of the same company decided I am German ... how cool is it?
The company that more cares of performances is doing a redirect, a lazy navigator.language analysis, in order to help me with the wrong choice made by the server ... and guess what? The translation team is not brilliant, is everything else that looks dumb!
It must be said that at least I have a Google in English link easy to spot ... but many other sites don't!

User Agent Myths

A user agent should follow W3C standards and AFAIK all do, more or less. It is not about the browser, the platform, it is simply about the only thing that I do believe is consistent across every platform: the language. Of course it's easy to hack a userAgent in order to show a different language ... but who the hell gonna do it for daily browsing? Even the IP could be hacked via userAgent, the one that sends it, isn't it? So why on earth people adopted such silly strategy to define the user language?

The Internet Cafe Context

If we are still thinking about edge cases ... believe me, these are truly rare. Even an internet cafe, most of the time populated by foreigners, could simply create accounts and most used languages set for each account. As example, we could have the user English, the user Deutche, the user Italiano, etc etc ... and the moment we login with this user the OS, and hopefully the software, will be presented in the same language. At that point, every website that will present content based on IP language could be easily labeled as dumb, because in this world were everybody travels and therms as mobile are used on daily basis by marketing, companies behind the same marketing do not get it: it's NOT about the IP!

Monday, October 25, 2010

JavaScript Coercion Demystified

This post is another complementary one for my front-trends slides, about performances and security behind sth == null rather than classic sth === null || sth === undefined.
I have already discussed about this in my JSLint: The Bad Part post but I have never gone deeper into this argument.

Falsy Values

In JavaScript, and not only JavaScript, we have so called falsy values. These are respectively: 0, null, undefined, false, "", NaN. Please note the empty string is empty, 'cause differently from php as example, "0" will be considered truish, and this is why we need to explicitly enforce a number cast, specially if we are dealing with input text value.
In many other languages we may consider falsy values even objects such arrays or lists:

<?php
if (array())
echo 'never'
;
?>

#python
if []:
print 'never'


Above example will not work in JavaScript, since Array is still an instanceof Object.
Another language that has falsy values is the lower C, where 0 as example could be considered false inside an if statement.
Falsy values are important to understand, specially if we would like to understand coercion.

About Coercion

In JavaScript world, coercion is considered a sort of evil and unexpected implicit cast, while in my opinion it's simply a feature, if we understand it and we know how to use it.
Coercion is possible only via == (eqeq) operator, but the thing is that everything is properly implemented cross browsers accordingly with ECMAScript 3 Standard.
This is the scary list newcomers have probably never read, directly from the even newer ECMAScript 5 specification, just to inform you that coercion will hopefully always be there, and nothing is evil.

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as
follows:


  1. If Type(x) is the same as Type(y), then

    1. If Type(x) is Undefined, return true: undefined == undefined

    2. If Type(x) is Null, return true: null == null

    3. If Type(x) is Number, then

      1. If x is NaN, return false: NaN != NaN

      2. If y is NaN, return false: NaN != NaN

      3. If x is the same Number value as y, return true: 2 == 2

      4. If x is +0 and y is −0, return true: 0 == 0

      5. If x is −0 and y is +0, return true: 0 == 0

      6. Return false: 2 != 1


    4. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false: "a" == "a" but "a" != "b" and "a" != "aa"

    5. If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false: true == true and false == false but true != false and false != true

    6. Return true if x and y refer to the same object. Otherwise, return false: var o = {}; o == o but o != {} and {} != {} and [] != [] ... etc etc, all objects are eqeq only if it's the same


  2. If x is null and y is undefined, return true: null == undefined

  3. If x is undefined and y is null, return true: undefined == null

  4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y): 2 == "2"

  5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y: "2" == 2

  6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y: false == 0 and true == 1 but true != 2

  7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y)

  8. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y): ToPrimitive means implicit valueOf call or toString if toString is defined and valueOf is not


About last point, this is the object coercion we are all scared about ...

var one = {
valueOf: function () {
return 1;
},
toString: function () {
return "2";
}
};

alert(one == 1); // true
alert(one == "2"); // false

If we remove the valueOf method, we will implicitly call the toString one so that one == "2" or, more generally, {} == "[object Object]".

null == undefined And null == null, Nothing Else!

99% of the time we do a check such:

function something(arg) {
if (arg === undefined) {
}
}

We are asking the current engine to check if the undefined variable has been redefined in the current scope, up to the global one, passing through all outer scopes.
Even worse, we may end up with the most silly check ever:

function something(arg) {
if (arg === undefined || arg === null) {
}
}

which shows entirely how much we don't know JavaScript, being the exact equivalent of:

function something(arg) {
if (arg == null) {
}
}

with these nice to have differences:

  • null cannot be redefined, being NOT a variable

  • null does NOT require scope resolution, neither lookup up to the global scope

The only side effect we may have when we check against null via == is that we consider for that particular case null and undefined different values .... now think how many times you do this ... and ask yourself why ...

Performances

Once again I send you to this simple benchmark page, where if you click over null VS undefined or null VS eqeq, or one of the lines showed under the header, you can realize that while it's usually faster and safer, it provides even more control when compared against the ! not operator.
The only way to reach better performances when we mean to compare against an undefined value in a safer way is to declare the variable locally without assigning any value, so that minifiers can shrink the variable name while the check will be safer.

// whatever nested scope ...
for (var undefined, i = 0; i < 10; ++i) {
a[i] === undefined && (a[i] = "not anymore");
}


There Is NO WTF In JavaScript Coercion!

Coercion in JavaScript is well described and perfectly respected cross browser being something extremely simple to implement in whatever engine. Rules are there and if we know what kind of data we are dealing with, we can always decide to be even safer and faster.
Of course if we are not aware the strict equivalent operator === is absolutely the way to go, but for example, how many times you have written something like this?

if (typeof variable === "string") ...

being typeof an operator we cannot overwrite neither change, and being sure that typeof always returns a string there is no reason at all to use the strict eqeqeq operator since String === String behavior is exactly the same of String == String by specs.
Moreover, as said before, coercion could be absolutely meant in some case, check what we can do with other languages, as example:

# Python 3
class WTF:
def __eq__(self, value):
return value == None

# Python 2
class WTF():
def __eq__(self, value):
return value == None

# in both cases ...
if WTF() == None:
"""WTF!!!"""

While this is a C# example:

using System;

namespace wtf {

class MainClass {

public static void Main (string[] args) {
WTF self = new WTF();
Console.WriteLine (
self ?
"true" : "false"
);
}
}

class WTF {
static public implicit operator bool(WTF self) {
return false;
}
}

}

Can we consider some sort of coercion latest cases as well? It's simply operator overloading, virtually the same JavaScript engines implemented behind the scene in order to consider specifications points when an eqeq is encountered.
Have fun with coercion ;-)

Sunday, October 24, 2010

The Layer ... Of The Layer ... Of The Layer ...

When I read tweets like this one I cannot avoid a quick comment but the reason I am posting, is simply to explain that every time we write a web page/application, we are dealing with at least 4 different layers.
Moreover, this post is complementary for few slides I have introduced at front-trends, specially regarding the "avoid classic OOP emulation when not necessary" point.

Layer #1: JavaScript Libraries

We all know the DOM is a mess, and this is most likely the reason we chose a JS library rather than deal directly with possible problems we can have when we develop an x?HTML page.
Even if many developers don't care, I keep saying that every millisecond gained in this first layer, the page itself, is important.
Moreover, if we have a good understanding of the JavaScript programming language, we can easily realize that all these "Java Pretending Style Frameworks" emulating classic inheritance and OOP are not easier to maintain neither faster for what we need on mobile devices, included Netbooks.
The "easier to maintain" fuzz, associated with "Java style JavaScript", a sentence that does not make sense itself, is only a Java developer point of view.
Well written JavaScript without any "wannabe another language" pragmas, is truly much easier to both understand and write, modify, or fix, while the great magic behind this or that framework/library could become our first enemy when something goes wrong and we would like to understand and debug that magic 'cause we had a problem and we have strict deadline that may not match with a bug lifecycle.
Finally, as easily demonstrated via this test page, we can all spot how much more it costs to simply initialize a new instanceof constructor, compared with proper way to go natively via JavaScript, in that case made easier by this essential script, developed following TDD and tested here cross browser.
Anyway, common sense first and fast production quality, should always be kept in mind when we decide an approach, rather than another one. So, here frameworks play usually quite good role, the one to bring same functionality cross browser.
But what is a browser?

Layer #2: The Browser

As libraries are considered an abstract way to reach same goal in all browsers, browsers are simply abstract applications able to bring the web cross platform.
This is were the browser speed may vary, accordingly with the platform, and were every technique able to speed up render ( DOM+CSS engine such Gecko, Trident, others ) and JavaScript ( engine a part such V8, JavaScriptCore, SpiderMonkey ) is more than welcome. These guys are implementing any sort of trick to make the page and the code that fast, even if they have to deal with different operating systems. And guess what is an operating system?

Layer #3: The Operating System

We are even lucky if the browser deals directly with the operating system graphic API, since many other middle layers could be part of this stack ( flash or third parts plugins, as example ).
You cannot expect that Linux, Mac, and Windows, just mentioning fews Desktop related ( more choices on mobile world ) magically display and provide browser functionalities via the same API. We would need something like a jOSQuery library here to make it happens ... but even worse, every operating system may have another abstract layer able to use, as example, Hardware Acceleration.

Layer #4: The Hardware

Open GL ES 2.0 is simply another abstraction able to transform API calls into specific hardware driver calls which means that starting back from the DOM and the used WebGL or CSS3 with HW support, things have been modified, translated, re-created at least a couple of times.
In few words, if we asked too many things to do on first abstract layer, and being the first the slower one, nothing can be that fast.

As Summary

We, as web or scripting programming languages developers, rarely think that performances on the highest level ever can be that important but unfortunately, that highest level is the slowest one ever so, specially if we would like to reach best frame rate via canvas, WebGL, or CSS3 animations, it's highly recommended to be sure that the strategy/code we are using is the best one for our requirements.
As example, if we spend just a millisecond more to create each object we need for a single frame, we can easily switch from 30fps, a decent visual framerate, to 29 or less, were things will start to be visually slower for our eyes ...
Finally, kudos for Opera Mini and its growing market share, I am pretty sure it will become soon the IE for mobile platforms, making developers life easier, being a portable browser fallback for whatever website or application, hoping will not have all IE problems we all know.