数与图——整理与分享
《数与图》系列文章的目标是借助于程序来学习数学。对于一个学生而言,在他(她)的日常生活中,数学的应用仅限于解题,无穷无尽的、各种类型的、各种难度的练习题和考试题。学习数学的时间成本是昂贵的,几乎伴随我们整个学生时代,然而我们却很难有机会利用这些知识和技能去解决现实世界中的问题。幸运的是,编写程序为数学的应用提供了一种可行性。可以盘点一下,在《数与图》系列中,我们都使用了哪些数学知识与技能:从小学的四则运算(绘制坐标系)、初中的因式分解、多项式乘法以及高中的函数及其图像,等等。在编写程序过程中,我们放大了知识的细节,把抽象的公式转变成了有“个性”的图像,无疑这些会加深我们对知识的理解,但同时,程序也为数学提供了一个无所不能的演练场,它可以提升我们用数学知识解决真实问题的能力。数学和程序,就象我们的左右手,配合起来可以创造奇迹!
以上是我个人的观点,希望能与大家分享。
《数与图》一路写下来,发现程序存在一些问题,因此不得不停下脚步,整顿一下再继续前行。
这些问题与变量的使用有关。以《数与图(11)-画圆》为例,项目中的某些数据只需要计算一次,然后在多处使用,如图1中所示的坐标轴的最大值、最小值、主辅间距、原点、缩放比例等。这两个过程里存在很多重复的计算,这会降低程序的运行效率,也给代码的维护带来麻烦。从复用的角度来看,应该将这些数据保存在全局变量中,供多个程序共同使用。
图1 在不同过程里重复计算某些值
我们将声明一系列的全局变量,并创建一个“绘图参数初始化”过程,对这些变量进行赋值。代码如图2所示。
图2 声明全局变量并在过程里为它们赋值
读者也许会问,有必要设立最大X、最小X这样的的全局变量吗?直接从组件的属性中读取不可以吗?答案是当然可以!不过要知道,从变量中读取数据,等于从内容中直接读取数据,而从组件的属性中读取数据,首先要找到这个组件,然后再读取数据,从效率上讲,前者效率更高。如果整个程序中只需要读取一次属性,那么这样的差别不会影响程序的运行效率,但是,当读取的次数很多时,情况就不同了。其实就“画圆”这个应用而言,运行效率并没有那么重要,只是想通过这个例子,阐述一个一般性的开发原则,这多少也带有一点程序员的偏执。
下面修改所有与这些变量有关的过程。修改的操作必须小心谨慎,否则会给程序带来错误。
这里强调一下修改的顺序,如果把靠近事件处理程序的过程看作“树根”,那么供树根调用的过程就被看作树干,而那些被树干调用的过程可能是树枝,也可能是树叶,树枝可以调用树叶,但树叶只能被调用。修改要从树叶开始,逐级上溯,直到树根乃至事件处理程序。稍后你将看到这个修改顺序的必要性。
先从画横线过程开始。首先将过程里引用的参数全部替换为全局变量,注意替换的准确性,这时候如果出错,纠正起来会非常麻烦。然后再删除过程原有的参数,删除参数后检查代码中是否有错误警告,确信完全正确后,折叠起来放在新建的全局变量下方,以区别于尚未修改的代码。修改前后的代码如图3所示,左图为原来的过程,右图为修改后的过程,观察代码得知它没有调用其它过程,的确是“树叶”。
图3 修改“画横线”过程
用同样的方法修改“画竖线”过程,修改后的代码如图4所示。
图4 修改后的“画竖线”过程
接下来修改“画无原点横线”过程,它也是一片“树叶”,修改后的代码如图5所示。
图5 修改后的“画无原点横线”过程
同样的方法修改“画无原点竖线”过程,结果如图6所示。
图6 修改后的“画无原点竖线”过程
然后修改“画坐标轴”过程,修改结果如图7所示。
图7 修改后的“画坐标轴”过程
最后一片“树叶”是“标注坐标轴”过程,修改后的结果如图8所示。
图8 修改后的“标注坐标轴”过程
当全部6片“树叶”修改完成后,编程视图的工作区中一片狼藉,原来调用过这些“树叶”过程的地方,有大量废弃的参数被遗留下来,需要小心地将它们全部删除,如图9所示。
图9 编程视图工作区中被丢弃的参数代码
接下来修改“树枝”及树干,先来修改“绘制坐标系”过程。同样,先用全局变量替换局部变量,然后再删除局部变量,修改后的结果如图10所示。
图10 修改后的“绘制坐标系”过程
用同样的方法修改“求曲线坐标列表”过程,修改后的结果如图11所示。
图11 修改后的“求曲线坐标列表”过程
最后不要忘记在屏幕初始化事件及画坐标按钮点击事件的处理程序中调用“绘图参数初始化”过程,代码如图12所示。
图12 修改屏幕初始化事件及画坐标按钮点击事件的处理程序
下面进行测试,测试结果如图13所示,目前为止尚未出现错误(bug)。
图13 测试结果
程序修改到这里,可以暂时告一段落,这个过程多少会令人忐忑不安,因为担心将bug引入程序,或者引入新的问题。对于开发者来说,这样的过程应该叫“程序的优化”。一般来说,当我们有了一个想法,想开发一款产品时,更愿意快速地搭建起一个原型产品,以便验证需求,或探索一下技术的可行性,待这些问题解决后,再进入正式的开发过程。即便是正式的开发,也很难做到一次完成,通常是早期快速搭建代码,实现功能,后期再进代码的优化。
本文通过对现有项目的整理改进,展示了项目开发的真实过程,希望为未来的开发者提供参考。