偷懒是程序员的美德

这是我最近的一个业余项目。用了两个周末午后的时间

我对插件机制一直饱含兴趣,这种东西,技术上关系到系统的灵活性,而商业上关系到对需求的适应能力

对edX的扩展,官方给出了四种手段,最令我激动的是xblock。关于xblock我此前有写过介绍文章

#缘起 前前后后,我自己写的xblock加上fork自国外的一些,合计有十几个了。写多了你会发现,xblock是极其强大的扩展机制,它比LTI的扩展性好,又比djangoapp来得简易,以至于大多数教育相关的商业点子,很适合以edX为基础平台,利用xblock作为定制机制,对很多需求就足够了。

写多了xblock又发现,每个插件的结构是大同小异的,无非是改改存储字段名(字段类型大多都不要动,多是String),改下项目名称,许多其他的命名都以项目名称为前缀,以至于我每回开始写新的xblock,都是先cp旧的,然后使用rename 's/old_repo_name/new_repo_name/'grep -rl "old_repo_name" ./ | xargs sed -i 's/old_repo_name/new_repo_name/g'以及grep -rl "old_field_name" ./ | xargs sed -i 's/old_field_name/new_field_name/g'来作为新xblock的基本框架,以省去复制粘贴

这样又写了几个插件后发现依然有不少重复劳动,于是就想为何不写一个xblock插件生成器呢。

当我们陷入重复劳动的时候,可能就是合适的时机来考虑如何自动化这项工作了,以便能省下时间来喝咖啡。而且我们知道,重复乏味的劳动中,人是容易出错的,而机器不知疲倦,所以偷懒是程序员的美德

#思路 我的设想里,xblock插件生成器做的是这样的工作:开发者将项目名,所需存储字段,字段属性,,项目依赖的外部静态文件等写入config.json配置文件(或者config.yml/config.py),而后自动生成xblock,而后只需要做些微调以及在指定位置加入自己的业务代码,一个插件便可用了。

这里的主要工作是将琐碎的工作自动化,然后提供一个通用的模板,给出大多的备选功能(属性或函数,默认以注释掉的方式存在于生成的xblock中),尽量按照现有的xblock组件布局方式,现有的xblock组件可以参考这里,这样一来,熟练的开发者不需要参考文档,仅需要取消注释,做些微调,就足以快速地完成工作,没错,眼尖的你可能已经看出来了,这是ROR中致力于鼓吹的convention over configuration

此外,说到设计原则,关于灵活性部分,我喜欢Open Closed Principle原则(也就是著名开放封闭原则),对扩展开放,对修改关闭。xblock满足这点,我很喜欢

#设计原则 * Open Closed Principle(开放封闭原则) * convention over configuration (约定优于配置)

#技术细节 剩下的就是技术细节的工作了。

我最初想以jinja2模板为基础, 我们知道ansible之类的大型项目也够选择了jinja2,这的确是个优秀的模板引擎。而后发现了cookiecutter,这个工具进一步简化了工作,于是决定基于它来写xblock插件生成器,这样一来根据配置文件来自动生成文件名的问题都解决了

#遇到的问题 这里存在一个很有意思的问题,它和正则相关,cookiecutter用的是标准的jinja2模板,jinja2模版的语法和django相似,而xblock中的模板我用的是django而不是mako,这样一来就导致xblock中有一部分{{var}},我们是想等xblock来渲染,结果却被cookiecutter先渲染了。这个问题可以通过更改jinja2语法风格来解决,或是通过使用mako模板来解决。我是quick and dirty的方式解决的。用到了正则

#此类问题 此类问题,或者说代码生成器问题(generator),十分吸引人,它本质上是字符处理问题(我觉得的本质也是这个),这类问题的极致形态是写一个parser,而一般形态是使用正则,当然使用模板往往是个捷径。

#xblock市场的构想 个人而言,我很看好edX,我一直相信xblock本身足以形成插件市场,我觉得以此作为出发点,构建一个咨询/定制/服务型的公司是很有意思的,我喜欢《黑客与画家》第六章提到的观点:财富就是创造人们需要的东西,我们可以看到即便是国内,这个需求也已经越来越膨胀却没有找到出口。我们今天可以看到,edx这个项目本身是很诱人的,许多教育业内人士与公司都跃跃欲试,而edx的技术门槛确实个拦路虎,那么提供edx相关的技术/开发咨询/培训,提供定制化的服务(插件定制),降低开发的门槛等等,是许多企业客户期待的,当然也是对推广edx本身很有价值的,我的兴趣点之一可能在这里吧,让技术变得易用使用,能方便地用来应对现实问题,我此前折腾docker,折腾云服务,折腾LTI,此次写的xblock生成器,可能都是受此观念的驱动吧

有了xblock插件生成器,我们尤其适合做一些为课程深度定制的组件,快速完成插件的基础上,又可以据此作为模板生成其他组件。

前段时间给公司展示了我业余时间折腾的d3组件,treed,十分适合结合到edx中,作为呈现知识的方式,类似思维导图 ,d3的案例千千万:bl.ocks.org,如果能将此领域与教育领域结合,首先市场部势必会很兴奋,有了xblock插件生产器,将d3组件移植到xblock就变得十分迅速。而这些还仅仅是d3。类似的组件还有许多,这里的核心想法是,通过xblock这种插件机制,我们可以将其他领域的成果(好比数据可视化),轻易得整合到教育中,所谓学科融合

如此一来,结合具体学科,快速打造易用性的组件就变得容易,易用性很可能造成高度的定制化,由此带来通用性的损失,而有了插件生成器,大量打造定制化的插件,时间成本也不至于太高,成本一旦降低,作为商业性的服务就容易被接受。

该组件可能暂时不会开源,想先进一步优化它,可能的话想以此试水xblock市场

#花絮 在写完大体框架的时候,打了个 v0.1 tag,觉得后续的改良还很多,出于谦虚的姿态,版本号慢慢来,而后又花了一个周末的下午,觉得妈蛋好像主要的事都做完了,直接打了个v1.0的tag。而后顺便把将MTV中的T(Template)换成了mako,于是mako/v1.0也出来了