i-Tasks - interactive workflow tasks for the WEB

Download Report

Transcript i-Tasks - interactive workflow tasks for the WEB

Task Oriented Programming
in
using
Rinus Plasmeijer – Bas Lijnse - Peter Achten
Pieter Koopman - Steffen Michels – Jurriën Stutterheim
Jan Martin Jansen (NLDA) - Laszlo Domoszlai (ELTE)
Part 2/2
1
Overview

Introduction to Task Oriented Programming

iTask Library

Task Values

Editors

Shared Data

Sequential Tasks

Parallel Tasks

Semantics

Conclusions and Future Work
2
Embedded Domain Specific Language
iTask Core
Basic tasks
Interactive Tasks : Editors
Non-interactive Tasks: Lifting & Conversion
Integrated Tasks: web-service-call, OS-call, exec application, access a database
Combinators for combining tasks
Define control flow (sequential / parallel) and data flow between tasks
+ iTask Library to support frequently occurring work patterns
+ Clean: general purpose pure functional programming language
Recursive -, higher order -, polymorphic -, overloaded -, generic - functions
Hybrid typing: strongly statically typed + dynamic typing
3
Core Concepts
Data
Tasks
Local data:
Shared data:
Task Values
Shared Data Sources
Basic Tasks
Non-interactive
return, throw, …
Interactive
Editors
Combinators
Sequential
Parallel
4
Core - Task Values
:: Task a
typed unit of work which should deliver a value of type a
While the task is going on, its value may change over time
:: TaskResult a
:: Value a
:: Stability
=
|
=
|
=
|
ValRes TimeStamp (Value a)
 e: ExcRes e
& iTask e
NoVal
Val
a Stability
Unstable
Stable
Val a
Unstable
NoVal
Val a
Stable
5
Interactive Editors (see InteractionTasks.dcl)
Basic tasks: Interactive editor for filling in forms of a certain type:
viewInformation
:: d [ViewOption a] a
 Task a
| descr d & iTask a
enterInformation :: d [EnterOption a]
updateInformation :: d [UpdateOption a a] a
 Task a
 Task a
| descr d & iTask a
| descr d & iTask a
enterChoice
updateChoice
 Task o
 Task o
| descr d & iTask o
| descr d & iTask o
:: d [ChoiceOption o] [o]
:: d [ChoiceOption o] [o] o
enterMultipleChoice :: d [MultiChoiceOption o] [o]
 Task [o] | descr d & iTask o
updateMultipleChoice :: d [MultiChoiceOption o] [o] [o]  Task [o] | descr d & iTask o
6
Overview

Introduction to Task Oriented Programming

iTask Library

Task Values

Editors

Shared Data

Sequential Tasks

Parallel Tasks

Semantics

Conclusions and Future Work
7
Core - Shared Data Sources
SDS: one abstraction layer for any type of shared data: easy to use for the progammer
- Shared Memory
, Files
, Cloud
, Time
, Sensors , ….
- Reading and Writing can be of different type
- SDS’s can be composed from others (e.g. lenses a la Benjamin Pierce)
:: RWShared r w
:: Shared a
:== RWShared a a
:: ReadOnlyShared a :== RWShared a Void
:: WriteOnlyShared a :== RWShared Void a
8
Shared Data Sources
Creating an SDS:
withShared
:: a ((Shared a) → Task b)
→ Task b
sharedStore
externalFile
sqlShare
:: String a
:: FilePath
:: SQLDatabase String …
→ Shared a
| iTask a
→ Shared String
→ ReadWriteShared r w
// Special File
// Ordinary File
// SQL Database
→ Task r
| iTask r
// read once
// write once
Reading an SDS:
get :: (RWShared r w)
| iTask b
// Shared memory
currentTime
currentDate
currentDateTime
currentUser
users
:: ReadOnlyShared Time
:: ReadOnlyShared Date
:: ReadOnlyShared DateTime
:: ReadOnlyShared User
:: ReadOnlyShared [User]
Updating an SDS:
set
:: w (RWShared r w)
→ Task w
| iTask w
update
:: (r → w) (RWShared r w)
→ Task w
| iTask r & iTask w
9
Interactive Editors on SDS’s
viewSharedInformation
:: d [ViewOption r] (RWShared r w)  Task r
| descr d & iTask r
updateSharedInformation
:: d [UpdateOption r w] (RWShared r w)  Task w
| descr d & iTask r & iTask w
enterSharedChoice
:: d [ChoiceOption o] (RWShared [o] w)  Task o
| descr d & iTask o & iTask w
:: d [ChoiceOption o] (RWShared [o] w) o  Task o
| descr d & iTask o & iTask w
updateSharedChoice
enterSharedMultipleChoice
updateSharedMultipleChoice
:: d [MultiChoiceOption o] (RWShared [o] w)  Task [o]
| descr d & iTask o & iTask w
:: d [MultiChoiceOption o] (RWShared [o] w) [o]  Task [o]
| descr d & iTask o & iTask w
10
Editors on SDS’s
viewCurDateTime :: Task DateTime
viewCurDateTime
= viewSharedInformation "The current date and time is:" [] currentDateTime
Editors on SDS’s
twoTasks :: a → Task a
| iTask a
twoTasks v = withShared v doTasks
Assign task to someone
do both tasks in parallel,
return first
doTasks :: (Shared a) → Task a
| iTask a
doTasks sv = user1 @: updateSharedInformation sv
-||
user2 @: viewSharedInformation
sv
12
Core - Basic Tasks : One editor for all cases
Basic Tasks / Editor
edit :: d l (ROShared r) (r → (l,v)) (l r v → (l,v))→ Task l
| descr d & iTask l & iTask r & iTask v
-
One editor for handling all editor variants in the iTasks API
-
An editable view v is created given the local value l and shared value r
-
The view v is updated when v is edited or someone changes r
-
An editor task never delivers a stable value (it is either NoVal or Val l Unstable)
-
Tasks do not terminate, but are discarded if they are not needed anymore
13
Overview

Introduction to Task Oriented Programming

iTask Library

Task Values

Editors

Shared Data

Sequential Tasks

Parallel Tasks

Semantics

Conclusions and Future Work
14
Sequential Combinator:
>>*
palindrome :: Task (Maybe String)
palindrome = enterInformation "Enter a palindrome" []
>>* [ OnAction ActionOk
(ifValue isPalindrome (\v  return (Just v)))
, OnAction ActionCancel (always
(return Nothing))
]
15
Sequential Combinator:
Task a
>>*
>>*
Task b
Task b
Task b
Observe Task a, continue with one of the Task b's:
- if a certain action is performed by the end-user
- if the value of the observed task is satisfying a certain predicate
- or the observed task has raised an exception to be handled here
16
Core – Sequential Combinator
Combinator for Sequential Composition
(>>*) infixl 1 :: (Task a) [TaskStep a b] → Task b
| iTask a & iTask b
:: TaskStep a b
=
OnAction Action
|
OnValue
| E.e: OnException
& iTask e
(Value a → Maybe (Task b))
(Value a → Maybe (Task b))
(e → Task b)
:: Action
= Action String [ActionOption]
:: ActionOption
= ActionKey
Hotkey
| ActionWeight Int
| ActionIcon String
| ActionTrigger DoubleClick
:: Hotkey
= { key :: Key, ctrl :: Bool, alt :: Bool, shift :: Bool }
ActionOk
:== Action "Ok“ [ActionIcon "ok", ActionKey (unmodified KEY_ENTER)]
17
Core – Sequential Combinator
Combinator for Sequential Composition
(>>*) infixl 1 :: (Task a) [TaskStep a b] → Task b
| iTask a & iTask b
:: TaskStep a b
=
OnAction Action
|
OnValue
| E.e: OnException
& iTask e
(Value a → Maybe (Task b))
(Value a → Maybe (Task b))
(e → Task b)
:: Action
= Action String [ActionOption]
:: ActionOption
= ActionKey
Hotkey
| ActionWeight Int
| ActionIcon String
| ActionTrigger DoubleClick
:: Hotkey
= { key :: Key, ctrl :: Bool, alt :: Bool, shift :: Bool }
ActionOpen
:== Action "/File/Open" [ActionIcon "open", ActionKey (ctrl KEY_O)]
18
Core – Sequential Combinator
Combinator for Sequential Composition
(>>*) infixl 1 :: (Task a) [TaskStep a b]
:: TaskStep a b
=
OnAction Action
|
OnValue
| E.e: OnException
→ Task b
(Value a → Maybe (Task b))
(Value a → Maybe (Task b))
(e → Task b)
always task
= const (Just task)
ifValue pred task (Value v _)
ifValue _ _ _
= if (pred v) (Just (task v)) Nothing
= Nothing
hasValue task (Value v _)
hasValue _ _
= Just (task v)
= Nothing
ifStable task (Value v stable)
ifStable _ _
= if stable (Just (task v)) Nothing
= Nothing
| iTask a & iTask b
& iTask e
19
Recursive Tasks
person1by1 :: [Person]  Task [Person]
person1by1 persons
=
enterInformation "Add a person" []
>>* [ OnAction (Action "Add" [])
(hasValue (\v  person1by1 [v : persons])
, OnAction (Action "Finish" []) (always (return persons))
, OnAction ActionCancel
(always (return []))
]
20
Recursive Tasks
person1by1 :: [Person]  Task [Person]
person1by1 persons
=
enterInformation "Add a person" []
-||
viewInformation "List so far.." [] persons
>>* [ OnAction (Action "Add" [])
(hasValue (\v  person1by1 [v : persons])
, OnAction (Action "Finish" []) (always (return persons))
, OnAction ActionCancel
(always (return []))
]
21
Monadic-style
Monadic style:
(>>=) infix 1 :: (Task a) (a  Task b)
return
:: a
(>>=) infix 1
(>>=) taska taskbf
=
>>*
:: (Task a) (a  Task b)
taska
[OnAction ActionContinue
, OnValue
]
 Task b
 Task a
| iTask a & iTask b
| iTask a
 Task b
| iTask a & iTask b
(hasValue taskbf)
(ifStable taskbf)
22
Simple Sum
calculateSum :: Task Int
calculateSum
=
enterInformation ("Number 1","Enter a number") []
>>= \num1  enterInformation ("Number 2","Enter another number") []
>>= \num2  viewInformation ("Sum","The sum of those numbers is:") [] (num1 + num2)
23
Overview

Introduction to Task Oriented Programming

iTask Library

Task Values

Editors

Shared Data

Sequential Tasks

Parallel Tasks

Semantics

Conclusions and Future Work
24
Parallel - I
parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a))  Task a)]
 Task [(TaskTime, TaskValue a)] | descr d & iTask a
What kind of task is it
and who should work
on it ?
A dedicated process table
(TaskList) is created as SDS
enabling the parallel tasks
to inspect each other
Other tasks can see
the current values
of the parallel tasks
Every task produces a
value of "type a"
25
Parallel - I
parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a))  Task a)]
 Task [(TaskTime, TaskValue a)] | descr d & iTask a
:: ParallelTaskType
= Embedded
| Detached
:: ManagementMeta =
{ title
, worker
, role
, startAt
, completeBefore
, notifyAt
, priority
}
:: UserConstraint
= AnyUser
| UserWithId
| UserWithRole
ManagementMeta
:: Maybe String
:: UserConstraint
:: Maybe Role
:: Maybe DateTime
:: Maybe DateTime
:: Maybe DateTime
:: TaskPriority
UserId
Role
26
Parallel - II
parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a))  Task a)]
 Task [(TaskTime, TaskValue a)] | descr d & iTask a
:: TaskList a
= { listId
, items
}
:: TaskListId a
:: [TaskListItem a]
:: TaskListItem a
= { taskId
, value
, taskMeta
, managementMeta
, progressMeta
}
:: TaskId
:: TaskValue a
:: TaskMeta
:: Maybe ManagementMeta
:: Maybe ProgressMeta
27
Parallel Task Handling
parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a))  Task a)]
 Task [(TaskTime, TaskValue a)] | descr d & iTask a
appendTask :: ParallelTaskType ((ReadOnlyShared (TaskList a))  Task a)
(ReadOnlyShared (TaskList a))  Task TaskId | iTask a
removeTask :: TaskId (ReadOnlyShared (TaskList a))  Task Void | iTask a
Only the parallel tasks
have access to their
process table and
they can add new tasks
or kill existing ones
28
Handy predefined functions based on parallel
and : return values of all (embedded) parallel tasks:
allTasks
:: [Task a]
 Task [a]
(-&&-) infixr 4
:: (Task a) (Task b)
 Task (a, b)
| iTask a
| iTask a & iTask b
or: return result of (embedded) parallel tasks yielding a value as first:
eitherTask
:: (Task a) (Task b)
 Task (Either a b)
anyTask
:: [Task a]
 Task a
(-||-) infixr 3
:: (Task a) (Task a)
 Task a
| iTask a & iTask b
| iTask a
| iTask a
one-of: start two tasks, but we are only interested in the result of one of them, use the other to inform:
(-||) infixl 3
:: (Task a) (Task b)
 Task a
| iTask a & iTask b
(||-) infixr 3
:: (Task a) (Task b)
 Task b
| iTask a & iTask b
29
Handy predefined functions based on parallel
allTasks :: [Task a]
 Task [a]
allTasks tasks
= parallel Void [(Embedded, const t) \\ t  tasks] @ res
where
res vs = [v \\ (_,Value v _)  vs]
| iTask a
(-&&-) infixr 4 :: (Task a) (Task b)
 Task (a,b)
| iTask a & iTask b
(-&&-) taska taskb
= parallel Void [(Embedded, \_  taska @ Left),(Embedded, \_  taskb @ Right)] @? res
where
res (Value [(_, Value (Left a) _),(_,Value (Right b) _)] s)
= Value (a,b) s
res _
= NoValue
The following conversion functions have already been introduced :


(@?) infixl 1 :: (Task a) (Value a → Value b)
(@) infixl 1 :: (Task a) (a → b)
→ Task b
→ Task b
| iTask a & iTask b
| iTask a & iTask b
30
Handy predefined functions based on parallel
anyTask :: [Task a]
 Task a
anyTask tasks
= parallel Void [(Embedded, const t) \\ t  tasks] @? res
where
res (Value l _) = hd ([v \\ (_,v=:(Value _ Stable))  l] ++
[v \\ (_,v=:(Value _ _))  sortBy (\a b -> fst a > fst b) l] ++
[NoValue])
res _
= NoValue
| iTask a
(-||) infixl 3 :: (Task a) (Task b)
 Task a
| iTask a & iTask b
(-||) taska taskb
= parallel Void [(Embedded, \_  taska @ Left),(Embedded, \_  taskb @ Right)] @? Res
where
res (Value [(_,Value (Left a) s),_] _)
= Value a s
res _
= NoValue
31
Handy predefined functions based on parallel
and : return values of all (embedded) parallel tasks:
allTasks
:: [Task a]
 Task [a]
(-&&-) infixr 4
:: (Task a) (Task b)
 Task (a, b)
| iTask a
| iTask a & iTask b
or: return result of (embedded) parallel tasks yielding a value as first:
eitherTask
:: (Task a) (Task b)
 Task (Either a b)
anyTask
:: [Task a]
 Task a
(-||-) infixr 3
:: (Task a) (Task a)
 Task a
| iTask a & iTask b
| iTask a
| iTask a
one-of: start two tasks, but we are only interested in the result of one of them, use the other to inform:
(||-) infixr 3
:: (Task a) (Task b)
 Task b
| iTask a & iTask b
(-||) infixl 3
:: (Task a) (Task b)
 Task a
| iTask a & iTask b
assign a task to a specific user:
(@:) infix 3
:: User (Task a)
 Task a
| iTask a
32
Standard iTask Client
33
Example: Chat with someone
chat :: Task Void
chat =
>>= \me 
>>= \you 
get currentUser
enterSharedChoice "Select someone to chat with:" [] users
withShared ("","") (duoChat you me)
duoChat you me notes
=
chat you toView fromView notes
-||(you @: chat me (toView o switch) (\a v  switch (fromView a v)) notes)
where
toView (you, me)
= (Display you, Note me)
fromView _ (Display you, Note me)
= (you, me)
switch (you, me)
= (me, you)
chat who toV fromV notes
=
updateSharedInformation ("Chat with " <+++ who) [UpdateWith toV fromV] notes
>>* [OnAction (Action "Stop") always (return Void)]
34
Example: Chat with someone
35
A Text Editor - I
editWithStatistics :: Task Void
editWithStatistics
=
enterInformation "Give name of text file you want to edit..." []
>>= \fileName 
let file = sharedStore fileName ""
in parallel Void
[ (Embedded, editFile fileName file)
, (Embedded, showStatistics file)
, (Embedded, replace initReplace file)
]
>>*
[ OnAction (Action "File/Quit") (always (return Void))]
36
A Text Editor - II
editFile :: String (Shared String) (SharedTaskList Void)  Task Void
editFile fileName sharedFile _
=
updateSharedInformation ("edit " +++ fileName) view sharedFile @ const Void
where
view
= [UpdateWith toV fromV]
toV text
= Note text
fromV _ (Note text) = text
37
A Text Editor - III
:: Statistics = {lineCount :: Int, wordCount :: Int}
derive class iTask Statistics
showStatistics sharedFile _ = noStat <<@ Window
where
noStat :: Task Void
noStat =
viewInformation Void [] Void
>>*
[ OnAction (Action "File/Show Statistics") (always showStat)
]
showStat :: Task Void
showStat =
viewSharedInformation "Statistics:" [ViewWith stat] sharedFile
>>*
[ OnAction (Action "File/Hide Statistics") (always noStat)
]
stat text = {lineCount = lengthLines text, wordCount = lengthWords text}
where
lengthLines "" = 0
lengthLines text = length (split "\n" text)
lengthWords ""
=0
lengthWords text = length (split " " (replaceSubString "\n" " " text))
38
A Text Editor - IV
:: Replace = {search :: String, replaceBy :: String}
derive class iTask Replace
replace cmnd sharedFile _ = noReplace cmnd
where
noReplace :: Replace  Task Void
noReplace cmnd =
viewInformation Void [] Void
>>* [ OnAction (Action "File/Replace") (always (showReplace cmnd))
]
showReplace :: Replace  Task Void
showReplace cmnd = updateInformation "Replace:" [] cmnd
>>* [ OnAction (Action "Replace") (hasValue substitute)
, OnAction (Action "Cancel") (always (noReplace cmnd))
]
substitute cmnd
=
>>|
update (replaceSubString cmnd.search cmnd.replaceBy) sharedFile
showReplace cmnd
39
Incidone – Coast Guard Search and Rescue Support
40
iTask Client
41
Overview

Introduction to Task Oriented Programming

iTask Library

Task Values

Editors

Shared Data

Sequential Tasks

Parallel Tasks

Semantics

Conclusions and Future Work
42
Semantics
The iTask system is quite powerful
tasks are defined on a complex domain and are reactive
multi-user system
shared data structures
The core is small
operational semantics described in Clean
readable, concise
type checked by the compiler
executable, one can check its behavior
blueprint for implementations
43
Core - Task Values
:: Task a
:: TaskResult a
:: Value a
:: Stability
typed unit of work which should deliver a value of type a
=
|
=
|
=
|
ValRes TimeStamp (Value a)
 e: ExcRes e
& iTask e
NoVal
Val a Stability
Unstable
Stable
NoVal
Val a
Unstable
Val a
Stable
44
Semantics - What is a Task ?
:: Task a
:: Reduct a
:==
=
Event *State → *((Reduct a, [(TaskNo, Response)]), *State)
Reduct (TaskResult a) (Task a)
Current Value
:: *State
=
:: SharedValue
Remaining Task To do
{ taskNo
:: TaskNo
, timeStamp :: TimeStamp
, mem
:: [SharedValue]
, world
:: *World
}
:==
Dynamic
//
//
//
//
highest unassigned number
current time stamp
memory shared between tasks
enables I/O in a pure FPL
45
Semantics - Types
:: Event
:: Response
=
|
|
=
|
RefreshEvent
EditEvent
ActionEvent
EditorResponse
ActionResponse
TaskNo Dynamic
TaskNo Action
EditorResponse
ActionResponse
:: EditorResponse = { description :: String
, editValue
:: (LocalVal, SharedVal)
, editing
:: EditMode
}
:: LocalVal
:==
Dynamic
:: SharedVal
:==
Dynamic
:: EditMode
=
Editing
|
Displaying
:: ActionResponse
:: Action
:==
=
|
|
|
[(Action, Bool)]
Action String
ActionOk
ActionCancel
…
Semantics -Task Rewriting
evaluateTask :: (Task a) *World → *(Maybe a, *World)
| iTask a
evaluateTask task world
# st
= {taskNo = 0, timeStamp = 0, mem = [], world = world}
# (ma, st)
= rewrite task st
= (ma, st.world )
rewrite :: (Task a) *State → *(Maybe a, *State)
| iTask a
rewrite task st
# (ev, nworld)
= getNextEvent st.world
# (t, nworld)
= getCurrentTime nworld
# ((Reduct result ntask, responses), st)
= task ev {st & timeStamp = t, world = nworld}
= case result of
ValRes _ (Val a Stable)
→ (Just a, st)
ExcRes _
→ (Nothing, st)
_
→ rewrite ntask {st & world = informClients responses st.world}
47
Semantics -Task Rewriting
throw :: e → Task e
throw e ev st = ((Reduct (ExcRes e) (throw e), []), st)
| iTask e
return :: a → Task a
return va ev st=:{timeStamp = t} = stable t va ev st
where
stable t va _ st = (Reduct (ValRes t (Val va Stable)) (stable t va),[],st)
(@?) infixl 1 :: (Task a) ((Value a) → Value b) → Task b
| iTask a & iTask b
(@?) task conv ev st
= case task ev st of
(Reduct (ValRes t aval) ntask, rsp, nst)
→ case conv aval of
Val b Stable
→ return b ev nst
bval
→ ((Reduct (ValRes t bval) (ntask @? conv), rsp), nst)
(Reduct (ExcRes e) _,_,nst)
→ throw e ev nst
48
iTask Core Summary - I
Basic Tasks / Editor
edit :: String l (RWShared r w) → (l r → Maybe a) → Task a
| iTask l & iTask r
Basic Tasks / Return
return:: a → Task a
| iTask a
Basic Tasks / Exception Handling
throw :: e → Task e
| iTask e
Shared Data Sources
withShared :: a
((Shared a) → Task b) → Task b
| iTask a
49
iTask Core Summary - II
Combinator for Conversion of Task Values
(@?) infixl 1 :: (Task a) ((Value a) → Value b)
→ Task b
| iTask a & iTask b
→ Task b
| iTask a & iTask b
Combinator for Sequential Composition
(>>*) infixl 1 :: (Task a) [TaskStep a b]
:: TaskStep a b
=
OnAction Action
|
OnValue
| E.e: OnException
((Value a) → Bool) ((Value a) → Task b)
((Value a) → Bool) ((Value a) → Task b)
(e → Task b)
& iTask e
Combinator for Parallel Composition
parallel :: [RWShared [(Int, Reduct a)] Void]
→ Task [(TimeStamp, Value a)] | iTask a
50
Overview

Introduction to Task Oriented Programming

iTask Library

Task Values

Editors

Shared Data

Sequential Tasks

Parallel Tasks

Semantics

Conclusions and Future Work
51
Conclusions


Task Oriented Programming

New style of programming for implementing multi-user web applications

Focusing on tasks, not on the underlying technology

All source code in one language

Client receives JSON data, dedicated interpretation for PC, Tablet, Smart Phone
Core





reactive tasks working on local and shared data
shared data sources abstracting from any type of shared data
editor: can handle all interactions
sequential and parallel combinators
Operational Semantics

defined in Clean

readable, concise, type-checked, executable

blueprint for implementations
52
Future Work


Real real-world applications

Coast Guard (Bas Lijnse, PostDoc)

TNO (Jurrien Schutterheim, PhD; Wessel van Staal, Master thesis)

Dutch Navy (to be defined)

Clean IDE

….
Applicability

efficiency, scalability, security, version management, collaboration existing systems…

Parallel & Distributed servers (Laszlo Domoszlai, PhD, Budapest)

Graphical Definition of iTasks, …
Server

Semantics

Reasoning ? Proving ? Testing ?
Error
Messages
Clean Code
Clean Compiler
Dynamic Linker
Dynamic Code
53
Future Work

More real-world applications (with Dutch Navy, Coast Guard, TNO)

Applicability: efficiency, scalability, security, …

Reasoning ? Proving ? Testing ?

At run-time one can decide to evaluate a task on the client



Intermediate SAPL code is just-in-time compiled to JavaScript
HTML-5 features can be used
Graphical Definition of iTasks
Server
iTask Web Service
iTask
Combinator
Library
iTask
GIN
Error
Messages
Clean Code

Clean Compiler
Dynamic Linker
Dynamic Code
Parallel executing servers
54
Questions ?
55