ReSharper和StyleCop与降压规则(清洁代码)

Tri*_*des 9 c# resharper coding-style code-cleanup

我想这可能是一个分裂的帖子,但这是我一直努力表达的一段时间,我想把它放到更广泛的发展社区.

我工作的角色是,在对文件进行检查之前,我们运行ReSharper自动格式化工具,该工具通过访问修饰符对区域内的事物进行分组,并按字母顺序对其中的成员进行排序.它基本上遵循这篇文章中描述的类布局模式:Visual Studio中的Alphabetizing方法,人们似乎非常热衷于此.

我很乐意使用任何编码标准,但我正在努力调和这种方法与编写干净的代码,主要是因为我严格遵守降级规则(Robert C Martin - Clean Code),以及按字母顺序打破了这一点.

降压规则描述如下:

我们希望代码能够像自上而下的叙述一样阅读.我们希望在下一个抽象层次上跟随每个函数,以便我们可以读取程序,在读取函数列表时一次降低一个抽象级别.我称之为降压规则.函数的理想参数数量为零.接下来是一个.然后两个.应尽可能避免三个论点.

按照这种方法,我可能会编写以下(人为的)代码:

public class Processor
{
    public Processor(ProcessData data)
    {
        Configure(data);
    }


    public void Configure(ProcessData data)
    {
        ClearState();
        UnpackData();
        ProcessData();
        TransformData();
        PostProcessData();
    }

    private void ClearState() { /*Snip*/ }

    private void UnpackData() { /*Snip*/ }

    private void ProcessData() { /*Snip*/ }

    private void TransformData() { /*Snip*/ }

    private void PostProcessData() { /*Snip*/ }


    public IEnumerable<GroupedRecordSet> AggregateRecords(IEnumerable<Record> records)
    {
        var groups = CalculateGrouping(records);
        PopulateGroups(groups, records);
        return groups;
    }

    private IEnumerable<GroupedRecordSet> CalculateGrouping(IEnumerable<Record> records) { /*snip*/ }

    private void PopulateGroups(IEnumerable<GroupedRecordSet> groups, IEnumerable<Record> records) { /*snip*/ }
}
Run Code Online (Sandbox Code Playgroud)

然后,当我运行自动格式时,我最终看到以下内容(注释已删除):

public class Processor
{
    #region Constructors and Destructors

    public Processor(ProcessData data)
    {
        Configure(data);
    }

    #endregion

    #region Public Methods and Operators

    public IEnumerable<GroupedRecordSet> AggregateRecords(IEnumerable<Record> records)
    {
        var groups = this.CalculateGrouping(records);
        this.PopulateGroups(groups, records);
        return groups;
    }

    public void Configure(ProcessData data)
    {
        this.ClearState();
        this.UnpackData();
        this.ProcessData();
        this.TransformData();
        this.PostProcessData();
    }

    #endregion

    #region Methods

    private IEnumerable<GroupedRecordSet> CalculateGrouping(IEnumerable<Record> records) { /*snip*/ }

    private void ClearState() { /*snip*/ }

    private void PopulateGroups(IEnumerable<GroupedRecordSet> groups, IEnumerable<Record> records) { /*snip*/ }

    private void PostProcessData() { /*snip*/ }

    private void ProcessData() { /*snip*/ }

    private void TransformData() { /*snip*/ }

    private void UnpackData() { /*snip*/ }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

现在,我发现第二种风格一目了然更难以理解,我发现自己会在第二种风格的范围内保持不寻常的长度以保持第一种风格的可读性.这些包括:

  • 所有者方法名称前缀 - 即ConfigureClearState,ConfigureUnpackData,AggregateRecordsCalculateGroupings,AggregateRecordsPopulateGroups等.这导致长成员名称,特别是如果'拥有'方法需要自己的其他'拥有'方法.
  • 解析 - 从我最初重构的小方法中移动代码,回到它来自的方法中.这导致了很长的方法.
  • 部分类 - 我还没有达到这一点,但我完全有可能最终将相关方法放入部分类中,以使它们与主体代码分开.这使用成堆的代码文件填充解决方案资源管理器.

显然,我对这些方法中的任何一种都不满意,但据我所知,它们是在操作参数中保持易读性的唯一真正选择.

显然,第二种方法是微软的家居风格,所以我想我的问题是:

  • 第二种方法是微软的家居风格是否正确?
  • 如果是这样 - 微软如何在第二种风格中保持清晰可读的代码?
  • 是否有其他人遇到过这种差异,人们用什么方法来实现高可读性?
  • 编写干净代码的一般样式首选项是什么?

我找到了Microsoft编码风格的副本:http://blogs.msdn.com/b/brada/archive/2005/01/26/361363.aspx

Bio*_*ode 5

罗伯特·马丁方法的目标是可读性。为了充分享受这些好处,您必须应用额外的约定或规则(例如,命名、为了选择有意义和描述性的名称而放弃注释、单一责任、简短的方法……)。然后您就可以像阅读普通文本文档一样阅读您的代码。如果缩进下一个抽象级别功能块也可以增强可读性。这样您就可以通过代码格式表达抽象级别:

public void Level1Member()
{
    RunLevel2Member();
    RunAnotherLevel2Member();
}

    private void RunLevel2Member()
    {
        RunLevel3Member();
    }

        private void RunLevel3Member()
        {
            //....
        }

    private void RunAnotherLevel2Member()
    {
        //..
    }
Run Code Online (Sandbox Code Playgroud)

也许您会发现自己在使用字母顺序样式时滥用鼠标滚轮,只是为了上下滚动以获取上下文。另一方面,在重构代码时,您不需要维护任何缩进和抽象级别。

这是具有不同目标的两种不同方法。一种喜欢增强可读性(对人类来说)并让您通过程序流程查找方法,而另一种喜欢您通过名称快速找到方法。按字母顺序排序支持将所有公共方法放在一起的通用约定,这也增加了(一目了然)弄清楚类的目的和行为的机会。Step-down 愉快地混合了公共和私人方法,以实现不同的目标。

你不能两者兼得。因此,在任何情况下都不要为了混合这两种风格而违反数百条规则并省略重构。没有任何意义,并且使代码的可读性大大降低。

如果您认为阅读逐步风格比阅读字典风格的代码更舒适、更自然,那么您应该使用它。我愿意。

从未听说过 Microsoft 内部约定,例如按字母顺序对代码进行排序。官方.NET 约定不针对代码结构的组织或约定(除了例如建议将事件委托放置在类的顶部等)。

降级规则只是一种非正式的风格。某些自动格式化工具不支持缩进方法,并将它们放回一级。

顺便说一句,对于关心干净和可维护代码的人来说,使用部分类来掩盖糟糕的设计(太大的类/太多的责任)并不是一个选择。

为了让你自己的事情变得更容易,我会尝试向你的团队展示你的风格的优势,或者接受你团队中大多数人喜欢的风格。

不要忘记,您的 IDE 通过突出显示代码中的方法或提供“转到实现”或“查找用法”或显示方法调用顺序的代码图等功能,可以很好地帮助您。关于代码可读性,还有一些更重要的规则,例如好的名称和好的设计。但我个人更喜欢降级。