Commit 642cfe44 authored by Johannes Salentin's avatar Johannes Salentin
Browse files

improved weakened modularity and some refactoring

parent 10805821
Pipeline #159898 passed with stages
in 1 minute and 21 seconds
......@@ -7,9 +7,11 @@ import java.util.List;
public class EASmellDetector {
public static void main(String[] args) {
// parsing of input xml to this ModelAdapter
ModelAdapter model = new ModelAdapter(args[0], args.length == 2 ? args[1] : null);
Detector.setModel(model);
// register detectors
List<Detector> detectors = new ArrayList<>();
detectors.add(new CyclicDependency());
detectors.add(new DeadComponent());
......@@ -23,6 +25,7 @@ public class EASmellDetector {
detectors.add(new StrictLayersViolation());
detectors.add(new WeakenedModularity());
// detect each smell
System.out.print("\n");
long startTotalTime = System.nanoTime();
for (Detector detector : detectors) {
......@@ -35,6 +38,8 @@ public class EASmellDetector {
System.out.println("Finished detection of " + detector.getSmellName() + " in " + time + " (" + memory + ")\n");
}
// print total result
System.out.println("The following " + Detector.getSmells().size() + " smells were detected:");
printSmells(Detector.getSmells());
String totalTime = calculateTimeConsumption(startTotalTime);
......
......@@ -13,8 +13,7 @@ public class CyclicDependency extends Detector {
}
public List<EASmell> detect() {
List<ElementType> elements = model.getElements();
for (ElementType element : elements) {
for (ElementType element : model.getElements()) {
detectCyclicDependency(element);
}
return result;
......
......@@ -13,24 +13,27 @@ public class DeadComponent extends Detector {
}
public List<EASmell> detect() {
List<ElementType> elements = model.getElements();
for (ElementType element : elements) {
Set<ElementType> cluster = model.getCluster(element);
boolean used = false;
for (RelationshipType relationship : model.getRelationships()) {
ElementType target = (ElementType) relationship.getTarget();
ElementType source = (ElementType) relationship.getSource();
// relationship to element outside the cluster -> so it is used
if ((cluster.contains(source) && !cluster.contains(target)) || (cluster.contains(target) && !cluster.contains(source))) {
used = true;
break;
}
}
if (!used) {
addToSmells(new EASmell(getSmellName(), element));
}
for (ElementType element : model.getElements()) {
detectDeadComponent(element);
}
return result;
}
private void detectDeadComponent(ElementType element) {
Set<ElementType> cluster = model.getCluster(element);
boolean used = false;
for (RelationshipType relationship : model.getRelationships()) {
ElementType target = (ElementType) relationship.getTarget();
ElementType source = (ElementType) relationship.getSource();
// relationship to element outside the cluster -> so it is used
if ((cluster.contains(source) && !cluster.contains(target)) || (cluster.contains(target) && !cluster.contains(source))) {
used = true;
break;
}
}
if (!used) {
addToSmells(new EASmell(getSmellName(), element));
}
}
}
......@@ -5,9 +5,14 @@ import de.example.main.ModelAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* A Detector is responsible for the detection of one particular smell
*/
public abstract class Detector {
static ModelAdapter model;
// detected smells of all different detectors
static List<EASmell> smells;
// detected smells of this detector
List<EASmell> result;
private String smellName;
......@@ -33,11 +38,21 @@ public abstract class Detector {
return smellName;
}
/**
* Adds the smell to both smell lists
*
* @param smell The smell to be added
*/
void addToSmells(EASmell smell) {
result.add(smell);
smells.add(smell);
}
/**
* Main method of the detector that is used to detect the smell
*
* @return result: simply use addToSmells when a smell was detected and return the list result
*/
abstract public List<EASmell> detect();
}
......@@ -14,8 +14,7 @@ public class Documentation extends Detector {
}
public List<EASmell> detect() {
List<ElementType> elements = model.getElements();
for (ElementType element : elements) {
for (ElementType element : model.getElements()) {
for (PreservedLangStringType documentation : element.getDocumentation()) {
if (documentation.getValue().length() > MAX_DOCUMENTATION_LENGTH) {
addToSmells(new EASmell(getSmellName(), element, " with a documentation of length " + documentation.getValue().length()));
......
......@@ -14,8 +14,7 @@ public class HubLikeModularization extends Detector {
}
public List<EASmell> detect() {
List<ElementType> elements = model.getElements();
for (ElementType element : elements) {
for (ElementType element : model.getElements()) {
int fanIn = model.getElementsWithReferenceTo(element).size();
int fanOut = model.getReferencedElementsOf(element).size();
if (fanIn > LARGE_FAN_IN && fanOut > LARGE_FAN_OUT) {
......
......@@ -40,6 +40,7 @@ public class MessageChain extends Detector {
private List<ElementType> getServiceChain(ElementType start, List<ElementType> current) {
List<ElementType> referencedServiceElements = model.getReferencedElementsOf(start).stream().filter(e -> e.getClass().getSimpleName().contains("Service")).collect(Collectors.toList());
List<ElementType> res = new ArrayList<>();
// no further referenced services
if (referencedServiceElements.isEmpty()) {
res.add(start);
return res;
......
......@@ -12,11 +12,10 @@ public class StrictLayersViolation extends Detector {
}
public List<EASmell> detect() {
List<RelationshipType> relationships = model.getRelationships();
List<ElementType> businessElements = model.getElementsInLayer("Business");
List<ElementType> technologyElements = model.getElementsInLayer("Technology");
if (!businessElements.isEmpty() && !technologyElements.isEmpty()) {
for (RelationshipType relationship : relationships) {
for (RelationshipType relationship : model.getRelationships()) {
ElementType source = (ElementType) relationship.getSource();
ElementType target = (ElementType) relationship.getTarget();
if ((businessElements.contains(source) && technologyElements.contains(target) || (businessElements.contains(target) && technologyElements.contains(source)))) {
......
package de.example.smells;
import de.example.model.ElementType;
import de.example.model.RelationshipType;
import java.util.List;
import java.util.Set;
import static de.example.smells.Constants.MODULARITY_RATIO;
......@@ -12,46 +14,54 @@ public class WeakenedModularity extends Detector {
super("Weakened Modularity");
}
public List<EASmell> detect() {
List<ElementType> elements = model.getElements();
for (ElementType element : elements) {
//String type = element.getClass().getSimpleName();
//if (!(type.contains("Process") || type.contains("Event") || type.contains("Function"))) {
String[] internalReferencedElements = {"Composition", "Aggregation"};
String[] internalElementsWithReference = {"Aggregation"};
int internal = model.getReferencedElementsOf(element, internalReferencedElements).size() + model.getElementsWithReferenceTo(element, internalElementsWithReference).size();
String[] externalReferencedElements = {"Triggering"};
String[] externalElementsWithReference = {"Composition", "Triggering"};
int external = model.getElementsWithReferenceTo(element, externalElementsWithReference).size() + model.getReferencedElementsOf(element, externalReferencedElements).size();
double mr = (double) internal / (double) external;
if (mr < MODULARITY_RATIO && mr > 0) {
addToSmells(new EASmell("Weakened Modularity", element, " with a modularity ratio of " + mr));
}
//}
}
return result;
}
// cluster scope
// public List<EASmell> detect() {
// for (ElementType element : model.getElements()) {
// Set<ElementType> cluster = model.getCluster(element);
// int internal = 0;
// int external = 0;
// for (RelationshipType relationship : model.getRelationships()) {
// ElementType target = (ElementType) relationship.getTarget();
// ElementType source = (ElementType) relationship.getSource();
// if (cluster.contains(source) && cluster.contains(target)) {
// internal++;
// } else if ((cluster.contains(source) && !cluster.contains(target)) || (cluster.contains(target) && !cluster.contains(source))) {
// external++;
// }
// }
// List<ElementType> elements = model.getElements();
// for (ElementType element : elements) {
// //String type = element.getClass().getSimpleName();
// //if (!(type.contains("Process") || type.contains("Event") || type.contains("Function"))) {
// String[] internalReferencedElements = {"Composition", "Aggregation", "Realization"};
// String[] internalElementsWithReference = {"Assignment"};
// int internal = model.getReferencedElementsOf(element, internalReferencedElements).size() + model.getElementsWithReferenceTo(element, internalElementsWithReference).size();
// String[] externalReferencedElements = {"Influence", "Access", "Serving", "Triggering", "Flow", "Association"};
// String[] externalElementsWithReference = {"Composition", "Triggering"};
// int external = model.getElementsWithReferenceTo(element, externalReferencedElements).size() + model.getReferencedElementsOf(element, externalReferencedElements).size();
// double mr = (double) internal / (double) external;
// if (mr < MODULARITY_RATIO && mr > 0) {
// addToSmells(new EASmell("Weakened Modularity", element, " with a modularity ratio of " + mr));
// }
// //}
// }
// return result;
// }
// cluster scope
public List<EASmell> detect() {
for (ElementType element : model.getElements()) {
Set<ElementType> cluster = model.getCluster(element);
int internal = 0;
int external = 0;
for (RelationshipType relationship : model.getRelationships()) {
ElementType target = (ElementType) relationship.getTarget();
ElementType source = (ElementType) relationship.getSource();
if (cluster.contains(source) && cluster.contains(target)) {
internal++;
} else if (isNotStructural(relationship) && ((cluster.contains(source) && !cluster.contains(target)) || (cluster.contains(target) && !cluster.contains(source)))) {
external++;
}
}
// String[] externalReferencedElements = {"Influence", "Access", "Serving", "Triggering", "Flow", "Association"};
// int external = model.getElementsWithReferenceTo(element, externalReferencedElements).size() + model.getReferencedElementsOf(element, externalReferencedElements).size();
double mr = (double) internal / (double) external;
if (mr < MODULARITY_RATIO && internal > 3) {
addToSmells(new EASmell("Weakened Modularity", element, " with a modularity ratio of " + mr));
}
}
return result;
}
private boolean isNotStructural(RelationshipType relationship) {
String type = relationship.getClass().getSimpleName();
return !type.contains("Realization") && !type.contains("Assignment") && !type.contains("Aggregation") && !type.contains("Composition");
}
}
......@@ -19,6 +19,6 @@ class TestWeakenedModularity {
@Test
void test() {
assertEquals(detector.detect().size(), 0);
assertEquals(detector.detect().size(), 3);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment