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

时间:2014-02-19 13:14:55

标签: c# coding-style resharper code-cleanup

我想这可能是一个分裂的帖子,但这是我一直在努力表达的一些事情,我想把它放到更广泛的发展中社区。

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

我很高兴能够使用任何编码标准,但我正在努力将这种方法与编写干净的代码相协调,主要是因为我严格遵守降级规则(Robert C马丁 - 清洁代码),以及字母顺序打破了。

降压规则描述如下:

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

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

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*/ }
}

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

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
}

现在,我发现第二种风格一眼就难以理解,我发现自己会在第二种风格的范围内保持不寻常的长度以保持第一种风格的可读性。其中包括:

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

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

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

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

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

1 个答案:

答案 0 :(得分:3)

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

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

    private void RunLevel2Member()
    {
        RunLevel3Member();
    }

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

    private void RunAnotherLevel2Member()
    {
        //..
    }

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

这是两种具有不同目标的不同方法。人们喜欢增强可读性(对人类而言),并允许您通过程序流程找到方法,而另一个人则喜欢通过名称快速查找方法。按字母顺序排序支持将所有公共方法放在一起的通用约定,这也增加了找出类的目的和行为的机会(一目了然)。降级愉快地混合了公共和私人方法,遵循不同的目标。

你不能兼得。因此,在任何情况下都不会违反数百条规则而忽略重构只是为了混淆这两种风格。没有任何意义,使代码的可读性更低。

如果您认为阅读降级风格比阅读字典风格的代码更舒适自然,您应该使用它。我做。

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

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

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

为了让自己更轻松,我会尝试向您的团队展示您的风格优势或接受团队大多数人喜欢的风格。

不要忘记,您的IDE会通过突出显示代码中的方法或提供“转到实现”或“查找用法”或显示方法调用顺序的代码映射等功能来帮助您。对于良好的名称和良好的设计等代码可读性,有一些更为重要的规则。

是的,但我个人更喜欢降级。