软件工程是研究和应用如何以系统性的、规范化的、可定量的过程化方法去开发和维护软件,以及如何把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来。各种软件已经成为人们日常生活中不可或缺的一部分,同时开发大型软件仍是已经非常困难的事情,所以软件工程学科的研究意义重大,值得我们深入学习。
然而软件工程对于没有过实际大型项目经验的学生来说,有些些概念很难理解。我本科也曾学过软件工程这门课,不过当时似懂非懂,只是一些粗浅的理解。研究生又上了这门课之后,在老师的指导下才真正理解什么是软件工程。下面是本学期的总结:
系统模块化
模块化(Modularity)是在软件系统设计时保持系统内各部分相对独立,以便每一个部分可以被独立地进行设计和开发。背后的基本原理是关注点的分离。关注点的分离的思想背后的根源是由于人脑处理复杂问题时容易出错,把复杂问题分解成一个个简单问题,从而减少出错的情形。
通过模块化,每一个软件模块都将只有一个单一的功能目标,并相对独立于其他软件模块,使得每一个软件模块都容易理解容易开发。从而整个软件系统也更容易定位软件缺陷bug,因为每一个软件缺陷bug都局限在很少的一两个软件模块内。而且整个系统的变更和维护也更容易,因为一个软件模块内的变更只影响很少的几个软件模块。
本地化外部接口
使用本地化外部接口来提高代码的适应能力, 将我们的代码接口分离出来,写成本地化的外部接口,能更好的帮助我们分离业务之间的关联性,使得代码开发更加高效。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NqPGQ0hz-1657448408781)(https://upload-images.jianshu.io/upload_images/20121483-7cefc363f6ad41ab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
接口的5个基本要素
- 接口的目的
- 接口使用前所需要满足的条件,一般称为前置条件或假定条件
- 使用接口的双方遵守的协议规范
- 接口使用之后的效果,一般称为后置条件
- 接口所隐含的质量属性
需求的四种类型:
- 功能性需求:根据需要的活动描述需要的行为
- 质量需求或非功能需求:描述软件必须具备的一些质量特征
- 设计约束:设计决策,如平台或接口组件的选择
- 过程约束:对可用于构建系统的技术或资源的限制
高质量需求的特点
解决冲突,需求是可测试的,正确的、一致的、无二义性、完整的、可行的、无与主要目标不相关的需求、可描绘的、可测试的
需求分析的两类基本方法
原型化方法(Prototyping)和建模的方法(Modeling)是整理需求的两类基本方法。原型化方法:可以很好地整理出用户接口方式(UI,User Interface),比如界面布局和交互操作过程。建模的方法:可以快速给出有关事件发生顺序或活动同步约束的问题,能够在逻辑上形成模型来整顿繁杂的需求细节。
用例建模的步骤
第一步:从需求表述中找出用例,往往是动名词短语表示的抽象用例;
第二步:描述用例开始和结束的状态,用TUCBW和TUCEW表示的高层用例;
第三步:对用例按照子系统或不同的方面进行分类,描述用例与用例、用例与参与者之间的上下文关系,并画出用例图;
第四步:进一步逐一分析用例与参与者的详细交互过程,完成一个两列的表格将参与者和待开发软件系统之间从用例开始到用例结束的所有交互步骤都列举出来扩展用例。
用例满足的四个必要条件
必要条件一:它是不是一个业务过程?
必要条件二:它是不是由某个参与者触发开始?
必要条件三:它是不是显式地或隐式地终止于某个参与者?
必要条件四:它是不是为某个参与者完成了有用的业务工作?
统一过程
统一过程(UP,Unified Process)的核心要义是用例驱动(Use case driven)、以架构为中心(Architecture centric)、增量且迭代(Incremental and Iterative)的过程。用例驱动就是我们前文中用例建模得到的用例作为驱动软件开发的目标;以架构为中心的架构是后续软件设计的结果,就是保持软件架构相对稳定,减小软件架构层面的重构造成的混乱;增量且迭代体现在下图中。

常用设计模式
单例模式
这一模式的目的是使得类的一个对象成为系统中的唯一实例。因此需要用一种只允许生成对象类的唯一实例的机制,阻止所有想要生成对象的访问。
建造者模式
将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。主要应用于复杂对象中的各部分的建造顺序相对固定或者创建复杂对象的算法独立于各组成部分。
代理模式
为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。代理模式是不要和陌生人说话原则的体现,典型的应用如外部接口本地化将外部的输入和输出封装成本地接口,有效降低模块与外部的耦合度。
适配器模式
将一个类的接口转换成客户希望的另外一个接口,是的原本由于接口不兼容而不能一起工作的那些类能一起工作。
装饰模式
在不改变现有对象结构的情况下,动态地给对象增加一些职责,即增加其额外的功能。装饰模式实质上是用对象组合的方式扩展功能,因为比继承的方式扩展功能耦合度低。
模板方法模式
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
职责链模式
为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。通过这种方式将多个请求处理者串联为一个链表,去除请求发送者与它们之间的耦合。
观察者模式
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为,这样所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式。
设计模式原则
单一职责原则:一个类应该只包含一个单一的职责
接口分离原则:把包含多个功能的接口分隔为多个接口
迪米特法则:每个实体只和它直接的朋友交谈,不和陌生人交谈
开闭原则:好的设计应该对扩展开放,对修改封闭
里氏替换原则:子类应该能替代父类而起到同样的作用
依赖倒置原则:高层模块、低层模块都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象
MVC架构
MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。
视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。
MVVM架构
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点:
- 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
- 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
- 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
没有银弹
软件危机发生后。人们一直寻找解决的方法,诞生了包括结构化程序设计、专家系统、面向对象的分析和设计方法等,当人们意识到大型软件中打造抽象软件的复杂概念结构的根本困难是缺乏有效的管理,而非技术本身时,于是针对软件开发活动及软件本身的管理,对软件生命周期建模,形成了众多有效管理软件开发过程的理论和方法,经过研究和实践逐渐演化成如今的CMM/CMMI、敏捷方法、DevOps等软件过程模型。
然而工程专家们所找到的各种方法都是舍本逐末,它们解决不了软件中的根本困难,即软件概念结构(conceptual structure)的复杂性,无法达成软件概念的完整性和一致性,自然无法从根本上解决软件危机带来的困境
V模型
V模型也是在瀑布模型基础上发展出来的,我们发现单元测试、集成测试和系统测试是为了在不同层面验证设计,而交付测试则是确认需求是否得到满足。也就是瀑布模型中前后两端的过程活动具有内在的紧密联系,如果将模块化设计的思想拿到软件开发过程活动的组织中来,可以发现通过将瀑布模型前后两端的过程活动结合起来,可以提高过程活动的内聚度,从而改善软件开发效率。
敏捷开发
互联网使得知识的获取变得更加容易,很多软件可以由一个小团队来实现。同时,技术更新的速度在加快,用户需求的变化也在加快,开发流程必须跟上这些快速变化的节奏。于是敏捷方法就产生了。敏捷宣言:
- 个体和互动高于流程和工具
- 工作的软件高于详尽的文档
- 客户合作高于合同谈判
- 响应变化高于遵循计划
经过孟老师的讲解,理解了软件工程就是一套用于软件的团队开发,以提高软件质量和程序员工作效率为目的的规范。其核心就是,对于软件开发的5个重要组成部分:需求分析,设计,编码,调试,维护,如何组织这5个部分的工作,以及如何完成每一个工作。团队在划分模块后明确了各自分工,渐渐形成良性循环。团队合作中的争议固然存在,但通过讨论、协商,群策群力,在不断磨合中一定能够达成一致与默契。
参考资料:代码中的软件工程