Serversideness Douglas Crockford Yahoo Inc Server Side Java

  • Slides: 42
Download presentation
Serversideness Douglas Crockford Yahoo! Inc.

Serversideness Douglas Crockford Yahoo! Inc.

Server Side Java. Script • 1996 Netscape Live. Wire PHP-like. Fail. • Now Node.

Server Side Java. Script • 1996 Netscape Live. Wire PHP-like. Fail. • Now Node. js on V 8. Event driven, turn based execution. Win.

node. js • node. js implements a web server in a Java. Script event

node. js • node. js implements a web server in a Java. Script event loop. • It is a high-performance event pump. fs. read. File(filename, encoding, function (err, data) {. . . }) • Everything is (or can be) non-blocking. • Except: – some synchronous functions – require

Your stuff runs on both sides Your stuff YUI 3 DOM node. js JS/V

Your stuff runs on both sides Your stuff YUI 3 DOM node. js JS/V 8 DOM Browser JS

Turn • A turn is started by an external event, such as the completion

Turn • A turn is started by an external event, such as the completion of an asynchronous request, a user action, or the ticking of the clock. • A callback function associated with the event is called. It runs to completion. When it returns, the turn ends. • No need for threads. No races. No deadlocks.

The Law of Turns Never wait. Never block. Finish fast.

The Law of Turns Never wait. Never block. Finish fast.

Turns • Nothing can ever block, not even I/O. • Do not poll. Instead,

Turns • Nothing can ever block, not even I/O. • Do not poll. Instead, register a callback. • This is how browsers work. • This is how servers should also work.

Long running tasks • Two solutions for long running programs: • Eteration: Break the

Long running tasks • Two solutions for long running programs: • Eteration: Break the task into multiple turns. • Move the task into a separate process (workers).

Threads are evil • In systems programming, threads are a necessary evil. • In

Threads are evil • In systems programming, threads are a necessary evil. • In application programming, threads are just evil. • Threads provide a deceptively simple model of concurrency. • Threads are subject to races and deadlocks.

Two threads • my_array = []; 1. my_array[my_array. length] = 'a'; 2. my_array[my_array. length]

Two threads • my_array = []; 1. my_array[my_array. length] = 'a'; 2. my_array[my_array. length] = 'b'; • ['a', 'b'] • ['b', 'a']

Two threads • my_array = []; 1. my_array[my_array. length] = 'a'; 2. my_array[my_array. length]

Two threads • my_array = []; 1. my_array[my_array. length] = 'a'; 2. my_array[my_array. length] = 'b'; • • ['a', 'b'] ['b', 'a'] ['b']

my_array[my_array. length] = 'a'; length_a = my_array. length; my_array[length_a] = 'a'; if (length_a >=

my_array[my_array. length] = 'a'; length_a = my_array. length; my_array[length_a] = 'a'; if (length_a >= my_array. length) { my_array. length = length_a + 1; }

my_array[my_array. length] = 'a'; my_array[my_array. length] = 'b'; length_a = my_array. length; length_b =

my_array[my_array. length] = 'a'; my_array[my_array. length] = 'b'; length_a = my_array. length; length_b = my_array. length; my_array[length_a] = 'a'; if (length_a >= my_array. length) my_array[length_b] = 'b'; my_array. length = length_a + } if (length_b >= my_array. length) my_array. length = length_b + } { 1;

It is impossible to have application integrity when subject to race conditions. Read -

It is impossible to have application integrity when subject to race conditions. Read - Modify - Write

Mutual Exclusion • semaphore • monitor • rendezvous • synchronization • This used to

Mutual Exclusion • semaphore • monitor • rendezvous • synchronization • This used to be operating system stuff. • It has leaked into applications because of networking and the multi-core problem.

Deadlock

Deadlock

Deadlock

Deadlock

Remote Procedure Call • Combines two great ideas, functions and networking, producing a really

Remote Procedure Call • Combines two great ideas, functions and networking, producing a really bad idea. • Attempts to isolate programs from time. The program blacks out. • In reading the program, it is by design difficult to see where time is lost. • This can result in a terrible experience for the user. Lost time === annoying delays. • Keeping the user waiting without warning is disrespectful and rude.

Turn-based program avoids the problems but is unfamiliar to non-Java. Script programmers.

Turn-based program avoids the problems but is unfamiliar to non-Java. Script programmers.

Quiz 1 function funky(o) { o = null; } var x = []; funky(x);

Quiz 1 function funky(o) { o = null; } var x = []; funky(x); alert(x); A. null B. [] C. undefined D. throw

Quiz 2 function swap(a, b) { var temp = a; a = b; b

Quiz 2 function swap(a, b) { var temp = a; a = b; b = temp } var x = 1, y = 2; A. 1 swap(x, y); B. 2 alert(x); C. undefined D. throw

Quiz 3 Make a function that puts a value in a variable when it

Quiz 3 Make a function that puts a value in a variable when it is finished.

Pass the name of the variable. function do_it(inputs, name) {. . . eval(name +

Pass the name of the variable. function do_it(inputs, name) {. . . eval(name + ' = ' + result); window[name] = result; } • Not only bad practice, but illegal in ES 5/strict.

function do_it(inputs, obj, name) {. . . obj[name] = result; } • Gives do-it

function do_it(inputs, obj, name) {. . . obj[name] = result; } • Gives do-it too much authority.

function do_it(inputs, func) {. . . func(result); } • • We pass a function

function do_it(inputs, func) {. . . func(result); } • • We pass a function to do_it cannot abuse the function. The function cannot abuse do_it. func is a callback.

Callbacks • Temporal isolation. • Event handlers. • Timers. • Lightweight, powerful, expressive. •

Callbacks • Temporal isolation. • Event handlers. • Timers. • Lightweight, powerful, expressive. • Continuation.

function do_it(inputs, callback) {. . . callback(result); } do_it(my_inputs, function (result) { my_object. blah

function do_it(inputs, callback) {. . . callback(result); } do_it(my_inputs, function (result) { my_object. blah = result; });

Generalize. function storer(obj, name) { return function (result) { obj[name] = result; }; }

Generalize. function storer(obj, name) { return function (result) { obj[name] = result; }; } do_it(inputs, storer(my_object, 'blah'));

function storer_maker(obj) { return function(name) { return function (result) { obj[name] = result; };

function storer_maker(obj) { return function(name) { return function (result) { obj[name] = result; }; }; } my_storer = storer_maker(my_object); do_it(my_inputs, my_storer('blah'));

function once(func) { return function () { var f = func; func = null;

function once(func) { return function () { var f = func; func = null; return f. apply(this, arguments); }; } do_it(my_inputs, once(storer(my_object, 'blah')));

function sequence() { var slice = Array. prototype. slice, functions = slice. call(arguments, 0);

function sequence() { var slice = Array. prototype. slice, functions = slice. call(arguments, 0); return function () { var args = slice. call(arguments, 0); functions. for. Each(function (func) { func. apply(null, args); }; }

function revokerness(func) { return { revocable: function () { return func. apply(this, arguments); },

function revokerness(func) { return { revocable: function () { return func. apply(this, arguments); }, revoker: function () { func = null; } }; }

do_it(my_inputs, once(sequence( storer(my_object, 'blah'), storer(other_object, 'wow'), alert )));

do_it(my_inputs, once(sequence( storer(my_object, 'blah'), storer(other_object, 'wow'), alert )));

Server programming can be more complicated. • Call 20 services, each contributing material for

Server programming can be more complicated. • Call 20 services, each contributing material for the page, wait until all respond, then assemble the result. • Call a service, use its result to call another service, avoiding deeply nested event handlers.

Requestor function requestor(sync) { service_request(param, function (error, result) { sync(error, result); }

Requestor function requestor(sync) { service_request(param, function (error, result) { sync(error, result); }

Requestor maker function request_maker(param) { return function (sync) { service_request(param, function (error, result) {

Requestor maker function request_maker(param) { return function (sync) { service_request(param, function (error, result) { sync(error, result); }; }

Requestor maker function request_maker(service) { return function (param) { return function (sync) { service(param,

Requestor maker function request_maker(service) { return function (param) { return function (sync) { service(param, function (error, result) { sync(error, result); }; }; }

Requestor maker request_maker (service) (param) (sync);

Requestor maker request_maker (service) (param) (sync);

Composition par([requestor…], sync, timeout); seq([requestor…], sync, timeout); map([requestor…], sync, timeout);

Composition par([requestor…], sync, timeout); seq([requestor…], sync, timeout); map([requestor…], sync, timeout);

Composition function makers paror([requestor…], timeout) seqor([requestor…], timeout) mapor([requestor…], timeout)

Composition function makers paror([requestor…], timeout) seqor([requestor…], timeout) mapor([requestor…], timeout)

Also see • Directing Java. Script with Arrows www. cs. umd. edu/~mwh/papers/jsarrows. pdf •

Also see • Directing Java. Script with Arrows www. cs. umd. edu/~mwh/papers/jsarrows. pdf • Reactive Extensions for Java. Script http: //blogs. msdn. com/b/rxteam/archive/ 2010/03/17/reactive-extensions-forjavascript. aspx • (fab) https: //github. com/jed/fab

Thank you and good night.

Thank you and good night.