首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

关于软件工艺,C语言[不抛砖,盼引玉],该如何处理

2012-02-23 
关于软件工艺,C语言[不抛砖,盼引玉]大家好!我是一名参加工作4年的IT民工,目前在一家中型企业从事嵌入式软

关于软件工艺,C语言[不抛砖,盼引玉]
大家好!

  我是一名参加工作4年的IT民工,目前在一家中型企业从事嵌入式软件开发维护工作。我们使用的语言工具为C语言,软件平台是风河公司的vxWorks,产品为一款工业级小型终端设备。

  我在软件开发维护的工作中,发现很多bug并不是大的技术缺陷造成的,而是由于不好的代码风格造成的。而我们公司对于代码风格也有一定的规定和要求,但是各个产品组并不是很统一,感觉各有利弊。我想把我有疑问的几点提出来,希望工作经验丰富的老师能够结合自己的经验,给出一些指导。不胜感激。

  1,关于命名规则。我们采用的是 “类型+含义”的方式,比如 char cOperateType。但是有的时候名字会比较长,如果采用缩写,含义又有可能不清晰。

  2,关于头文件。头文件是否应该和实现文件一一对应?哪些东西应当放在头文件里?如果需要引用外部函数或外部全局变量,是该引用其头文件还是直接在本文件声明?各有什么利弊呢?

  3,关于封装。C的封装性比较差,但是软件工程模块化设计又要求有比较好的封装,用什么样的规则能够比较好的实现呢?现在我们的工程耦合性很强,经常是改动了1处牵动了全身。大家对于封装性都是持肯定态度的,但是苦与没有找到很好的方法,有没有比较好的规则可以遵守呢?

  4,关于数据结构的定义。我们现在基本有两种观点:一,定义一个大的数据结构,包含了主要的控制字段、数据区地址、函数方法指针等,从主函数下去,几层函数的接口都使用这个结构的指针;二,将各控制信息、数据区打散,函数方法就地使用(要求函数方法全部声明为外部)。第1种方法感觉封装性好,但是程序阅读的时候有点困难,而且调试的时候不太方便(带着一个大结构走,主机反应速度变慢);第2种方法感觉信息全部暴露。请专家予以指导。

  5,关于pclint。我们没有使用pclint,其他组有使用的。我感觉lint工具太过于严格,不知道用过的前辈有什么感受,或者有什么建议。

  另外,我们的软件规模大约30万--50万,C语言,嵌入式软件。


[解决办法]
刚刚在CSDN混,还没达到楼主的水平呢!期待以后工作了有更大的长进!30-50万,爱,对我来说还是天文呢!
[解决办法]
有本书,叫《代码大全》,讨论这方面,还不错

lint等工具自然是需要用的。lint是可配置的,可根据需要配置检查的规则,而且可在代码中通过特定格式的注释在一定范围内屏蔽lint,如果你在c代码中嵌入汇编的话可能会有用。

[解决办法]
潜力贴。。
[解决办法]
做项目,规范是最重要的,至少我认为是这样
现在我做项目,代码一般5W(在自己公司产品上开发的)

不是说自己对了就行,你必须规范一个项目,保证其它项目成员也按规范;才能尽可能的减少BUG
[解决办法]
感觉和我们公司的有点像,虽然在大的地方比较规范,但是细节上可以自由发挥..比如命名,数据结构..头文件,全局变量或函数风格各异;有时候维护别人的代码,很痛苦很无力,只能在原来基础上打补丁
[解决办法]
客观的说,你所讨论的不是语言层次的问题,而是思想层次的问题

语言的一些特性,比如继承、封装、多态,是为了实现某些思想而设计的。所以可以认为,语言和思想是相互制约,相互促进的

关系。C语言是结构化的语言,它本来就没有被设计来用于大型的程序设计,这个是和C产生的历史背景有关系的;所以才有后来

C++的产生,当然,这个是后话...

我个人觉得,嵌入式产品,C未必就比C++要弱,甚至还要更强。这个是由嵌入式产品本身的条件决定的。大多数嵌入式产品的状

况是接近系统底层,资源受限,且代码量相对来说都不大,这正是C大显身手的场合!通常代码量都不超过十万行。这个时候,用

良好的设计可以避免出现维护困难的情况,例如你说的,耦合性过大,牵一发而动全身。我觉得如果可以,重新设计一套产品的

架构,尽量的高内聚,低耦合,然后产品文档一定要齐全,科学合理的进行版本控制,应该不是很难维护

如果真的代码量很大了,那可以考虑用C++。利用面向对象的思想去组织系统。我个人觉得,C++对底层的支持不如C,C++最最强悍

的地方在于思想和库!这两个方面针对于大型或者超大型的程序来说至关重要!也是C无法比拟的
[解决办法]
C++不会比C效率低多少的,这个我确定!如果你们的低了,那可能是引用的某些库做的不好

文档的规范是非常非常必要的!!!

我曾经在日企和欧美的企业都待过,客观的说,日本人的文档规划的真的非常非常的好!而欧美的公司相对就差很多了

要是没有良好的文档做后盾,对于后期接手的维护人员来说,简直就是噩梦,很可能这个噩梦永远都都不会醒...

什么时候,软件工程真的能像建筑工程那样规范,就天下太平了!呵呵
[解决办法]
我觉得整体软件的规模不是问题,重要的是要把一个大项目切成若干个小项目/模块,每个项目/模块的功能单一,注意管理好接口,这样项目就好做了。设计的关键是模块之间的接口必须清晰、干净和唯一。
[解决办法]
楼主的问题,主要在于软件架构的设计问题。封装并不是简单地把软件划分成若干模块了事,而是要做仔细规划,规划的基本原则其实可以参照面向对象设计的那些基本原则,信息隐蔽、职责单一、开闭等等,面向对象的设计思想用C语言照样可以在一定程度上比较容易地实现。

楼主的系统代码量超过30万行,对于嵌入式系统来说,可是大型软件了,这种软件在分析阶段和概要设计的工作很重要,这两个阶段都会对软件架构产生决定性的影响。

对于这样的大型嵌入式系统软件,最起码的原则是分层原则,例如划分成硬件抽象层(设备驱动程序)、系统服务层、应用层等等,各层次之间要有一套规范定义的API,这个API应该是在公司级别通用的。各个层之间通过这些规范定义的API交换数据。API的设计基本原则就是每个API函数的功能最小化、职责单一化。例如,一个A/D采样API的职责就是简单地启动ADC采样并等待采样完成后获取并返回采样数据。这个函数通常不需要增加诸如转换成物理量值之类的额外工作。当每个接口的功能和职责都单一化之后,对各个模块的改动的影响就会大大降低。

另外,要尽量避免使用全局变量——除非因数据传递而导致严重的性能瓶颈。全局变量是导致模块间紧耦合的的罪魁祸首之一,对全局变量的一点点修改,往往就会影响到很多地方,导致代码的可维护性极差。在我主持的项目中,一般都要求设计师对全局变量的使用进行论证,只有特别必要的情况下才允许使用全局变量。即便使用全局变量,仅要尽量把全局变量的影响范围压缩,例如尽可能用static类型的仅仅作用于模块文件内部的全局变量。

楼主所在公司有能力做这么大型的嵌入式系统,应该是积累了丰富的软件代码,我认为应该考虑建立全公司通用的软件标准代码库,包括标准的API及其在一些公用平台上的实现。有了这些API,软件的移植工作量将会大大降低,会大大提高软件开发的效率。



对于楼主的问题,仓促之间,就简单地说这么多吧。

另外对于9楼“C++对底层的支持不如C”的说法表示异议,C++完全兼容ANSI C(C90以前的版本),C语言对底层的支持C++同样支持。而且我认为对于大型软件的设计,C++的设计效率和简易性远远高于C,API定义就是最明显的例子。我在定义通用的设备驱动程序接口API时,用C语言在语义表达、命名等方面就遇到了不小的麻烦,而用C++轻易就完成了,C++的基于类的API从表达、实现等方面远胜于C的函数型API。当然C语言的运行效率比C++高一些,但是这主要体现在函数调用方面,因为C++的多态性实现机制会带来一些额外的开销。但是对于那些需要频繁调用并且会导致运行效率瓶颈的代码,可以用C实现,C++和C是可以混用的。

最后对于楼主提出的用一个大的结构体从顶层带到底层的做法我表示不赞同。这种做法恰恰违反了封装和隐蔽的原则,除了导致大的运行开销、可读性变差之外,也会导致代码之间的关联性过强。好的做法是个用个的数据结构,这样各个单元在测试和维护的时候都会有很大的便利,而且单元模块之间的耦合性可以降低。一系列规划良好的小数据结构将会带来长久的好处。
[解决办法]
楼上的,你书确实看了一些,但是实践性差了,所以对书本的东西理解的深度还不够

呵呵,如果你非说用C++中那部分兼容C的来当C++用,那我也无话可说,但我印象中,这是阉割C++!

至于你说的其它方面,尤其是这句“因为C++的多态性实现机制会带来一些额外的开销。”,简直有玩笑之嫌了,试问C++中所有

的函数调用都与多态有关吗?搞笑一样
[解决办法]
C嵌入工程中,全局变量的大量存在是个事实。

名字长点就长点吧,缩会造成缩的想法都不一样,乱七八糟。

头文件看需求。封装也要具体问题具体分析了。

“大数据结构”不好。
[解决办法]
17楼,我什么时候说过“用C++中那部分兼容C的来当C++用”,我只是告诉你C能做到的事情,C++照样可以做到,关于底层的操作C++不比C差,这根阉割C++有什么关系?找你这么说,C++就不能使用指针来直接操作内存地址?你当C++是JAVA啊!搞笑!事实上,C语言唯一能和“底层”扯上关系的,也就是指针了。

至于你提出的“试问C++中所有的函数调用都与多态有关吗?”,我和曾说过C++所有的函数都跟多态性有关?我只是在告诉楼主C++中涉及到多态性的使用会带来额外的开销,你仔细看清楚我的原话。另外,多态性是OO语言的最重要特性,为了实现OO原则,没有多态性的支持是不可想象的。用C++编写的大型代码中,通常会大量用到多态性,这肯定会带来额外的函数调用开销,你自己研究一下C++的对象模型就知道了。

再次指出你一处错误:你说的“C语言是结构化的语言,它本来就没有被设计来用于大型的程序设计”,才真是搞笑。你以为UNIX当初是用什么语言编写的?C++出现之前的大型操作系统几乎都是用C编写的!大型程序的设计与语言没有本质的联系,关键是设计思想,只要使用了好的设计思想,哪怕使用汇编语言照样可以写出高质量的大规模程序来(当然工作量也很可观)。若是设计思想不好,即便使用C++这样的OO语言,写出的代码照样可能是很糟糕的。这就像武功,一流高手用一根树杈就可以打败一个手持钢刀的末流武师。

17楼别把C++看得那么高,C++源自C,用OO思想重新实现罢了,没什么大不了的。其实用C++能够做到的,C照样可以做到,只不过做起来比较麻烦而已。别老拿自己那点实践来说事儿,你的实践那么好,倒是给楼主出点有用的实践的主意啊。搞笑~
[解决办法]
再跟楼主楼嗦几句,楼主和同事们都是汇编语言和C语言出身,这不要紧,用这两种语言照样可以写出出色的作品。正如我前面所说,软件设计的关键不在语言,而是设计思想,灵活运用好的设计思想,用C语言照样可以写出很漂亮的大型软件。关于代码风格的问题,你们公司有必要对此制定严格的、详尽的、统一的规范,尽可能减少各个项目组乃至开发人员之间的代码编制风格的差异,否则后患无穷。

另外我再次建议楼主的公司规划一下软件标准库的事情,安排人好好研究一下以往的项目中哪些应用和代码可以抽象、提炼出来作为标准件、通用件,被全公司共享。这种事情一开始花时间,但是一劳永逸,会带来长远的好处。
[解决办法]
基本同意16楼兄弟的回答。

建议楼主还是要看看,面向对象的编程思想及设计模式。

设计模式虽然是面向对象的。

但是,有很多思想面向过程和面向对象是一样的。


[解决办法]
OK.临上班之前,再回你一贴

1、UNIX最早是用汇编写的,而不是C写的。写UNIX的人叫Thompson。后来Ritchie发明了C语言,然后Thompson才用C重写了UNIX

2、受限于当时的软硬件条件和项目的大小,C只是被设想用来支持十万行数量级的程序,根本就没考虑到后世会有百万行程序的

出现,所以那个时候根本就没考虑面向对象

3、你别把操作系统和操作系统内核搞混了,操作系统中用C和汇编的部分,只是内核而已。别的部分可以用但不是必须用,所以

很多上层应用是多语言集合体

4、我在前面已经说了,语言的产生是为了适应特定的环境,你非说用C++兼容的部分能完成C的功能,我也无话可说。就像说铡刀

也能杀鸡一样,客观的说,确实能!但是...我至今为止还没见到...

5、别把面向对象看成是完美的解决方案,它本身也有N多的问题,也并是不能解决所有的问题。根据哲学中矛盾的对立与统一理

论:这个世界中的事物,凡有一利,就必有一弊!你要是不知道开阔思路,可以去搜搜“面向语言编程”,当然,我没说这个就

是将来的趋势,但至少它是一种开阔人的思路

我最近很忙,实在是没时间在这上面吵架。只是奉劝你一句,要对自己说出的话负责,不要随便看到某句话就贴上来,你要晓得,

凡是你贴上来的东西,受影响的就不仅仅是你自己了!

下面是你的回复吧,再仔细review一遍,尤其是带颜色的部分

另外对于9楼“C++对底层的支持不如C”的说法表示异议,C++完全兼容ANSI C(C90以前的版本),C语言对底层的支持C++同样支持。而且我认为对于大型软件的设计,C++的设计效率和简易性远远高于C,API定义就是最明显的例子。我在定义通用的设备驱动程序接口API时,用C语言在语义表达、命名等方面就遇到了不小的麻烦,而用C++轻易就完成了,C++的基于类的API 从表达、实现等方面远胜于C的函数型API。当然C语言的运行效率比C++高一些,但是这主要体现在函数调用方面,因为C++的多态性实现机制会带来一些额外的开销。但是对于那些需要频繁调用并且会导致运行效率瓶颈的代码,可以用C实现,C++和C是可以混用的。


[解决办法]

探讨
能给介绍本关于 面向对象的书吗?
我没有系统学习过C++

另外,关于设计模式的书也很多
能给推荐一本吗?

精力实在有限,只能利用工作之余学习。。。

[解决办法]
1,关于命名规则。我们采用的是 “类型+含义”的方式,比如 char cOperateType。但是有的时候名字会比较长,如果采用缩写,含义又有可能不清晰。


-----------------------------------------------------------------
这叫骆驼命名法,但我觉得前面表示类型的字符没必要了,特别是类型名比较多的时候,会很难看,只需写单词就行了,但不要用缩写,缩写是大忌。

单词的含义应尽量贴近其类型,尽量让阅读者看到单词就能捉摸到大概的类型。例如计数器就用Counter,标志用Flag不要用token等等。



2,关于头文件。头文件是否应该和实现文件一一对应?哪些东西应当放在头文件里?如果需要引用外部函数或外部全局变量,是该引用其头文件还是直接在本文件声明?各有什么利弊呢?
-------------------------------------------------------------
宏、typedef、结构和联合模板以及函数声明都应放在头文件里,外部函数和变量使用的时候再声明,不要放头文件里。




3,关于封装。C的封装性比较差,但是软件工程模块化设计又要求有比较好的封装,用什么样的规则能够比较好的实现呢?现在我们的工程耦合性很强,经常是改动了1处牵动了全身。大家对于封装性都是持肯定态度的,但是苦与没有找到很好的方法,有没有比较好的规则可以遵守呢? 

4,关于数据结构的定义。我们现在基本有两种观点:一,定义一个大的数据结构,包含了主要的控制字段、数据区地址、函数方法指针等,从主函数下去,几层函数的接口都使用这个结构的指针;二,将各控制信息、数据区打散,函数方法就地使用(要求函数方法全部声明为外部)。第1种方法感觉封装性好,但是程序阅读的时候有点困难,而且调试的时候不太方便(带着一个大结构走,主机反应速度变慢);第2种方法感觉信息全部暴露。请专家予以指导。 
------------------------------------------------------------------------
你们怎么没想到ADT呢??ADT就是专门解决数据的封装的。建议你们看一本书,叫《C语言接口与实现》,讲ADT的经典。
[解决办法]
比较同意16楼的说法,另说下我的感受,头文件和C文件对应出现组成模块,头文件里定义对外接口,也就是外部需要的才在头文件里出现,其他的数据以及函数都封装到C文件里,把已经成熟的模块转成库文件,这点非常重要,分工合作的时候只需要调用别人的库文件即可,至于数据结构尽量各自模块定义各自的,只有必须外部知道的才在头文件中传递出去,另最好有个Gloabe.h来组织所有的头文件,避免每个C文件里都包含一堆头文件。模块内部也可以分开两对头文件和C文件分别实现应用层和驱动层,驱动层负责给应用层提供接口,应用层负责给其他模块提供接口
暂时只能想到这么多,后面的朋友继续补充。
[解决办法]
底层编程,至少现在的大多数情况下,C++是不适用的,硬件适应不了
用C就不要考虑什么面向对象了,面向接口是更好的选择
至于全局变量和命名冲突,只要规划好,再定义适当的宏来处理就可以了
至于软件规模比较大,我想WINDOWS就是最好的参照范例,关键还是组织
[解决办法]
1、如果公司或项目组内的人水平很高,规范性的约束(比较命名规则等)比较难实行,而且比较容易造成反作用;如果人员水平一般,规范倒是很重要。正所谓先僵化再优化...

2、文档这个东西,在很多情况下,后期改变代码一般都没有时间没有精力去刷新文档,所以一般只具备指导意义。后期维护的人可能简单看一下,最终要理解的还是代码本身。


[解决办法]
请查阅代码大全2的相关章节
[解决办法]
首先大的工程需要层次感比较清晰。其次由于是团队合作,不可能每个人的编程规范都一样,但重要的是每个人负责提供的接口要方便他人使用。
[解决办法]

探讨
1、UNIX最早是用汇编写的,而不是C写的。写UNIX的人叫Thompson。后来Ritchie发明了C语言,然后Thompson才用C重写了UNIX

[解决办法]
呵呵,好的,那就一点一点玩

1、我之所以说UNIX和OS kernel是想说明,UNIX的内核和其它OS的kernel其实并不大,所以它们都是用C加上汇编来写。这点可以

证明C到今天为止,基本还依然停留在当初贝尔实验室设计它所应用的领域的初衷

2、API和service layer属于上层应用,它们不属于OS的kernel,而且因为底层已经有了OS kernel的支持,它们可以用C++来开发

了,这个有两点原因:一是Apllication层的程序可能会比较大,远远大于kernel的代码量;二是C++的面向对象特性可以更搞笑

的开发。当然,这个也是有局限性的,比如开发系统服务,可能选C++的要多一些,而开发基于网络类型的ERP系统,C#和JAVA可

能会更好一些。注意,我没有说用C不行,但是这个要考虑开发成本和实现起来的复杂程度,所以此处C不适合

3、你比对一下当今主流的大型机,PC,嵌入式等等的OS kernel,看看用C和用C++的比例是多少?我再一次强调,C++最强的地方

在于库和思想,而kernel不大,很显然库和思想的依赖性都不大

4、既然你不会分析你的原话,那我来给你分析。

而且我认为对于大型软件的设计,C++的设计效率和简易性远远高于 C,API定义就是最明显的例子。我在定义通用的设备驱动程序接口API时,用C语言在语义表达、命名等方面就遇到了不小的麻烦,而用C++轻易就完成了
你是想说,C提供的API不好用,而用C++封装以后就好用了,对吧?那你想过没,你的API是谁提供的?用C++封装完以后的东西叫

什么呢?C++封装完了以后的,就叫库了!比如MFC,封装的就是Win32 API,可你想过没,Win32 API是谁提供的?如果没有

Windows Kernel提供这些API,你的C++还怎么玩?像你说的,用C++中兼容C的部分自己写,那这和C有啥区别了?微软和各个OS厂

商就傻到不知道这一点吗?另外再提醒你一点,C和C++的编译器其实有很大很大的不同,你要是自己写过.so库就会知道

C++的基于类的API 从表达、实现等方面远胜于C的函数型API。
1、这里有几个疑问,啥叫“基于类的API”?其实说白了,你想说的就是成员函数对吧?为啥成员函数的表达、实现就胜于C的

API?其实你还是想阐述封装好了的类库对大型程序的框架设计很有好处,很可惜,你的思想依然是建立在“类库”的基础之上!
2、当然C语言的运行效率比C++高一些,但是这主要体现在函数调用方面,因为C++的多态性实现机制会带来一些额外的开销。但是对于那些需要频繁调用并且会导致运行效率瓶颈的代码,可以用C实现,C++和C是可以混用的。
我最BS你的就是这句话,说的实在是太没水平了。错误百出!

你凭什么就说C的运行效率会比C++高,就是牵强一点,你至少也要加个限定条件吧?

而且你竟然说体现在函数调用方面,因为C++得多态性等等,那我问下,C++多态产生的两个必要条件是什么?你要是不知道,我



来告诉你:一是有虚函数,二是要有基类的指针或者引用绑定在派生类的对象上。那如果我不用多态的特性的?C++的函数调用效

率是否还比C高呢?

还有,从底层的角度看函数调用,都有哪些步骤,简单的说就是返回值压栈,参数压栈,那C++在哪一步比C的效率低了?您给讲讲
[解决办法]
听你们吵架,

我觉得那些写内核的人之所以用c,是因为不能保证大家都懂c++
要是在linux内核里面出现一个超级模版,90%的人都看的迷糊,那也是大煞风景

linux嵌入式c,linux 内核写的不错,busybox也写的不错,

c语言的程序, ffmpeg写的不错,这几个咚咚,我都初略的浏览过

和 c++的程序,boost库比起来,更清爽,简洁。

我估计写c++的人要笨一点。。。

楼主说的:
软件规模大约30万--50万

我估计要是30~50万是一坨,那估计也是个垃圾

要是分层,分模块,一个小咚咚也没多少

我也写嵌入式,公司就我一个人写,那没关系,c++里面什么前卫,用什么,boost/tr1啥都上,也没啥速度问题

c/c++的速度是个伪命题,测试的时候,写些小函数测的挺开心,得出各种结论,编码起来,不知道多占多少cpu了,也没人管的。






[解决办法]

探讨
涉及到具体产品,那些讲编程的书基本上用不上了,最好的方法就是反复开发,根据俺的经验,每重复开发一次就规范一次。


[解决办法]
引用:
涉及到具体产品,那些讲编程的书基本上用不上了,最好的方法就是反复开发,根据俺的经验,每重复开发一次就规范一次。

这种方式,在个人编程初期,我觉得是对个人进步有帮助的.但对公司而言,代价确实太大了.
本人有过这种经历.项目发布第一个版本.程序全部重构.对个人而言,有较大的进步.学到了不少.对公司而言,需要一点时间.

不过还是尽量少这样做.

热点排行