【问题标题】:Guidelines to improve your code改进代码的指南
【发布时间】:2010-09-08 19:24:00
【问题描述】:

您遵循哪些准则来提高代码的总体质量?许多人都有关于如何编写 C++ 代码的规则(据说)这使得出错变得更加困难。我见过有人坚持每个if 语句后面都有一个大括号({...})。

我对其他人遵循的准则及其背后的原因很感兴趣。我也对你认为是垃圾但普遍持有的指导方针感兴趣。谁能推荐几个?

为了让事情顺利进行,我先提几个:

  • 总是在每个if / else 语句后使用大括号(如上所述)。这背后的基本原理是,要判断单个语句实际上是一个语句还是扩展为多个语句的预处理器宏并不总是那么容易,因此这段代码会中断:
// 文件顶部: #define 语句 doSomething();做点别的 // 在实现中: 如果(某些条件) 做一点事();

但是如果你使用大括号,那么它会按预期工作。

  • 仅将预处理器宏用于条件编译。预处理器宏可能会导致各种麻烦,因为它们不允许 C++ 范围规则。由于头文件中具有通用名称的预处理器宏,我已经多次搁浅。如果您不小心,可能会造成各种破坏!

现在交给你了。

【问题讨论】:

    标签: c++ coding-style


    【解决方案1】:

    一些我个人最喜欢的:

    努力编写const correct 的代码。您将使用编译器来帮助清除易于修复但有时令人痛苦的错误。您的代码还将讲述您在编写它时的想法——一旦您离开,这对新手或维护者都很有价值。

    退出内存管理业务。学习使用智能指针:std::auto_ptrstd::tr1::shared_ptr(或boost::shared_ptr)和boost::scoped_ptr。了解它们之间的区别以及何时使用它们。

    您可能会使用标准模板库。阅读Josuttis book。不要只是在读完关于容器的前几章后就停下来,以为你知道 STL。推进好东西:算法和函数对象。

    【讨论】:

      【解决方案2】:
      1. 删除不必要的代码。

      就是这样。

      【讨论】:

      • ...然后我得到编译器错误:unnecessaryFunction() undefined.
      • 使用递归删除功能删除所有不必要代码的奖励积分。
      【解决方案3】:
      • 使用并执行通用的编码风格和准则。 理由:团队或公司中的每个开发人员都能够阅读代码,而不会因大括号样式或类似情况而分心。
      • 定期对整个源代码库进行全面重建(即每日构建或每次签入后构建)并报告任何错误! 理由:源几乎总是处于可用状态,问题在“实施”后不久就会被检测到,而解决问题的成本很低。

      【讨论】:

        【解决方案4】:

        打开编译器中可以出现的所有警告(gcc:-Wall 是一个好的开始,但不包括所有内容,因此请查看文档),并使其出错,因此您必须修复它们(gcc:@ 987654322@).

        【讨论】:

          【解决方案5】:

          其中一个答案中提到的 Google 风格指南非常可靠。里面有一些无意义的东西,但总比坏的好。

          Sutter 和 Alexandrescu 就这个主题写了一本不错的书,名为C++ 编码标准

          以下是 lil' ole me 的一些一般提示:

          1. 您的缩进和括号样式都错误。其他人的也是如此。因此,请遵循项目的标准。吞下你的骄傲并设置你的编辑器,以便一切都尽可能与代码库的其余部分保持一致。不得不阅读缩进不一致的代码真的很烦人。也就是说,括号和缩进与“改进代码”没有任何关系。更重要的是提高您与他人合作的能力。

          2. 好好评论。这是非常主观的,但一般来说,编写 cmets 总是很好地说明为什么 代码按它的方式工作,而不是解释它的作用。当然,对于复杂的代码,可能不熟悉算法或代码的程序员也可以了解它在做什么。非常欢迎提供所用算法描述的链接。

          3. 以尽可能简单的方式表达逻辑。我认为具有讽刺意味的是,像“将常量放在比较左侧”这样的建议在这里出错了。它们非常受欢迎,但对于说英语的人来说,它们经常会破坏程序的逻辑流程以供阅读者使用。如果您不能相信自己(或您的编译器)能够正确编写相等比较,那么请务必使用这样的技巧。但是当你这样做时,你会牺牲清晰度。也属于这一类的还有......“我的逻辑有 3 级缩进吗?它可以更简单吗?”并将类似的代码滚动到函数中。甚至可能拆分功能。编写优雅表达底层逻辑的代码需要经验,但值得努力。

          那些很笼统。对于具体的提示,我不能比 Sutter 和 Alexandrescu 做得更好。

          【讨论】:

          • 我不使用 C++,但现代 IDE 是否没有设置来强制缩进样式,或实现此类代码美化的插件?
          【解决方案6】:

          在 if 语句中,将常量放在左侧,即

          if( 12 == var )
          

          不是

          if( var == 12 )
          

          因为如果你错过了输入“=”,那么它就变成了赋值。在最高版本中,编译器说这是不可能的,在后者中它运行并且 if 始终为真。

          如果 if 不在同一行,我会使用大括号。

          if( a == b ) something();
          if( b == d )
          {
              bigLongStringOfStuffThatWontFitOnASingleLineNeatly();
          }
          

          左大括号和右大括号总是有自己的行。但这当然是个人惯例。

          【讨论】:

          • 我同意将常量放在左侧可以防止缺少 = 符号……但我一直无法采用它。反过来,代码读起来更自然。幸运的是,大多数编译器都有一个设置来警告“if (a=b)”结构。
          • 这是我喜欢 VB.Net 的原因之一。 If 语句不接受赋值,您可以只使用 = 符号进行赋值并测试相等性。它使一些代码更加冗长,但意味着很多这样的错误不会发生。
          【解决方案7】:

          仅在仅需要解释代码在做什么时才发表评论,而阅读代码无法告诉您相同的内容。

          不要注释掉不再使用的代码。如果您想恢复旧代码,请使用您的源代码控制系统。注释掉代码只会让事情看起来很混乱,并使实际上很重要的 cmets 淡入注释代码的背景混乱中。

          【讨论】:

            【解决方案8】:
            1. 使用一致的格式。
            2. 在处理遗留代码时,请使用现有的格式样式,尤其是。大括号样式。
            3. 获取 Scott Meyer 的《Effective C++》一书的副本
            4. 获取 Steve MConnell 的书 Code Complete 的副本。

            【讨论】:

              【解决方案9】:

              还有一个不错的C++ Style Guide 供 Google 内部使用,其中包含这里提到的大部分规则。

              【讨论】:

                【解决方案10】:

                开始编写大量 cmets —— 但以此为契机重构代码,使其具有自我解释性。

                即:

                for(int i=0; i<=arr.length; i++) {
                  arr[i].conf() //confirm that every username doesn't contain invalid characters
                }
                

                应该更像

                for(int i=0; i<=activeusers.length; i++) {
                  activeusers[i].UsernameStripInvalidChars()
                }
                

                【讨论】:

                  【解决方案11】:
                  • 使用制表符进行缩进,但将数据与空格对齐 这意味着人们可以通过更改标签大小来决定缩进多少,但也可以保持对齐(例如,在为结构分配值时,您可能希望所有的 '=' 都在一条垂直线上)

                  • 尽可能使用常量或内联函数,而不是宏

                  • 1234563 /p>
                  • 如果某些内容超过 80 列,请将其分成多行,例如

                    if(SomeVeryLongVaribleName != LongFunction(AnotherVarible, AString) &&
                       BigVaribleIsValid(SomeVeryLongVaribleName))
                    {
                        DoSomething();
                    }
                    
                  • 只有重载运算符才能使它们按照用户的期望进行,例如重载 2dVector 的 + 和 - 运算符就可以了

                  • 始终注释您的代码,即使它只是说明下一个块在做什么(例如“删除此级别不需要的所有纹理”)。有人可能需要稍后使用它,可能在您离开之后,他们不想找到没有 cmets 的 1000 行代码来指示什么在做什么。

                  【讨论】:

                    【解决方案12】:
                    1. 设置编码约定并让参与的每个人都遵守约定(您不会希望阅读需要您弄清楚下一个语句/表达式在哪里的代码,因为它没有正确缩进)
                    2. 不断重构代码(获取 Martin Fowler 撰写的 Refactoring 的副本,书中详细介绍了优缺点)
                    3. 编写松散耦合的代码(避免通过编写不言自明的代码来编写注释,松散耦合的代码往往更易于管理/适应更改)
                    4. 如果可能,请对您的代码进行单元测试(或者如果您足够有男子气概,请使用 TDD。)
                    5. 尽早发布,经常发布
                    6. 避免过早优化(分析有助于优化)

                    【讨论】:

                      【解决方案13】:

                      同样,您可能会在这里找到一些有用的建议:How do you make wrong code look wrong? What patterns do you use to avoid semantic errors?

                      【讨论】:

                        【解决方案14】:

                        在可能的情况下,使用前增量而不是后增量。

                        【讨论】:

                          【解决方案15】:

                          我在我的 C++ 项目中使用 PC-Lint,特别喜欢它引用现有出版物的方式,例如 MISRA 指南或 Scott Meyers 的“Effective C++”和“More Effective C++”。即使您计划为静态分析工具检查的每条规则编写非常详细的理由,最好指出您的用户信任的已建立的出版物。

                          【讨论】:

                            【解决方案16】:

                            这是一位 C++ 大师给我的最重要的一条建议,它帮助我在一些关键的场合找到了代码中的错误:

                            • 当方法不应该修改对象时使用 const 方法。
                            • 当对象不应该修改对象时,在参数中使用 const 引用和指针。

                            有了这 2 条规则,编译器会免费告诉你代码中的逻辑缺陷在哪里!

                            【讨论】:

                              【解决方案17】:

                              另外,对于一些好的技术,您可以关注Google's blog "Testing on the Toilet"

                              【讨论】:

                                【解决方案18】:

                                六个月后再看

                                【讨论】:

                                  【解决方案19】:

                                  确保正确缩进

                                  【讨论】:

                                    【解决方案20】:

                                    嗯 - 我可能应该更具体一点。

                                    我并不是在为自己寻找建议 - 我正在编写一个静态代码分析工具(当前的商业产品还不足以满足我的需求),我正在寻找插件的想法突出显示代码中可能存在的错误。

                                    有几个人提到了诸如 const 正确性和使用智能指针之类的事情——这是我可以检查的想法。检查缩进和注释有点困难(无论如何从编程的角度来看)。

                                    【讨论】:

                                    【解决方案21】:

                                    智能指针有一种非常清楚地指示所有权的好方法。如果你是一个类或一个函数:

                                    • 如果你得到一个原始指针,你就没有任何东西。您可以使用指针,由您的呼叫者提供,他保证指针会比您活得更久。
                                    • 如果您获得 weak_ptr,则您不拥有该指针,除此之外,指针可能随时消失。
                                    • 如果您获得了一个shared_ptr,那么您将与其他人一起拥有该对象,因此您无需担心。压力更小,控制力也更小。
                                    • 如果您获得 auto_ptr,则您是该对象的唯一所有者。这是你的,你是国王。您有权销毁该对象,或将其交给其他人(从而失去所有权)。

                                    我发现 auto_ptr 的情况特别强大:在设计中,如果我看到 auto_ptr,我会立即知道该对象将从系统的一个部分“游走”到另一个部分。

                                    这至少是我在我的宠物项目中使用的逻辑。我不确定这个主题会有多少变化,但到目前为止,这个规则集对我很有帮助。

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 2013-03-09
                                      • 2011-04-14
                                      • 2013-09-11
                                      • 2013-11-12
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2021-02-25
                                      • 2016-03-17
                                      相关资源
                                      最近更新 更多