`
mqzhuang
  • 浏览: 187568 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论
阅读更多

程序员 在软件开发过程中离不开 编码 和调试,这两个过程也是相辅相成的,我就个人的体会来谈谈这两个方面。

 

编码篇:

 

1 ,程序为什么会有 bug ?其中一个比较关键的原因是程序员的主观因素造成的,比如编码习惯不好,粗心,不理解系统,系统太复杂没有想清楚设计,没有考虑到某些意外情况,单元测试不到位等等。

 

2 ,编码前想清楚设计的细节,对设计细节越清楚,编码越顺利,想清楚了后写代码,往往能体会到那种行云流水,一气呵成的感觉,并且代码的 bug 更少。

 

3 我 有种体会就是,当想清楚了自己的设计细节,在头脑最清楚的时候写好代码的框架,一气呵成把一个可以运行的最小功能代码写好,在第一次编译的时候,如果经过 很小的修改就顺利编译通过,再尝试运行,如果遇到运行时的几个问题也比较简单,很快解决,意味着这部分代码质量不错,以后这块代码出问题的可能性也会小很 多。

 

4 编码前最好想清楚自己的设计细节,至少要想好 80% 以上的设计细节,我通常会写一份简单的文档来描述自己的设计,文档不一定正式,但一定要写简洁清楚,发给其 pm 或是其他同事拍砖,如果他们能很快看懂并没有异议,证明这个方案还不错,要是同事提出了一些意见,一定要考虑他们的意见,多讨论权衡后决定如何做。

 

5 编码是软件开发中比较小的一部分,但无疑是很核心的一部分,也是程序员最喜欢的一部分工作,但花在编码上的时间一般不会太长,假设一个 5000 行左右的模块,我一般会用 3-5 天时间把整个模块的框架代码和基础功能代码一口气写完,写代码时真的很充实,完全处于“颠疯”状态。

 

6 看代码的时间远远超过了写代码的时间,写完一段代码要及时回想一下,站在高一层的角度来审视代码,就像在高中考试答题一样,及时检查可以用最小的代价第一时间出代码的问题。

 

7 当第一个已基本功能的模块完成时,第一遍审查自己的代码,加上一些必要的注释,编写单元测试代码,这部分工作很单调但很关键,完备的单元测试可以把 bug 扼杀在摇篮中。单元测试一般以最简单的方式编写,使用一个不错的单元测试框架就事半功倍,比如 gtest cppunit ,必要的时候写一些 mock 。我的单元测试代码不像项目代码那么正规,单元测试代码的重构做得比较少,要是某个模块有大的修改,就直接放弃那部分的测试代码,重新写新的测试代码。我写的单元测试代码一般会比项目代码多,经过自己亲手测试的代码比较放心。

 

8 ,尽量用最简单的方式实现功能,程序员有时候会随做经验的增加,把简单的问题复杂化,但开发中常常需要的是把复杂的问题简单化,用最简洁,最快的方式解决眼下的问题。

 

9 使用自己最熟悉的语言特性实现功能,不要使用费解或是不直观的语言特性。毕竟程序员不是语言专家,最简单的招式用到极致就是绝招。比如在我们的高性能分布式服务器系统中,虽然采用的是 C++ 开发,但我们主要使用的 C 的语言特性,不使用 STL boost ,我们只使用我们最熟悉,最可控的语言特性。服务器是需要长时间运行的,一个不可控的因素就可能导致系统崩溃。

 

10 程序有 bug 是难免的,但我们尽量让 bug 无处藏身,相信自己的开发水平,相信编译器,相信自己的单元测试,相信系统测试,相信压力测试,一步一步地, bug 真的无处藏身。

 

调试篇:

 

1 这里主要讨论开发的代码调试,没有源代码的的调试要借助比较多的额外工具,包含比较多的技巧性的东西,这个话题留着以后做进一步探讨。

 

2 在学习程序开发的初级阶段,最喜欢用的调试方法就是 " 暴力 "printf 方法,不是说这个方法不好,而是这个调试方法一般不会成为调试方法的首选,当进入正规的开发项目后,系统中都要求实现比较完善的 log 机制,根据 log 的不同级别,一般就能实现 bug 的初步定位。代码中实现完善的 log 机制对多线程程序的调试带来了便捷。

 

3 在 代码的的基本功能实现以后,第一时间审查代码和实现单元测试,确保单元测试通过,然后不断完善代码功能和添加相关的单元测试,每添加一个新功能都确保单元 测试通过,如果单元测试不能通过,第一步想到的就是检查最近修改的代码,由于是迭代开发的,每个阶段都保证了单元测试通过,所以查找一个新引入的 bug 是比较容易的。

 

4 在项目开发后期,系统进入连调阶段,如果你的单元测试做得比较到位,设计清晰简洁,那时候你就会看到其他人都忙着修改 bug ,你却很清闲。那时候你会体会到完备单元测试 + 迭代开发的好处。

 

5 我不太常用 gdb ,一般程序的 bug 在单元测试阶段构造一些简单的测试场景就修复了,并在程序中每个函数都做了充分的参数检查,程序出 core 的情况并不多,但程序发生段错误时, gdb 是一个比较方便的定位方法。

 

6 一般情况下,程序出错,首先看 log ,如果 log 比较完备,并对自己的代码比较熟悉,基本就能定位 bug 的地方了。如果没有头绪并且 bug 很容易复现,就采用 gdb 调试,使用 gdb 也需要有针对性,首先查看自己怀疑的对象,如果涉及到其他同事写的代码,在调试过程中可以熟悉代码的执行过程。一般简单的 bug ,凭着经验应该能很快定位。能反复重现的 bug gdb 查找是比较快的。

 

7 使用 gdb 调试比较复杂的多线程问题时,我比较喜欢用 gdb attach  <pid> 想象一下,一个程序直接跑就出错,但是放到gdb下就能得到正确的结果,好像故意在耍我们一样 这种方法的好处是能够使gdb对程序执行的影响最小,而且可以只接管程序中某一条我们所关心的线程,而其他线程不受影响 。如果 还没来得及attach线程就已经执行完或者 crash ,我们可以在线程中加入 sleep ()。

 

8 在做压力测试时要是系统崩溃,一般有几种方式来处理这种情况,最常见的一种情况就是 segmentation fault ,我们可以将程序运行在 gdb 中,一旦程序 crash gdb 可以看到最后的出错堆栈信息,但在 gdb 中会影响到程序的性能。第二种办法是查看程序的 core 文件,但程序消耗的内存很庞大时,生成 core 文件也需要很长时间。还有一种办法是使用信号来保存现场。 这样你可以晚上写个脚本让程序无限跑,早上起来你会发现程序停在出错的地方,这是很惬意的事情 ,我们只需要在信号的处理函数中添加一段循环 sleep 的代码就可以了。

 

9 内存问题调试采用 valgrind ,一般的内存错误都逃不出它的魔眼,但关键还是需要自己在开发过程中多注意,养成正确使用内存的好习惯,简单设计是防止内存问题的一个比较有效的方法。

 

10 更复杂的系统 bug 就需要用一些工具来辅助解决了,比如性能问题,我们会采用 oprofile ,或是 systemtap 来找到系统的热点。比如全异步,多并发,分布式的服务器程序,我们在试运行时可以采用内存 log 的方式,将系统的的 log 级别定为 DEBUG ,系统将 log 写入一个循环内存缓冲区,当系统出问题时可以看到系统最后那段时间的详细信息,方便调试。对已经在线上运行的系统的 bug 调试,调试手段真的有限,一般采用监测系统状态和系统的一些 stat 接口来间接定为系统是否运行正常,有时候也使用 systemtap 这样的工具对重点怀疑的对象进行监测。

分享到:
评论
1 楼 boyhailong 2013-03-31  
总结的很好,顶

相关推荐

    编码器调试软件

    压缩包中的"TWK"文件很可能包含了与TWK编码器相关的配置文件、驱动程序、说明书或者其他支持文档。用户在使用调试软件时,可能需要这些文件来确保软件正常运行或了解如何配置硬件。 总的来说,"编码器调试软件"是...

    西门子数控系统828D_调试相关手册集合(主轴调试_编码器调试_备份等).rar

    本集合包含了一系列与系统调试相关的手册,旨在帮助用户更好地理解和操作828D系统,确保设备的高效运行和精准控制。下面我们将深入探讨其中涉及的主轴调试、编码器调试以及备份等重要知识点。 一、主轴调试 主轴是...

    CICS联机程序开发与调试

    ### CICS联机程序开发与调试 #### 一、CICS概念与功能 **CICS**(Customer Information Control System),即客户信息控制系统,是由IBM开发的一款先进的联机事务处理(OLTP)系统,专为大型主机环境设计。它提供了...

    电子-关于IAR下对MSP430G2553程序下载与调试附图.pdf

    针对标题和描述中提到的IAR环境下对MSP430G2553程序下载与调试的知识点,以下是详细的说明: 标题中的“IAR下对MSP430G2553程序下载与调试附图”指出了文档的内容重点在于介绍如何在IAR开发环境中下载和调试MSP430G...

    编码器.rar_单片机连接编码器测速程序_编码器与pwm_编码电机

    7. **调试与优化**:实际运行系统并进行调试,根据测试结果调整参数以达到理想的性能。 总结来说,这个“编码器.rar”文件可能包含了实现上述功能的源代码、配置文件和其他相关文档。通过单片机与编码器的结合,...

    基于Android的手机卫士开发与实现系统

    该系统的总体的一个结构图有主界面以及主界面上的一些模块构成,主界面为HomeActivity,在主界面上有手机防盗、...数据库的实施主要包括:建立实际数据库结构、装入数据、应用程序编码与调试、数据库试运行和整理文档。

    中文短信编码调试工具.zip

    本压缩包“中文短信编码调试工具.zip”提供了一个实用工具,用于帮助开发者在调试通信模块发送中文短信时,正确地进行Unicode编码和PDU(Protocol Data Unit)编码。 PDU编码是GSM系统中用于短信传输的一种二进制...

    用C++写的图像方块编码程序(调试已通过)

    图像方块编码是一种在数字图像处理领域常用的压缩技术,它主要应用于图像的编码与传输。在C++中实现这样的程序,需要对图像处理的基本概念、数据结构和算法有深入理解。下面将详细介绍图像方块编码的基本原理以及...

    基于51单片机的光电编码器测速.zip_51测速程序_saddlegw7_strike4nm_光电编码器_编码器

    本篇将深入探讨51单片机与光电编码器结合实现的测速程序设计,帮助读者更好地理解和应用这一技术。 首先,我们需要了解光电编码器的工作原理。光电编码器通常由光源、光敏元件和编码盘组成。编码盘上刻有不同密度的...

    倍福VC++显示器程序编码翻译

    标题 "倍福VC++显示器程序编码翻译" 涉及的核心技术主要是在使用Microsoft的Visual C++(简称VC++)编程环境下,为贝克霍夫(Beckhoff)的工业自动化设备开发显示器程序,并进行代码的编译和翻译。这个过程涉及到的...

    Seay正则编码调试器

    此外,Seay正则编码调试器的“文件名称列表”中包含的"Seay正则编码调试器.exe"是该软件的可执行文件,意味着这是一个独立的应用程序,用户下载后可以直接运行,无需安装其他依赖,方便快捷。 总之,Seay正则编码...

    多摩川编码器读取程序,STM32

    2. HAL库源代码:包括编码器读取的中断服务程序、主循环中的数据处理逻辑。 3. 示例应用程序:可能包含读取编码器数据的示例代码,展示如何将数据解析并显示或存储。 4. Makefile或其他构建脚本:用于编译和烧录程序...

    HEVC视频编码调试环境HM9.0

    6. **调试与优化**:通过HM9.0提供的调试工具,可以深入到编码过程的各个层次,检查和优化算法,以达到预期的效果。 总的来说,HEVC视频编码调试环境HM9.0是一个强大的工具,对于那些从事视频编码研究、开发或优化...

    stm32f103编码器程序

    最后,编码器程序的调试至关重要,可以使用逻辑分析仪或示波器检查编码器信号与MCU的输入是否一致,确保计数正确无误。在实际项目中,还需要根据具体硬件环境和应用需求对程序进行适当的调整和优化。 总的来说,STM...

    stm32读取编码器程序

    总结来说,“stm32读取编码器程序”涵盖了嵌入式系统设计的多个层面,从底层的硬件接口配置到上层的软件开发,再到实际的运动控制应用,每一个环节都需要精确的设置和调试,以实现高效可靠的编码器数据读取。

    VC图像编码源程序,调试通过,直接可用

    本文将深入探讨基于VC++(Visual C++)的图像编码源程序,这些源代码已经过调试,可以直接使用,并且为用户提供了一个理想的平台进行二次开发。 首先,让我们了解“VC”即Visual C++。VC++是微软公司开发的一款强大...

    《数据结构课程设计》指导书.docx

    课程设计的考核标准涉及设计内容、程序编码与调试能力、报告质量和答辩表现。此外,出勤率和平时表现也是评价的一部分。设计进度应包括初步设计、详细设计、编码调试和验收答辩阶段。 参考题目提供了具体的应用场景...

    STM32编码器程序

    STM32编码器程序是基于STM32微控制器的编码器接口实现,它允许设备读取编码器的信号并处理这些信号以获取速度、位置等信息。编码器是一种传感器,通常用于测量机械运动,如旋转角度、速度或方向。STM32作为一款广泛...

    EC11编码器基于STM32程序源码

    7. **调试与测试**: 开发过程中,可能需要使用ST-Link或J-Link等调试器进行程序下载和调试。通过示波器检查编码器输出信号,验证STM32对信号的正确处理。同时,上位机端也需要编写相应程序接收并解析STM32发送的...

    原创c#串口调试助手 支持中文字符编码 源程序代码

    【标题】中的“原创c#串口调试助手 支持中文字符编码 源程序代码”揭示了这个项目的核心内容。这是一个使用C#编程语言开发的串口调试工具,其特点是能够正确处理中文字符编码,这在处理中文数据时非常重要。串口通信...

Global site tag (gtag.js) - Google Analytics