FOLLOWING

BEST PRACTICES

WHAT WE ARE GOING TO TALK ABOUT



  • HTML and CSS Best Practices
  • Principles of Writing Consistent JavaScript
  • Importance of JSLint
  • Commenting made easy - JSDocs
  • Tools for improving Development


Best Practices for writing HTML and CSS

Why is this important?

One Simple Idea

All code in any code-base should look like a single person typed it, no matter how many people contributed.

HTML and CSS 101


  1. Use DOCTYPE
    <!-- HTML 5 -->>
    <!DOCTYPE html>
  2. Close the tags. Always.
    <li>Some text here.
    <li>Some new text here.
    <li>You get the idea.
  3. Use Semantic Elements

//Bad code
<span class="heading"><strong>Welcome Back</span></strong>
<br><br>
It has been a while. What have you been up to lately?
<br><br>
 //Good Code

<h1>Welcome Back</h1>
<p>It has been a while. What have you been up to lately?</p>

4.  Keep the Syntax Organized
    • Use lowercase letters within element names, attributes, and values
    • Indent nested elements
    • Strictly use double quotes, not single or completely omitted quotes
    • Remove the forward slash at the end of self-closing elements
    • Omit the values on Boolean attributes

5. Use alt for img tags

6. No inline - CSS or JavaScript

7. Learn the html tags

    • What is <abbr> tag used for?
    • How about <cite>?

8. Understand and use CSS Resets

9. Do not use IDs in CSS selectors

10. Use specific classes when necessary

11. Use shorthand properties and values

img {
  margin: 5px 10px;
}
button {
  padding-left: 20px;
}
12. Write CSS lines using multiple lines and spaces
a,
.btn {
  background: #aaa;
  color: #f60;
  font-size: 18px;
  padding: 6px;
}
13. Use proper class names
 .Red_Box { ... } //NO
 .alert-message { ... } //YES

14.  Modularize styles for re-use

15. Avoid using tables!!

16. Browser support

    • Use fallbacks and shims

17. Provide fallbacks for media

<audio controls>    
    <source src=sound.ogg type=audio/ogg>    
    <source src=sound.mp3 type=audio/mp3>      
    <!-- fallback content: -->      
    <a href=sound.ogg>Ogg</a>
    <a href=sound.mp3>MP3</a>  
</audio>
<video controls>    
    <source src=video.webm type=video/webm>    
    <source src=video.mp4 type=video/mp4>      
    <!-- fallback content: -->      
    <iframe width="480" height="360" src="#" frameborder="0" allowfullscreen>/<iframe>  
</video>

18. Forms

    • Enclose all label names with the <label> tag.
    • Use the new email and url input types to define these common fields.
    • Use the placeholder attribute to provide input hints.
    • Use the required attribute to request validation.
    • Drop the name attribute in favor of an id where needed.
19. Understand Device limitations
20. Avoid using iframes
21. Use .htaccess to the maximum
    • Enable GZIP compression
    • Add expire headers to static content
    • Using redirects
    • Add MIME types

22. Place CSS links in the head tag
23. Place JS links at the end of the body tag




Principles of writing consistent and correct JavaScript code






"law of code style consistency"

Whitespacing

  • Never mix white spaces and tabs
  • Check for indentation
  • No extra spaces / tabs at the end of line / file
  • Use SublimeText to convert between spaces and tabs
  • The file .jshintrc does all the work. Just use it correctly.


Beautiful Syntax

a. Parenthesis, Braces and Linebreaks

Have spaces, braces and span multiple lines

  • if
  • else
  • for
  • while
  • try

Encourages readability

Beautiful Syntax


DO NOT DO THIS
if(condition) doSomething();

while(condition) iterating++;

for(var i=0;i<100;i++) someIterativeFn();

YOU CODE IS MINIFIED AT END
IMPROVE READABILITY NOW

Beautiful Syntax

 // Use whitespace to promote readability

if ( condition ) {
  // statements
}

while ( condition ) {
  // statements
}

for ( var i = 0; i < 100; i++ ) {
  // statements
}var prop;

for ( prop in object ) {
  // statements
}

if ( true ) {
  // statements
} else {
  // statements
}

Beautiful Syntax

b. Assignments, Declarations, Functions

Use only one 'var' per scope

 // Variables
var foo = "bar",
  num = 1,
  undef;

// Literal notations:
var array = [],
  object = {};
// Using only one `var` per scope (function) promotes readability // and keeps your declaration list free of clutter (also saves a few keystrokes)

Beautiful Syntax


 // Bad
var foo = "";
var bar = "";
var qux;

// Good
var foo = "",
  bar = "",
  quux;
One Scope -> One var

Beautiful Syntax

var statements should always be in the beginning of their respective scope (function).
 // Bad
function foo() {

  // some statements here

  var bar = "",
    qux;
}
 // Good
function foo() {
  var bar = "",
    qux;

  // all statements after the variables declarations.
}

Beautiful Syntax

Using Function Declaration, Expression and Usage
 // Named Function Declaration
function foo( arg1, argN ) {

}

// Usage
foo( arg1, argN );

// Function Expression
var square = function( number ) {
  // Return something valuable and relevant
  return number * number;
};// Constructor Declaration
function FooBar( options ) {

  this.options = options;
}

// Usage
var fooBar = new FooBar({ a: "alpha" });

fooBar.options;

Beautiful Syntax

c. Exceptions and Slight Deviations
 // Functions with callbacks
foo(function() {
  // Note there is no extra space between the first paren
  // of the executing function call and the word "function"
});

// Function accepting an array, no space
foo([ "alpha", "beta" ]);
// Function accepting an object, no space foo({ a: "alpha", b: "beta" }); // Single argument string literal, no space foo("bar"); // Inner grouping parens, no space if ( !("foo" in obj) ) { }

Beautiful Syntax

d. Be Consistent everywhere
 if (condition) {
  // statements
}

while (condition) {
  // statements
}

for (var i = 0; i < 100; i++) {
  // statements
}

if (true) { // statements } else { // statements }

Beautiful Syntax


e. Quotes

  • Single or Double - Doesn't matter
  • ABSOLUTELY MUST BE CONSISTENT
  • NEVER MIX QUOTES IN THE PROJECT

Type Checking

a. Actual Types
-----Use 'type of'-----
String:
typeof variable === "string"

Number: typeof variable === "number"
Boolean: typeof variable === "boolean"
Object: typeof variable === "object"
Array: Array.isArray( arrayLikeObject ) (wherever possible)

Type Checking

b. Coerced Types
 // `foo` has been declared with the value `0` and its type is `number`
var foo = 0;

// typeof foo; ?

foo = document.getElementById("foo-input").value;
// typeof foo; ?
if ( foo === 1 ) { importantTask(); }

Type Checking

Solution??

 // You can preempt issues by using smart coercion with unary + or - operators:

foo = +document.getElementById("foo-input").value;
//    ^ unary + operator will convert its right side operand to a number

// typeof foo; ??

if ( foo === 1 ) {

  importantTask();

}

Type Checking

More examples
 var number = 1,
  string = "1",
  bool = false;

number;  //answer?
number + "";
string;
+string;
+string++;
string;
bool;
+bool;
bool + "";
"1", "1", 1, 1, 2, false, 0, "false"

Type Checking

Small Exercise
var number = 1,
  string = "1",
  bool = true;

string === number;

string === number + "";

+string === number; bool === number; +bool === number; bool === string; bool === !!string;

Conditional Evaluation

For Arrays

 // When only evaluating that an array has length,
// instead of this:
if ( array.length > 0 ) ...

// ...evaluate truthiness, like this:
if ( array.length ) ...


// When only evaluating that an array is empty, // instead of this: if ( array.length === 0 ) ... // ...evaluate truthiness, like this: if ( !array.length ) ...

Conditional Evaluation

For Strings
// When only evaluating that a string is not empty,
// instead of this: if ( string !== "" ) ...
// ...evaluate truthiness, like this: if ( string ) ...
// When only evaluating that a string _is_ empty, // instead of this: if ( string === "" ) ...
// ...evaluate falsy-ness, like this: if ( !string ) ...

Conditional Evaluation

For Variables
// When only evaluating that a reference is true,
// instead of this:
if ( foo === true ) ...

// ...evaluate like you mean it, take advantage of built in capabilities: if ( foo ) ... // When evaluating that a reference is false, // instead of this: if ( foo === false ) ... // ...use negation to coerce a true evaluation if ( !foo ) ...
// ...Be careful, this will also match: 0, "", null, undefined, NaN // If you _MUST_ test for a boolean false, then use if ( foo === false ) ...

Conditional Evaluation

A Simple Trick
 // When only evaluating a ref that might be null or undefined, but NOT false, "" or 0,
// instead of this:
if ( foo === null || foo === undefined ) ...
// ...take advantage of == type coercion, like this:
if ( foo == null ) ...
// Remember, using == will match a `null` to BOTH `null` and `undefined`
// but not `false`, "" or 0
null == undefined
ALWAYS EVALUATE FOR THE BEST
USE '==='* and Booleans

Naming

  • You are not computer / compiler
  • Don't save space by using short variable names
  • Use meaningful variable names

NO NO to these
 // Example of code with poor names

function q(s) {
  return document.querySelectorAll(s);
}
var i,a=[],els=q("#foo");
for(i=0;i<els.length;i++){a.push(els[i]);}

Naming

 // Same code with improved names

function query( selector ) {
  return document.querySelectorAll( selector );
}

var idx = 0,
  elements = [],
  matches = query("#foo"),
  length = matches.length;

for ( ; idx < length; idx++ ) {
  elements.push( matches[ idx ] );
}

Naming

Conventions
 // Naming strings

`dog` is a string

// Naming arrays

`dogs` is an array of `dog` strings// Naming functions, objects, instances, etc

camelCase; function and var declarations

// Naming pseudo-classes, constructors, prototypes, etc.

PascalCase; constructor function

// Naming regular expressions

rDesc = //;

Naming

Google Closure Library Style Guide

functionNamesLikeThis;
variableNamesLikeThis;
ConstructorNamesLikeThis;
EnumNamesLikeThis;
methodNamesLikeThis;
SYMBOLIC_CONSTANTS_LIKE_THIS;

Naming

Using this and bind correctly
 function Device( opts ) {
  this.value = null;  // open an async stream,
  // this will be called continuously
  stream.read( opts.path, function( data ) {
// Update this instance's current value // with the most recent value from the // data stream this.value = data; }.bind(this) ); // Throttle the frequency of events emitted from // this Device instance setInterval(function() { // Emit a throttled event this.emit("event"); }.bind(this), opts.freq || 100 ); }

Naming

Using this and bind with libraries

 // underscore, _.bind()
function Device( opts ) {

  this.value = null;

  stream.read( opts.path, _.bind(function( data ) {

    this.value = data;

  }, this) );

  setInterval(_.bind(function() {

    this.emit("event");

  }, this), opts.freq || 100 );
}

Naming

Last resort
NOT ADVISABLE
 function Device( opts ) {
  var self = this;

  this.value = null;

  stream.read( opts.path, function( data ) {

    self.value = data;

  });

  setInterval(function() {

    self.emit("event");
  }, opts.freq || 100 );
}

Naming

a special 'thisArg' signature

var obj;

obj = { f: "foo", b: "bar", q: "qux" };

Object.keys( obj ).forEach(function( key ) {

  // |this| now refers to `obj`

  console.log( this[ key ] );

}, obj ); // <-- the last arg is `thisArg`

// Prints...
// "foo"
// "bar"
// "qux"

Miscellaneous

Early returns promote code readability
 // Bad:
function returnLate( foo ) {
  var ret;

  if ( foo ) {
    ret = "foo";
  } else {
    ret = "quux";
  }
  return ret;
}
// Good:

function returnEarly( foo ) {

  if ( foo ) {
    return "foo";
  }
  return "quux";
}

Misc

Comments

  • Single lines above the code -> Subject
  • Multiline commenting -> Very Good
  • End of line commenting -> Prohibited


More about commenting later...

Misc


The semicolon confusion

 var foo = function() {
  return true;
};  // semicolon here.

function foo() { return true; } // no semicolon here.

Misc

Function declaration within blocks

NO TO THIS
 if (x) {
  function foo() {}
}

USE THIS
 if (x) {
  var foo = function() {};
}

Misc

Prefer nullifying than deleting

Use this.foo = null, instead of delete this.foo

//Use Foo.prototype.dispose = function() {
  this.property_ = null;
};
//Instead of:

Foo.prototype.dispose = function() {
  delete this.property_;
};

Misc

eval??
Only for code loaders and REPL (Read Eval Print Loop)
{
  "name": "Alice",
  "id": 31502,
  "email": "looking_glass@example.com"
}
//NO TO THIS PLEASE var userInfo = eval(feed);
var email = userInfo['email'];
// USE ALTERNATIVES INSTEADvar userInfo = JSON.parse(feed); var email = userInfo['email'];

Misc

Multiline String Literals
//NO TO THIS var myString = 'A rather long string of English text, an error message \
                actually that just keeps going and going -- an error \
                message to make the Energizer bunny blush (right through \
                those Schwarzenegger shades)! Where was I? Oh yes, \
                you\'ve got an error and all the extraneous whitespace is\
                just gravy.  Have a nice day.';
//USE CONCATENATION INSTEADvar myString = 'A rather long string of English text, an error message ' + 'actually that just keeps going and going -- an error ' + 'message to make the Energizer bunny blush (right through ' + 'those Schwarzenegger shades)! Where was I? Oh yes, ' + 'you\'ve got an error and all the extraneous whitespace is ' + 'just gravy. Have a nice day.';

Misc

Using Array  Literals
Do not use 'new'
//BAD // Length is 3.
var a1 = new Array(x1, x2, x3);
// Length is 2.
var a2 = new Array(x1, x2);
//GOODvar a = [x1, x2, x3];var a2 = [x1, x2];

Misc

Using Object Literals
//BADvar o = new Object();

var o2 = new Object();
o2.a = 0;
o2.b = 1;
o2.c = 2;o2['strange key'] = 3;

//GOODvar o = {}; var o2 = { a: 0, b: 1, c: 2, 'strange key': 3 };

Misc

Modifying Prototypes of built in Objects


DO NOT MODIFY BUILTINS like
Object.prototype
Array.prototype
Function.prototype

Misc

Boolean Expressions
Boolean('0') == true
'0' != true
0 != null
0 == []
0 == falseBoolean(null) == false
null != true
null != falseBoolean(undefined) == false
undefined != true
undefined != falseBoolean([]) == true
[] != true
[] == false
Boolean({}) == true
{} != true
{} != false

Misc

Use ternary operators like || and && for short-circuiting

 /** @param {*=} opt_win */
function foo(opt_win) {
  var win = opt_win || window;
  // ...
}
 var kid = node && node.kids && node.kids[index];
if (kid) {
  foo(kid);
}
Don't have more than 4 filters while checking

Misc

Iterating over Node lists

NO NO
 var paragraphs = document.getElementsByTagName('p');
for (var i = 0; i < paragraphs.length; i++) {
  doSomething(paragraphs[i]);
}

YES YES YES
 var paragraphs = document.getElementsByTagName('p');
for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
  doSomething(paragraph);
}




Using JSLint

JS Lint


Checks your code for structural and formatting errors

Install the latest SublimeLinter v3

Install these packages
  • SublimeLinter-jshint
  • SublimeLinter-json
  • SublimeLinter-phplint
  • SublimeLinter-csslint
  • SublimeLinter-html-tidy




Commenting Code using JSDocs

JSDocs

 /**
 * Illustrates line wrapping for long param/return descriptions.
 * @param {string} foo This is a param with a description too long to fit in
 *     one line.
 * @return {number} This returns something that has a description too long to
 *     fit in one line.
 */
project.MyClass.prototype.method = function(foo) {
  return 5;
};
Install DocBlockr plugin in SublimeText

Run /** or // and 'tab' to auto form the comments

Works across HTML, JS, CSS and PHP




Tools for easy development


Next Session

Best Practices

By Chaithanya Yambari

Best Practices

Best Practices to follow while developing HTML / JS Applications

  • 638