【问题标题】:Why Does Lack of Cohesion Of Methods (LCOM) Include Getters and Setters为什么缺乏凝聚力的方法(LCOM)包括getter和setter
【发布时间】:2011-08-26 03:54:31
【问题描述】:

我正在查看此处显示的 LCOM 指标,

http://www.ndepend.com/Metrics.aspx

所以我们要说几件事,

1) A class is utterly cohesive if all its methods use all its instance fields
2) Both static and instance methods are counted, it includes also constructors, properties getters/setters, events add/remove methods

如果我看到这样的课程,

public class Assessment
{
    public int StartMetres { get; set; }
    public int EndMetres { get; set; }
    public decimal? NumericResponse { get; set; }
    public string FreeResponse { get; set; }
    public string Responsetype { get; set; }
    public string ItemResponseDescription { get; set; }
    public string StartText { get; set; }
    public decimal? SummaryWeight { get; set; }
}

因为每个 getter 和 setter 都没有访问“所有其他实例字段”,所以它得到了 0.94 的差分。

是这样计算的,

accessAverage - methodCount / 1 - methodCount

(2 - 17) / (1 - 17) = 0.94 (rounded)

我不理解这个指标,为什么它应该包括 getter 和 setter? getter 和 setter 将始终只访问一个实例字段。

【问题讨论】:

  • 我认为 LCOM 指标应该考虑自动属性与字段相同。
  • 类似 LCOM 的指标的问题是,Assessment 的东西,这不是一个真正的类。它只是一个愚蠢的 POCO(dumb 具有特定的、非贬义的含义),一个结构(或类似 Pascal 的说法中的记录。)它没有行为(行为通常由方法之间的状态关系表示。)因此,它是不是真正的类。它可能来自语言 POV,但不是来自域 POV(这是您真正关心的)。我要么避免在 POJOS 或结构中收集 LCOM 指标,要么忽略它们的结果。 LCOM 是对的——它不是一个类。只需相应地使用该信息。

标签: c# .net ndepend lcom


【解决方案1】:

这表明,如果你盲目地将其发挥到极致,每个软件指标都会存在缺陷。

当你看到一个“不连贯”的课程时,你就知道了。例如:

class HedgeHog_And_AfricanCountry
{

   private HedgeHog _hedgeHog;
   private Nation _africanNation;

   public ulong NumberOfQuills { get { return _hedgeHog.NumberOfQuills; } }
   public int CountOfAntsEatenToday { get { return _hedgeHog.AntsEatenToday.Count(); } }

   public decimal GrossDomesticProduct { get { return _africanNation.GDP; } }
   public ulong Population { get { return _africanNation.Population; } }
}

这显然是一个没有凝聚力的类,因为它包含两条不需要相互关联的数据。

但是,虽然对我们来说很明显这个类是不连贯的,但是你怎么能得到一个软件程序来确定不连贯呢?它如何判断上面的类没有凝聚力,但事实并非如此?

class Customer
{
    public string FullName { get; set; }
    public Address PostalAddress { get; set; }
} 

他们提出的指标肯定会检测到内聚性,但也会出现误报。

如果您认为该指标很重要怎么办?您可以创建一个仅包含字段的“CustomerData”类,以及一个将数据字段作为属性公开的“Customer”类。

// This has no methods or getters, so gets a good cohesion value.
class CustomerData
{
    public string FullName;
    public Address PostalAddress;
}

// All of the getters and methods are on the same object
class Customer
{
   private CustomerData _customerData;
   public string FullName { get { return _customerData.FullName; } }
   // etc
}

但如果我在玩这个游戏,我也可以将它应用到不连贯的例子中:

class Hedgehog_And_AfricanCountry_Data
{
   public Hedgehog _hedgehog;
   public AfricanNation _africanNation;
}

class Hedgehog_And_AfricanCountry
{
   private Hedgehog_And_AfricanCountry_Data _hedgehogAndAfricanCountryData;
   // etc;
}

真的,我认为最好了解什么是凝聚力,以及为什么它是一个值得的目标,但也要了解软件工具无法正确衡量它。

【讨论】:

  • 再想一想,getter 和 setter 不都只能访问一个字段吗?还是应该在有大量方法的类上降低指标的价值?
  • 我想我想说的是我们不应该删除 getter 和 setter 吗?这不会给出更准确的结果吗?
  • 然后溢出到“属性与字段”的辩论中。见csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx
  • 只有 setter 和 getter 的东西(Java POJO、C# POCO、C/C++ 结构),它们不是真正意义上的类。他们没有感兴趣的行为,因此显然 LCOM-* 指标会给出一个无意义的数字(垃圾进,垃圾出)。更糟糕的是,如果 LCOM-* 工具无法将 CustomerData 检测为病态情况(没有方法 -> 没有消息; 没有消息 -> 没有行为; 没有行为 -> 不是对象。)所以这不是 LCOM-* 的缺陷,而是 a) 采用度量的工具的缺陷,b) 按原样获取 LCOM 结果而没有进一步的分析。指标是指南,而不是神圣的福音。
  • 我们注意到在 LCOM 度量计算中检测 POCO
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
相关资源
最近更新 更多