Difference between revisions of "AppSuite:UI Development Style Guide"

m
m
Line 3: Line 3:
 
There lots of stuff we don't need to talk about because JSHint will bug you! (white space, formatting, undefined variables, globals, etc.)
 
There lots of stuff we don't need to talk about because JSHint will bug you! (white space, formatting, undefined variables, globals, etc.)
  
'''Indentation is 4 spaces'''
+
'''Indentation is 4 spaces'''<br>
 
No tabs! And there's no need for two consecutive empty lines. If possible turn on "show white-spaces" in your editor.
 
No tabs! And there's no need for two consecutive empty lines. If possible turn on "show white-spaces" in your editor.
  
 
''Eclipse seems to have a bug on MacOS that makes the editor really slow when showing white-spaces. However, as long as you configure Eclipse properly to use spaces instead of tabs and remove all trailing white-space on save (yep, there's a flag for that), you can leave that option turned off.''
 
''Eclipse seems to have a bug on MacOS that makes the editor really slow when showing white-spaces. However, as long as you configure Eclipse properly to use spaces instead of tabs and remove all trailing white-space on save (yep, there's a flag for that), you can leave that option turned off.''
  
'''Use underscore's high-level functions (e.g. each, filter, map)'''
+
'''Use underscore's high-level functions (e.g. each, filter, map)'''<br>
 
Because it's nice to read and it uses native code if available. For example, iterating an array via .each() is faster than a classic for-loop (in Chrome at least). Don't use jQuery's each (except for DOM nodes). If you need "break" you have to use a classic for-loop.
 
Because it's nice to read and it uses native code if available. For example, iterating an array via .each() is faster than a classic for-loop (in Chrome at least). Don't use jQuery's each (except for DOM nodes). If you need "break" you have to use a classic for-loop.
  
'''Don't make functions within a loop'''
+
'''Don't make functions within a loop'''<br>
 
For most cases, JSHint will bug you. But when using .each(), for example, it won't. However, you might still create functions over and over again - so avoid that. And if there no good reason, try to avoid creating nested sub functions (bit slower; might leak memory).
 
For most cases, JSHint will bug you. But when using .each(), for example, it won't. However, you might still create functions over and over again - so avoid that. And if there no good reason, try to avoid creating nested sub functions (bit slower; might leak memory).
  
'''Require modules only when they're required!'''
+
'''Require modules only when they're required!'''<br>
 
Review your code if your module really needs all required modules upfront. Check if some dependencies can be resolved at runtime, e.g. event handlers or functions that are working asynchronously.
 
Review your code if your module really needs all required modules upfront. Check if some dependencies can be resolved at runtime, e.g. event handlers or functions that are working asynchronously.
  
 
''Hint: We patched require.js, so require() returns a deferred object.''
 
''Hint: We patched require.js, so require() returns a deferred object.''
  
'''Use jQuery's .on() and .off() instead of .bind() .unbind() .delegate()'''
+
'''Use jQuery's .on() and .off() instead of .bind() .unbind() .delegate()'''<br>
 
Because the new event system of jQuery 1.7 was completely redesigned and bind/unbind are now marked as deprecated.
 
Because the new event system of jQuery 1.7 was completely redesigned and bind/unbind are now marked as deprecated.
  
'''Use delegated event handlers if possible'''
+
'''Use delegated event handlers if possible'''<br>
 
Instead of adding tons of click handlers for each element, use one (!) delegate on the parent element (VGrid uses that technique for example).
 
Instead of adding tons of click handlers for each element, use one (!) delegate on the parent element (VGrid uses that technique for example).
  
'''Don't create global code'''
+
'''Don't create global code'''<br>
 
underscore.js is an exception. There some basic jQuery plugin that extend jQuery.fn (that's global as well). Even for rarely used jQuery plugins create AMDs (Asynchronous Module Definition) and load them via require().
 
underscore.js is an exception. There some basic jQuery plugin that extend jQuery.fn (that's global as well). Even for rarely used jQuery plugins create AMDs (Asynchronous Module Definition) and load them via require().
  
'''Naming'''
+
'''Naming'''<br>
 
Use camelCase for variables (e.g. variableName). Use upper-case/underscores for constants (e.g. MAX_WIDTH). Use camel-case with upper-case first char for class names (e.g. ClassDefinition). Don't use special notations for jQuery-Objects: var node = $(…) is better than var $node = $(…);
 
Use camelCase for variables (e.g. variableName). Use upper-case/underscores for constants (e.g. MAX_WIDTH). Use camel-case with upper-case first char for class names (e.g. ClassDefinition). Don't use special notations for jQuery-Objects: var node = $(…) is better than var $node = $(…);
  
'''Try to define all variables at the beginning of a function'''
+
'''Try to define all variables at the beginning of a function'''<br>
 
And please just use one (!) "var" statement.
 
And please just use one (!) "var" statement.
  
'''Use $.Deferred() whenever possible'''
+
'''Use $.Deferred() whenever possible'''<br>
 
Instead of using simple callbacks. Remember that your functions might need an error callback as well.
 
Instead of using simple callbacks. Remember that your functions might need an error callback as well.
  
 
''Hint: You can use "return $.when();" instead of "return $.Deferred().resolve();"''
 
''Hint: You can use "return $.when();" instead of "return $.Deferred().resolve();"''
  
'''Use options instead of long argument lists'''
+
'''Use options instead of long argument lists'''<br>
 
Avoid creating functions like foo("1234", true, null, null, cb_success). Instead use: foo({ folder: "1234", cache: true }).done(….);
 
Avoid creating functions like foo("1234", true, null, null, cb_success). Instead use: foo({ folder: "1234", cache: true }).done(….);
  
'''Don't use $('&lt;div class="foo" style="float: left">Hello</div>')'''
+
'''Don't use $('&lt;div class="foo" style="float: left">Hello</div>')'''<br>
 
This is hard to read, hard to extend, doesn't allow i18n. Might become evil once 'Hello' is replaced by a variable (evil HTML injection). Just use $('<div>') plus proper helpers like addClass(), css(), text() etc.
 
This is hard to read, hard to extend, doesn't allow i18n. Might become evil once 'Hello' is replaced by a variable (evil HTML injection). Just use $('<div>') plus proper helpers like addClass(), css(), text() etc.
  
'''Use $('&lt;div>') instead of $('<div/>')'''
+
'''Use $('&lt;div>') instead of $('<div/>')'''<br>
 
There's no need for XHTML
 
There's no need for XHTML
  
Line 55: Line 55:
 
Example: { a: 1000, b: 2000 } has better readability than {a:1000,b:2000}.
 
Example: { a: 1000, b: 2000 } has better readability than {a:1000,b:2000}.
  
'''Don't COPY/PASTE code you don't understand!'''
+
'''Don't COPY/PASTE code you don't understand!'''<br>
'''Never ever do COPY/PASTE inheritance'''
+
'''Never ever do COPY/PASTE inheritance'''<br>
 
Always try to code stuff by yourself. Don't just imitate what others developed. If it looks like what you need, understand it first. If you can use it, try to really reuse it (define & require are your friends). If you need a slight modification, try to add that via options. Talk to the author if possible.
 
Always try to code stuff by yourself. Don't just imitate what others developed. If it looks like what you need, understand it first. If you can use it, try to really reuse it (define & require are your friends). If you need a slight modification, try to add that via options. Talk to the author if possible.
  
'''Of course… Don't repeat yourself!'''
+
'''Of course… Don't repeat yourself!'''<br>Try to be smart. Look for patterns. Create local helper functions once you have to do stuff twice.
Try to be smart. Look for patterns. Create local helper functions once you have to do stuff twice.
 

Revision as of 15:57, 9 April 2013

UI Development Style Guide

There lots of stuff we don't need to talk about because JSHint will bug you! (white space, formatting, undefined variables, globals, etc.)

Indentation is 4 spaces
No tabs! And there's no need for two consecutive empty lines. If possible turn on "show white-spaces" in your editor.

Eclipse seems to have a bug on MacOS that makes the editor really slow when showing white-spaces. However, as long as you configure Eclipse properly to use spaces instead of tabs and remove all trailing white-space on save (yep, there's a flag for that), you can leave that option turned off.

Use underscore's high-level functions (e.g. each, filter, map)
Because it's nice to read and it uses native code if available. For example, iterating an array via .each() is faster than a classic for-loop (in Chrome at least). Don't use jQuery's each (except for DOM nodes). If you need "break" you have to use a classic for-loop.

Don't make functions within a loop
For most cases, JSHint will bug you. But when using .each(), for example, it won't. However, you might still create functions over and over again - so avoid that. And if there no good reason, try to avoid creating nested sub functions (bit slower; might leak memory).

Require modules only when they're required!
Review your code if your module really needs all required modules upfront. Check if some dependencies can be resolved at runtime, e.g. event handlers or functions that are working asynchronously.

Hint: We patched require.js, so require() returns a deferred object.

Use jQuery's .on() and .off() instead of .bind() .unbind() .delegate()
Because the new event system of jQuery 1.7 was completely redesigned and bind/unbind are now marked as deprecated.

Use delegated event handlers if possible
Instead of adding tons of click handlers for each element, use one (!) delegate on the parent element (VGrid uses that technique for example).

Don't create global code
underscore.js is an exception. There some basic jQuery plugin that extend jQuery.fn (that's global as well). Even for rarely used jQuery plugins create AMDs (Asynchronous Module Definition) and load them via require().

Naming
Use camelCase for variables (e.g. variableName). Use upper-case/underscores for constants (e.g. MAX_WIDTH). Use camel-case with upper-case first char for class names (e.g. ClassDefinition). Don't use special notations for jQuery-Objects: var node = $(…) is better than var $node = $(…);

Try to define all variables at the beginning of a function
And please just use one (!) "var" statement.

Use $.Deferred() whenever possible
Instead of using simple callbacks. Remember that your functions might need an error callback as well.

Hint: You can use "return $.when();" instead of "return $.Deferred().resolve();"

Use options instead of long argument lists
Avoid creating functions like foo("1234", true, null, null, cb_success). Instead use: foo({ folder: "1234", cache: true }).done(….);

Don't use $('<div class="foo" style="float: left">Hello')
This is hard to read, hard to extend, doesn't allow i18n. Might become evil once 'Hello' is replaced by a variable (evil HTML injection). Just use $('

') plus proper helpers like addClass(), css(), text() etc. Use $('<div>') instead of $('
')

There's no need for XHTML

Prefer $('<input>', { type: 'radio' }); over $('<input>').attr('type', 'radio'); Actually there's a semantic difference (not just syntax) - IE will teach you this! Never please write $('<label ...></label>'), $('<div></div>') or even $('<input...></input>')

Try to write readable code - even if JSHint is already happy. Example: { a: 1000, b: 2000 } has better readability than {a:1000,b:2000}.

Don't COPY/PASTE code you don't understand!
Never ever do COPY/PASTE inheritance
Always try to code stuff by yourself. Don't just imitate what others developed. If it looks like what you need, understand it first. If you can use it, try to really reuse it (define & require are your friends). If you need a slight modification, try to add that via options. Talk to the author if possible.

Of course… Don't repeat yourself!
Try to be smart. Look for patterns. Create local helper functions once you have to do stuff twice.