[lua]再版jobSchedule与脚本描述范型
首先贴上代码
-- CPM:关键路径法(Critical Path Method) jobSchedule = { todos = { -- todo list ... ["finale"] = function()end; }; schedule = function ( self, task, ... ) --由具体job构造任务列表 local finale = false local msg = nil local rc = nil local params = table.pack(self, task, ...) repeat local task = params[2]; local fn = self.todos[task] if type(fn) == "function" then rc = fn(table.unpack(params, 3)) end finale = (task == "finale") msg = self.name.."["..task.."] done!" if not finale then -- yield 传回进度描述及任务反馈 -- 打包调度入参 params = table.pack(coroutine.yield(msg, rc)) end until finale self.co = nil -- over return msg, rc end; perform = function ( self, task, ... ) local co = self.co or coroutine.create(self.schedule) if self.co == nil then self.co = co end return coroutine.resume(co, self, task, ...) end; }--jobSchedule --------------------------------------------------------------- --记得华罗庚的统筹方法论对烧水泡茶的描述过程 --就是多任务协调的执行程序 --示例:project, another两项任务节点的调度与描述 --{}, 构造描述的脚本模式 local project = { name = "projectSample"; todos = { ["stage1"] = function() end; ["stage2"] = function() end; ["stage3"] = function() end; ["finale"] = function()end; }; perform = jobSchedule.perform; schedule = jobSchedule.schedule; } --记得区分对象调用与域调用,一不小心就写成. 就无法识别self了 print(project:perform("stage1")) --creator, object based; 基于创建对象,对象扩展的脚本模式 function jobSchedule:Base() -- for the override method local meta = getmetatable(self) return meta and meta.__index end function jobSchedule.create( name, todos ) -- 生产工厂 local o = {name = name, todos = todos} return setmetatable(o, {__index = jobSchedule}) end local another = jobSchedule.create( "anotherProject", { ["stage1"] = function() end; ["stage2"] = function() end; ["finale"] = function()end; }) print(another:perform("stage1")) print(project:perform("stage2")) print(project:perform("stage3")) local another_perform = another.perform -- back up for override it. function another:perform( ... ) -- example method override print("[override] another:perform called") -- return another:Base().perform(self, ...) return another_perform(self, ...) end print(another:perform("stage2")) print(project:perform("finale")) print(another:perform("finale"))
描述jobSchedule模型
上一篇已记录过jobSchedule脚本初稿;主题就是协同式多任务与并发性事务关系。
jobSchedule就是为了描述清楚现实中关于项目计划与进度管理的一类程式化思维方法。
现实中思维,对于工作的计划与实施的方案求解,通常认为是以下步骤:
- 工作内容划分
- 依赖归类
- 时间预估
- 优先级
- 寻找最佳工作路径
- 矩阵式搜索:寻求最优可行方案
- 方案选择:制定计划
jobSchedule脚本意义就是提倡基于这类思维方式解决问题。合理化流程制定,清晰化脚本描述。
描述范型见解
脚本语言往往是提供更强有力的描述性方法;能够把过程描述清楚及把范围规划清晰,问题就已经得到解决了。
提供过程描述能力是脚本语言的主要目的,除了脚本之外的描述语言多为xml描述内容结构与依赖,json描述对象数据与结构,css……
js融合了json描述与脚本能力;
同样,lua也是这样一种强有力的法器;驾驭它的人可称谓脚本世界的巫师。
通常脚本都是提供结构化描述能力和基于对象模型的组织访问,基本的function过程描述。
脚本工作不只是构建过程,更强调内组织方式。以下主要列举三点关键
对象构造的描述
local project = { name = "projectSample"; todos = { ["stage1"] = function() end; ["stage2"] = function() end; ["stage3"] = function() end; ["finale"] = function()end; }; perform = jobSchedule.perform; schedule = jobSchedule.schedule; }
最直明简洁的构造表达,就是{}赋值示意,现值构造最好如此;对象构造对外方法最好预先注释声明于其中。
生产方式
--creator, object based; 基于创建对象,对象扩展的脚本模式 function jobSchedule:Base() -- for the override method local meta = getmetatable(self) return meta and meta.__index end function jobSchedule.create( name, todos ) -- 生产工厂 local o = {name = name, todos = todos} return setmetatable(o, {__index = jobSchedule}) end local another = jobSchedule.create( "anotherProject", { ["stage1"] = function() end; ["stage2"] = function() end; ["finale"] = function()end; })
对外产生一类功能对象,最好像这样提供对外一个生产对象通过特定的方法创造新实例。实例在运行过程中,又将允许动态扩展与改造;
对象改造
local another_perform = another.perform -- back up for override it. function another:perform( ... ) -- example method override print("[override] another:perform called") -- return another:Base().perform(self, ...) return another_perform(self, ...) end
这就说明对象功能方法的改造。这里说明了两方式改造原有方法;注释中的使用的方式依赖上文,只是为了效仿类化语言的一致化基类方法调用,并无大义。
对象扩展:装备其他特性
这里单独声明一个标题来强调脚本语言中对象的可塑性。
简单扩展
最基本的再简单不过,字段赋值表示。
组件化扩展
#sum.lua--
local fn = { -- sum: 求和 } function fn:sum( ) local sum = 0 local array = self for i=1, #array do sum = sum+array[i] end return sum end function fn.install( target ) local meta_= getmetatable(target) if not meta_ then setmetatable(target, setmetatable({}, {__index=fn})) else meta_.__index end end function fn.uninstall( target ) end return fn
#target.lua--
local array = {1, 2, 3, 4, 5, 6} require("sum").install(array) print(array:sum())
--接近现实思维的操作描述。