代码之家  ›  专栏  ›  技术社区  ›  stej

代码中的表布局被认为不好的原因是什么?

  •  5
  • stej  · 技术社区  · 15 年前

    我这么问是因为对我来说它更具可读性。

    示例(非真实代码):

    if (res == ResultType.Failure)               
      something = ProcessFailure(..);
    if (res == ResultType.ScheduledAndMonitored) 
      something = DoSomething(...) && DoSomething3(..);
    if (res == ResultType.MoreInfoAvailable)     
      info = GetInfo(..);
    if (res == ResultType.OK && someCondition)   
      something = DoSomething2(..);
    .... continued
    

    if (res == ResultType.Failure)               something = ProcessFailure(..);
    if (res == ResultType.ScheduledAndMonitored) something = DoSomething(...) && DoSomething3(..);
    if (res == ResultType.MoreInfoAvailable)     info      = GetInfo(..);
    if (res == ResultType.OK && someCondition)   something = DoSomething2(..);
    .... continued
    

    为什么我认为第二个更好:

    • 我不需要用眼睛来解析文本-我一眼就能看到命令的结构。
    • 我马上就明白了
      • 有一些假设和任务
      • 只有最后一个条件由两个表达式组成

    18 回复  |  直到 15 年前
        1
  •  2
  •   Community CDub    5 年前

    我认为你的“基于表格”的例子 它本身就更容易阅读。问题是我们有50年的基于文本的工具来处理源代码 线 一段文字。您将遇到的两个最明显的问题是:

    1. diff grep

      (如果您在可扩展编辑器中使用更规则语法的语言进行编写,比如Emacs中的Lisp,那么这并不是什么大问题,因为遍历实际结构很简单。但C#的语法非常复杂,我不知道有什么简单的方法可以用一两行代码遍历我的C#代码,所以文本工具仍然在这里占主导地位。)

    2. 你最长的一行大约是95个字符——这就是 ..

    我想写这个代码。我很喜欢读这个代码。我真的很讨厌在这段代码上进行三方合并。:-)

    相比之下,我要冒险说,我认为到目前为止,这里的大多数其他答案都是废话:

    • 0x09 :那么,使用空格而不是制表符;这只是现在的常识
    • 等距字体:全部 种类 如果你使用可变宽度字体,我看到的很多代码标准都会失效,而不仅仅是这个
    • “it's the convention”:好吧,但这并不能说明为什么它是约定,或者为什么这个案例不应该是约定的例外(因为我见过的每一组代码约定都允许例外)
    • StyleCop说这很糟糕:你是为你的工具工作,还是他们为你工作?另见:“这是惯例”
    • 很难维护:在我的编辑器中是不行的,如果在你的编辑器中很难维护,你需要学习如何使用它,或者找一个更好的
    • 有些人不会有你的编辑器:你所有的编码标准是否都依赖于用一个任意软弱的编辑器编写代码的容易程度?如果我们雇了一个坚持使用记事本的人,那就是 他们的
    • 这是不一致的:当然,但(因为我不是机器人)这不一定会让一些东西更难读;我报纸上的每一个连环画都有不同的格式(在某些情况下) 不一样!),但我并不觉得其中任何一本难读

    (火焰消失!)

    最后,出于不同的原因,我认为这两种样式对于这种代码来说都有点糟糕。如果你需要一桌东西,那就用吧 switch ,或 IDictionary<ResultType,Action> ,或列表或元组列表(如果顺序重要),或将规则卸载到配置文件或其他文件中。你认为桌子应该看起来像桌子是对的。你唯一缺少的是,我们有一些构造,让事情看起来像表,在这里可以正常工作,而且 if 不是其中之一。:-)

        2
  •  13
  •   Peter Recore    15 年前

        3
  •  5
  •   Community CDub    8 年前

    您描述的“基于表格”布局在某些情况下非常有用:

    public string GetMessageFromErrorCode(int code)
    {
        switch (code)
        {
            case 1: return "OK";
            case 2: return "Syntax Error";
            case 3: return "Other error";
        }
    }
    

    注意,这个例子是c规则的一个有效例外,即“所有 case 语句还必须包含 break ."

    我不喜欢拘泥于代码布局。遵循编码标准是一件好事。但是一旦你开始做一些事情,比如在函数调用中使用几个长名称的参数,编写linq查询,或者使用匿名方法或复杂的lambda语句,你的代码就可以更容易阅读 打破规则

    另请参见:
    Anonymous Methods / Lambda's (Coding Standards)

        4
  •  5
  •   CaffGeek    15 年前

    原因很简单。

    如果您使用制表符来缩进所有内容,并将其排列成一行,那么在每个人的计算机上看起来都不一样,因为不是每个人都将制表符设置为相同的宽度。有些人将它们设置为3个字符,其他人设置为5个字符,其他人则设置为不同的字符。在你的机器上看起来又漂亮又整洁又像“桌子”的东西,在他们的机器上看起来是一团糟。

    在if执行的语句周围加大括号,并正常格式化它。

    if (res == ResultType.Failure)               
    {
      something = ProcessFailure(..);
    }
    
    if (res == ResultType.ScheduledAndMonitored) 
    {
      something = DoSomething(...) && DoSomething3(..);
    }
    
    if (res == ResultType.MoreInfoAvailable)     
    {
      info = GetInfo(..);
    }
    
    if (res == ResultType.OK && someCondition)   
    {
      something = DoSomething2(..);
    }
    

    哦,另一个原因是,不是每个人都用固定字体来编程。信不信由你,有些开发人员使用比例字体。

        5
  •  3
  •   ilivewithian    15 年前

    something
    something
    info
    something
    

    在心里把它们分组,就像在另一个地方一样,我看到了代码的流程和逻辑,然后是细节。这让我更直截了当地把需要的东西塞进脑子里。

        6
  •  3
  •   Chris Marisic    12 年前

    错误的 . 您的示例可以使用多态性、策略模式或其他明显更好的方法编写,这使得这一点完全没有意义。

        7
  •  2
  •   Aaron Anodide    15 年前

    我学会了上面的话,但我大部分时间都不遵循它-这是不值得的头痛有时。

        8
  •  2
  •   Nilesh Gule    15 年前

    我认为这在很大程度上取决于个人的选择以及使用什么格式。在专业环境中,您希望团队拥有一个所有团队成员都遵循的定义和商定的编码标准。

    IDE中有许多工具和外接程序,比如visualstudio,它们使您能够通过解析源代码文件来建议对代码结构的更改。

    我发现其中一个非常有用的方法是[StyleCop][1]。

    我个人觉得Stylecop有一个统一的编码准则非常有用。

    尼莱什

        9
  •  2
  •   AleÅ¡ Roubíček edbond    15 年前

    如果您觉得需要将代码列表化,那么现在正是思考的时候。闻起来像是重构时间。代码应该像sentense一样可读。

    第二个原因是代码可维护性成本。表格化代码更难维护。

        10
  •  2
  •   Peter Mortensen icecrime    14 年前

    另外,标签也在说谎。

    if (!HydrogenTankFull())                          FillHydrogenTank();
    if (!OxygenTankFull())                            FillOxygenTank();
    if (HydrogenTankFull() && OxygenTankFull())       TestGimbals();
    if (GimbalsTested() && LaunchButtonPressed())     IgniteEngine(); BlowRestrainingBolts();
    if (LaunchPadCleared())                           TransferControlToHouston();
    

        11
  •  1
  •   Hamish Grubijan    15 年前

    很难说你的样本中发生了什么,但看起来你做了很多。如果是这样的话,在我看来,你想把这么多的逻辑塞进4行是错误的。这是C#,不是Python。说到C#vs Python,您没有为if语句体使用大括号,这是许多人不喜欢的。StyleCop也不喜欢。说到StyleCop,您可能还需要运行FxCop和ReSharper—这可能会提供一种改进代码的很酷的方法。你为什么不用 return ? 即使条件相互排斥,我发现 返回 非常有用-允许跳过其余的东西,而不使用大量的 else if ,但仍然能够检测到所谓的“默认”情况(想想 switch ). 我的刺:

    // This should be in it's own function; I am just too lazy to spell out a signature.
    {
        if (res == ResultType.Failure)
        {
            return ProcessFailure(..);
        }
    
        if (res == ResultType.ScheduledAndMonitored)
        {
            bool result = DoSomething(...);
            result = result && DoSomething3(..);
            return result;
        }
    
        if (res == ResultType.MoreInfoAvailable)
        { 
             info = GetInfo(..);
             // Ok, and then?
        }
    
        if (res == ResultType.OK && someCondition)
        { 
            return DoSomething2(..);
        }
    
        // Else ...
    
        Debug.Assert(false, "Why did we get here? Explanation: ");
    }
    

    我上面写的不是最好的代码,但我试着清理它。不要担心额外的变量-优化编译器会处理它们。一定要追求逻辑可读性。在我看来,把事情变成表格形式是没有帮助的。如果一旦StyleCop满意,代码就很难阅读,那么您可能需要重新考虑它,以及简化逻辑/状态等。

        12
  •  1
  •   Paul Nathan    15 年前

    把重点放在给出的例子上,我会这样格式化它。我觉得你的两个例子都很难读。

    if (res == ResultType.Failure)               
    {
      something = ProcessFailure(..);
    }
    if (res == ResultType.ScheduledAndMonitored) 
    {
      something = DoSomething(...) && DoSomething3(..); //Bit-and on the results? huh.
    }
    if (res == ResultType.MoreInfoAvailable)     
    {
      info = GetInfo(..);
    }
    if (res == ResultType.OK && 
        someCondition)   
    {
      something = DoSomething2(..);
    }
    

        13
  •  1
  •   MartinStettner    15 年前

    尽管我也发现您的第二个(类似表格的)示例更具可读性,但我不会使用它,因为

    1. 这种布局不容易维护(你可能要经历整个过程) 如果一行更改,请列出)。因此,很有可能有人最终懒得调整它,布局会变得一塌糊涂。
    2. 如果一条线有三到四个条件, 行将变得不必要的长,因此无法阅读。
    3. 当然,如果这违反了你团队的编码标准,请不要这样做:)。。。
        14
  •  1
  •   supercat    15 年前

    如果编程语言、标记语言和文本编辑器都能相互协作,允许文本格式合理地调整自己以适应代码,那就太好了。例如,如果与一行代码关联的注释太长,无法放在该行的右侧,并且如果后续代码行较短,则允许注释换行并保留在后续代码行的右侧,用某种箭头或方框表示注释的续行都属于第一行代码。

    不幸的是,我知道没有一种广泛使用的编程语言能够很好地嵌入标记。

        15
  •  1
  •   Borek Bernard    15 年前

    太麻烦了。

        16
  •  0
  •   Jacob    15 年前

    所以这就是为什么代码格式化标准很重要;没有一种真正的方法可以让所有人都满意地格式化代码。

        17
  •  0
  •   wageoghe    15 年前

    void LogMessage(LogLevel lvl, string msg)
    {
      if (!this.loggingManager.IsLogging) return;
      if (lvl < this.loggingLevel) return;
    
      this.loggingManager.Write(this.loggerName, msg);
    }
    

    或者

    void DrawGeometry(Graphics g, Geometry geom, Layer layer, double scale)
    {
      if (geom == null) return;
      if (!layer.IsDisplayed) return;
      if (this.isDisplayByScale && (scale < this.minScale || scale > this.maxScale) return;
      if (this.ColorsToTreatAsTransparent.Contains(layer.Color)) return;
    
      Geometry xformed = this.Transform(geom);
      using (Pen p = new Pen(layer.Color, layer.Width))
      {
        g.Draw(xformed, p);
      }
    }
    

    请注意,这两个都是完全虚构的例子。我来来回回,但我确实有点喜欢一行健全性检查/返回语句的简洁性。

        18
  •  0
  •   Jimmy Hoffa    15 年前

    创建语句块的花括号在整个行业中更为常见,现在就养成这个习惯吧,因为如果你这样写代码,大多数人会认为你的代码看起来很小。

    另一方面,我看到这个规则的原因之一是,if语句总是使用大括号,而从不使用if(condition)单行语句;是因为一行代码在4个月后更改,导致if语句在您没有意识到的情况下跳转到下一个语句,这并不少见,因此作为安全起见,if应该始终是:

    if (condition)
    {
        single-line-statement;
    }