欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > C++学习笔记----3、设计专业的C++程序(一)---- 程序设计

C++学习笔记----3、设计专业的C++程序(一)---- 程序设计

2025/10/18 14:22:00 来源:https://blog.csdn.net/weixin_71738303/article/details/141184652  浏览:    关键词:C++学习笔记----3、设计专业的C++程序(一)---- 程序设计

        在写第一行代码之前,你应该首先设计你的程序。应该用什么样的数据结构?写什么样的类?在团队合作时这尤其重要。想像一下,你坐下来写程序,根本不知道你的同事在写什么内容的代码,是否会很诡异?

        先不管程序设计,恐怕是软件工程过程中最容易被误解与未被利用的特点了。程序员经常在没有清晰的计划之前就开始写应用:边写边设计,导致程序弯弯绕绕,复杂性增加。使系统开发、排错与维护更加困难。虽然看起来与直觉相反,但其实是磨刀不误砍柴工。

1、什么是程序设计

        开始新程序或者既有程序的新特性的第一步是分析需求。需要与客户及相关方进行讨论,在该分析阶段重要的输出物就是功能需求文档,该文档描述了新代码要干什么,但并没有解释如何去做。需求分析也可能会有非功能需求文档的输出,相比于功能需求文档,它描述了最终的系统的样子。举例说明一下非功能需求文档的内容,它描述了系统的安全性,可扩展性,可达到的性能水平等等。

        当所有的需求都收集完毕之后,设计阶段就可以开始了。程序设计或者说是软件设计就是完成程序功能需求与非功能需求的架构规格。通俗一点讲,设计就是怎么计划写程序。应该使用设计文档的格式来写设计。虽然每个公司或者每个项目的文档格式不同,但一般设计文档都会用通过的格式,包含以下两部分:

  • 项目总体细分为子系统,包含接口与子系统之间的相互依赖,子系统之间的数据流,每个子系统的输入输出,以及通用线程模型
  • 每个子系统的细节,包含将子系统细化为类,类层次结构,数据结构,算法,特定的线程模型,以及错误处理描述

        设计文档通过包含图表,描述子系统的交互与类层次结构。UML是这类图表的工业标准。当然了,重要的是设计的思考过程而不是设计文档的准确格式,还是要分清形式与内容的,形式固然重要,但没有了内容,就是买椟还珠,舍本逐末。

        通常来讲,在编码之前要尽可能地设计好。设计应该能够提供给程序员相应的框架图,根据此图,正常的程序员就可以遵循其设计开始编码。当然了,不可避免地会遇到一些一开始想不到的问题,在编码过程中需要进行修改。软件工程过程被设计成给了这些变更的灵活性。Scrum就是一个灵活的软件开发方法论,在应用开发过程周期中迭代过程的一个例子就是著名的sprints,每一个sprint,设计都可以被修改,新的需求也可以被考虑进去。

2、程序设计的重要性

        程序员总是无法拒绝尽快开始写代码的诱惑,对于分析与设计的步骤总想跳过或者马马虎虎做完就行了。看到程序编译与执行才能给你取得进步的成就感。多多少少,去做那些设计,去写你早就知道的功能需求,怎么去结构化你的程序,看起来都像是在浪费时间。还有就是写设计文档可不像写代码那么有趣。如果你想整天写文档,你不会想做一个计算机程序员!作为程序员的我自己,也是能够理解这种诱惑的,有时候也会抵挡不住,立刻开始写代码。然而,除了术简单的项目之外,这种做法总是会导致问题的出现。不管你有多少经验,在设计模式上有多专业,对C++的理解有多深,问题领域,需求,设计是你工作的一部分,没有预先的设计,是行不通的。

        如果在一个团队中每个成员干项目的不同部分,最重要的是要有一个团队成员都要遵守的设计文档。该文档也能够帮助新进的成员跟上项目设计的步伐。如果没有设计文档,新加入的成员就不知道设计在哪儿,就会修改代码,破坏未经文档化的设计,在项目过程中就会导致后面的问题。

        有些公司是有专门的功能分析师去年功能需求,专门的软件架构师去进行软件设计。这样的公司中,开发者通常只会关注于项目的程序方面。还有一些公司,开发者也要做需求收集,自己进行程序设计。有些公司是介于两者之间;可能只有一个程序架构师做大的架构决定,而开发者自己做小的程序设计。

        为了帮助你理解程序设计的重要性,还是举个例子吧,想像一下,你要在你家建一座房子,建筑公司的人来了之后,你问他们要蓝图图纸,他们说:什么蓝图图纸?我们知道我们在做什么,不需要提前计划第一个小的细节。两层楼而已,没有问题,我们几个月前刚建了一座一层的房子,按那个模型开始干就行了。

        假设这时的你满怀着不信任,但还是让建筑工人开始工作了,几个月以后,你注意到上下水管道出现在了房子的外面而不是墙体内。当你询问建筑公司这种非正常现象时,他说:“哦,这个嘛,我忘了在墙体中给上下水留空间了。对于这种新的在我大脑中闪过的干墙技术感到兴奋。在墙外面也很好啊,毕竟完成功能才是最重要的啊。”你开始对这种方法表示怀疑,但是,没有更好的方法,你只有让他们继续。

        当你对完成的房子看第一眼时,你注意到厨房没有下水管。建筑公司解释说:“我们注意到厨房没有下水管空间的时候已经干了三分之二了。为了不重新来过,我们只是 在隔壁房间加一个单独的下水管了,也可以,是哈?”

        建筑公司的解释把它翻译成软件领域听起来是否很熟悉?你是否发现你自己用了一个很“丑”的解决方案来解决像把上下水管道放到室外?例如,你可能忘记在不同线程之间共享的队列数据中包含锁,当你意识到这个问题的时候,你决定在所有乃至这个队列的地方手工加锁。当然了,你会说,这很丑,但是管用啊。这种情况直到有新人加入进来,默认锁机制在数据结构内,在对共享数据操作的双向排除失败后,制造了一个竞赛条件错误,花了三个星期才搞定。一个专业的C++程序员永远不会对于队列存取进行手工加锁,只会将其加入到队列类或者将队列类以无锁的方式使其线程安全。

        在编码之前形成正式的设计文档有助于决定每个部分都是合适的。就像建筑蓝图图纸表明了各个房间之间的关系,一起共同完成房子的需求,程序设计表明了程序各个子系统之间的相互关联性,一起完成软件需求。没有设计计划,在子系统之间就容易忽略相关性、对于重用或共享信息的可能性以及完成任务的最简单的方式。没有整体的设计,你可能就会在个人实现代码功能时陷入泥潭,失去对整体架构与目标的跟踪。还有,就是设计给整个项目成员提供 了可参考的纸面文档。如果你使用了前面提到的像Scrum方法论的灵活迭代过程,你需要在过程的每一个循环当中保持文档得到更新。有的灵活方法论指出:要在软件而不是复杂文档上下功夫。那你至少要保持设计文档在项目的大的部分与项目工作保持同步吧。我们还是坚持文档与项目一致,如果不能保持文档同步更新,要么删除,要么标志过期不可用。

        如果上面的这些依然无法说服你在编码之前进行设计的话,那我们就按你的方式来,直接写代码,看会发生什么?假设你要写一个国际象棋的程序,在开始编码之前不进行整体程序的设计,决定先进行最容易的部分,然后慢慢再做难一些,听起来不错吗?先易后难,君子之道。使用面向对象的设计思想,你决定用类来对国际象棋建模。你认为卒是国际象棋最简单的部分,于是从这里开始。考虑完卒的属性与行为后,你写了一个拥有如下属性与成员函数的类,用UML类图表示:

        在这个设计中,m_color属性表明卒是黑色还是白色,promote()成员函数执行到比赛盘的对方领域。

        当然了,按你的行为方式,你不会去用UML做出这样的图表,你会直接去写代码,去实现,很开心,很有成就感,使用这个类,你走向了下一个最容易的部分:象。考虑完其属性与功能性之后,你写了一个带有如下属性与成员函数的类:

        当然了,你还是不会去生成这些类图,你只会直接编码。然后,这时候你开始怀疑你是否做错了什么。象与卒看起来很像。实际上,其属性是一样的,大部分成员函数也一样。虽然move()成员函数的功能有可能不同,两者都需要移动的能力。如果你在直接编码前对程序进行设计,你就会意识到许多棋子其实是相类似的,你只需要将基本功能写一次就够了。我们以后再讨论面向对象的设计技巧。

        我们继续,在程序中棋子的一些特点依赖于子系统。例如,如果不知道怎么对棋盘进行建模的话,你就无法准确表达柜子类自身在棋盘上的位置。另一方面,也许你设计程序使棋盘来管理棋子,不需要知道他们的位置。再举一个例子,你怎么写一个棋子的draw成员函数而没有决定程序的用户界面?是图形界面还是字符界面?棋盘长什么样儿?这些问题不是子系统独立存在的,与其他的子系统相关联。大部分的设计工作决定了这些关系。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词