您通常如何布置班级的区域?


17

我想知道是否有制定班级区域布局的标准。

我目前使用

Fields
Constructor
Properties
Public Methods
Private Methods

Fields成为私有财产而Properties成为公共财产。通常,如果需要,我通常在其中使用子区域,或者偶尔在下面添加其他区域(例如interface或baseClass成员)。


1
您是在总体上谈论布局还是在使用“ #regions”?
snmcdonald 2011年

1
@snmcdonald我使用#region标签定义了一个部分
Rachel

这不应该是社区维基问题吗?我不相信有一个标准,答案可能会因语言而异。
Raveline'3

7
我开始通过删除所有#region小号
埃德S.

3
@Ed S. +1,因为区域是魔鬼。他们所允许的所有事情掩盖了您的代码文件太大而需要重构的事实。
MattDavey

Answers:


4

与类相关的枚举或偶尔的struct / pure-data类(高于实际的类定义)

-类定义-

私人会员

CTOR / DTOR(如果语言具有DTOR)

公共财产

实用方法(范围较小的私有方法或受保护的方法)

类功能(根据类范围可分为多个区域)。


17

子区域?您的班级有单一职责吗?(隐含的意思是……我的回答是“几乎没有任何区域,除了可能将属性,构造函数和方法分组在一起……”但是即使那样,我也不会使用太多)


2
我现在正在WPF中进行编程,我将使用的一些子区域示例是ViewModel,其公共属性分为与UI相关的属性,命令,数据等。这使查找我要的内容变得更加容易快速寻找
Rachel

2
为什么不使用大注释横幅而不是区域? // ----------ViewModel Properties---------- 这样,您仍然可以看到代码(或通过概述折叠代码并查看成员)。区域用于隐藏事物。除非代码是自动生成的,否则不应将其隐藏。
Kyralessa

1
@雷切尔青睐组成。
MattDavey 2011年

10

我只是想确认您的意思是“ #regions”,而不是一般的类布局。

我很惊讶没有人提到要避免使用区域。我知道OP希望对布局区域进行民意测验,但我想提出一个替代的观点。

我避开区域。我喜欢看正在使用的代码。如果发现难以找到所需内容,则使用代码折叠并将相似的类构造组合在一起。

为什么我讨厌地区?CTRL+M,LCTRL+M,O将切换代码折叠。但是,折叠时会隐藏整个区域。我只需要折叠方法/属性/注释。

如果区域太多,则可能是代码气味,您的班级做了太多工作。Jeff Atwood在一些地区提供了不错的文章,值得一读。

我最喜欢的#regions报价:

不,我不会使用#regions。不,我不与恐怖分子谈判。闭嘴。

- 杰夫·阿特伍德

话虽如此,我知道许多程序员都坚持使用它们。这个问题是主观的。我只是想我会提供一个替代方案。


1
这是一个宏,用于折叠到定义但扩展区域,以防万一您迷恋于对区域迷恋的人们: stackoverflow.com/questions/523220/awesome-visual-studio-macros/… 除非您与真正患病的人一起工作,他们将区域置于方法之中
Kyralessa

一个非常有用的宏!我不确定他们为什么不将其构建到Visual Studio中,谢谢。
snmcdonald 2011年

我的老板喜欢地区,喜欢他们。他还喜欢私人内部阶级和庞大的方法。我们的代码具有一个类,该类具有将其划分的大约十二个区域,三个内部类,以及某些方法,直到它们在内部具有十二个顶级区域,在其中具有子区域。
CodexArcanum 2011年

4

它因语言而异。由于我是Delphi编码员,因此我倾向于遵循Delphi标准约定,如下所示:

type
  TMyClass = class(TBaseClass)
  private
    private fields
    private methods
  protected
    protected fields
    protected methods
    protected properties
  public
    constructor(s)
    destructor
    public methods
    public properties
  end;

我发现这是组织易于阅读和理解的信息的好方法。


3
我感到非常惊奇的是,私有,受保护,公共和已发布都按字母顺序和封装顺序排列,并且都以P开头!
彼得·特纳

可笑,我没有。我一直发现,public首先列出是更自然的做法,因为大多数用户只关心public事物。
Matthieu M.

我一直觉得这个约定真是个愚蠢的主意。可见性与功能有什么关系?无论如何,我总是使用接口来定义公共功能,但在接口上将其实现为受保护的类。我将一致地分组的唯一项目是组件的发布方法和属性,否则,我总是根据需要使用多个可见性关键字按接口和继承分组。那些对于类实现来说是唯一的项(即,不是重写)应该真正地首先列出。
S.Robins '02

3

我倾向于按以下方式布置它们:

Public fields (usually static constants)
Constructors
Public methods
Private methods
Private fields

没有使用过使用的语言,Properties这就是为什么这些语言没有列出的原因。我将私有方法和字段放在底部,因为如果其他人在他们的代码中使用此文件,则他们只需要关心API(这是公共的东西)即可。我所知道的所有文本编辑器,甚至是IDE,在打开文件时都将光标置于顶部。


+1用于将私有字段置于底部。我将公共方法按它们实现的接口分组,然后将那些未实现任何接口的公共方法放在构造函数/析构函数之后。
Sjoerd

2

这是对我的判断。我使用区域以提高可读性。

我还在Visual Studio配色方案中使用了另一种颜色(当前为深红色),以使其在其余的代码中脱颖而出。


我可能在其中使用#region的示例:如果我为需要多行XML代码段的单元测试编写了一种测试方法,则XML字符串将破坏通常的缩进(因为它是从XML的左边缘开始的)为了隐藏丑陋的地方,我将其包裹在#region中,以便将其折叠起来。


2

鲍勃·马丁(Bob Martin)的“ 清洁代码Clean Code)”一书将整个第5章致力于格式化。我觉得有几个要点总结得很好。

  • 通过可见性和整洁度对变量和方法进行分组的大多数尝试都没有多大意义,并且会使您在代码中四处浏览。
  • 保持彼此垂直调用的方法减少了所需的导航量,并使查找内容更加容易。
  • 如果您必须停下来想一想“这段代码属于哪个区域?”,您的思路将不会被打破。每隔几分钟。
  • 实例变量通常应该很少,并且很可能在所有地方使用,因此它们属于最容易定位的类的顶部。仅在一种方法中使用的变量和声明必须存在于该方法内。如果仅由两种方法使用,则它们应垂直关闭,但应在使用它们的几种方法之上。

将代码与相互交互的元素垂直排列在一起可以有效地消除对创建特定区域的任何需求。如果您的代码太长,以至于需要区域来隐藏很多代码,那么这也许是一种代码味道,表明该类正在尝试做太多事情。也许其中一些功能可以移到实用程序类中,或者推到祖先。

如果由于代码太长或太“丑陋”而需要“隐藏”代码,那么与是否使用区域相比,您可能要担心更大的问题。我个人不需要使用它们,而在处理其他人的代码时,我总是需要打开它们,所以为什么要麻烦呢?


1
+1-令我惊讶的是,它没有被更明显地提及。内聚性原则也适用于您如何布置代码,并且按访问修饰符分组(通常(但通常不是))适得其反。
丹尼尔·B

0

我目前正在布局这样的类:

class types
constructors
destructor
accessors
methods
properties (where properties are present in the language)
member variables

然后为每个声明添加访问级别前缀(排序,有时按访问分组)。我以前是按访问权限进行顶级分组的,但是在某个时候,我不知道什么时候,它不能像上面那样很好地工作。例如,在C ++ / CLI(此刻我被迫使用:-()中,您可以执行此操作,这会弄乱按访问分组:

public: property int SomeProperty
{
private: void set (int value) { ... }
public: int get () { ... }
}

底部的“成员”是什么?对我来说,这是一个班级所有部分的统称。
梅森惠勒

@梅森:应该是“成员变量”,以避免混淆。
Skizz

我真的没有像那样按类型对事物进行分组。方法和属性之间到底有什么区别?我从来没有去过寻找类的属性,但是我会寻找逻辑上相关的代码,无论它们是属性,方法还是其他。
Ed S.

0

Lunatic的回答:我不知道,至少在C#方面。在Visual Studio和R#之间,我可以神奇地导航到任何成员或实现,因此对这些内容的关注没有任何意义。只需在光标所在的位置开始输入即可。


0

像怀亚特(Wyatt)和其他几个答案一样,我通常也避免使用区域。地区有一个目的;隐藏不需要的代码。如果一个类中有很多代码,您不想看,那么您需要很多区域来折叠所述代码,那么该类中可能有太多代码。ReSharper在决定放置新代码的位置时不会考虑区域,除非它创建了区域(它对接口实现是这样做的)。

我认为可接受的区域的一种用法是隐藏“不可避免的丑陋”代码;处理特定实现细节的代码,这些细节无法在当前标准内部进行良好地架构。这通常是高级的,深奥的代码,一般的初级程序员编写后通常不应该将其弄乱。这些是这样的:

  • 某些内置接口实现(IDisposable,IConvertible,有时是IEnumerable或IComparable,因为它们需要通用和非通用实现)
  • 嵌入式P / Invoke externs和相关结构。
  • 终结器/析构函数(通常与IDisposable一起使用)
  • 挂钩到非托管内存/指针/“不安全”代码。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.