This page aims to present different queries one might want to perform when analyzing a model. It can be used as a baseline for further analysis.
We present how to perform the queries in a playground or with the visual tool proposed by Moose.
The shortest way to find a class with a name is to use the
classes := model allWithType: FamixStClass. withPrefix := classes detect: [ :class | class name = #'MyClassName' ].
When performing queries, it is often useful to start with a substep of classes by looking at their names.
This can be done easily using the
beginWith: and the
classes := model allWithType: FamixStClass. withPrefix := classes select: [ :class | class name beginsWith: #'MyPrefix' ]. withSuffix := classes select: [ :class | class name endsWith: #'MySuffix' ]
God classes are classes that knows too much or does too much. One way to find god classes is to count the number of lines or the number of methods of a class.
Using a playground, one can perform a query on a model to retrieve the god classes by numbers of lines:
model allModelClasses select: [ :each | each numberOfLinesOfCode > 150 ]
Or by numbers of methods:
model allModelClasses select: [ :each | each numberOfMethods > 50 ]
The cyclomatic complexity presents the complixity of a program. It basically corresponds to the number of possible branches in a method. The less cyclomatic complexity for a method, the better it is.
The following script sorts the methods extracted in a model by their cyclomatic complexity.
((self model allBehaviourals) collect: [ :entity | entity -> entity cyclomaticComplexity ] thenSelect: [ :assoc | assoc value > 3 ]) asOrderedCollection sort: #value descending
Deprecated methods are methods existing in the current version of an application, and that will disappear in the next version. Such a method should not be used.
In Java, it is possible to retrieve the deprecated methods by searching the method with the
model allModelMethods select: [ :t | t annotationInstances notEmpty and: [ t annotationTypes anySatisfy: [ :a | a name = 'Deprecated' ] ] ]
Dead methods are methods that are not invoked by any other methods.
Be careful; some methods might not be directly called but are referenced thanks to abstraction or are dedicated to be extended by another application. It is often the case when dealing with a framework.
model allModelMethods collect: [ :method | method -> method incomingInvocations ] thenSelect: [ :assoc | assoc value isEmpty ]) asOrderedCollection
^ (model allModelMethods select: [ :t | t annotationInstances notEmpty and: [ t annotationTypes anySatisfy: [ :annotation | annotation name endsWith: 'Test' ] ] ]) asOrderedCollection flattened
The class hierarchy presents the classes of a model with their hierarchy links (e.g. superclass, subclasses, …). It also includes the methods and attributes of each class.
builder := RSUMLClassBuilder new. classes := mooseModel allModelClasses. builder modelDescriptor instVars: [ :aFamixClass | aFamixClass attributes ]; instVarSelector: [:aFamixAttribute | aFamixAttribute name]; methods: [ :aFamixClass | aFamixClass methods]; methodSelector: [:aFamixMethod | aFamixMethod name]. builder classes: classes. builder build. builder canvas @ RSHierarchyPacker. builder canvas
tarjan := MalTarjan new. tarjan nodes: model allModelNamespaces. tarjan edges: model allModelNamespaces from: #yourself toAll: [ :a | a allProvidersAtScope: FamixTNamespace ]. tarjan run. tarjan inspect
It is possible to visualize the meta-model with a class hierarchy.
builder := RSUMLClassBuilder new. classes := FamixJavaModel metamodel classes. builder modelDescriptor instVars: [ :metaDescription | metaDescription primitiveProperties ]; instVarSelector: [:metaDescription | metaDescription implementingSelector]; methods: [ :metaDescription | metaDescription complexProperties]; methodSelector: [:metaDescription | metaDescription implementingSelector]. builder classes: classes. builder build. builder canvas @ RSHierarchyPacker. builder canvas