【软件构造课程相关】以MIT实验Turtle Graphcis为例,探讨底层实现和复用相关
前言
在我们软件构造实验中,包含了MIT的原实验Turtle Graphcis的任务,接下来我就在完成这一实验过程中的思考谈谈个人关于底层实现和复用相关的观点。
MIT的原实验页面链接为http://web.mit.edu/6.031/www/fa18/psets/ps0/,通过阅读页面我们可以了解这一实验的目的。简要来说,就是实验给你提供了java语言下简化的turtle绘图模型的实现代码,要求你读懂这部分代码,接着能正确的运用这些代码来实现绘制多边形、计算轴承、计算凸包、设计个人图案等任务。由于这些任务难度不高,并且已在Lab1实验中完成,在本博客中不会涉及这些部分。在本博客中,我的讨论重点并不是对这些代码的运用,而是谈谈这些给定代码的实现原理和底层逻辑,从中给出我关于底层实现和复用的思考。
案例
现在我们着手于这一实验。首先,由于你无法连接MIT的服务器,因此不能按照实验页面的要求clone代码,可以从https://github.com/rainywang/Spring2022_HITCS_SC_Lab1/tree/master/P2中获取代码。
当你将代码clone到本地后,其实对本博客来说,实验页面的要求已经不会再使用了,只需要聚焦于这些代码即可。
我们先来谈谈Turtle,即海龟绘图。海龟绘图是对最早在 Logo 中引入的受欢迎的几何绘图工具的实现,它由 Wally Feurzeig, Seymour Papert 和 Cynthia Solomon 在 1967 年开发。在 Python 中,海龟绘图提供了一个实体“海龟”形象(带有画笔的小机器动物),假定它在地板上平铺的纸张上画线。在Python的Turtle库中,提供了诸多关于实现海龟移动、画笔控制、海龟状态等功能的方法,比如常用的有forward(),backward(),right(),left(),goto(),color()等。
但在本实验中,我们并非基于Python的Turtle中实现要求,而是用java来实现一个简化的Turtle模型。显然,由于Python中Turtle库十分复杂,用java语言完美复刻是难以实现且没有必要的,给出的代码也仅仅实现了海龟绘图的核心功能。现在我们来具体分析代码。
首先定义Turtle接口,即画笔可以实现的操作。完美复刻Python中Turtle库的全部功能显然是不现实的,在此我们挑选了几个重要的绘图操作:forward()(向着画笔方向前进units长度),turn()(画笔方向顺时针旋转degrees度),color()(画笔颜色变为color),draw()(开始画图指令)。
而要想实例化这个接口,我们不得不做些准备工作。
首先我们需要定义一些图的基础构成。在Point记录中,我们给出了浮点像素空间中点的定义:给定的x轴与y轴坐标确定一个点。
接着我们定义基础要素(类)边。显然,边是由起始点和终止点唯一确定,且附带有唯一的颜色。而点调用了上面实现的Point抽象数据类型。对边长这一特征我们可以由起始点与终止点的坐标距离得出,写在LineSegment类的方法中。
而上面提到的边的特征颜色也应当为抽象数据类型,可以由枚举PenColor给出。
至此,图的基础构成已经完成。现在,我们思考绘图的过程是否可以被看做是一步步的行动?由此我们抽象出类Action,每执行一步Action,展现在我们眼中的便是海龟绘图“画”出了一条边。
既然要绘图,那么一定需要一块“画布”。这个画布不仅是绘图的媒介,最后的图形也会呈现在画布中。在本案例中,我们可以设计一个窗口来作为画布界面。由于Java提供了JFrame类这一底层容器,即通常所称的窗口,故在实现turtleGUI时可以继承JFrame类。由于实现较为复杂,在此我只说明核心思想。在创建新窗口时,需要的参数显然为这个窗口的宽度(像素)和高度(像素),但这只能得到空白的窗口(即初始画布)。要想呈现出最后的图形,我们需要传入前面定义的Action序列,经过所有Action后,得到的即为预期图形,因为预期图形就是由一系列这样的操作绘出的。
现在,绘图流程已经全部准备完成,只需实例化turtle接口中的方法,保证海龟真能绘出线条来即可。前面三个方法直接实现即可,而draw方法我们可以调用已经实现的TurtleGUI中的方法即可。
现在我已经梳理了该项目实现的全部思路,由于篇幅所限,想要了解所有代码可按照案例最前面给的链接通读源代码。
思考
海龟绘图原本是Python语言中设计好的一个现成库,但从本实验中我们可以看出,用java也能写出海龟绘图。即使我们现在写出的Turtle相比Python下的十分简陋,但如果给足时间、技术足够的情况下,用java语言完美复刻Python是可行的。更近一步,用C语言也可以实现Turtle,虽然貌似更为困难,预测代码量会更多。
就这一点继续探讨,我们发现Python底层是用C语言写的,Java底层是用C++写的,而由于C++是由C语言扩展升级而产生的,故归根结底还是用C语言写的。那么,所谓高级语言与C语言相比,除了表达语法会有差异,还有什么区别呢?我想,正是因为C语言中只有基本的数据结构,而高级语言用C语言实现了各种各样应用广泛的抽象数据类型并提供一套成熟的使用方法,才被称为高级语言。
联系上学期学习的数据结构,当时实验要求使用C语言实现栈及其基本操作,我认为和本次博客内容主题十分相似。因为在C++中是直接有Stack这个数据类型的,而单纯用C语言也可以套用struct来手写一个栈。我想,历史的发展大概率就是程序员手写完一个栈后,不想每次使用到它时都重新写,开始大范围复用以前写的代码,最后索性觉得复用也麻烦了,干脆重新写一个新语言,里面直接在语言给定的库中就有这些数据类型多方便,就这样不断推出新的、更便于使用的、功能更强大的高级语言。
由此生发到未来的工作岗位中,一个公司的全部代码又何尝不是一个新的语言?只是,并没有人将自己公司设计的全部ADT囊括进一个语言中,他们做的应该是将其放入特定包中直接复用,但二者之间无根本区别。谈谈我个人的经历,三国杀是一款热度很高的游戏,该游戏可玩性高,里面核心的内容是设计武将且设计空间很大,由于原游戏氪金力度太大,民间有一群人复刻了一款无盈利的游戏——无名杀,并且添加了一系列的扩展。我也进入了设计组的一个分群,虽然由于个人能力不足我未参与过实际代码实现,但我在群里看见过大佬设计的代码。设计新武将都会直接复用武将牌这个ADT,追根溯源该ADT,包含名称、势力、性别、血量、血量上限、手牌上限、技能等属性,而且看似全新的技能很多也是重写以前相似的其他武将的技能代码得到的。
综上,尽管原实验中Turtle底层代码直接给出,并未做出过多要求,但通过对这部分的思考,我对复用方面的感悟颇深。
__EOF__
本文作者: 秒速五厘米。 本文链接: https://www.cnblogs.com/2022112842zbx/p/18189931 关于博主: 评论和私信会在第一时间回复。或者直接私信我。 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处! 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。