A meta-model offers the vocabulary for defining reasonings about a given class of models. This is a critical piece in making analyses simple to build.
Let us consider the case of computing the Tight Class Cohesion metric. This is a classic metric that calculates, as the name says, the cohesiveness of a class. The idea stems from the observation that a class is deemed cohesive if the methods work with the same attributes. Technically, the metric computes the number of method pairs that use at least one variable in common, and divides it by the total number of method pairs in the class. The result is a value between 0..1, 0 meaning no cohesion, and 1 meaning full cohesion.
There are a couple of variations of how various people interpret the definition of the metric, but a possible pseudocode can be:
tightClassCohesion (classSource) count = 0 methodCount = methodBodies(classSource) attributes = attributes(classSource) methodsToAttributes = new Dictionary for (methodBody in methodBodies(classSource)) accessedAttributes = new Set for (statement in methodBody) accessedAttributes.add(attributesIn(statement)) end methodsToAttributes.put(methodBody, accessedAttributes) end for (methodToAttributes in methodsToAttributes) for (attribute in methodToAttributes.value) for (methodToAttributes2 in methodsToAttributes) if (methodToAttributes.value.contains(attribute) & methodToAttributes ~= methodToAttributes2) count++ end end end end return count / methodCount * (methodCount - 1) / 2 end
The code does the job, but in a rather obscure way. It actually could be even more obscure, would it not be for the helper methods like methodBodies
or attributes
. The obscurity comes from the main logic being intertwined with implementation details of building intermediary data structures. Take a look at methodToAttributes
and methodToAttributes2
. Their main goal is simply to offer some structure for further computation.
Once we have a better representation of the data we want to manipulate, the code becomes much simpler:
Class::tightClassCohesion () count = 0 methodCount = this.methods.size() for (attribute in this.attributes) temp = attribute.accessingMethods() count = count + temp * (temp - 1) / 2 end return count / methodCount * (methodCount - 1) / 2 end
In this case, the code exposes primarily the intended logic. The means to extract it from the data becomes transparent. This is the power of an expressive meta-model.
In a sense, meta-modeling is nothing but object-oriented design. But, object-oriented design has a larger meaning. The main focus of meta-modeling is to get the formulating of reasonings on top of the data. Performance can be a concern too (for example, by means of smart caches), but the essence is on getting the analysis code clean and easy to write.
So, next time you will be presented an analysis tool, ask about the meta-model. The functionality is important, too, but if you cannot understand what it does and how to customize it, it is close to useless.