跨考991之软工复习见解
跨考991之软工复习见解
我自己的一些想法,但请不要将我的想法上升到复习指导这种层次,我没有研究过到底该如何在不接触实际开发的情况下学软工,所以这里这只能是一些想法,或者说建议。此外我也不是做题家,我也不喜欢当做题家,但是991就是一个应试性很强的专业课,我也没有精力年年关注991动向,也没人给我钱做这个,还会抢人家机构饭碗,出力不讨好,所以,且行且珍惜吧。991并不算难,多一份努力就多一分回报。
此外,软工见仁见智,所以你在读的时候最好已经复习过一遍,有了大致的了解和自己的一些看法,再来批判地看,最好不要被别人的思想先入为主。其次,我这里也不一定全对,所以,一定要有你自己的想法。
最后,在没有实践经历的前提下裸学本身就是一种非常别扭的方式,所以如果你还很轻松的话,找点项目自己玩一玩看一看,会好很多。
在我看来软件工程这门课几乎是跨考生备考991最大的阻碍,事实也基本如此,无论是全日制跨考,还是对于非计算机专业想考非全的同学来说,这门课如同天书。虽然在软工人看来,这门课几乎没有任何技术难度,纯纯背诵课程,但如果没有工程经验或者软工专业素养,这门课也并不那么好理解,就算能背熟也很难做到活学活用。
当然,由于我本科就是软件工程专业,而且本科也一直在给一些中小项目做贡献,以及经常性的去做课程设计的项目,所以软工对我来说并不是很难的一门课,我学软工的瓶颈更多的甚至是背不过的问题(笑死)。所以这里也只是从一个软工科班生的角度来讲,如何更有效、更高效、更轻松地学习、复习软工。
为什么会有软件工程这门课
什么是软件工程?
说白了,现代化软件的生产流程,与工业品的制造是十分相似,他们都是因生活中某种需求而生,都要经历设计、实现、测试,包括此过程中的反复迭代,最后发布、维护(售后)等等这一系列过程,软件团队动辄几十上百人,各司其职,软件工程要教会你的,就是作为一名 Team Leader,你该对项目的每一个环节都能够熟悉,并且能够统筹整个过程,让工程能按时、高质量地交付,而这其中又牵扯软件工程过程的诸多环节与细节,所以才有了一整个软件工程。或者说,我从网上摘了一段:
软件工程是一个包含可行性分析、软件需求、软件设计、软件开发、软件测试、软件维护、软件过程和项目管理等方面的学科,它的主要目标是通过系统化、规范化和量化的方法,提高软件开发过程的效率和质量。
软件工程并不是教会不怎么会写程序的人开发软件。尽管软件工程涉及到许多方面的软件开发过程,但它也需要开发人员具有良好的编程能力和技能。在软件工程中,开发人员需要使用编程语言、工具和框架来实现软件应用程序,并需要理解软件系统的设计、架构和实现细节。因此,对于软件工程师来说,编程能力是至关重要的。
当然,软件工程不仅仅关注编程方面,还涉及到许多其他方面,如需求分析、软件设计、测试和项目管理等。这些方面也需要软件工程师具备相应的技能和知识,以确保软件项目的成功。因此,软件工程是一个综合性很强的学科,需要软件工程师具备多方面的能力和技能。
总之,软件工程不是教会不怎么会写程序的人开发软件,它需要软件工程师具备丰富的技能和知识,才能够有效地开发高质量的软件应用程序。
为什么软件工程能够一直发展,而不会墨守成规呢?
软件工程不像数据结构,确定之后基本就不会改变,随着软件开发模式的不断迭代、时代需求的不断发展,软件工程也需要适应这一过程而持续发展,在我看来,其中最大的推力来自于时代发展带来的软件危机,这个在软件工程的开始一般就会讲。更详细但不一定全面的说,软件工程的目的是:
提高软件开发效率:软件工程方法论提供了一套完整的开发过程和工具,可以帮助开发人员在开发过程中高效地完成各个阶段的工作,提高开发效率,减少开发时间和成本。
提高软件质量:软件工程方法论提供了一套标准的开发规范和质量保障体系,可以帮助开发人员在开发过程中保证软件的质量和可靠性,减少软件缺陷和错误。
降低软件开发风险:软件工程方法论提供了一套完整的风险管理体系,可以帮助开发人员在开发过程中及时发现和解决潜在的风险,降低软件开发风险,提高项目成功率。
改善软件开发团队合作:软件工程方法论强调团队协作和沟通,可以帮助开发人员更好地协作和交流,提高团队工作效率和成果。
促进软件持续发展:软件工程方法论提供了一套完整的软件生命周期管理体系,可以帮助开发人员在软件开发完成后进行维护和升级,保证软件的持续发展和更新。
软件工程复习见解
软件过程本身就是一门相对泛泛的课程,我的评价是,大处着眼,小处着手。也就是说,我们在学习的时候,要整体的去看待这一部分的知识,软件工程的环节是环环相扣的,彼此之间多有联系,有时如果考虑到上下文过程的联系,往往就能理解一些问题。而在解决具体问题时,则要根据这一部分所学的具体内容来解决。
我相信小处着手是不难的,但是大处着眼可能就需要对这门课非常理解才能做到了。举个栗子,为什么软件需求要画用例图?而且用例图的绘制还是需求工程里非常重要的一部分。在软工的实践中,需求是给甲方看的,他们是一群不懂代码甚至不懂架构、设计、算法的人,他们只知道他们想要什么。在可行性验证完成后,软件团队需要对甲方提出的需求进行调查、分析,而我们并不能保证我们所分析得到的就是甲方想要的,所以会有需求说明书,用例图其实就是其中非常重要的一环,因为他非常直观的展示了软件的未来愿景,就像施工的鸟瞰图那样,甲方只需要稍加学习就能看懂软件团队的需求理解是否到位,然后再去细细看需求说明书,就会轻松很多。此后,用例图还会与需求说明书一起,指导软件设计的方向,因为设计就是为了满足需求,最后的验收测试,还会有需求说明书的参照,验收软件是否完成预定的需求,当然,也少不了用例图的参照。
所以,将一个问题放到全局来思考,往往就不会出现,“我为什么要搞这个” 这种疑惑。
当然,你也可以直接谷歌,搜搜这玩意到底有什么用(我也很难保证到底真的有没有用(笑死
上面bb了一堆概念性的东西,不是说没用,我是希望大伙复习的时候,能够对这门课有一个大致的了解,尤其是这类需要理解、背诵的科目,在开始学习前,对课程有一个大致的方向上的了解,能够让你在学这门课的时候不迷失自己,不会轻易陷入到局部的问题中钻牛角尖,能够知道自己为什么而学,学了有什么用,这大概就有点所谓的学科素养的意思在吧。
进入正题。
第一部分 软件工程概述
包括但不限于软件、软件工程等基本概念,主要内容有:软件的概念、特征和分类;软件危机产生的原因和表现;软件工程的概念和原则;软件工程知识体以及相关标准。
这一部分其实就是很综述的一章,主要记住软件的特点、分类,软件危机的表现,尤其是原因,了解软工的目标和原则,基本就ok了,没什么很难的东西,也没什么很难理解的。
其实主要还是理解软件危机,我们大可把软件当成一种工业产品,也就不难理解其在需求、质量、开发成本、及时交付以及运维上的问题。此外,就灵活性而言,随着生活发展,软件需求在迭代、开发技术在迭代,这就使得老软件很难跟上时代的步伐,而推倒重来的成本又太高(举个例子,你们学校or公司官网,很可能就是屎山)。
其次,很多跨考的人可能不理解文档的重要性,一方面,开发者和甲方不是三体人,可能开发者A和甲方B因为沟通不良(比如语言的二义性),脑子里想的就不是一个东西,但都以为对方懂自己,最后软件做出来发现不对,一方面就要付出很大成本,第二方面如果没有文档,这东西找谁说理去。同样的 开发者A和开发者B(尤其是合作负责一块业务的)也需要对某一模块或需求的开发统一信息,如果两个人各做各的,很可能南辕北辙各奔东西,就算侥幸写到一块,也可能出现看对方写的代码头大的情况,要知道,程序员最讨厌看别人的代码,尤其是一个需求可能要上千行代码,如果是分布在一个万行级代码的大型项目里,那估计看一天也看不明白。而如果有文档贯穿始终,那么开发者和开发者、开发者与用户间的沟通就能保持一个基准,开发和维护的效率也会大大提高。当你接手一个十年前的老项目,你就会非常希望他有一份健全的文档了。
当然,文档在现实中一般来说都是滞后的,尤其是开发阶段,就如Linus所言,Talk is cheap, show me your code. 所以很多人往往会开发完才回头补文档,这其实很容易造成文档与代码不一致的情况(我第二天就能把第一天写的代码忘得一干二净),这其实是造成软件修改、维护困难的一个原因,同时也包含新技术的迭代而老软件更希望修改而不是重构以节约成本、一些Bug没有及时解决而造成的后续开发暴雷等等其他原因。
说了这么多,还是希望大伙能理解,不要死记。
第二部分 软件工程过程
包括但不限于软件生命周期和基本过程模型等基本概念,主要内容有:软件生命周期概念和各个阶段,典型软件过程模型:瀑布模型、快速原型模型、螺旋模型、统一过程模型、敏捷模型等。
传统意义上讲,我们可以把软件工程分为这么几个阶段,可行性分析,需求分析,软件设计,开发,测试,维护。这其实是软件工程过程这一部分的知识点,基于这个比较传统的、笼统的过程,现实中我们会有很多种类的软件过程,他们描述了在现实中我们是怎么做软件工程的,所以这其实是相当灵魂的一部分内容。
这几个阶段分别干什么,我想你应该很容易就能搞懂吧
所以其实这一部分重点就在于,考纲里提到的典型软件过程模型:瀑布模型、快速原型模型、螺旋模型、统一过程模型、敏捷模型。
瀑布模型属于最老的一类。也是最好理解的,就是纯线性模型,如果深入一点,我建议了解V模型和W模型,虽然考纲里没有。
快速原型其实也没什么好说的,就是先做个demo(原型,初号机),修修改改确认符合需求、设计合理后进行开发(成品,量产机)
螺旋模型更加考虑风险,一般用在大型项目,这个直接看课本也好说,转圈=迭代。
RUP其实有点抽象,核心工作流其实就是大致上的软件工程的各个阶段,核心支持工作流其实就是一些运维的活,辅助整个软件工程过程的正常进行。其中环境可以指软件运行环境,比如后端部署需要服务器,服务器可以选Linux系统,也可以是win,或者老一点,CentOS,系统里还要装一些支持性软件,比如Docker,此外也可以是一些辅助工具的环境,比如K8s等等,也可以指开发环境,比如客户端Android Studio,通用一点的VSCode,写后端可能用到IDEA,前端WebStorm等等(不是给JetBrains打广告)
敏捷模型其实是我心中最重要的那个,很多互联网公司扁平化的目的,一部分其实就是敏捷,或者说,灵活。记住敏捷开发宣言,这就是敏捷模型的灵魂。至于XP,了解就好。
所以总的来说,这一部分其实是对于软件整个过程的抽象描述,但由于软件的种类其实有很多,各有各的侧重点,所以会有不同的模型,当然还有一部分原因是模型随着时代、技术发展而发展。从记忆的角度上讲,对比记忆其实是一种很好的方法,各个模型之间各有优劣,各有侧重,能够做到将其对比、区分,我觉得就基本上理解的差不多了。
第三部分 软件需求分析
包括但不限于需求和需求分析相关的概念和应用,主要内容包括:软件需求的基本概念、功能需求、非功能需求和需求的评价准则;常见的需求调方法:竞品分析、观察、访谈、开会、原型和问卷调查等;结构化需求分析基本概念,数据流图、状态转换图和ER图的基本用法;基于用例的需求建模方法和过程,参与者、用例、用例图、用例文档的基本概念,基于用例方法开展需求建模实践;面向对象技术的基本概念,对象和类,面向对象的基本原则:抽象、封装、分解、泛化、多态、分层和复用等;可视化建模语言UML的基本概念、UML特点,UML基本构造块和通用机制,常见的UML图:用例图、活动图、类图、对象图、包图、顺序图、通信图、状态机图、构件图和部署图等;利用UML开展面向对象的分析基本过程,抽取分析类:边界类、控制类和实体类,基于顺序图、通信图等开展交互分析,定义分析类的职责和属性,分析类的关系:泛化关系、关联关系、聚合关系和组合关系。
可行性研究与需求分析
可行性研究并不是重点,只需要理解其目的不在于提出解决问题的方案,而在于研究解决问题的必要性和可能性,就必要性而言,软件产品推出后需要有足够的市场,至少能够实现一定目标的盈利等等一系列目的,如果市场对某类软件几乎没有需求,或者该类软件市场早已卷的很成熟、不再有市场的开拓发展空间、或很难达到预期市场占有而盈利,等等,那么就没有必要去开发某一款软件(这里开发指的是软件工程全流程,不是指软件本体的编码和开发)。至于可能性,首先制约项目可能性的一点就是技术,一方面,该软件开发是否超过公司所能承担的技术水平,另一方面,其开发,尤其是软件编码的技术是否能够支撑项目完成,比如如果没有Unity等引擎,可能很多游戏项目都不会立项,其次,开发的各项风险也要在考虑范围内,比如技术风险、进度风险、需求风险、人员风险和质量风险等,可以直接谷歌搜索。
可行性考虑的是是否值得做,需求分析考虑的是做什么。一般我们会分成功能性需求和非功能性需求,功能性需求顾名思义,就是涉及到软件具体功能实现的需求,比如腾讯会议要求实现多人会议室的建立,其中又会涵盖到音视频流推拉流,视频处理,会议室组织管理等等子功能。而非功能性需求则相对广泛,涵盖了系统应该具备的性能、安全、可靠性、可用性、可维护性等方面的要求,不同于功能性需求,非功能性需求衡量的是系统运行的质量和性能。
结构化需求分析
结构化需求分析方法就是一种面向数据流的分析方法,基于分解和抽象的基本思想,数据流其实也顾名思义,因为软件是数据驱动的,数据会在软件不同模块间传递、调用,所以数据流其实也在一定程度上反映了软件不同部分、模块之间的关系。数据流也为系统不同模块间接口设计提供了非常有力的指导(因为接口在很大程度上就是模块间数据流与控制流交换的关口)。
结构化需求分析会有多种工具(示意图)作为支撑,比较重要的是实体关系图,数据流图,状态转换图以及数据字典,这些工具一同为结构化需求分析提供了支持。其中比较重要的是数据流图和状态转换图。
这种分析方式其实类似于模块化思想,将整个系统自顶向下地划分为不同模块,不同模块间有各自的数据字典,有各自的实体关系与状态,通过数据流进行交互协作,越底层的模块越细致。自底向上逐步由具体到抽象(类似于从具体的承担功能实现的子类,到承担定义的父类,或者说一般是抽象类或者接口),我们也能对整个软件系统的需求有更好的把握。
面向对象分析
面向对象的软件工程方法涉及到更多面向对象的思想,首先要对面向对象的知识有一定了解,那么其次对比传统软件工程方法,也就不难理解面向对象在复用性、维护性等方面的优势。所以,真的,如果你对面向对象一无所知,先学一下这门课吧。
UML其实没什么好说的,它只是一套工具,一套体系,并没有什么理解上的难度,只需要掌握绘制方法,其中尤以用例图、类图、状态图、顺序图为重。其实UML在面向对象中应用的非常广泛,所以如果你发现这部分学起来有点吃力,不如先去学学面向对象,这部分也就没那么难以理解。
理论上我不太应该把用例图放到UML这里,但是用例图其实是非常能体现面向对象软件中的最顶层、最综合的设计思路的,所以也是非常重要的。
有了这些,我们就可以使用面向对象的思想,以UML为工具进行分析与建模,所以如果这部分不是很理解的话,还是建议先看看面向对象。毕竟考纲也提到了:面向对象技术的基本概念,对象和类,面向对象的基本原则:抽象、封装、分解、泛化、多态、分层和复用等
第四部分 软件设计
包括但不限于软件设计的概念和应用,主要内容有:软件设计的基本原则,概要设计(架构设计)和详细设计(构件设计)的基本过程;软件体系结构(架构)的基本概念和过程、典型架构模式(风格)、性能、安全、可靠性等关键质量属性设计;面向数据流设计的基本概念,流程图、判定表、判定树和过程设计语言等基本设计方法;数据库设计的基本概念,界面设计的基本概念;面向对象设计基本概念,设计类的操作、方法和状态设计,关联关系设计,依赖关系、泛化关系等设计,面向对象设计模式的基本概念。
软件设计研究的是做什么才能实现软件需求的问题,或者说,就是怎么做的问题。一般来说,在整个软工流程中,这一步是最重要的。此时我们已经明确了软件系统的需求,也就是说知道了甲方想要什么,那么我们就需要对如何实现这些需求做出规划,可能有的需求优先级高就要先做,此外还涉及从上到下的软件整体架构到底层的详细算法的设计,设计的好坏几乎直接关系到软件的灵活性与可维护性。
一般来说我们先进行概要设计,对系统架构、模块间的关系等等这些骨架性的部分进行设计,然后我们再进行内容的填充,也就是详细设计,对模块内以及模块间交互的具体细节和算法进行设计。设计也会遵循一定的原则,这几部分原则其实也跟面向对象有或多或少的类似之处。
结构化设计
结构化设计的思想类似于结构化需求分析,从软件的整体结构出发,通过图形的手段,在不同阶段实施不同的设计方法,这也是因不同阶段的侧重点而异的。
面向对象的设计
这个也跟面向对象的需求分析类似的,基本倒也没什么好说的。
所以综合来讲,这一部分就是最吃经验的一部分,从知识量上来讲并不比前面几章多,但是拿到一个需求(题目),该如何设计却往往让人无从下手。这个问题我一直想了好多天,却很难有一个很令我满意的快速入手的速成方案,矮子里面挑将军,我比较倾向于这种方案:
我称之为结构化面向对象设计,按照自顶向下、由概要到详细的思路。以直播带货系统为例。
如果是真实世界,拿到问题后,比如设计这个直播带货系统,我会先考虑架构,或者说,技术架构。比如:
这都快成我这几年开发的架构设计模板了,实际上也大可不必这么复杂,对于客户端而言,直接进化成MVC就可以,你要是有兴趣,MVP,MVVM任您挑选,后端属于是经典架构,
Controller
、Service
、Mapper
三层架构,最后通过MyBatis
等等连接数据库。这其实是一个很技术性的架构,这只是我的一点个人偏好,因为这个架构相对于991题目可能出到的问题而言,太庞大了也太接近现实了。
如果不那么技术性的,可以考虑自己看一下MVC架构思路。
如果是做题,我可能更推荐直接进行业务架构设计,顾名思义,其更偏向业务性。
我们完全可以从业务的角度出发,对整个系统的业务需求进行建模后进行设计,比如:
这只是一种模块上的划分,也可以看做一种变相的结构图,在我看来,只有这个可能不够,在此基础上,如果能梳理出一份数据流图,则会更完善。
因为在做题时我们很难画的像实际工程一样很完善、丰富、面面俱到,所以只能抓关键图来画,或者题目规定,画出某个图,那就更简单了。
无论如何,在我看来,架构永远都是很结构性的。当然,概要设计直接用软件整体的类图也是一种非常常见的操作(我这里只是没放)
对于详细设计,我可能更倾向于推荐类图、顺序图、流程图,当然面向数据结构的图表也不错,比如我会考虑:
或者顺序图:
甚至类图,尤其是涉及到某个模块的架构。(整体的也能画,只是比较大
无论如何,我会更倾向于在详细设计的时候使用面向对象的思想,当然,也就不可避免的要对数据结构进行详细思考与设计。基于这一点,流程图可能不是一个很好的选择,因为他是面向过程的,但其实这其中还有一层需要我们注意的,就是我的设计思路永远是自顶向下为主的,在详细设计的顶层,类图会是规划一个模块大致框架的一个很好选择,然后我会倾向于用顺序图或者数据流图描述这个模块的整体的业务流,最终在最细节的算法流程或者小功能点的流程上,使用流程图描述。
我很倾向于在这些图表中加入其使用到的数据结构,或者是使用到的类,因为设计类的过程在一定程度上就是设计数据结构的过程。
所以上面只是简要的介绍了一下我的思路,总结而言,自顶向下的,概要设计采用业务结构化的设计,偏向逻辑结构、数据流、比较笼统的类的结构,详细设计采用面向对象的设计,偏向数据结构与逻辑流程,以及具体类和算法的细节。但是一般来说,991不会搞得这么复杂,题目一般只会要求做其中的某一部分,或者画出给定需求的某几个图,毕竟如果真的是一整个设计的话,那可太开放性了。
所以总的来说,如果想要快速入门成为一个还不错的软件设计师,面向对象和设计模式其实是非常重要的两部分内容,虽然不在考纲之内,但是却会深深地影响你的软件设计能力。面向对象自不必说,设计模式其实就是经过考研的软件架构、设计的思维模式汇总,我一直觉得它会潜移默化地提升一个人对软件设计的思考能力,当然,直接应用到题目里,指出你的设计参照了某某设计模式,也会是非常强的综合素质的体现。我承认不能拘泥于某一种或者几种模式,但熟悉规则才能更好的超越规则,这是成为更好的软工人的必经之路,当然这都是后话了。
第五部分 软件构造和测试
包括但不限于软件构造和测试的概念和应用,主要内容有:软件构造的基本概念、一般原则和要点,设计模型与实现模型的映射;软件测试的基本概念、原则和方法;测试用例的基本概念和设计方法,黑盒测试概念和方法:等价类、边界值、因果图等,白盒测试概念和方法:程序流图、逻辑覆盖、圈复杂度等;单元测试、集成测试、系统测试、验收测试、回归测试等基本概念和方法。
这部分感觉没什么不好理解的,单元测试,集成测试,系统测试,验收测试,如果不太理解,可以看一下W模型或者V模型,或许就能理解其与其他软件工程步骤的对应之处。
但这一部分其实也很重要,稍微难理解一点的比如集成测试的自上而下和自下而上以及三明治式的测试方法,其实跟软件设计的一些思路有点类似,其实就是项目里模块分解(自上而下)、模块集成(自下而上)以及像挖隧道一样从两头往中间挖这种思路,如果复习到的话,其实你会发现这几种方法各有优劣,对比来看也就不难理解。
这里插一嘴,考纲里虽然没有写,但是测试这里我其实一直觉得可以包含面向对象的测试,但是实际上在其中所表现的面向对象的思想可能没那么强。但无论如何,如果有时间,还是可以考虑看一下。
第六部分 项目管理基础
包括但不限于软件项目管理的基本概念,主要内容有:软件项目管理基础及项目规划;软件成本管理、风险管理、质量管理、配置管理等各类管理概念。
这部分内容不多,而且感觉都是考项目管理的思想,考纲泛泛,简答居多。可能最难的就是软件估算那部分的计算类的题目啥的。但是。。。。感觉真就是靠理解和记忆
总结与碎碎念
总而言之还是这几方面,一是触类旁通,多跟其他章节的知识点联系起来,从整个过程的角度上理解知识点,不谋全局者不足谋一隅。其次是理解,如何判断自己对某一个知识点理解的还算可以呢?试着找张纸讲给自己听,自己作为学生去挑里面的毛病。如果最终对比课本能够讲的条理清晰,没有纰漏,那么说明这个知识点理解的不错了。再者,如何去理解记忆呢?其实你会发现软件工程中针对某一问题的解决方案往往有很多,对比着进行记忆我认为是一种很高效的方式,如果有的东西不理解,谷歌或者GPT其实是一种非常有效的手段。最后,画图能力很重要,几种UML多动手,强过考场上干瞪眼。
我一直觉得,面向对象与设计模式这两部分知识其实对于软件工程的综合能力非常重要。前者的思想几乎贯穿了近半数的软件工程的知识点,而后者对于软件设计的能力的提升以及对类图的使用有着非常大帮助,尤其是对于跨考的同学来说。
所以如果你真的对软件工程这一系列的知识都没有接触过,我会推荐你以 面向对象,设计模式,软件工程 这样的顺序来进行学习,面向对象是区别于传统开发思维模式的非常重要的思想,也是更优雅的软件需求、设计、开发的最佳指导,而设计模式,其实也是对于软件架构、设计方面前人经验的宝贵总结,通过这些模式,相信你会对如何设计构建高可用、高鲁棒、高内聚的软件有更深刻的思考和见解,虽然有些模式的某些部分看起来真的多此一举,但如果你真的参与过中大型项目开发,我敢说设计模式的思想一定会给你非常强有力的帮助的(用不用另说)。
又,数据结构那边的AOV网与拓扑排序、AOE网与关键路径,是可以应用在软工或者说项目管理中的,近两年都没有考,我觉得这真的是一个不错的考查方式,真的不考虑考一下吗?