接触了不少图表工具,关于API的变化有一点启示
首先图表是图形,图形的要素非常多,所以图表的要素也不会少。典型的例子GUI的工作量和API数量都很多,windows的图形界面比字符界面需要考虑的东西也多得多。
图表的要素的多反映在用代码生成图形,必然需要指定很多元素,很麻烦。是的,重要的是怎么麻烦法。图形是用程序画出来的,构成程序的有方法,和输入的参数,输出则是图表。我的一个假设就是参数空间和方法空间总量是保持不变的,无论是采用什么设计方案。函数中多增加一个参数,那么就可以减少一族函数。
可以用draw(chartType, parameters)来代替一族方法drawPieChart(), drowBarChart(), drawAreaChart()…,同样可以增加其他参数,来减少方法空间中方法的数量。最极端的,如果参数足够的多,那么可以将画图方法中的方法空间减少到只有一个。但是api减少的代价是参数变得复杂了。所以这里就像一个矩形的两维,参数数量和api数量各为两条边,矩形的面积是大致不变的。
那么为什么需要变来变去呢?在现实中,jfreechart就是采用api空间较大,参数列表较小的选择(其实也不小,没有办法,画图就是有很多参数),但是可以采用适当包装参数,并且结构化方法参数的方法减低复杂度。而新的图表工具,比如flex,flash图表,都采用的是一个巨型方法, 接收一个复杂的参数,这个参数就是一个结构化的xml文件,或者json格式的数据。原来的参数往往只包括数据部分,但是现在的参数包括了图形的格式信息,等非数据的结构化信息,包括图表类型等等。
巨型方法的坏处在哪里?坏处在参数会多,对于一般的方法来讲,参数最好不超过2个,极少情况下可以有三个,参见clean code。如果参数多了怎么办?可以用对象将参数结构化包装起来。我在刚刚接触图表的时候,没有包装,传入的都是各种基本类型。所以参数列表甚至到了7,8个,可读性非常差。但是这是可以解决的,如果使用对象,或者更广泛的xml文件(序列化了,便于网络传输)来组织这种非常大量的,数据非常复杂的数据,可读性可以变好。但是这只解决参数列表的问题,对于巨型方法本身的维护性成了一个问题。巨型方法对client段是好用的,因为只需要调用一个单一的接口,然后组织好参数列表就可以了,刚才解释了,xml等可以很好的组织参数列表。巨型方法对于编写库的人员来说也不是不能克服的,因为他可以在内部将巨型方法,分解为一个个小方法。每个方法只有两三个方法,库的可读性也没有遭到损失。却只暴露给客户端一个单一的接口非常友好。
其实就可以利用jfreechart里现有的方法,组织出一个巨型方法。暴露给客户端调用生成图形。接口的参数包含了很多结构信息,而不只是单纯的数据信息。实际上,我相信我原先可以这么设计我的图表接口,给jfreechart包装一下。或者现在的图表api也是这么来组织他们的单一的巨型方法,而不是就真的只写一个方法。这样也不违反我们的clean code对方法参数的要求。
为什么麻这个烦呢?因为人对数据结构的认识更容易,相对于代码流程,不仅是记忆还是学习还是设计。所以更多的把复杂度留在数据结构这一维是好的。而图表api的转变就体现了这个原则。这个原则有一个抽象的描述在unix编程艺术这本书里面。
如果你要用jfreechart的api,画一个图表,定制是有非常多的api,涉及到很多策略模式的对象,每个对象里的setxxx的api非常多。总是画图是不容易的,要记住也不容易。但是把这些小的方法,封装到一个通用方法中,然后定义好通用方法接收的参数结构。那么这种xml文件或者对象是非常容易记忆和使用的。而且通用方法是由小方法组成的,也没有伤害到可维护性。数据结构的复杂性比api的复杂性对人类更友好的多。 从图表api中得到了印证。
下一个谈一下最近接触的快速开发工具
接触的两个快速开发工具,一个是大名鼎鼎的ror,一个是在java世界模仿ror的spring roo,java世界对ror的模仿还有play framework和grails。我用了spring roo,印象深刻,因为他大量应用了spring的东西,所以比较倾向。
ror的快速在于,第一它是脚本语言,这一点敏捷上有天生的优势,但是java也是可以模仿的,有在运行时植入的方法aspectj和反射等技术,也是可以得到媲美脚本语言的灵活性,典型的是在框架上可以拥有极端的灵活性。
第二是约定优于配置的理念,这个可以及大量的减少配置。其实第一减少难度,第二减少错误,第三减低曲线,第四很优美。
这些都不是要谈的,要谈的的是自动化的理念对这种框架产生的快速理念。这种自动化是由脚本或者各种工具实现的。
rails和roo生成框架的时候都不是自己敲进去的,而是运行某些命令脚本,这些脚本生成的程序框架和配置。这些脚本就是自动化的程序生成器,程序生成器的利弊后面会说。搭框架实际上是非常烦的事情,而且还有各种问题。而这些快速开发框架,将最佳实践融入到自动生成的代码里面。这些框架的结构本身都反映出开发者的理念。roo是拿来主义是用java世界里比较出色的各种开源项目来个大整合。粘合剂就是maven,maven充当了构建工具,依赖管理工具,包下载管理工具。这些自动化都由maven出色的完成了。相当于ruby里的rake和gem。roo里面还提供了类似bash的命令行工具用来运行脚本。
如果生成一个model,也是和rails一样用一个命令。因为这样可以做很多附加的工作。然后可以把精力集中在业务的开发上。
maven和ant等工具在我看来其实做了java做起来很麻烦的脚本工作。例如copy,构建,部署等等。一个程序不是万能的,例如c程序就需要一些脚本程序粘合在一起。在我看来是因为写程序,其实有两种性质不同的任务。往往构建等任务因为没有被自动化,依靠人工的所以被忽略了。程序员往往更加忽视了自己工作中可以自动化的部分,而没有编程实现这些任务。在自动构建,持续集成等概念被引进来以后,这些任务的自动化就被重视起来了。而这些任务往往是用java实现比较麻烦的。诚然maven和ant本身也是java程序,但是一般是用脚本的概念来编程的,我们是编写的xml形式的脚本程序。
由于习惯了每天在IDE上,点来点去按钮,没有意识到其实自己做的这些其实都是可以编程实现的。