Showing posts with label best practice. Show all posts
Showing posts with label best practice. Show all posts

June 16, 2011

Why your Java math might be wrong

We all know that mathematical operations with decimals in JavaScript are no good. For instance:

alert(1.1 + 2.2); // should be 3.3, but the result is 3.3000000000000003

It turns out this is a cross to bare for pretty much any language that uses the IEEE-754 standard to implement a floating point number and that includes... *drums*... Java.

// Adding doubles
System.out.println(1.1 + 2.2); // 3.3000000000000003

// Adding floats
System.out.println(1.1f + 2.2f); // 3.3000002

So if you're doing these kinds of operations with float or double in Java you might be doing them wrong.

This is huge because an application that deals with money is almost certain to have to deal with decimals. You have to get it right or you'll be in a lot of trouble.

"People have a reasonable expectation that when you’re adding up their money you’re going to come up with the right result, and you don’t" - Douglas Crockford

float and double should never be used for currency or high precision operations.

The proper way to do this is using the BigDecimal class. Check out the documentation.

Let's try it again, this time using BigDecimal:

BigDecimal num1 = new BigDecimal(1.1);
BigDecimal num2 = new BigDecimal(2.2);
System.out.println(num1.add(num2)); // 3.30000000000000026645352591003756...etc.

Oh noes! what happened? I thought BigDecimal was supposed to solve all my problems.

Hold on, take another look at the code above. You'll notice we're constructing our BigDecimal objects using a... *drums*... double.

So? Well, that's the deal with float and double, it's why they should not be used in these operations. They cannot accurately represent numbers with decimals.

OK, how do we fix this? There's a constructor that takes a String argument (didn't you look at the documentation?). That's how we should always do it. Pass a String so you won't lose precision:

BigDecimal num3 = new BigDecimal("1.1");
BigDecimal num4 = new BigDecimal("2.2");
System.out.println(num3.add(num4)); // 3.3, finally

Perfect! now lawsuits won't be falling from the sky.

Thanks for reading and let me know your comments.

Sources:
Representing money
Beware of floating point numbers

March 3, 2011

Using innerHTML

innerHTML is a read/write property of a DOM element that gets/sets the HTML contained in the element.

It's fast
This might vary between browsers but, it's almost a fact that creating and inserting elements using innerHTML instead of DOM methods is faster, not only at execution time, it'll also make the script size lighter because less code is needed.

It's clean & readable
Although the name, innerHTML, might seem confusing at first, it comes as the better choice in terms of code readability because DOM methods are very verbose and can consume a lot of lines of code.

It's supported
It was first introduced by Microsoft as proprietary to IE and there's no spec that defines the behavior of innerHTML but it has been adopted by all major browsers because of its usefulness and it pretty much works the same in all of them.

Creating and inserting using DOM methods:
var newDiv = document.createElement('div');
newDiv.setAttribute('id', 'new-div');
newDiv.setAttribute('class', 'big-div');
var text = document.createTextNode('Some text here');
newDiv.appendChild(text);

document.body.appendChild(newDiv); // div is inserted in the tree

Creating and inserting using innerHTML:
var newDiv = '<div id=\'new-div\' class=\'big-div\'>Some text here</div>';
document.body.innerHTML = newDiv; // div is inserted in the tree

Reasons not to use it

  • Not standard. Although it's fast and it works, the bottom line is that it is not part of any W3C or DOM standard. However, there are plans of adding it to the HTML5 specification.
  • XSS unsafe. You have to know when to use it, otherwise you are exposing your application to XSS attacks, choose DOM methods until you're familiar with the subject.
  • Not implemented everywhere. There are some table related elements, in IE, that can't be modified with it. The implementation and behavior might vary from browser to browser.
  • Destroys the children. Setting a value to innerHTML will destroy every descendant to that element, if any of those descendants had event handlers, that could potentially create a memory leak in some browsers.
Thanks for reading and let me know your comments.

Sources:
innerHTML (Mozilla Developer Network)
innerHTML (Microsoft Developer Network)

February 28, 2011

Manipulating DOM elements and styles

Manipulating elements
Once you have access to an element, you can manipulate it using assignment of object properties or DOM methods. Let's take a look at the examples:

HTML
<img src="small-dog.png" id="img-dog">
JavaScript
var myImage = document.getElementById('img-dog');

// Object property
myImage.src = 'big-dog.png';

// DOM method
myImage.setAttribute('src', 'big-dog.png');

In both examples we're changing the src of our image element. It's recommended to use the first example, it's easier, shorter, faster and works across browsers. If, for some reason, you can't use it, use the second one. Here's a link to quirksmode.org with more information.



Style
You can also change an element's style dynamically . You can do so by changing the className property or applying a style directly into the style object.

HTML
<span id="my-span">Some text here</span>
JavaScript
var mySpan = document.getElementById('my-span');

mySpan.className = 'big'; // the CSS class 'big' makes the text big
mySpan.style.textAlign = 'center'; // centers the text

Both, className and style, are read/write. But, the style object will only reflect styles that are directly applied to the element (i.e. in the markup), not the ones from the cascade. To get those you need go a little bit further:

HTML
<span id="my-span">Some text here</span>
CSS
#my-span { font-weight: bold; }
JavaScript
var mySpan = document.getElementById('my-span');

mySpan.style.fontWeight; // returns an empty string
mySpan.currentStyle['fontWeight']; // returns 'bold', works only in IE
document.defaultView.
        getComputedStyle(mySpan, null).
        getPropertyValue('font-weight'); // returns 'bold', doesn't work in IE
As you can see:

  • The CSS property on the style object didn't have anything and returned an empty string.
  • IE's proprietary method is very nice and readable (you could also use the dot notation, e.g. mySpan.currentStyle.fontWeight).
  • The standard way is very verbose and complicated but works on all standards compliant browsers.
If you need to get styles individually I suggest creating a utility function to deal with the cross browser issues (an example from quirksmode.org).
But in general, I recommend using CSS classes for dynamic styling. It is way easier and faster to add/modify/delete CSS classes. It's a style agnostic practice, in case you don't have control over the styles, and also encourages layer separation.

Thanks for reading and let me know your comments.

Source: Douglas Crockford: "Theory of the Dom" (2 of 3)

February 7, 2011

The script tag and the DOM

Today I'm going to talk about the DOM. Things you might not know, tricks, nuances and some best practices (I think). So, let's get to it.

The <script> tag
It first appeared in Netscape Navigator 2 as a way to put programs in HTML documents and it then became part of the HTML standard in version 4.
<script type="text/javascript">...</script>



<!-- // -->
The <!-- // --> hack was a workaround to prevent HTML documents from displaying code on the page by older browsers like Mosaic. You can still see this pattern in pages but it's no longer necessary as today's browsers understand both the script tag and JavaScript.
<script type="text/javascript">
<!--
  code here
// -->
</script>



The language attribute
Microsoft came up with it as a way to select what kind of language (e.g. VBScript) you wanted to use for your program. The W3C deprecated this in favor of the type attribute. Avoid the language attribute.
<script language="javascript" type="text/javascript">...</script>



The src attribute
It allows you to load a script from an external file. Great, because you don't want to put JavaScript in your HTML, for a large number of reasons: it makes the HTML file heavier, it becomes less maintainable, it becomes less scalable, it's not cachable, it becomes hard to minify or inspect, etc. It is highly recommended that you do not write JavaScript in your HTML and instead use the src attribute.
<script type="text/javascript" scr="js/script.js"></script>



The type attribute
The W3C added the type attribute to replace the language one. It takes a MIME type instead of the name of the language. The official MIME type for JavaScript is application/javascript or application/ecmascript and the most up to date browsers understand this, but not IE. So, if you want cross-browser support (and you should) you have to use type="text/javascript", at least for now. This is a required attribute for HTML validation, but in practice you can just leave this out, the default language on all major browsers is JavaScript and besides if you're using src, it ignores it.
<script type="text/javascript">...</script>
<script>...</script>
<script type="text/javascript" src="js/script.js">...</script>
<script src="js/script.js">...</script>



Loading time
Because of the way the browser works, loading of a page's assets is incremental and single-threaded, it is recommended that the script tags be placed as low in the body as possible. It is also recommended to place your CSS i.e. link, as high in the head as possible, this will greatly improve the user experience.
You should also minify, gzip and join your script files into one. These will reduce file size and the number of HTTP requests and thus, the time it takes for the browser to load the page.
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="css/styles.css">
    <!-- head contents here -->
  </head>
  <body>
    <!-- body contents here -->
    <script type="text/javascript" src="js/script.js"></script>
  </body>
</html>



document.write
If you call this before the onload event triggers it will insert stuff into your document, but if you do it after it, it destroys your document and replace it with new stuff. You should avoid using document.write, there are better alternatives now.



Collections
  • document.anchors
  • document.applets
  • document.embeds
  • document.forms
  • document.frames
  • document.images
  • document.plugins
  • document.scripts
  • document.stylesheets
Netscape provided these as a way to get and modify elements easier. These are still available but obsolete and you should avoid using them as there are better alternatives now.



The name and id attributes
If an element didn't have an id but it had a name with the same value, you could still get access to it via DOM methods. They used to be interchangeable but they are not anymore.

The HTML:
<input type="text" name="firstname" value="my value">
The JavaScript:
var input = document.getElementById('firstname');
input.value = 'another value'; // sets a value to "firstname" field



document.all
Microsoft came up with this as a type of super collection that contained any tag that had a name or id. Since this is propriety thing and not cross-browser, it is best to not use it.



Some of the topics that I did not cover in this post were browser history, how a browser works and document tree structure. If you're interested, click the link below to watch the video.

Thanks for reading and let me know your comments.

Source: Douglas Crockford: "Theory of the DOM" (1 of 3)