CoffeeScript, An Introduction for Nodejs developers

mehdivk 3,717 views 49 slides Oct 14, 2014
Slide 1
Slide 1 of 49
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49

About This Presentation

No description available for this slideshow.


Slide Content

|
COFFEESCRIPT
AN INTRODUCTION FOR NODE DEVELOPERS
BY: MEHDI VALIKHANI
SOFTWARE ENGINEER @ ALPHATISE
Follow me: @[email protected]

IT'S JUST JAVASCRIPT
COFFEESCRIPT IS A PROGRAMMING LANGUAGE THAT
TRANSCOMPILES TO JAVASCRIPT.
SYNTACTIC SUGAR TO JAVASCRIPT

IT'S MATURE AND PRODUCTION-READY
DEVELOPED BY: JEREMY ASHKENAS
INITIAL COMMIT: DECEMBER 13TH, 2009
FIRST RELEASE: DECEMBER 24H, 2009
VERSION 1.0: FEBRUARY 2010
CURRENT VERSION: 1.8

WHO'S USING
COFFEESCRIPT?
DROPBOX
GITHUB

WRITE LESS, DO MORE
HUMAN-READABLE CODE
STAY AWAY FROM WEIRD JS BEHAVIOUR
SAY GOODBYE TO PROTOTYPE! USE CLASSES
ANY MANY MORE ...

COFFEESCRIPT SYNTAX

NO MORE VAR ; ( )

async = require 'async'
console.log async.VERSION



var async = require('async');
console.log(async.VERSION);

FUNCTIONS
IT'S PART OF OUR EVERYDAY LIFE IN JS WORLD
LET'S BE AGILE!

addUser = (user, cb) ->
model = new User
#DO SOMETHING
model.save (err, result) ->
cb null, result



var addUser = function(user, cb) {
var model = new User();
//DO SOMETHING
model.save(function(err, result){
cb(err, result);
});
}

IMPLICIT RETURN

someFunction = (param1, param2) ->
param1 * param2 * param2
console.log someFunction 100, 200



var someFunction;
someFunction = function(param1, param2) {
return param1 * param2 * param2;
}
console.log(someFunction(100, 200));

OBJECTS
GET RID OF THOSE { } ,

bus =
routeNumber: 273
from: 'Wynyard'
to: 'Chatswood'
via: 'North Sydney, Pacific Highway'



var bus = {
routerNumber: 273,
from: 'Wynyad',
to: 'Chatswood',
via: 'North Sydney, Pacific Highway'
}

query =
status:
$in: ['active', 'pending_for_approval']
payment:
$nin: ['invoice', 'free']
tc:
$exists: true



var query = {
status: {
$in: ['active', 'pending_for_approval']
},
payment: {
$nin: ['invoice', 'free']
},
tc: {
$exists: true
}
}

STRING INTERPOLOATION

meetup = 'Node'
msg = "#{meetup} meeup is awsome!"
console.log msg


var meetup = 'Node';
var msg = meetup + ' meetup is awsome!';
console.log(msg);

CLASSES
BETTER INHERITANCE WITHOUT PROTOTYPE
WE SHOULDN'T USE LIBRARIES TO HAVE CLASSES IN JS

class Cache
generateCacheKey: (key) ->
throw new Error 'Not Implemented'
getPeriod: ->
120 * 60
store: (key, data) ->
throw new Error 'Not Implemented'
clearCache: (key) ->
#DO SOMETHING
class RedisCache extends Cache
generateCacheKey: (key) ->
"redis_cache_#{key}"
store: (key, data) ->
period = @.getPeriod()
#STORE IN REDIS

DESTRUCTURING OBJECTS

{Router} = require 'express'
router = new Router



var express = require('express');
var Router = experss.Router;
router = new Router();

DESTRUCTURING ARRAYS

student = 'Mehdi Valikhani'
[firstName, lastName] = student.split ' '



var student, ref, firstName, lastName;
student = 'Mehdi Valikhani';
ref = student.split(' ');
firstName = ref[0];
lastName = ref[1];

DESTRUCTING ARGUMENTS

calculator = ({width, height}) ->
width * height
options =
width: 10
height: 5
alert calculator options

EXISTENTIAL OPERATOR ?
REMOVE THOSE NULL OR UNDEFINED CHECKES FROM CODE

if err?
#log to logger
cb err



if (typeof err !== "undefined" && err !== null)
//log to logger
cb(err);

INSTALL COFFEESCRIPT
npm install -g coffee-script

EXECUTE A SCRIPT
coffee /path/to/script.coffee

COMPILE A SCRIPT
coffee -c /path/to/script.coffee

NODE + COFFEE
FROM SCRATCH
REST API DEVELOPMENT USING EXPRESS + NODE + COFFEE

CODE STRUCTURE

+ lib
+ books
Book.coffee //Our Mongoose Model
router.coffee //router for books API
+ node_modules
+ body-parser //from JSON responses
+ coffee-script //compiler of Coffee files
+ express //express framework
app.coffee //express app config
package.json // NO DESCRIPTION
index.js //ACTUAL MAGIC HAPPENS HERE!

app.coffee

bodyParser = require 'body-parser'
express = require 'express'
userRouter = require './lib/books/router'
app = express()
app.use bodyParser.json()
app.use '/users', userRouter
module.exports = app

lib/books/router.coffee

{Router} = require 'express'
Book = require './Book'
router = new Router
fetchBook = (req, res, next) ->
req.paramBook = Book
next()
getBook = (req, res) ->
res.json(req.paramBook)
router.route('/:book_id')
.all(fetchBook)
.get(getBook)
module.exports = router

index.js

require('coffee-script/register');
var app = require('./app');
app.listen(1984, function(){
console.log('App is available via http://127.0.0.1:1984');
});

RUN THE APP
node index.js
nodemon -e js,coffee index.js

NODE + COFFEE
AN EXISTING PROJECT

ADD FOLLOWING CODE TO YOUR STARTER FILE
require('coffee-script/regiter');

THAT'S IT!
Add .coffee files, write your code in coffee
require other .js or .coffee files as always

RUN THE APP
node index.js
nodemon -e js,coffee index.js

DEBUGGING
COFFEESCRIPT
APPLICATIONS

USE "DEBUGGER" AS ALWAYS

fetchBook = (req, res, next) ->
debugger
req.paramBook = Book
next()


node debug index.js

BUT DON'T FORGET!
in debug mode, you will be faced with compiled
JS code

break in lib/books/router.coffee:11
9
10 fetchBook = function(req, res, next) {
11 debugger;
12 req.paramBook = Book;
13 return next();
debug> repl
Press Ctrl + C to leave debug repl
> req.params.book_id
'123'
>

JAVASCRIPT SCOPING
in JavaScript, the scope of a variable is
defined by its location within the source code
(it is apparent lexically) and nested
functions have access to variables declared in
their outer scope. - mozilla.org

Question: What's result of running this code?

name = 'Alex'
greeting = ->
name = 'James'
console.log "Hey #{name}!"
greeting()
console.log "Hey #{name}!"

A:
> Hey James!
> Hey James!
B:
> Hey James!
> Hey Alex!

"A" IS CORRECT ANSWER
> Hey James!
> Hey James!

THIS IS COMPILED-TO-JS VERSION OF ABOVE
CODE

var greeting, name;
name = 'Alex';
greeting = function() {
name = 'James';
return console.log("Hey " + name + "!");
};
greeting();
console.log("Hey " + name + "!");

TWO IMPORTANT FACTS
ABOUT COFEESCRIPT SCOPING
Variable shadowing is not allowed
variable is created at the moment of the first assignment to it

"VARIABLE SHADOWING IS NOT ALLOWED"
DOESN'T MEAN
YOU CAN'T DEFINE A VARIABLE MORE THAN
ONCE IN DIFFERENT FILES
IT MEANS
YOU CAN'T DEFINE IT MORE THAN ONCE IN A
SINGLE FILE

SO WHAT SHOULD I DO IF I WANT TO HAVE
SHADOWS?
It's not a good practice, don't do that!
It decreases readbility of your code!
Brings more confusion to your code
With shadowing you can't access our variables anymore (with
same name)

USE `` TO BRING VAR BACK

name = 'Alex'
greeting = ->
` `
name = 'James'
console.log "Hey #{name}!"
greeting()
console.log "Hey #{name}!"

var name
It a kind of hack! Don't do that!

SHADOW IT USING FUNCTION PARAMETER

name = 'Alex'
greeting = (name = '')->
name = 'James'
console.log "Hey #{name}!"
greeting()
console.log "Hey #{name}!"


Better first solution!

USE COFEESCRIPT'S CLOSURE FEATURE
This is much much better!

name = 'Alex'
greeting = ->
do (name = '') ->
name = 'James'
console.log "Hey #{name}!"
greeting()
console.log "Hey #{name}!"

MORE INFO ABOUT LEXICAL SCOPING:
https://github.com/raganwald-
deprecated/homoiconic/blob/master/2012/09/actually-YOU-
dont-understand-lexical-scope.md
https://github.com/raganwald-
deprecated/homoiconic/blob/master/2012/09/lexical-scope-
in-coffeescript.md

USEFUL RESOURCES
Your best friend
Don't translate CoffeeScript to JS, try to learn as new langage
Teaches CoffeeScript as new language instrad of translating to
JS
Best Practices
CoffeeScript Docs
CoffeeConsole: A Google Chrome Extention
CoffeeScript Ristretto
The Little Book On CoffeeScript
CoffeeScript Style Guide

Thank you!