2014-软件工程基础-总结
本学期接近尾声,软件工程的课程也到了末尾,在此做一下总结。总结中可能涉及到其他课程,未必仅限于软件工程。
第一部分:链接到以前的博客,进行现在的体会的分析和说明:
个人项目:http://www.cnblogs.com/hks1994/p/3991963.html
第一次的个人项目,现在看来,其实还是有难度的,当时应该也是花了很多功夫,不过当时虽然时间紧张,但是事情不多,因此还是可以专心的做软工。不得不说,当时是非常幸运地了解到了c#中的dictionary类,否则,要么在数据结构的选择中纠结,要么在链表的使用中备受煎熬,不仅程序会变得难写,出来的结果也不会太好。其实也是一种机遇,当然也是积累的结果,有一定的必然性。与他人相比,数据结构方面我无疑占了很多的优势,与使用链表的同学相比,我的程序的运行时间是秒级,而他们的是小时级,这充分说明了数据结构的重要性。
阅读代码大全体会小结:http://www.cnblogs.com/hks1994/p/4025345.html
这应该是第一次阅读作业了。当时听到要看这么大的一本书时很是惊讶,后来才发现,其实基本的思路,基本的东西就是那几块,精髓并不是太多。
将函数分割为子程序,将类中定义的方法分开,方法之间,类之间的耦合度需要降低,这是面向对象课程上老师多次强调的东西。现在想来,面向对象课当时看起来那么蛋疼烦人,现在看来讲的东西虽然抽象但是还是很有道理,是很有帮助的思想。之前写java程序的时候,虽然写到了上千行,但是我仍然不想把函数和类给分开,因为分开显得太麻烦,有的时候函数长,代码量大,执行的速度不一定慢。这一句话我现在依然比较相信,不过,子程序的重要性我已经深刻地体会到了,主要来自两个事件。第一个是软件工程团队项目的第一个阶段。在团队项目的alpha阶段,我当时还认为任务量并不大,这无非是一个比较简单,功能比较基础的安卓应用而已。后来在开发的过程中才了解到,实际的开发比想象的要难得多,自己的力量其实很有限,这一点在数据库大作业、编译器实现和ruby大作业中也有体会。当时我弄一个搜索的部分就花费了很多的精力,更不用说其他的队员,有一个花了一周的时间,每天都在死磕文件的上传下载,另一些着眼于繁杂的界面设计和经受着各种崩溃的考研。而这些东西,如果都写在一个方法里,写在一个类里,你能想象吗,那对于维护将是非常可怕的。就拿搜索来说,搜索处理分不同的内容进行搜索,具体对用户的输入进行分解处理,然后再搜索,搜索后再整理搜索结果,将结果高亮,在界面上输出,同时还要做好页面的跳转,另一方面还要考虑到在android4.0中出现的新规定对项目开发带来的影响,比如说在主程序中不允许使用handleMessage消息循环,必须在子线程中进行,而涉及到多线程,一般都不会太容易解决。将这些复杂的东西分开,有利于理清楚自己的思路,也便于测试盒修改。虽然我一直很讨厌单元测试,因为他很繁杂,测试程序也不好写,但是在实际中往往不自觉地就是用了瀑布模型的开发方式,对单个模块进行不断地迭代测试,确认无误了才敢放心地进行接下来的开发。又说编译系统,编译器是一个非常典型的,必须采用子程序分割法的开发过程。如果你不把编译器的设计分为词法分析、语法分析、语义分析、代码优化、代码生成几个部分,那你真的能够想象程序构思和编写的复杂度吗,以及一个部分出问题对于整体的影响么。程序出错的时候,有的时候你的子程序分割不开,错误都无法准确判断在哪里出现,这又应该怎样去解决呢?总而言之,代码分割,子程序的使用,确实是非常重要的,不管是在递归和循环中,还是在普通的基本块中。
对于全局变量的使用,其实我个人已经高度认可全局变量了。现在经历了用java、c#和c++进行开发,不得不说,类的概念非常重要,没有类的程序,在我看来无法想象。在类中,各个函数之间对于类变量的共享是非常方便的,尤其是在大型的程序当中,比如说编译程序中,各个部分,各种语句成分的分析,各种分析函数对于变量值的共享,而类变量无疑提供了很好的访问方式。但是显然,这样大规模的共同访问很容易出问题,这里还不考虑多线程的问题,而是数据不一致的问题。代码量一大,程序就变得难以控制,有的时候一个变量复用好几十次上百次,你查都查不过来,而实际调试的时候费尽心力才发现是某一个地方少写了一个加号,或者少运算了一次,这些都是非常常见的,并且非常让人无奈的。
关于类的封装,现在还是没有什么更加深刻的体会,大概是因为没有什么特别需求private的地方吧,所以也就随便写随便用了。不过有一点收获很大:头文件的定义作用。以前没写过c++,这一次编译写了c++,发现头文件的作用还是非常大的。将类的定义放在头文件中,在cpp文件中实现类中的方法。这样查看类的定义方便,查看每个函数的具体内容也比较方便,自己两个文件(头文件和实现文件)对照起来看,程序的(类的)结构也比较清楚明白。在软件工程第二次结对项目中,编写电梯时,当时也在c#中强制使用了已有的接口进行定义与实现。这大概就是定义和实现分开的思想吧。这种思想也挺好的,之前没有体会到。
至于类的组合与继承,现在从来不用继承,至于类的组合,也就是类作为其他类的成员而存在。如果作为局部变量而存在,所耗费的栈空间无疑非常大,是不可忍受的,因此一般将这些类的指针作为参数传进来,一个类保存其他类对象的指针,指向堆空间中的其他对象。这样看起来是很好的,不过最近遇到的一个问题就是,在c++中,delete这些对象时,由于指针重复引用,delete一个之后,另一个对象还包含已被delete的指针的内容,再次delete,就会导致程序崩溃结束。也就是说,类的重复引用,或者是指针空间的重复,导致已经被delete的空间再次被delete而是程序出现运行时错误而崩溃。对于表驱动法,虽然没用过,但是其实在编译器设计中,对于switch语句的分析,与表驱动法有异曲同工之妙。在switch语句的分析当中,借鉴gcc的分析方式,将一个switch语句内所有的case语句后的常量收集在集合中,进行排序,然后进行二分查找,也就是利用折半查找来进行case语句的匹配从而实现跳转,不得不说,这是简单而又便利的思考方式,是对传统和简单数据结构的活用。
经过现在一段时间的编程,会发现复杂的数据结构,例如格式各样的树和图,除了他们的特殊功能(例如红黑树和B+树等),都可以用更加简单的数据结构进行替代。树和图都可以用多重数组来代替,由于在高级语言中动态数组的出现,再加上数据库中关系模式二维表的提出,表结构(实际就是多维数组)扮演着越来越重要的作用。只要空间足够,完全可以利用多维哈希表进行表构建,由于哈希表高效的查询效果,这样进行查询,可能比树和图嗨哟啊更加简便。根据问题选择适合的数据结构,敢于使用多样化的数据结构,将各种数据结构进行比较,通过实践找出当前问题对应的最佳的数据结构,是今后一直需要做的重要工作。
软件工程结对项目:http://www.cnblogs.com/hks1994/p/4034028.html
结对项目附加:http://www.cnblogs.com/hks1994/p/4034036.html
虽然上一次个人项目比较成功,但是这一次结对项目回望起来比较失败,而且现在回望那时的表现,仿佛就决定了会有那样的结果,以及决定了如今的窘境。
我是相信命运的,或者这样,上天以及定好了剧本,你做出不同的选择,就会出现的不同的剧情走向,这些有的已经决定好,有的是动态决定的,因为他人也在变化,就像编译时系统和运行时系统一样。因此,那时的失败,就决定了我今日会失败。在现在这个节骨眼上,只有两三天的时间了还有三门大作业,一门考试和答辩。我这一学期的数据库大作业、编译课大作业、ruby大作业、软件工程都比较失败,其中前三个的情况简直惨不忍睹。原因说白了就是:心太大,但是自己没有分配好时间。我一直知道自己是感性的人,而时至今日我才知道我是一个理想主义者,具体表现为我认为很多事情我都可以实现,哪怕只剩一天了,我也认为我能做得完。再加上我对质量的高要求,因此就很有可能导致中途夭折而影响到最后的结果。大二上学期有一门计算机组成原理实验课,当时做的不错,大二下学期的操作系统实验做的也不错,现在想来可能是因为当时大作业少,因此有精力弄。而像这一个学期,最后的阶段,大作业大概毕竟十个,而且其中的软件工程课的团队项目还分两个阶段,而第一个阶段花费了那么多的时间以至于整个人大概有三四个月以来的作息都是混乱的,自己的身体和心情都变得很糟,就认为自己是能做到的,但是就是没时间做了,真的是太遗憾了。这些东西确实是难,但也并不是做不到的。这么多大作业的糟糕的完成情况无疑给了我很大的打击,让我开始思考时间分配的重要性,以及对自身实力的正确估计,加上问题分析和计划制定的重要性。这些东西迟早是要考虑的,而如果到了后面才考虑,那么就可能因为来不及而没有什么补救办法了。因此,时间分配一定要做好,事前不管是否详细,一定要做计划,心里要有一些数,明确问题的主要矛盾和任务目标的需求重点,合理分配时间,达到最优的效果,也就是以完成目标为第一,具体的优化和其他细节不能纠缠不放,计划始终是要想的,想不明白就容易白白耽误时间,而同时却没有做什么,影响身体和心情。
代码复审:http://www.cnblogs.com/hks1994/p/4046913.html