+ All Categories
Home > Engineering > deepjs - tools for better programming

deepjs - tools for better programming

Date post: 22-Nov-2014
Category:
Upload: nomocas
View: 166 times
Download: 2 times
Share this document with a friend
Description:
deepjs is a javascript isomorphic framework to design and run modular web app.
26
o Ļõõàį ¦õĩ hĻĻĩ ĒĩõºĩTççËî» p TŇĻÇõĩ ºËààį võõçTîį v 0.13.1 ÇĻĻĒįĸĸºËĻÇŇhęvõèĸ ĒÙį deep
Transcript
Page 1: deepjs - tools for better programming

oĹĻõõàįŦõĩĹh�ĻĻ�ĩĹĒĩõºĩTççËî»Ĺp

TŇĻÇõĩĹ�ĹºËàà�įĹvõõçTîį

v 0.13.1

ÇĻĻĒį�ĸĸºËĻÇŇhęvõèĸ���ĒÙį

deepMƖ

Page 2: deepjs - tools for better programming

GHHSMƖ7 Generic Design Tools

FRUĠ�� generic design solutionsGHHSMƖ�IUDPHZRUś���7DUJHWƖ

design :objects, functions, classes, async and concurrent run time, transformations, roles,resources,constraints, isomorphism,modularity,...

views

controllers and directives

DOM

restful

homogeneous collections

RQL

JSON-Schema & ...

CRUD, range, RPC, bulk

routes

dynamic routing

sub controllers

IOC on map

LVRPRUSKLFƖ�� write once, run everywhere

...

shell

CLI tools

sh/sshnodejs process

autobahn

Thin Server

restful services

statics files

login/session pattern

browser

Browser App

deep-link

login/session pattern

HQYLURQQHPHQWƖ�� where to run ?

...

Page 3: deepjs - tools for better programming

GHHSMƖ�IUDPHZRUś

Isomorphic : Environnement independent libs

deepjs core tools : design

deep-restful homogeneous restful collectionsdeep-views views & directivesdeep-routes dynamic routingdeep-jquery (dom) dom manipulation (jquery/cheerio)deep-marked markdown with macros + clients (nodejs + jq-ajax)deep-swig swigjs template clients (nodejs + jq-ajax)

/LEUDULHƖ

you create with this (and more...)

you use with this (and more...)

Nodejs specific libs

autobahnjs restful thin server : middlewares (expressjs) + routesdeep-shell sh & ssh chains and clideep-nodejs nodejs related tools (restful fs, ...)deep-mongo restful mongodb clientdeep-elastic restful elastic-search client, index, layered queries...

Browser specific libs

deep-browser browser app environnementdeep-local-storage restful local storage storedeep-jquery (ajax) restful ajax clients (json, html, xml)

Misc

deep-air Adobe air adapted browser env.deep-node-webkit node-webkit mixed browser/nodejs env.

Page 4: deepjs - tools for better programming

To finally do what ?

fits well for :

GHHSMƖ IUDPHZRUś

VLQJOĠ�SDJĠ�DSS���UHVWĽŝ�DSŋ- views structure and resources + routes mapping

- templating- restful stores : JSON-Schema, constraints and API

- roles and context design- login decoration pattern

and/or

ZRUNHUƖ6LQJOĠ�3DJĠ�DSS

��Ţ9&��5HVWĽŝ�êLŨ�6HUYHU

��0RGHŝ��Restful/HTTP/JSON

. service oriented

Page 5: deepjs - tools for better programming

3DXVĠ%UHDWKĠ�ö�OLWWOĠ�ELƜ�

)RUJHƜ�DUFKLWHFWXUĠ�

Page 6: deepjs - tools for better programming

êLQś�FRGĠ�GHVLJŨ�

KRZ�WŬ�PDNĠ�WKLQJƖ��

- iterable friendly- async friendly

- concurrency friendly- transformations friendly

- roles friendly- highly modular

- reusable- ...

Page 7: deepjs - tools for better programming

7 JHQHULĊ�GHVLJŨ�WRROƖ�IDPLOOLHƖGHHSMƖFRUĠ

OD\HUƖ inheritance & specialisation : objects on objects

deep({ /* ... */ }).bottom(model1, ...).up(aspect1, “json::/my/file”, ...).flatten().done(...)...

TXHULHƖ (fuzzy) ask before use : jquery paradigm for code

deep({ /* ... */ }).query(“./(foo.*)?bar=gt=4/zoo”).up(...).run(...).map().done(...)...

VKHHWƖ super aspects & transformations rules : css paradigm for code

deep({ /* ... */ }).sheet({ “dq::./foo”:deep.sheet.bottom(...).map(...)... }).done(...)...land

scap

e pr

ogra

mm

ing

FKDLQƖ (async) run time management : super promises

deep.when(...).toState(”myVar”).fs(”../folder”).from(”myFile.json”)...log()...

SURWRFROƖ asbtract resource locator : resource says...

deep(”products.range(10,19)::?my_rql_query”).map(”swig::/my/templ.htm”).done(...)...

FRQWġƜ gift for concurrency : simply ask

deep.contextualise({ req:request )})....done(function(s){ deep.context(”req”).write(s); })...

RFŢ object capability manager : object’s nature depends on observer

deep.modes({ roles:”admin” }).rest(”myStore”).put(”my new title”, “id/title”).done(...)...

Page 8: deepjs - tools for better programming

ODQGVFDSĠ�RULHQWHĘ�SURJUDPPLQŁ����

whole app, module,

config,datas,

classes,controllers,

routes map,aspects,

transformations,elastic search queries,

whole 3D scene,...

models,other landscapes,

...

specialisations,aspects,transformations,other landscapes,...

up & bottom, objects on objects, queriable joint points,deep merge, compositions for functions, colliders for datas,

transformations-in-place

deep({ /* ... */ }).bottom(model1, ...).query(“./(foo.*)?bar=gt=4/zoo”).up(aspect1, “js::/my/file”, ...).flatten().done(...)...

methods, primitives, array, subobjects

Page 9: deepjs - tools for better programming

myBool :myBool :myVar : hello

src

{

} myVar : hello

target

{

}

truetrue

target

{

}

up

No collision :

myVar : hello

src

{

}myVar : hello

target

{

}myVar : true

target

{

}

up

With collision :

upspecialisation

ODQGVFDSĠ�RULHQWHĘ�SURJUDPPLQŁ������default up & bottom rules : when collision, what is above is kept

myVar : hello

src

{

}myVar : hello

target

{

}true

true

target

{

}

bottom

No collision :

myVar : hello

src

{

}

target

{

}myVar : truemyVar : true

target

{

}

bottom

With collision :

ERWWRŢinheritance

myBool :myBool :

deep({ a:true }).bottom({ a:false, b:false }).up({ b:true, c:true }, { d:false }).log(); // { a:true, b:true, c:true, d:false }

Page 10: deepjs - tools for better programming

ODQGVFDSĠ�RULHQWHĘ�SURJUDPPLQŁ������

{ arr:[”peer”, ”citrus”], arr2:[ { id:”e1”, title:”hello” }, { id:”e2”, title:”world” } ],

subobj:{ foo: false, foobar: 12 },

myFunc: function(){ /*...*/ },

zoo: ”landscape forever”}

{ arr:[”peer”, ”citrus”, ”apple” ], arr2:[ { id:”e1”, title:”hello” }, { id:”e2”, title:”deepjs” }, { id:”e3”, title:”tools” } ],

subobj:{ foo: true, foobar: 12, bar: false }, myFunc: Function,

zoo: ”landscapeForever”}

{ arr:[”apple”, ”peer”], arr2:[ { id:”e2”, title:”deepjs” }, { id:”e3”, title:”tools” } ],

subobj:{ foo: true, bar: false },

myFunc: deep.compose .after(function(r){ /*...*/ }) .around(function(old){ /*...*/ }),

zoo: deep.collider.changeCase(”camel”)}

src target targetup

natural deep merge & fine grained merge tools

objects (including arrays) are (recursively) merged.

arrays merge try to be smart.

primitives properties (tree leafs) collisions follow default rule : above is kept.

compositions allow fine grained functions merge (after, before, around, fail and custom API + chainable).

colliders allow fine grained merge and/or “while-collision” logics (chainable).

Page 11: deepjs - tools for better programming

ODQGVFDSĠ�RULHQWHĘ�SURJUDPPLQŁ�(4/5)when queries give control

deep-query, Resource Query Language, traversal, ...

deep({ /* ... */ }).query(”./(foo.*)?bar=gt=4/zoo”).up(...).run(...).query(...).map()...

queries allow jquery style logics

var mySheet= { “dq::/my/query” : deep.sheet.up(...).map(...).query(...)..., “dq::/my/other/query” : deep.sheet.bottom(...).sheet(...)..., //...};

deep( { /*...*/ } ).sheet( mySheet ).done(...);

sheets are super aspects and/or transformations units (css style)

Page 12: deepjs - tools for better programming

ODQGVFDSĠ�RULHQWHĘ�SURJUDPPLQŁ�(5/5)in-object landscapes declaration : backgrounds & foregrounds

var myOtherObject = {

_backgrounds:[ ... ], //...

};

var myObj = {

_backgrounds:[ myOtherObj, ”json::/a/json/src” ],

//...

subobj:{

_foregrounds:[ ”js::/a/js/src”, mySheet ],

//...

sub_subobj:{

_backgrounds:[ ”this::../my_brother” ],

_foregrounds:[ anObject ],

//...

}

}

};

deep.flatten( myObj ).done(...);

backgrounds & foregrounds are applied from root to leaf, at any depth

applied resources could also contains backgrounds & foregrounds (recursive)

backgrounds & foregrounds are consumed : they are removed at flatten

they could contains objects or sheets references, resources locators, or queries for inner inheritance

Page 13: deepjs - tools for better programming

SURPLVĠƐƖ�FRQWġƜ���FRQFXUUHQFƯ�JLļglocal namespace for contextualised globals

request reception

request endasync call

user 1 context

user 2 context

user 3 context

- nodejs request - dom manipulator ($) - session

- session

-...

-...

-...

- nodejs request - dom manipulator ($) - OCM modes

- nodejs request - dom manipulator ($)

User 1request

User 2request

User 3request

server timeContext association for each (concurrent) request.

Typical context’s content : dom global manipulator (jquery ref ), catched route, current session, modes (environnements flags (prod/dev/...), roles (admin, user, public, ...), ...), server request, ...

- No more arguments cascading (as middleware pattern does)- No more globals- Allow real isomorphism : concurrent env or not = same code (think about dom or login or route mngt)

deep.contextualise({ req:request, $:cheerio.init() )})....done(function(s){ deep.context(”req”).write(s); })...

Page 14: deepjs - tools for better programming

SURWRFROƖ���DNö�DĄWUDFƜ�UHVRXUFĠ�ORFDWRU

deep.protocols.myProtoc = {

get : function(request, options)

{

return ”default with : ” + request;

},

myFunc : function(arg1, arg2, request, options)

{

return “custom with : ” + arg1 + ”,” + arg2 + ” : ” + request;

}

};

Define your protocol controller in deep.protocols namespace :

deep( “myProtoc::anything” ).done(...)...;

// => default with : anything

Then, from anywhere,

by default : it uses the get method from the protocol controller :

deep( “myProtoc.myFunc(12,hello)::anything” ).log()...;

// => custom with : 12,hello : anything

and you could access custom methods with classical dot notation :

deepjs natives protocols : js, instance, eval, dq, this

Protocols from deepjs libs : dom, json, html, swig, marked, ...

Protocols management tools are OCM aware.

Page 15: deepjs - tools for better programming

RFŢ���REMHFƜ�FDSDELOLWƯ�PDQDJHUobject’s nature depends on context

prod :

dev :

admin :

user :

public :

Define a pool of layers1.var myOCManager = deep.ocm(

methods, primitives, array, subobjects

);

Make it sensible to particular “flags” (called modes)

2.myOCManager.sensibleTo(”env”, ”roles”);

Set modes depending on your needs3.deep.Modes({

env:”prod”,

roles:”public”

});

Ask your manager current combination depending on current modes :(combinations are compiled/merged only once)

4.

var my_combination = myOCManager();

deep.modes({ env:”dev”, roles:”admin” }).restful(”myProtoc”).put(”my new title”, “object_id/title”).done(...)...

Modes could be contextualised, and ocm could be placed in protocols to obtain dependency injection :example with ocm restful store placed in protocols and used through chained restful mediator API.

Page 16: deepjs - tools for better programming

LVRPRUSKLFƖZULWĠ�RQFĠ��UXŨ�HYHU\ZKHUĠ

Page 17: deepjs - tools for better programming

UHVWĽŝ�KRPRJHQHRXƖ�FROOHFWLRQƖOne for all

one language to query them all : Resource Query Language (RQL)deep.restful(”myStore”).get(”?or(amount=gt=5,title=in=(hello,world))”).done(...)...

deep.restful(”myStore”).put(”my new title”, “id/title”).del(”item_id”).done(...)...one API to C(R)UD them all : post, put, patch, del (HTTP/Restful verbs)

deep.restful(”myStore”).rpc(”my_procedure”, [12, true], ”item_id”).done(...)...fine grained action with JSON-RPC

deep(”myStore.range(10,19)::?my_rql_query”).done(...)...Pure HTTP range paging hidden behind homogeneous range object

deep.restful(”myStore”)...Promise based chained mediator

API

JSON-Schema validation

JSON-Schema dynamic constraints declaration : owner, private, readonly, ...

JSON-Schema transformers declaration : sanitize, change case, ...

JSON-Schema links for ORM (embryonnar)

OCM friendly

Constraints

deep.collection, deep.mongo, deep.jquery.json/html/xml, deep.elastic, deep.jstorage, ...Implemented in :

Page 18: deepjs - tools for better programming

RFŢ��UHVWĽŝ�VWRUĠ�EƯ�ġDPSOĠWhere all deepjs tools converge

deep.ocm({

dev: deep.Collection({

collection: deep.Shared([{ id:"e1", title:"My product", amount:24 }])

}),

prod: deep.Mongo({

url:"...",

collectionName:"products"

}),

admin: {

schema: {

properties: {

title: { type:"string", required:true },

amount: { type:"number", required:true }

}

}

},

user: {

_backgrounds: ["this::../admin", deep.Disallow("del", "rpc", “post”)],

schema: {

properties: {

amount: { readOnly:true }

}

},

put: deep.compose.after(function(obj){

// do something custom after original put

})

},

"public": {

_backgrounds: ["this::../user", deep.AllowOnly("get", "range")]

}

}, {

sensibleTo: ["env","roles"],

protocol: "products"

});

//...

deep.modes({ env: "dev", roles: "user" })

.restful( "products" )

.put( "My new title.", "/e1/title" )

.get( "?amount=gt=5" )

.done( /*... */ )

.elog();

Page 19: deepjs - tools for better programming

YLHZƖ���IURŢ�PLQLPDOLVWLĊ�WŬ�ĽOŝ�FRQWUROOHĘlayered & concurrent friendly views controller

var ctrl = deep.View({

how:”<div>hello world</div>”,

where:”dom.htmlOf::#my_selector”

});

ctrl.refresh().done(...)...;

PLQLPDOLVWLĊvar ctrl = deep.View({

init : function(){ /* bind listeners */ },

what : {

products : ”products.range(0,9)::?amount=gt=5”,

profile : ”profile::?userId={ context.session.user.id }”

},

how : ”marked::/path/to/my/markdown/template”,

where : ”dom.appendTo::#my_selector”,

done : function(renderObject){ /* custom behaviours */ },

fail : function(error){ /* any refresh error */ },

clean : function(){ /* unbind listeners */ }

});

ctrl.refresh().done(...)....;

ĽOŝ�FRQWUROOHĘ

Page 20: deepjs - tools for better programming

URXWHƖ���GHHSOƯ�VWUXFWXUHĘ�G\QDPLĊ�URXWLQŁlayered & concurrent friendly routes IOC controller

var map = { home: deep.View({ navigation: false, route: "/$", how: "<div/>" }), layers: { route: "/layers", subs: { overview: deep.View({ route: "./$", how: "docs::/pages/layers/overview.html" }), up_bottom: deep.View({ route: "./up-bottom", how: "docs::/pages/layers/up-bottom.html" }), compositions: deep.View({ route: "./compositions", how: "docs::/pages/layers/compositions.html" }), ... } }, ...};

Page 21: deepjs - tools for better programming

WŬ�EĠ�FRQWLQXHĘ���

Page 22: deepjs - tools for better programming

deepMƖ

oĹçT��ĹŕËĻÈĹàõŔ� }TŇĻÇõĩĹ�ĹºËàà�įĹvõõçTîį

Many thanks to Kris Zyp, from dojo foundation, who is the man behind JSON-Schema, RQL and persvr/pintura.I’ve been really inspired by his great work on compositions, promises, context, thin server, OCM and homogeneous restful management.Without him, deepjs would still be just good ideas.

Also, many thanks to my friend Philippe Delabye that has followed me while I was rewriting everything permanently. Thanks for his patience and for hours of discussions and help that he has provided since 3 years.

Last but not least, huge thanks to my love, Pomme, my marvelous son, Ivan, and my friends whom support and encourage me all this time.

Page 23: deepjs - tools for better programming

GHHSMƖ���FRQFHSWƖ�DQĘ�GHĴQLWLRQƖ����

Any object designed to be merged (deeply) with others. It could be active (sheets) or passive (js values, objects, array, ...).It could be model, specialisation, transformation, datas, config, prototype, function,...

A bunch of layers attached/applied (deeply) together.

Event that happend when two properties from two layers being merged share the same path (from root merge point)

A function that perfom custom logics when collided with values.

A particular type of collider that allow fine grained functions merging (after, before, around, ...)

A simple DSL aimed to query js objects structures. A query is composed of a succession of steps (move - select - filter).e.g. : ./(foo.*)?or(amount=gt=5,year=2014)/barFilters are expressed in RQL (see below).

Active layer that could be seen as Transformations units or super aspect. Inspired from style sheet (CSS), it’s defined as a simple object, where root’s properties : - keys give queries (as selectors) to select sub-structures from any object - values give transformations sequences to apply on selected sub-structures

fact to inherit from or be specialised by any local query result.A local query result is some structure selected in the whole object where the one that is being specialised is attached. e.g. the brother, the oncle, the cousin, etc.

OD\HU

ODQGVFDSĠ

FROOLVLRŨ

FROOLGHU

FRPSŮLWLRŨ

GHHS�TXHUƯ

VKHHƜ

LQWHUQDŝ�LQKHULWDQFĠ

Page 24: deepjs - tools for better programming

GHHSMƖ���FRQFHSWƖ�DQĘ�GHĴQLWLRQƖ����

The art of designing things with layers and queries. Kind of super-aspect oriented programming.

(AOP) A style of programming that attempts to abstract out features common to many parts of the code beyond simple functional modules and therebyimprove the quality of software. (http://wwwtrese.cs.utwente.nl/aop-ecoop99/)

Abstract Resource Locator. Simple tool to define resource controller and to use it by specifying them in front of resource string pointer.e.g. “products.range(0,10)::?amount=gt=5”

(...) encapsulate the processes involved in obtaining a service with a strong abstractionlayer. (...) uses a central registry known as the "service locator", which on request returns the information necessary to perform a certain task.(http://en.wikipedia.org/wiki/Service_locator_pattern)

An injection is the passing of a dependency (a service) to a dependent object (a client). The service is made part of the client's state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.(http://en.wikipedia.org/wiki/Dependency_injection)

The object capability model is an approach to security that utilizes object references as the primary means of controlling access and providing authority. (http://en.wikipedia.org/wiki/Object-capability_model)

ODQGVFDSĠ�RULHQWHĘ�SURJUDPPLQŁ

DVSHFƜ�RULHQWHĘ�SURJUDPPLQŁ

SURWRFROƖ

VHUYLFĠ�ORFDWRU

GHSHQGHQFƯ�LQMHFWLRŨ

RFŢ

Page 25: deepjs - tools for better programming

GHHSMƖ���FRQFHSWƖ�DQĘ�GHĴQLWLRQƖ����

Program composition that supports building object-oriented systems as compositions of subjects, extending systems by composing them with new subjects, and integrating systems by composing them with one another (http://research.ibm.com/sop/)

Allows loose coupling between classes by being the only class that has detailedknowledge of their methods - (http://shichuan.github.io/javascript-patterns/#code-reuse-patterns)

Pattern for sequencing async successes and error with promise.(http://sitr.us/2012/07/31/promise-pipelines-in-javascript.html)

concurrent computing is a form of modular programming, namely factoring an overall computation into subcomputations that may be executed concurrently.(http://en.wikipedia.org/wiki/Concurrent_computing)

The model-driven architecture approach defines system functionality using a platform-independent model (PIM) using an appropriate domain-specific language (DSL). Then, given a platform model( ...), the PIM is translated to one or more platform-specific models (PSMs) that computers can run. This requires mappings and transformations and should be modeled too.(http://en.wikipedia.org/wiki/Model-driven_architecture)

Said about complex objects than can be runned, without change, server side orbrowser side.

VXEMHFƜ�RULHQWHĘ�SURJUDPPLQŁ

PHGLDWRU

SURPLVĠ�SLSHOLQLQŁ

FRQFXUUHQƜ�SURJUDPPLQŁ

PRGHŝ�GULYHŨ�DUFKLWHFWXUĠ

LVRPRUSKLVŢ

Page 26: deepjs - tools for better programming

GHHSMƖ���FRQFHSWƖ�DQĘ�GHĴQLWLRQƖ����

In computer programming, homoiconicity (...) is a property of some programminglanguages in which the program structure is similar to its syntax, and therefore the program's internal representation can be inferred by reading the text's layout.(http://en.wikipedia.org/wiki/Homoiconicity)

Express that complexity has been delegate to client. Server only manage data model.(more info with single page app below)

A single-page application (SPA), also known as single-page interface (SPI), is a web application or web site that fits on a single web page with the goal of providing a more fluid user experience akin to a desktop application.(http://en.wikipedia.org/wiki/Single-page_application)

Inversion of control (IoC) describes a design in which custom-written portions of a computer program receive the flow of control from a generic, reusable library.(http://en.wikipedia.org/wiki/Inversion_of_control)

Representational state transfer (REST) is an abstraction of the architecture of the World Wide Web; more precisely, REST is an architectural style consisting of a coordinated set of architectural constraints applied to components, connectors, and data elements, within a distributed hypermedia system.(http://en.wikipedia.org/wiki/Representational_state_transfer)

Resource Query Language (RQL) is a query language designed for use in URIs with object style data structures.(https://github.com/persvr/rql)

KRPRLFRQLFLWƯ

WKLŨ�VHUYHU

VLQJOĠ�SDJĠ�DSSOLFDWLRŨ

LRĊ

UHVWĽŝ

UTŝ


Recommended