一.软件工程实务概念
软件工程实务是一门将软件工程的理论知识应用于实际软件开发过程的课程或领域。它涵盖了软件开发从项目启动到维护的各个阶段,旨在培养学生或软件从业者具备实际开发高质量软件系统的能力。
二.软件产品质量属性和可靠编程
1、软件产品质量属性
-
a.功能性
- 指软件能够实现用户所需功能的程度。软件应准确无误地执行其预定的功能,满足用户在业务流程、数据处理等方面的需求。例如,一个财务管理软件需要能够正确地进行账目记录、报表生成等功能。
-
b.性能
- 包括软件的响应时间、吞吐量、资源利用率等指标。性能良好的软件能够在不同的负载条件下,快速响应用户请求,高效处理数据,同时合理利用系统资源。例如,在线购物平台需要在高峰时段能够快速处理大量订单,保证页面加载速度快。
-
c.可靠性
- 是指软件在规定的条件下和规定的时间内,完成规定功能的能力。可靠的软件能够稳定运行,很少出现故障,即使出现故障也能快速恢复。例如,航空交通管制软件需要具备极高的可靠性,以确保飞行安全。
-
d.易用性
- 关注用户与软件交互的便捷性和舒适性。软件应具有直观的界面、简单易懂的操作流程,方便用户学习和使用。例如,手机应用程序通常会采用简洁的设计,方便用户快速上手。
-
e.可维护性
- 指软件易于理解、修改和扩展的程度。良好的可维护性使得软件在后续的升级、修复漏洞等工作中能够高效进行。例如,采用模块化、分层架构的软件,各个模块职责明确,便于维护人员进行修改和扩展。
-
f.可移植性
- 是指软件能够在不同的硬件平台、操作系统、数据库等环境中运行的能力。具有高可移植性的软件可以更容易地适应不同的应用场景和用户需求。例如,一些跨平台的游戏可以在多种操作系统和设备上运行。
2、可靠编程
-
定义
- 可靠编程是一种编程理念和方法,旨在编写具有高度可靠性、稳定性和正确性的软件代码。它通过遵循一系列的编程原则、规范和技术,减少软件中的错误和缺陷,提高软件的质量和可靠性。
-
实现方法
-
a.遵循编程规范
- 制定和遵循统一的编程规范,包括代码风格、命名规范、代码结构等方面的要求。这有助于提高代码的可读性和可维护性,减少因代码风格不一致导致的错误。例如,在 Java 开发中,遵循阿里巴巴 Java 开发手册中的规范。
-
b.进行代码审查
- 通过同行之间对代码进行审查,可以发现代码中的潜在问题,如逻辑错误、安全漏洞、性能瓶颈等。代码审查还可以促进知识共享和团队协作,提高整个团队的编程水平。
-
c.编写单元测试
- 为每个函数、类或模块编写单元测试,通过测试用例来验证代码的正确性。单元测试可以在开发过程中及时发现代码中的错误,并且方便在后续的代码修改和扩展中进行回归测试,确保功能没有被破坏。
-
d.异常处理
- 合理地处理程序中的异常情况,避免因异常导致程序崩溃。通过捕获和处理异常,可以提高软件的稳定性和容错能力。例如,在读取文件时,要处理文件不存在、读取错误等异常情况。
-
e.代码复用
- 尽量复用已有的经过测试和验证的代码,避免重复开发。代码复用可以减少代码量,降低出错的可能性,同时提高开发效率。例如,使用开源的代码库或框架来实现一些常见的功能。
-
三.理解程序复杂度:耦合
1.定义
耦合指的是不同模块之间的相互关联程度。如果一个模块的修改会导致另一个模块的行为发生变化,那么这两个模块之间就存在耦合。模块间的耦合程度越低,说明它们之间的独立性越强,一个模块的变化对其他模块的影响就越小,软件的可维护性和可扩展性也就越高。
2.耦合的类型
-
2.1. 数据耦合
- 模块之间通过传递简单的数据参数来进行通信,这是一种较为松散的耦合方式。数据耦合只涉及到数据的传递,不涉及控制信息或复杂的数据结构,模块之间的独立性相对较强,对软件的可维护性和可扩展性较为有利。例如:
-
2.2.接口耦合
- 接口耦合指的是模块之间通过接口进行交互而产生的耦合关系。这里的接口是指模块对外提供的一组操作或服务的定义,它规定了其他模块如何与该模块进行交互,包括输入参数、输出结果以及操作的语义等。模块之间只依赖于彼此的接口,而不依赖于对方的内部实现细节。。例如:
-
2.3.内容耦合
- 这是耦合程度最高的一种类型。当一个模块直接访问另一个模块的内部数据,或者一个模块不通过正常入口而直接转入另一个模块内部时,就发生了内容耦合。这种耦合方式会使得模块之间的独立性完全丧失,一个模块的任何修改都可能影响到其他模块,严重降低了软件的可维护性和可理解性。例如:
四.可靠编程的主要关注点
-
正确性:
- 功能实现准确:程序应按照需求规格说明书的要求,准确实现各项功能,确保在各种正常和边界情况下都能产生正确的结果。例如,在一个计算银行利息的程序中,要保证利息的计算结果精确无误,符合金融业务的规则。
- 算法和数据结构正确:选择合适的算法和数据结构是保证程序正确性的关键。不同的问题需要采用不同的算法和数据结构来高效解决,并且要确保其逻辑正确。例如,在处理大规模数据排序时,选择快速排序、归并排序等合适的算法,以保证排序结果的正确性和效率。
-
健壮性:
- 输入验证和容错处理:程序应能够对用户输入和外部环境的各种可能情况进行充分的验证和处理,避免因非法输入或异常情况导致程序崩溃或产生错误结果。例如,在用户注册页面,要对输入的用户名、密码等进行格式验证,对不符合要求的输入给出提示;在网络通信程序中,要处理网络连接中断、超时等异常情况。
- 错误处理和恢复机制:当程序发生错误时,应具备良好的错误处理和恢复机制,能够尽可能地减少错误对系统的影响,并使系统能够恢复到稳定状态。例如,在数据库操作中,如果出现数据库连接失败的情况,程序应能够尝试重新连接,并在一定次数失败后给出合理的错误提示和处理措施。
-
性能:
- 时间复杂度和空间复杂度:关注程序的时间复杂度和空间复杂度,优化算法和数据结构,以减少程序的运行时间和内存占用。例如,在设计一个搜索算法时,尽量选择时间复杂度较低的算法,如二分查找算法在有序数组中的查找效率就比顺序查找算法高得多;在处理大量数据时,合理使用数据结构来减少内存的消耗。
- 资源利用效率:合理利用系统资源,如 CPU、内存、磁盘 I/O 等,避免资源的浪费和过度占用。例如,在多线程程序中,要合理分配线程资源,避免线程过多导致 CPU 上下文切换频繁,影响程序性能;在文件读写操作中,要采用合适的缓冲策略,减少磁盘 I/O 次数。
-
安全性:
- 数据安全:保护程序中的敏感数据,防止数据泄露、篡改和破坏。例如,对用户的密码进行加密存储,使用安全的通信协议(如 HTTPS)来传输敏感数据,对数据库中的重要数据进行备份和恢复等。
- 系统安全:防止程序受到各种安全攻击,如 SQL 注入攻击、XSS 攻击、缓冲区溢出攻击等。例如,在 Web 应用中,对用户输入进行严格的过滤和验证,防止 SQL 注入攻击;在 C 语言程序中,要注意对数组边界进行检查,防止缓冲区溢出攻击。
-
可维护性:
- 代码可读性和规范性:编写清晰、易读的代码,遵循统一的代码规范和命名约定,使代码易于理解和维护。例如,使用有意义的变量名和函数名,合理添加注释,将代码按照功能进行模块化组织等。
- 软件架构设计:采用良好的软件架构,如分层架构、微服务架构等,使系统具有良好的可扩展性和可维护性。例如,在分层架构中,不同层次之间职责明确,当需要对某一功能进行修改或扩展时,可以在相应的层次进行操作,而不会影响到其他层次。
-
可测试性:
- 单元测试和集成测试:编写易于测试的代码,以便能够方便地进行单元测试和集成测试。例如,将程序中的功能模块划分得足够小,每个模块具有明确的输入和输出,便于编写单元测试用例;在设计模块接口时,要考虑到集成测试的方便性,使模块之间的集成测试能够顺利进行。
- 测试覆盖率:关注测试覆盖率,通过编写全面的测试用例,尽可能覆盖程序中的各种逻辑路径和功能点,以发现潜在的问题。例如,使用代码覆盖率工具来分析测试用例对代码的覆盖情况,根据覆盖结果补充测试用例,提高测试的充分性。
五.通过捕获异常规避缺陷
1.处理数组越界异常
2.处理文件读取异常
六.本章小结
1、对于大多数软件产品而言,最重要的质量属性包括可靠性、安全性、可用性、易用性、响应能力和可维护性。
2、为了避免在1程序中引入错误,应使用能够降低犯错概率的编程实践。、
3、应始终致力于简化程序的复杂性,复杂性会使程序更难以理解,增加程序员出错的可能性,并使得程序更难以进行更改。
4、设计模式是对常见问题经过验证和测试的解决方案。使用模式是减少程序复杂性的一种有效方法。
5、应假设程序可能存在失败,并对这些失败进行管理,确保对用户影响最小。
七.个人心得体会
学习 “可靠编程” 让我收获颇丰,深感其在软件开发领域的关键价值。
在理解软件产品质量属性时,我认识到可靠性、性能等要素对软件至关重要。这督促我在编程时不仅要实现功能,更要注重软件的整体质量。就像搭建房屋,质量属性是稳固的基石,可靠编程则是精心施工的过程。
可靠编程的多种实现方法,如遵循编程规范、编写单元测试等,为我编写高质量代码指明方向。代码审查环节,让我体会到团队协作在提升代码质量上的强大力量,众人智慧能揪出个人难以察觉的问题。而异常处理教会我为程序穿上 “防护衣”,增强其应对风险的能力。
程序复杂度中的耦合概念也让我警醒,高耦合如同错综复杂的线路,牵一发而动全身,低耦合的模块独立又灵活,利于维护与扩展。
这次学习为我编程之路点亮明灯,我会将所学融入实践,努力打造更可靠、优质的软件。
附件
1.软件产品质量属性对比表
质量属性 | 定义 | 重要性 | 示例 | 提升措施 |
---|---|---|---|---|
功能性 | 软件能实现用户所需功能的程度 | 满足用户基本业务需求,是软件存在基础 | 财务管理软件准确记账、生成报表 | 充分调研需求,详细设计功能模块,加强功能测试 |
性能 | 涉及响应时间、吞吐量、资源利用率等指标 | 影响用户体验和软件可扩展性,性能差易致用户流失 | 电商平台高峰时段快速处理订单 | 优化算法,合理分配资源,进行性能测试与调优 |
可靠性 | 在规定条件和时间内完成规定功能的能力 | 保障软件稳定运行,避免故障造成损失 | 航空管制软件需极高可靠性 | 采用成熟技术,增加冗余设计,进行可靠性测试 |
易用性 | 关注用户与软件交互的便捷舒适程度 | 影响用户接受度,易用的软件更易推广 | 手机应用界面简洁易操作 | 遵循易用性设计原则,开展用户体验测试 |
可维护性 | 软件易于理解、修改和扩展的程度 | 方便软件后续升级、修复漏洞,降低维护成本 | 采用模块化架构的软件易维护 | 良好的代码结构设计,编写清晰注释,使用版本控制 |
可移植性 | 软件能在不同硬件、系统等环境运行的能力 | 扩大软件适用范围,提高复用性 |
2.可靠编程相关方法对比表
可靠编程方法 | 操作要点 | 作用 | 示例 | 注意事项 |
---|---|---|---|---|
遵循编程规范 | 制定并遵守统一代码风格、命名等规范 | 提高代码可读性、可维护性,减少错误 | Java 开发遵循阿里开发手册 | 规范需团队统一且严格执行 |
进行代码审查 | 团队成员相互检查代码 | 发现逻辑错误、安全漏洞等,促进知识共享 | 每周定期组织代码审查会议 | 审查人员需具备专业知识,审查后及时跟进修改 |
编写单元测试 | 为函数、模块编写测试用例验证正确性 | 及时发现代码错误,方便回归测试 | JUnit 用于 Java 单元测试 | 测试用例要全面覆盖各种情况 |
异常处理 | 捕获并合理处理程序运行中的异常 | 防止异常致程序崩溃,增强稳定性 | 读取文件时处理文件不存在异常 | 精确捕获异常类型,避免宽泛捕获 |
代码复用 | 复用已测试验证的代码 | 减少代码量,降低出错概率,提高效率 | 使用开源库实现常见功能 | 确保复用代码符合项目需求和质量标准 |