Why Does Lack of Cohesion Of Methods (LCOM) Include Getters and Setters
Asked Answered
B

1

21

I am looking at the LCOM metric as shown here,

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

So we are saying a few things,

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

If I look at a class such as this,

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; }
}

It gets a bad score of 0.94 because each getter and setter doesn't access 'all of the other instance fields'.

It is calculated like this,

accessAverage - methodCount / 1 - methodCount

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

I am not understanding this metric, why should it include getters and setters? A getter and setter will always only access one single instance field.

Bread answered 16/5, 2011 at 3:58 Comment(2)
I would argue that the LCOM metric should consider automatic properties to be the same as fields.Jewfish
The thing about LCOM-like metrics is that, that Assessment thing, that's not really a class. It's just a dumb POCO (dumb having a specific, non-derogatory meaning), a struct (or record in Pascal-like parlance.) It has no behavior (behavior typically represented by state relationships among methods.) Ergo, it is not a true class. It might be from a language POV, but not from a domain POV (which is what you really care for.) I either avoid collecting LCOM metrics in POJOS or structs, or ignore the results for them. LCOM is right - it is not a class. Simply use that info accordingly.Dermatoplasty
J
27

This demonstrates that every software metric is flawed if you blindly take it to its extreme.

You know an "incohesive" class when you see one. For example:

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; } }
}

This is obviously an incohesive class, because it contains two pieces of data that don't need to be with one another.

But while it's obvious to us that this class is incohesive, how can you get a software program to determine incohesion? How would it tell that the above class is incohesive, but this isn't?

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

The metric they came up with certainly detects incohesion, but also comes up with false positives.

What if you decided this metric was important? You could create a "CustomerData" class containing just fields, and a "Customer" class that exposes the data fields as properties.

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

But if I'm playing this game, I can apply it to the incohesive example as well:

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

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

Really, I think it's best to understand what cohesion is, and why it's a worthwhile goal, but also understand that a software tool can not properly measure it.

Jaxartes answered 16/5, 2011 at 4:21 Comment(5)
Just thinking about it a bit more though, wouldn't a getter and setter only ever be accessing one field each anyway? Or is value of the metric supposed to be brought down on classes where there are heaps of methods?Bread
I guess what I am trying to say is shouldn't we remove the getters and setters? Wouldn't that give more accurate results?Bread
That then spills over into the "Properties vs Fields" debate. See csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspxJaxartes
Things with nothing but setters and getters (Java POJOs, C# POCOs , C/C++ structs), they are not classes in the true sense. They have no behavior of interest, so obviously LCOM-* metrics will give a nonsensical number (garbage in, garbage out.) Worse still if a LCOM-* tool cannot detect CustomerData as a pathological case (no methods -> no messages; no messages -> no behavior; no behavior -> not an object.) So it's not a flaw of LCOM-*, but a) a flaw of the tool taking the metric, and b) taking the LCOM results as-is without further analysis. Metrics are guides, not sacred gospel.Dermatoplasty
We take note to detect POCO in LCOM metric computationLynnett

© 2022 - 2024 — McMap. All rights reserved.