C++项目开发指导(新员工培训材料)

        (注:这是一份给新员工的培训材料,集合了实际工作的经验和教训,不一定具有普适性。这份东西大概写于2014-1016年,不涉及之后的社会新气象。特别需要强调的是,这是面向新员工的培训,重点在于破除学习阶段形成的幻觉、了解工作和学习的不同。本文中所有“注”都是本次发表时增加的

目录

一、序-学以致不用

二、软件工程

2.1软件工程的目标和手段

2.2最基础的要求:让其他人看懂

2.3即使没有过程管理

三、可维护性

四、开发环境与工具

 4.1花一些时间学习工具软件的高级特性

4.2使用版本管理软件

4.3没有工具可用时:用最原始的方式工作

4.4常用工具软件

4.5基本的工作方式

五、兼容性

5.1主机差异

5.2编译器差异

5.3版本差异

5.4第三方软件

六、编码

6.1遵循编码规范

6.2首先考虑可读性,然后再优化

6.3多花精力在代码结构设计上

6.4避免使用不兼容的代码

6.5记住:出错处理是编码中最大的工作量

6.6用Interface的标准设计类

6.7避免使用C++的降低可读性的特性

6.7.1避免使用IO流

6.7.2避免使用异常

6.7.3避免使用同名函数-全项目范围

6.7.4避免使用单参数构造函数

6.7.5避免使用运算符重载

6.7.6避免滥用类继承

6.8保留测试代码和数据

七、继续学习的指引

7.1自行学习的书籍

7.2编程规范

7.3具体项目的开发指南


一、序-学以致不用

        编程这种活计,是一种技术活,是非常依赖经验的。经验之中最重要的经验是,最好的技术不是最炫的技术而是最熟悉的技术。

        作为商业软件的开发者,编码的目标是为了实现需求、更好地实现需求以及有限地实现未来的需求。

        “学习”不是商业软件开发本身的内容。“学习”包括但不限于这些东西:最新版本的C++语法(比如C++11),时下时兴的开发库(比如ACE,曾经时兴),最新的开发工具,等等。

        “学习”当然是非常重要的事情,但是只有少数人明白,“学以致不用”是比“学以致用”更高的境界。

        不同的技术有不同的适用场合,不同的项目有不同的适用的技术(放弃所有不适合的技术)。脱离具体要求的“最佳”技术是不存在的。

        必须不断地学习才会获得在不同的技术中做出选择的能力。

        技术人员追求的境界是“广”和“专”,但是只有极少数人可以同时做到广和专。

如果没有能力做到“广”,就请“专”。如果没有能力做到“专”,请改行。广而不专做不了程序员。

        我们的绝大多数项目都是工程性项目,就是按照特定的要求开发一套东西然后部署在给定的硬件之上最后持续地提供支持。

        具体项目有具体的硬件和软件条件,程序员大多数时候没有选择权,只能在给定的硬件和软件条件下编程。

        大多数项目需要在多个平台下运行,最好从一开始就考虑兼容问题,后期再考虑移植是个噩梦。

        学院里倾向于研究最新的技术,但是在我们这里,不得不为了兼容性而放弃很多新特性。

        通俗地说,就是一句话:学习和生产是两回事

二、软件工程

2.1软件工程的目标和手段

        目标:交付代码正确的符合功能和性能要求的软件

        手段:文档、测试和评审

        

        测试已经能够验证代码是否正确(无BUG)、功能和性能是否符合要求,为什么还需要评审呢?这是因为测试只能验证最终结果,不能保证开发过程顺利,也不能保证代码质量,更不能代码的可维护性。

         对于一个孤立的项目,可维护性可能不是短期目标的一部分,但是对于绝大多数情形而言,软件交付以后都是需要维护的,因此可维护性是很重要的。

        对于一个软件开发组织而言,不同项目总是有各种可以借鉴、重用的地方,缺乏良好组织的代码很难被其他项目利用。

        评审包括对各阶段文档的评审和对代码的评审。即使一个软件开发组织完全是无管理的开发,一个优秀的程序员也会自己留下一些文档,同时也会不时地修改自己的代码,而且一定会留下一些自己的可重用的代码(据说每一个程序员都会有一个自己的socket类)。

2.2最基础的要求:让其他人看懂

        对于代码的要求有很多:正确、高效、节省空间、可靠、易读。

         这些要求多数是是互相冲突的。

         “正确”当然是个首要的前提,然而并不容易实现,“没有BUG”早已是个传说。

        “高效”和“节省空间”通常是对立的,我们的系统的很多部分对这两方面要求都追求极致。这要求很高的编程技巧,同时也带来复杂难懂的代码。

         “可靠”的代码不会犯错,能正确处理各种罕见情形,必然会变得冗长低效。

         “易读”的代码是别人能够看懂的代码,“高手”写出的代码固然可能是晦涩难懂的,然而“低手”缺乏正确逻辑和设计的代码才是最难以理解的。

         我个人认为代码的可读性是首要的要求,因为破坏可读性的因素最常见的因素就是糟糕的代码结构、不自然的功能划分,这代表程序设计能力低下。

         良好的设计是完成“正确、高效、节省空间、可靠、易读”的基础,而设计能力是各种编程技术和逻辑分析能力的综合。

2.3即使没有过程管理

        即使没有严格的过程管理……(注:我诚实地口头告诉他们“我们的CMM证书跟你们无关”

        仍然应该尽可能向软件工程靠拢,尽量提高开发质量。

        尽可能多地留下一些“有价值”的文档。

三、可维护性

        由于公司绝大多数项目都是开发、维护一体的,甚至直接参与运营,因此项目的可维护性非常重要。

         可维护性除了靠良好设计来保证之外,代码的可读性是对编码人员的最基础的的要求。

         我们建议把可读性放在“高效”和“节省空间”之前,作为优先原则。

四、开发环境与工具

        (注:这部分与具体企业和项目关系很大,越是大项目,历史包袱越重

 4.1花一些时间学习工具软件的高级特性

        现在的开发工具越来越强大,也需要越来越多的学习时间,但是相对于更强大的工具带来的高效,学习工具所需的时间并不算多,特别是像VS这样以容易使用著称的软件。所谓磨刀不误砍柴功,VS肯定是一把好刀。自从VS2010以来,不再需要插件便可以轻松发觉所有的语法错误,基本上都能一次性编译通过(当然,逻辑问题是工具发现不了的)。

        多数软件都有很多高级特性用来方便用户,不要满足于基本的使用,花时间研究一下工具软件的高级特性能够很大地提高生产力。

        越是功能强大的软件界面越是复杂,于是很多人宁愿使用简单的工具,好吧,这算价值观不同吧。

4.2使用版本管理软件

        我们所用的版本管理软件是SVN。

        不论你的项目是否使用版本管理技术,你都应该为自己使用一个独立的版本管理软件。如果你觉得你的历史代码是无关紧要的,你不用继续往下看了。

        有时候修改代码过于复杂或者具有尝试性,为了避免使项目的正式版本库过于混乱,你可能会考虑只在最终完成以后才提交给项目正式库,之前只在自己的私有库里面提交。

        你还会有一些私人的代码,比如自己的练习,有个版本控制比没有版本控制好。

        VSS和SVN是两个互不干扰的版本控制软件,可以同时在相同的目录下工作。

        VSS和GIT也互不干扰。GIT和SVN是否互不干扰有待考察。

        VSS在win10正式版中仍然可以良好运行,虽然需要下载较早的.net2.0库。

        (注:VSS-Visual SourceSafe已经彻底淘汰了,现在免费版本管理的主流就是SVN和GIT

4.3没有工具可用时:用最原始的方式工作

        具体项目的开发环境受制于具体的硬件和软件条件,有时候主机上没有安装调试工具,或者程序没有用调试开关编译,或者程序太复杂以至于使用断点调试非常困难,只能通过增加调试代码来发现问题。

        调试工具dbx或者gdb有时候很有帮助,但是并不是必须的。

        目前的系统中一直存在一个全局的调试开关,可以动态地打开或关闭调试代码。对于我们这种边生产边维护的系统,使用宏断言的机制并不适合。

4.4常用工具软件

        (注:这部分时代感很强,当时去IOE尚未完成

        推荐使用的编程工具是Visual Studio 2010以上版,免费的express版就足够了,毕竟我们只是编辑代码。借助一些插件,其他一些源码编辑软件也可以胜任。但是,过去几年来,最好的C++编码工具一直是Visual Studio,没有之一。

        UltraEdit,快速查看和修改代码的工具,可以直接打开ftp服务器上的文件。借助插件也有很强大的能力。

        vi,UNIX上的文件编辑命令,最直接的工具,仅在需要立即查看和简单修改代码的情况下使用。维护人员可能需要用这个。完全可以用CuteFtp的编辑功能代替。

        CuteFtp,FTP工具,注意传输模式,用错了传输模式会导致文件错误。

        telnet,windows自带的telnet工具,足够强大,但是很多人仍然喜欢其它的telnet工具。

        SecureCRT,连接linux的工具。linux通常不安装传统的telnet服务器,而是安装更安全的终端服务(ftp也换用了安全的ftp,不过CuteFtp都支持)。

        TortoiseSVN,SVN客户端。SVN是上级母公司规定的版本管理工具。

        另外还需要oracle客户端和开发工具,大多数人用的是TOAD或者SQL Developer,前者适合C++程序员,后者适合数据库开发人员(以编写PL-SQL为主要工作)。

4.5基本的工作方式

        (注:哈哈哈哈,我们相当得原始

        SVN管理版本

        windows编辑

        ftp上传

        telnet编译运行

五、兼容性

        我们的程序可能在四种机型上运行:IBM、HP、SUN的小型机和运行Linux的PC-SERVER,由此引发了普遍性的兼容性问题。

         主要系统最初在三种小型机上运行,后仅在IBM上运行,目前正在试图移植到Linux上。

         小型项目最初可能只在一种机型上运行,然而经常会在后来要求移植到其他机型上去。

         在最终完成全部迁移到linux以前,兼容性一直是必须考虑的。

5.1主机差异

        主机的差异具体体现在下面几个方面(STL的差异属于编译器差异):

        系统头文件不同

        函数参数不一致(比如文件和网络函数)

        函数功能细节不同(比如信号函数)

        函数不同(linux通常有较多新函数)

        支持的信号不同

        动态链接实现机制不同(问题主要出在IBM上)

5.2编译器差异

        由于主机机型不同,编译器也就不相同(理论上g++也可以安装在三种小型机上,但是没有这样做,理由很多)。IBM和HP是老牌厂家,他们的编译器缺乏对C++新特性的支持,STL也是很老的版本,甚至不支持allocator的一些特性(在SUN上开发的代码拿到IBM和HP上无法编译,导致一项很有价值的升级失败)。

        编译器的差异体现在下面几个方面:

        编译命令和参数不同

        标准头文件不同(不带后缀名的头文件)

        库交叉依赖支持性不同(g++不支持两个库交叉依赖)

        部分类已经废弃(strtream等)

        容器的内存特性不同(如vector最少申请1024个空间,导致极大的内存)

        模板新特性不支持

        部分语法差异(for变量声明差异,typename的使用,using的使用)

        警告不同(由于多数警告确实意味着潜在的BUG,建议在所有平台打开所有警告)

5.3版本差异

        同一个厂家的机型因为系统版本不同也会有所差异,目前已知SUN和HP新机型的编译参数与旧机型不同,不过这问题不大,只需要修改一个配置文件即可。

5.4第三方软件

        谨慎使用第三方软件,由于前面所述的兼容性问题,第三方软件可能是一个隐藏的炸弹——当需要移植的机型不支持这个第三方软件的时候,这可能造成灾难。

        第三方软件也会给其他的维护人员造成困难。

        借助开源软件永远是一个最有诱惑的解决方案,但并不总是正确和容易的方案(版权问题另议)。

六、编码

6.1遵循编码规范

        所有的编码规范的内容都包含代码格式、避免易错代码、避免低效代码几个部分,大多数都应该被遵守。

        的确存在一些编码规范是有争议的,这是需要结合实际情况考虑的。

        C++标准本身就存在巨大的争议,是追求代码漂亮、高效还是追求不易出错,不同的人有不同的选择。

6.2首先考虑可读性,然后再优化

        后期改善可读性的难度很大。实际上,如果代码可读性很差,优化的难度也很大。

6.3多花精力在代码结构设计上

        好的代码结构设计是可读性的基石。浅显的流水账代码当然也是“可读”的,但是你很难读到有价值的信息。

6.4避免使用不兼容的代码

        即使当前只为单一机型开发。

        宁愿使用朴实一些但是兼容的代码而不使用最新的精彩的特性。

        尽量使用老版书籍而非新版,这是一个无奈的选择……在我们仍然使用IBM的时候。

6.5记住:出错处理是编码中最大的工作量

        一个一行的函数调用也许需要20行代码来处理各种不同的出错情形,即使时间紧迫,无论如何,至少要判断函数返回是否正确。

        顺便的,尽可能把函数设计为返回bool值,可以避免写错了判断代码。

6.6用Interface的标准设计类

        总是用接口标准来设计类能使你抓住设计的精髓——接口的合理性而不是内部实现。

        从接口的角度来思考能使你正确地划分类和层次。

        经验表明,草率的设计迟早会被发现问题,而良好的设计给重用和重构带来极大的便利。

6.7避免使用C++的降低可读性的特性

6.7.1避免使用IO流

        (注:这里主要谈的是数据输入,因为系统主要是处理文件,至于输出,cout是不可能不使用的

        虽然IO流是C++课程的重要一部分,IO流在实际软件开发中的价值却不大,除了日志输出这样没什么细节要求的场合,大多数输入输出都不是IO流发挥作用的场合。

        IO流处理格式化输入输出的问题在于,格式错误是程序必须处理的部分,而IO流不能处理格式错误。

        绝大多数程序中的输入处理方式是按行读取,然后分解,判断格式是否正确。

6.7.2避免使用异常

        进入C++标准的是exception而非interface是个悲剧。

        异常的支持者认为应该使用异常,但是很少有人能够合理地使用异常,而且异常导致不能仅仅通过上下文顺序寻找来理解代码,这对于代码维护是一堵墙。

6.7.3避免使用同名函数-全项目范围

        当需要替换一个函数或者改变一个函数的行为的时候,为了快速发现函数的影响范围,立即搜索到函数的所有调用位置是很重要的,此时你会立即意识到本条建议的价值。

6.7.4避免使用单参数构造函数

        单参数构造函数会导致自动类型转换,这可能引起及其晦涩的BUG,特别是系统中大量存在与string的自动转换时。此问题曾经在系统中引起了一个BUG,费了很大劲才解决。

6.7.5避免使用运算符重载

        运算符重载有助于写出简洁的代码,但是出问题的时候很难快速查出函数被调用的地方,因为完全无法使用文本搜索功能。

        目前开发工具的发现函数调用点的功能很糟糕,所以最好还是避免使用无法用文本搜索来发现的函数(建议避免使用IO流也有同样的原因)。

6.7.6避免滥用类继承

        继承被毫无疑问地滥用了,绝大多数使用继承的场合应该使用“包含”,一小部分应该直接修改基类,只有被称为接口的才是正确的使用继承的场合。

6.8保留测试代码和数据

        写程序的时候总是要自我测试,测试用的代码和数据都不应该丢弃,而应该作为项目产出的一部分,毕竟,修改和维护是不可避免的。而且,在我们这里,通常维护人员还是你自己。

七、继续学习的指引

7.1自行学习的书籍

        一本关于UNIX/LINUX编程的书

        一本关于UNIX命令和shell的书

        一本C++教材

        一本C++代码设计的书

        一本面向对象设计的书

7.2编程规范

        几份不同的编程规范,由于并未严格实施,因此都可作为参考。

7.3具体项目的开发指南

        不同的项目有不同的公共库和开发习惯,这是我们正在努力统一的。

(这里是结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/110768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins+vue发布项目

在Jenkins 中先创建一个任务名称 然后进行下一步,放一个项目 填写一些参数 参数1: 参数2: 参数3:参数4: 点击保存就行了 配置脚本 // git def git_url http://gitlab.xxxx.git def git_auth_id GITEE_RIVER…

微服务拆分的思考

一、前言 前面几篇文章介绍了微服务核心的两个组件:注册中心和网关,今天我们来思考一下微服务如何拆分,微服务拆分难度在于粒度和层次,粒度太大拆分的意义不大,粒度太小开发、调试、运维会有很多坑。 二、微服务划分…

面试知识点--基础篇

文章目录 前言一、排序1. 冒泡排序2. 选择排序3. 插入排序4. 快速单边循环排序5. 快速双边循环排序6. 二分查找 二、集合1.List2.Map 前言 提示:以下是本篇文章正文内容,下面案例可供参考 一、排序 1. 冒泡排序 冒泡排序就是把小的元素往前调或者把大…

xray的使用

不需要扫描 点击 双击xray 1.打开 2.使用 主打扫描 3.被动扫描 网站 与 Burp 联动 - xray 安全评估工具文档 双击 xray cmd xray_windows_amd64.exe webscan --listen 127.0.0.1:7777 --html-output text.html 1.bp 2.这道这个 3.配置 xray 改为* 4.代理

一些ECharts配置

基于vue3&#xff0c;EChart5.4.3版本 Line <script setup lang"ts"> import {onBeforeUnmount, onMounted, ref, watch} from "vue" import {useEcharts, type ECOption} from "/composables" import * as echarts from "echarts/c…

CSS3 网格布局

CSS3 网格布局&#xff08;CSS Grid Layout&#xff09;是一种强大的布局方式&#xff0c;用于创建复杂的网页布局。它允许你以网格的形式将页面划分为行和列&#xff0c;然后将内容放置在这些行和列的交叉点上。以下是 CSS3 网格布局的基本概念和用法&#xff1a; 1. **创建网…

C++中统计代码的运算时间

在C中&#xff0c;有几种方法可以用来统计代码的运算时间&#xff1a; 使用std::chrono库&#xff1a; C11引入了chrono库&#xff0c;用于处理时间相关的操作。通过使用std::chrono::system_clock和std::chrono::duration_cast&#xff0c;可以很容易地测量代码段的执行时间…

全志A40i PRREMPT-RT Linux平台搭建IgH环境

1、编译安装内核 参考创龙开发板官方文档&#xff0c;在menuconfig中把gmac设置成M&#xff0c;方便卸载原始gmac驱动&#xff0c;然后加载优化后的实时网卡驱动 2、编译IgH 把IgH主站代码放到开发板上&#xff0c;进行配置编译(配置和编译可以参考网上ubuntu…

tensorrt安装使用教程

一般的深度学习项目&#xff0c;训练时为了加快速度&#xff0c;会使用多GPU分布式训练。但在部署推理时&#xff0c;为了降低成本&#xff0c;往往使用单个GPU机器甚至嵌入式平台&#xff08;比如 NVIDIA Jetson&#xff09;进行部署&#xff0c;部署端也要有与训练时相同的深…

python学习7

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

Ansible的debug模块介绍,fact变量采集和缓存相关操作演示

目录 一.debug模块的使用方法 1.帮助文档给出的示例 2.主要用到的参数 &#xff08;1&#xff09;msg&#xff1a;主要用这个参数来指定要输出的信息 &#xff08;2&#xff09;var&#xff1a;打印指定的变量&#xff0c;一般是通过register注册了的变量 &#xff08;3&…

GEE:对二值图层进行腐蚀和/或膨胀操作

作者:CSDN @ _养乐多_ 腐蚀和膨胀 是数学形态学图像处理中的两个基本操作,用于修改和分析二值图像(包含只有两个像素值的图像,通常是黑和白)。这些操作可用于处理遥感图像、地理信息系统(GIS)中的栅格数据以及其他领域的图像处理。 腐蚀(Erosion):腐蚀是一种用于缩小…

电脑出现关于kernelbase.dll文件找不到的情况,有什么办法可以解决?

在使用电脑中&#xff0c;突然提示找不到kernelbase.dll&#xff0c;这时候应该怎么办呢&#xff1f;出现这样的问题&#xff0c;有神办法可以解决。看到有小伙伴在问这个问题&#xff0c;那么今天就带大家了解一下这个文件&#xff0c;同时教大家如何解决kernelbase.dll丢失的…

最佳买股票的时机------题解报告

题目&#xff1a; 暴力双循环会时间超限 一次循环&#xff0c;不断更新min和sum值 时间复杂度为O(n),空间复杂度为O(1) 写完之后看了一眼题解&#xff0c;发现没有更好的方法 public int maxProfit(int[] prices) {int sum 0,minprices[0];for(int i1;i <prices.length;i…

Python【猜拳游戏】

猜拳游戏&#xff1a;石头、剪刀、布的游戏 代码如下&#xff1a; 双人对战&#xff1a; choices ["石头", "剪刀", "布"] player1_score 0 player2_score 0while True:# 玩家1进行选择player1_choice input("玩家1请出拳(石头、剪刀、…

乙酰基四肽-3/Acetyl Tetrapeptide-3——刺激毛囊,长出新头发,有效防止秃头

社会对头发很着迷。从圣经人物参孙&#xff08;他从头发中获得力量&#xff0c;并说如果剃光头他就会失去力量&#xff09;&#xff0c;到社交媒体上无休无止地谈论名人的标志性风格&#xff0c;头发是一个永恒的话题。 为什么痴迷&#xff1f;好吧&#xff0c;我们的头发是外…

睿趣科技:现在开抖音小店到底要多少钱

随着短视频平台的兴起&#xff0c;抖音小店成为了越来越多创业者的选择。那么&#xff0c;现在开抖音小店到底要多少钱呢?这个问题涉及到以下几个方面的费用。 首先&#xff0c;我们需要了解的是&#xff0c;开设抖音小店本身是免费的。你只需要在抖音APP上申请开店&#xff0…

idea不识别yaml文件导致,配置文件点击跳转不了类

文章目录 场景确认的idea安装了ymal插件,确认你的配置文件是yml格式的还是ymal格式的然后在项目配置中看看是否有对应的后缀.最后看看在项目模块里面有没有spring模块跟对应的配置文件,如果没有就要添加这样点击配置文件就能跳转到对应的实体类了 场景 在使用idea时&#xff0…

wpf主页面解析

1、 开头的网址作用 1和2都是引入命名空间的&#xff0c;每一个字符串代表一系列的命名空间&#xff0c;这样就可以不用一个一个引用了。wpf中规定有一个名称空间是可以不加名字的&#xff0c;xmlns不加名字是默认命名空间。 "http://schemas.microsoft.com/winfx/2006/x…

微信小程序实现类似于 vue中ref管理调用子组件函数的方式

微信小程序中确实有类似于 vue 中 ref管理子组件的方式、 这里 我给子组件定义了一个 class 只要是 css选择器拿得到的 都没什么问题 但你要保证唯一性 建议前端开发还是慎重一点 就算是不能重复也尽量用class 因为id总还是有风险的 然后 我在子组件中顶一个了一个函数 start…