From 7f26a4c9865347b0aadb2ed98f57e1f49ad2e663 Mon Sep 17 00:00:00 2001 From: outbounder Date: Tue, 12 Jan 2016 17:31:21 +0200 Subject: [PATCH] docs: improve towards organic concept v1.0.0 + removed reactions definitions - es6 and beyond render them absolete + consolidate guidelines/best practices into docs per topic + shrink Plasma's interface definition + add Plasma's interface detailed explanation about feedback support and hints towards its implementations --- README.md | 133 ++++++++++++++++++++++++++++++++-- docs/Cell.md | 22 ++++++ docs/Chemical.md | 12 +-- docs/DNA.md | 6 +- docs/Nucleus.md | 14 +--- docs/Organel.md | 12 +-- docs/Plasma.md | 81 ++++++++++++++++----- docs/README.md | 133 ---------------------------------- docs/Reactions.md | 33 --------- docs/guidelines/cells.md | 19 ----- docs/guidelines/organelles.md | 39 ---------- 11 files changed, 230 insertions(+), 274 deletions(-) create mode 100644 docs/Cell.md delete mode 100644 docs/README.md delete mode 100644 docs/Reactions.md delete mode 100644 docs/guidelines/cells.md delete mode 100644 docs/guidelines/organelles.md diff --git a/README.md b/README.md index eec8e85..d7467df 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,135 @@ -[node-organic](http://node-organic.com) -============ +# [node-organic](http://node-organic.com) + +# Organic v1.0.0 + +[Organic Computing](en.wikipedia.org/wiki/Organic_computing) inspired implementation based on nodejs. + +This document represents a draft outline of the fundamental principles, understandings and concepts in engineering `node-organic` as package library named `organic` published in http://npmjs.org. + +The library represents abstract form of the implementation bundled with concept documentation. +Further [modules/libraries/packages](http://node-organic.com/#/modules) inheriting `organic` core classes provide actual implementation and the ability to extend, improve and adapt furthermore the concept and its outcome. + +## [Chemical](./Chemical.md) + +Chemical **is raw data structure**. + +Every chemical has a type and in its nature is a plain object filled with properties (primitive values and/or references to other objects). + +One chemical has this generalized structure + + { + type: String, + // ... other custom properties + } + +## [DNA](./DNA.md) + +DNA is **configuration**. + +It is the collected internal knowledge of the entire cell application - its relations, abilities, build phases, functionalities and modes. DNA information can be acquired from various sources and can be transmited across various mediums if needed because it is a Chemical (raw data structure) + + var dnaStructure = { + "OrganelleName": { + "source": "path/to/organelle_implementation" + }, + "branchName": { + "OrganelleName2": "path/to/implementation" + } + } + + var dna = new DNA(dnaStructure) + console.log(dna.OrganelleName.source) // "path/to/organelle_implementation" + +## [Plasma](./Plasma.md) + +Plasma is **EventBus/EventDispatcher/PubSub pattern**. + +It is the fluid/environment which contains different kinds and copies of Organelles and/or Chemicals. The plasma also has main purpose in transmitting Chemicals between Organelles and within the Cell itself. + + var plasma = new Plasma() + plasma.on(chemicalPattern, chemicalReactionFn) + plasma.emit(chemical) + +Implementations: + +* [organic-plasma](https://github.com/outbounder/organic-plasma) + +## [Organelles](./Organel.md) + +Organelle is **Controller/Command/Strategy pattern**. + +These are the building blocks of organic application. Organelles are simple class implementations having the following form: + + var Organelle = function(plasma, dna) { + this.plasma = plasma + plasma.on(dna.reactOn, self.reactionToChemical) + } + + Organelle.prototype.reactionToChemical = function(c) { + // -- reaction logic + } + +## [Nucleus](./Nucleus.md) + +Nucles is **DependencyInjector/Factory pattern**. + +Nucleus is an `Organelle`. It however has reactions vital for a 'living' Cells - ability to process DNA and execute reactions involved in constructing Organelles. + + var nucleus = new Nucleus(plasma, dna) + + // add ability to construct organelles on demand via "build" typed chemical. + plasma.on({type: "build"}, function(c){ nucleus.build(c) }) + + // build some organelles from dna + plasma.emit({type: "build", branch: dna.organelles}) + +## [Cell](./docs/Cell.md) + +Cell is **Application**. + +It is usually a single constructor logic which brings up Plasma and Nucleus. The Cell also can provide support to "build" organelles using `build` chemicals. + + // dna/organelles.json + { + "plasma": { + "organelle": { + "source": "path/relative/to/cwd" + } + } + } + + // cell.js + var Cell = function Cell(dna){ + this.plasma = new Plasma() + var nucleus = new Nucleus(this.plasma, dna) + this.plasma.on("build", nucleus.build, nucleus) + } + + // main.js + var loadDNA = require('organic-dna-loader') + loadDNA(function(err, dna){ + + // instantiate + var instance = new Cell(dna) + + // trigger building + instance.plasma.emit({type: "build", branch: "organelles.plasma"}) + }) + + +Cells can be in different kinds - command line, web services, desktop apps. +Cells themselfs can form up and organize into a Systems. +Different kinds of systems can build up even more complex structures interconnecting with each other like Organisms... + +----- +Note that the proposed concept and its respective implementations **doesn't simulate the actual nature order and processes**. +The concept follows closely nature's patterns where applicable to software development discipline. + Organic development in node.js * [documentation](https://github.com/VarnaLab/node-organic/blob/master/docs) * [organic-presentation-101](http://outbounder.github.io/organic-presentation-101/#/) * [organic development (an article at net.tutsplus.com)](http://net.tutsplus.com/tutorials/javascript-ajax/organic-development/) - * [simple app which uses Organic](https://github.com/tutsplus/organic-development) * [organic ecosystem](http://wisdom.camplight.net/wisdom/51194d8ca672da1148000007/ecosystem) - -* [trello board](https://trello.com/board/node-organic/50659ffd3a3664af033e2024) \ No newline at end of file +* [trello board](https://trello.com/board/node-organic/50659ffd3a3664af033e2024) diff --git a/docs/Cell.md b/docs/Cell.md new file mode 100644 index 0000000..8f68ac8 --- /dev/null +++ b/docs/Cell.md @@ -0,0 +1,22 @@ +# Cell + +## Cell abstract + + var Cell = function Cell(){ + this.plasma = new Plasma() + } + + module.exports.prototype.build = function(dna){ + var nucleus = new Nucleus(this.plasma, dna) + this.plasma.on("build", nucleus.build, nucleus) + this.plasma.emit({type: "build", branch: "organelles"}) + } + + module.exports.prototype.kill = function(){ + this.plasma.emit({type: "kill"}) + } + +## Best practices + +* Do not store reference of DNA object within the cell because access to DNA should be provided only to trusted instances like Nucleus based implementations. +* Provide `build` and `kill` methods with their respective implementations so that a cell instance can be managed and tested. diff --git a/docs/Chemical.md b/docs/Chemical.md index 221645a..fe03c5b 100644 --- a/docs/Chemical.md +++ b/docs/Chemical.md @@ -1,15 +1,9 @@ # Chemical -One chemical has this generalized structure +One chemical is just an Object structure: { - type: String, - // ... - reference: Object, - // ... - property: Value - // ... - function: Function(also an Object or Class) + // ... properties } ## abstract Chemical @@ -22,4 +16,4 @@ Every property of data object if present will be copied over the Chemical object property: "value" }) - console.log(c.property) // "value" \ No newline at end of file + console.log(c.property) // "value" diff --git a/docs/DNA.md b/docs/DNA.md index cc6d5bf..fbe8c97 100644 --- a/docs/DNA.md +++ b/docs/DNA.md @@ -10,7 +10,7 @@ It is the collected internal knowledge of the entire cell application - its rela "OrganelleName2": "path/to/implementation" } } - + var dna = new DNA(dnaStructure) console.log(dna.OrganelleName.source) // "path/to/organelle_implementation" @@ -18,6 +18,6 @@ It is the collected internal knowledge of the entire cell application - its rela ### construction function DNA(data) -Should implement [Chemical's constructor function logic](./Chemical.md) at least. +Should implement [Chemical's constructor function logic](./Chemical.md). -> Every property of data object if present will be copied over the DNA object. \ No newline at end of file +> Every property of data object if present will be copied over the DNA object. diff --git a/docs/Nucleus.md b/docs/Nucleus.md index 3830fa0..c8a0dcc 100644 --- a/docs/Nucleus.md +++ b/docs/Nucleus.md @@ -1,6 +1,6 @@ # Nucleus -Nucleus is an Organelle. It however has reactions vital for a living Cell - ability to read DNA and execute reactions involved in constructing Organelles. +Nucleus is an Organelle. It however has reactions vital for a 'living' Cell - ability to read DNA and construct Organelles. // construct Nucleus giving its own dna branch for configuration. var plasma = new Plasma() @@ -12,14 +12,9 @@ Nucleus is an Organelle. It however has reactions vital for a living Cell - abil "OrganelleName2": "path/to/implementation" } }) - - var nucleus = new Nucleus(plasma, dna) - - // add ability to construct organelles on demand via "build" typed chemical. - plasma.on("build", nucleus.build, nucleus) - // build some organelles from dna - plasma.emit({type: "build", branch: "organelles"}) + var nucleus = new Nucleus(plasma, dna) + nucleus.build({type: "build", branch: "organelles"}) ## abstract Nucleus @@ -32,9 +27,8 @@ Should implement construction and build logic for Nucleus Organelle. * `plasma` is expected to implement [Plasma](./Plasma.md) * `dna` is expected to implement [DNA](./DNA.md) -### function build(chemical [, callback]) +### function build(chemical) Should implement logic for building Organelles using combined information from `chemical` argument and provided `dna` structure upon construction. * `chemical` is expected to implement [Chemical](./Chemical.md) -* `callback` is expected to implement [ReactionFn callback form](./Reactions.md#reactionfn-callback) \ No newline at end of file diff --git a/docs/Organel.md b/docs/Organel.md index 67a5205..3770dda 100644 --- a/docs/Organel.md +++ b/docs/Organel.md @@ -9,7 +9,7 @@ These are the building blocks of organic application, they in general are clonab Organelle.prototype.reactionToChemical = function(c, next) { // -- reaction logic - // -- submits new chemical in plasma via this.plasma.emit(...) + // -- submits new chemical in plasma via this.plasma.emit(...) // -- calls next() } @@ -22,9 +22,11 @@ Should implement construction and building logic of Organelle. * `plasma` is expected to implement [Plasma](./Plasma.md) * `dna` is expected to implement [DNA](./DNA.md) -### function dispose(chemical, callback) -A [Reaction](./Reactions.md#reactionfn) function. Should implement if required destruction and disposal logic of Organelle instance. +## Best practices -* `chemical` is expected to implement [Chemical](./Chemical.md) -* `callback` is expected to implement [reactionFn callback form](./Reactions.md#reactionfn-callback) form of `function(err, result)` +* attach organelle's reaction functions to its prototype, this way inheriting of organelles and overriding reactions can be achieved. +* store references to plasma and dna so that reaction functions can use them accordingly when needed. +* dispose resources acquired during the lifetime of the Organelle +* unregister any previously registered reactions during dispose process +* do not hard code chemical patterns and their relation to reactions. Instead use the information provided by the dna structure to build the mappings. diff --git a/docs/Plasma.md b/docs/Plasma.md index ca3a453..f4d11e1 100644 --- a/docs/Plasma.md +++ b/docs/Plasma.md @@ -1,14 +1,12 @@ # Plasma -This is a Class(OOP) implementation with support of decorations/extensions/plugins. The plasma also has main purpose in transmitting Chemicals between Organelles and within the Cell itself. +The plasma has main purpose in transmitting Chemicals between Organelles and within the Cell itself. var plasma = new Plasma() - plasma.on("ChemicalName", reactionFn) - plasma.off("ChemicalName", reactionFn) - plasma.once("ChemicalName", reactionFn) - - // ... any kind of plasma interaction can be achieved via applied on instance level decorations - plasma.onAll("ChemicalName1", "ChemicalName2", reactionFn) + plasma.on(chemicalPattern, reactionFn) + plasma.off(chemicalPattern, reactionFn) + plasma.once(chemicalPattern, reactionFn) + plasma.emit(chemical) ## abstract Plasma @@ -16,28 +14,75 @@ This is a Class(OOP) implementation with support of decorations/extensions/plugi Should implement construction and building logic of Plasma instance. -### function on(chemicalPattern, reactionFn [, context]) +### function on(chemicalPattern, reactionFn) Should implement logic for registering reaction functions capable to handle chemicals by given pattern. -* `chemicalPattern` is a value used to link emitted chemicals to their respective reaction functions. Current implementations assume chemicalPatterns as of having String, Object and/or Prototype values. -* `reactionFn` is expected to have the form of [Reaction function](./Reacitons.md#reactionfn) -* `context` argument is optional and is indicator that the `reactionFn` should be invoked with other than its own context. +* `chemicalPattern` - pattern for matching chemical(s) +* `reactionFn` - reaction function upon matched chemical(s) ### function off(chemicalPattern, reactionFn) Should implement logic for unregistering reaction functions previously registered with respective chemicalPattern. -* `chemicalPattern` is expected to have the same value when `reactionFn` has been registered. -* `reactionFn` is expected to be the same `reactionFn` which has been previously registered. - -### function once(chemicalPattern, reactionFn [, context]) +### function once(chemicalPattern, reactionFn) Should implement the same logic as `function on(...)` with the important difference that `reactionFn` function should be invoked only once and then unregistered. -### function emit(chemical [, callback]) +### function emit(chemical) -Should implement logic for trasmitting and delivering chemicals to registered reaction functions based on their respective patterns. +Should implement logic for trasmitting and delivering chemical(s) to registered reaction functions matched by their respective patterns. * `chemical` is expected to implement [Chemical](./Chemical.md). -* `callback` is optional and is expected to implement [reactionFn's callback form](./Reactions.md#reactionfn-callback). \ No newline at end of file + +#### action <-> feedback + +Nature's pattern for feedback and results delivery for organelles is based on emitting back a different chemical eg (over-simplified): + +``` +// worker organelle +plasma.on(doWorkPattern, function (doWorkChemical) { + // do work with chemical + plasma.emit(doWorkResultsChemical) +}) + +// cell +// register worker organelle results feedback +plasma.on(doWorkResultsChemical, function (resultsChemical) { + +}) +// engage action on worker organelle +plasma.emit(doWorkChemical) +``` + +However with increase in algorithmic complexity of implementations such can be shortened to be developer-friendly to its abstract form in code implementations: + +##### via callbacks + +``` +// worker organelle +plasma.on(doWorkPattern, function (doWorkChemical, doneCallback) { + // do work with chemical + doneCallback(null, doWorkResults) +}) + +// cell +// engage action on worker organelle +plasma.emit(doWorkChemical, function (err, results) { + +}) +``` + +##### via promises + +``` +// worker organelle +plasma.on(doWorkPattern, function (doWorkChemical) { + // do work with chemical + return doWorkResultsPromise +}) + +// cell +// engage action on worker organelle +var doWorkResultsPromise = plasma.emit(doWorkChemical) +``` diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index f6ec358..0000000 --- a/docs/README.md +++ /dev/null @@ -1,133 +0,0 @@ -# An Organic concept v0.2 - -[Organic Computing](en.wikipedia.org/wiki/Organic_computing) inspired implementation based on nodejs. - -This document represents a draft outline of the fundamental principles, understandings and concepts in engineering `node-organic` as package library named `organic` published in http://npmjs.org. - -The library represents abstract form of the implementation bundled with concept documentation. -Further [modules/libraries/packages](http://node-organic.com/#/modules) inheriting `organic` core classes provide actual implementation and the ability to extend, improve and adapt forthermore the concept and its outcome. - -## [Chemical](./Chemical.md) - -In standard naming conventions Chemical is raw data structure. - -Every chemical has a type and in its nature is a plain object filled with properties (primitive values and/or references to other objects). - -One chemical has this generalized structure - - { - type: String, - // ... - reference: Object, - // ... - property: Value - // ... - function: Function(also an Object or Class) - } - -## [Reactions](./Reactions.md) - -In standard naming conventions Reactions are implementations of functions with optional callback support. - -Reactions are operations performed over a chemical solution (one or more chemicals). -Reactions take the form: - - function reaction(c:Chemical(s) [, done:Done]):void - -where Done is optional and having the following definition: - - function done(error:Error/false, data:Chemical(s)):void - -## [DNA](./DNA.md) - -In standard naming conventions DNA is implementation of Configuration utilities and structure. - -It is the collected internal knowledge of the entire cell application - its relations, abilities, build phases, functionalities and modes. DNA information can be acquired from various sources and can be transmited across various mediums if needed. - - var dnaStructure = { - "OrganelleName": { - "source": "path/to/organelle_implementation" - }, - "branchName": { - "OrganelleName2": "path/to/implementation" - } - } - - var dna = new DNA(dnaStructure) - console.log(dna.OrganelleName.source) // "path/to/organelle_implementation" - -## [Plasma](./Plasma.md) - -In standart naming conventions Plasma is implementation of EventBus/EventDispatcher/PubSub pattern. - -It is the fluid/environment which contains different kinds and copies of Organelles and/or Chemicals. The plasma also has main purpose in transmitting Chemicals between Organelles and within the Cell itself. - - var plasma = new Plasma() - plasma.on("ChemicalName", function(c){ /* ... chemical reaction logic ... */}) - plasma.emit({type: "ChemicalName"}) - -## [Organelles](./Organel.md) - -In standart naming conventions Organelle is implementation of Controller/Command/Strategy pattern. - -These are the building blocks of organic application. Organelles are simple class implementations having the following form: - - var Organelle = function(plasma, dna) { - this.plasma = plasma - plasma.on(dna.reactOn, this.reactionToChemical, this) - } - - Organelle.prototype.reactionToChemical = function(c, next) { - // -- reaction logic - // -- submits new chemical in plasma via this.plasma.emit(...) - // -- calls next() - } - -## [Nucleus](./Nucleus.md) - -In standard naming conventions Nucles is implementation of DependencyInjector/Factory pattern. - -Nucleus is an Organelle. It however has reactions vital for a living Cell - ability to process DNA and execute reactions involved in constructing Organelles. The DNA itself is a plan Chemical. - - var nucleus = new Nucleus(plasma, dna) - - // add ability to construct organelles on demand via "build" typed chemical. - plasma.on("build", nucleus.build, nucleus) - - // build some organelles from dna - plasma.emit({type: "build", dna: query(dna, "organelles.plasma")}) - -## Cell - -The standard naming conventions a Cell is called Application. - -This is the abstract form of the building action. It is usually a single constructor logic which brings up Plasma and Nucles. The Cell can also provide reaction support to "build" Chemicals which are then piped to Nucleus's build implementation for execution. - - // simple cell definition - var Cell = function Cell(dna){ - this.plasma = new Plasma() - var nucleus = new Nucleus(this.plasma, dna) - this.plasma.on("build", nucleus.build, nucleus) - } - - // load dna - var query = require("organic-dna-query") - var loadDir = require("organic-dna-fsloader") - var dna = new DNA() - - loadDir(dna, "cwd/relative/path/to/dna", function(){ - - // instantiate - var instance = new Cell(dna) - - // trigger building - instance.plasma.emit({type: "build", branch: "organelles.plasma"}) - }) - - -Cells can be in different kinds - command line, web services, desktop apps. -Cells themselfs can form up and organize into a Systems. -Different kinds of systems can build up even more complex structures interconnecting with each other like Organisms... - ------ -Note that the proposed concept and implementation doesn't reflect the actual nature order and processes. It is not a simulation of nature patterns but rather the resulted abstract form of them applicable within the Software Engineering discipline. diff --git a/docs/Reactions.md b/docs/Reactions.md deleted file mode 100644 index 166a4b4..0000000 --- a/docs/Reactions.md +++ /dev/null @@ -1,33 +0,0 @@ -# Reactions - -Reactions are operations performed over a chemical solution (one or more chemicals). - -## ReactionFn - -Reaction function take the form: - - function reaction(c:Chemical(s) [, callback:Done]):void - -## ReactionFn callback - -Reaction `callback` is optional and having the following definition: - - function callback(error:Error/false, data:Chemical(s)):void - -## ReactionFn contract and requirements - -Reactions can be considered event handlers, with the passed chemical being the event itself. They are required to: - - * declare `done` as argument when reaction logic is asynchronious. - * always invoke `done` once declared wither with `error` argument or with `false, data` arguments. - * not to throw an exception. - -A simple example reaction looks like the following: - - var divide = function (c, done) { - if (c.b === 0) { - return done(new Error("can not divide by zero")); - } - var result = c.a / c.b; - done(false, result); - } \ No newline at end of file diff --git a/docs/guidelines/cells.md b/docs/guidelines/cells.md deleted file mode 100644 index ba2efba..0000000 --- a/docs/guidelines/cells.md +++ /dev/null @@ -1,19 +0,0 @@ -# Cells guidelines - - var Cell = function Cell(){ - this.plasma = new Plasma() - } - - module.exports.prototype.build = function(dna, done){ - var nucleus = new Nucleus(this.plasma, dna) - this.plasma.on("build", nucleus.build, nucleus) - this.plasma.emit({type: "build", branch: "organelles"}, done) - } - - module.exports.prototype.kill = function(done){ - this.plasma.emitAndCollect({type: "kill"}, done) - } - ----- -* Do not store reference of DNA object within the cell because access to DNA should be provided only to trusted instances like Nucleus based implementations. -* Always provide `build` and `kill` methods with their respective implementations so that a cell instance can be managed and tested. \ No newline at end of file diff --git a/docs/guidelines/organelles.md b/docs/guidelines/organelles.md deleted file mode 100644 index f268294..0000000 --- a/docs/guidelines/organelles.md +++ /dev/null @@ -1,39 +0,0 @@ -# Organelles guidelines - - var util = require("util") - var Organel = require("organic").Organel - - module.exports = function MyOrganelle(plasma, dna) { - this.plasma = plasma - this.dna = dna - - this.plasma.on(dna.asyncOn, this.asyncReaction) - this.plasma.on(dna.syncOn, this.syncReaction) - - this.plasma.on(dna.killOn, this.dispose) - } - - util.inherits(module.exports, Organel) - - module.exports.prototype.asyncReaction = function(chemical, callback) { - // asyncReaction implementation calling callback once finished/needed - } - - module.exports.prototype.syncReaction = function(chemical) { - // syncReaction implementation, note that callback argument is missing - } - - module.exports.prototype.dispose = function(chemical, callback) { - this.plasma.off(this.dna.asyncOn, this.asyncReaction) - this.plasma.off(this.dna.syncOn, this.syncReaction) - - // ... dispose any resources acquired during lifetime of the Organelle - } - ----- - -* attach organelle's reaction functions to its prototype, this way inheriting of organelles and overriding reactions can be achieved. - * store references to plasma and dna so that reaction functions can use them accordingly when needed. -* dispose resources acquired during the lifetime of the Organelle - * unregister any previously registered reactions during dispose process -* do not hard code chemical patterns and their relation to reactions. Instead use the information provided by the dna structure to build the mappings. \ No newline at end of file