Skip to content

Commit 2ed4f58

Browse files
Merge pull request #59 from jimbethancourt/feat/CBO
Feat/cbo
2 parents 8baf5c9 + cdde3b4 commit 2ed4f58

File tree

21 files changed

+397
-153
lines changed

21 files changed

+397
-153
lines changed

RefactorFirst_Sample_Report.png

35.3 KB
Loading

change-proneness-ranker/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.hjug.refactorfirst</groupId>
77
<artifactId>refactor-first</artifactId>
8-
<version>0.3.1-SNAPSHOT</version>
8+
<version>0.4.0-SNAPSHOT</version>
99
</parent>
1010

1111
<groupId>org.hjug.refactorfirst.changepronenessranker</groupId>

cost-benefit-calculator/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.hjug.refactorfirst</groupId>
77
<artifactId>refactor-first</artifactId>
8-
<version>0.3.1-SNAPSHOT</version>
8+
<version>0.4.0-SNAPSHOT</version>
99
</parent>
1010

1111
<groupId>org.hjug.refactorfirst.costbenefitcalculator</groupId>

cost-benefit-calculator/src/main/java/org/hjug/cbc/CostBenefitCalculator.java

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
import org.hjug.git.GitLogReader;
1414
import org.hjug.git.RepositoryLogReader;
1515
import org.hjug.git.ScmLogInfo;
16-
import org.hjug.metrics.GodClass;
17-
import org.hjug.metrics.GodClassRanker;
18-
import org.hjug.metrics.PMDGodClassRuleRunner;
16+
import org.hjug.metrics.*;
1917

2018
@Slf4j
2119
public class CostBenefitCalculator {
2220

23-
public List<RankedDisharmony> calculateCostBenefitValues(String repositoryPath) {
21+
Map<String, ByteArrayOutputStream> filesToScan = new HashMap<>();
22+
23+
public List<RankedDisharmony> calculateGodClassCostBenefitValues(String repositoryPath) {
2424

2525
RepositoryLogReader repositoryLogReader = new GitLogReader();
2626
Repository repository = null;
@@ -31,7 +31,7 @@ public List<RankedDisharmony> calculateCostBenefitValues(String repositoryPath)
3131
log.error("Failure to access Git repository", e);
3232
}
3333

34-
List<GodClass> godClasses = getGodClasses(repositoryLogReader, repository);
34+
List<GodClass> godClasses = getGodClasses(getFilesToScan(repositoryLogReader, repository));
3535

3636
List<ScmLogInfo> scmLogInfos = getRankedChangeProneness(repositoryLogReader, repository, godClasses);
3737

@@ -46,12 +46,12 @@ public List<RankedDisharmony> calculateCostBenefitValues(String repositoryPath)
4646
return rankedDisharmonies;
4747
}
4848

49-
List<ScmLogInfo> getRankedChangeProneness(
50-
RepositoryLogReader repositoryLogReader, Repository repository, List<GodClass> godClasses) {
49+
<T extends Disharmony> List<ScmLogInfo> getRankedChangeProneness(
50+
RepositoryLogReader repositoryLogReader, Repository repository, List<T> disharmonies) {
5151
List<ScmLogInfo> scmLogInfos = new ArrayList<>();
5252
log.info("Calculating Change Proneness for each God Class");
53-
for (GodClass godClass : godClasses) {
54-
String path = godClass.getFileName();
53+
for (Disharmony disharmony : disharmonies) {
54+
String path = disharmony.getFileName();
5555
ScmLogInfo scmLogInfo = null;
5656
try {
5757
scmLogInfo = repositoryLogReader.fileLog(repository, path);
@@ -67,17 +67,10 @@ List<ScmLogInfo> getRankedChangeProneness(
6767
return scmLogInfos;
6868
}
6969

70-
private List<GodClass> getGodClasses(RepositoryLogReader repositoryLogReader, Repository repository) {
71-
Map<String, ByteArrayOutputStream> filesToScan = new HashMap<>();
72-
log.info("Identifying God Classes from files in repository");
73-
try {
74-
filesToScan = repositoryLogReader.listRepositoryContentsAtHEAD(repository);
75-
} catch (IOException e) {
76-
log.error("Error reading Git repository contents", e);
77-
}
78-
70+
private List<GodClass> getGodClasses(Map<String, ByteArrayOutputStream> filesToScan) {
7971
PMDGodClassRuleRunner ruleRunner = new PMDGodClassRuleRunner();
8072

73+
log.info("Identifying God Classes from files in repository");
8174
List<GodClass> godClasses = new ArrayList<>();
8275
for (Map.Entry<String, ByteArrayOutputStream> entry : filesToScan.entrySet()) {
8376
String filePath = entry.getKey();
@@ -92,4 +85,61 @@ private List<GodClass> getGodClasses(RepositoryLogReader repositoryLogReader, Re
9285
godClassRanker.rankGodClasses(godClasses);
9386
return godClasses;
9487
}
88+
89+
public List<RankedDisharmony> calculateCBOCostBenefitValues(String repositoryPath) {
90+
91+
RepositoryLogReader repositoryLogReader = new GitLogReader();
92+
Repository repository = null;
93+
log.info("Initiating Cost Benefit calculation");
94+
try {
95+
repository = repositoryLogReader.gitRepository(new File(repositoryPath));
96+
} catch (IOException e) {
97+
log.error("Failure to access Git repository", e);
98+
}
99+
100+
List<CBOClass> cboClasses = getCBOClasses(getFilesToScan(repositoryLogReader, repository));
101+
102+
List<ScmLogInfo> scmLogInfos = getRankedChangeProneness(repositoryLogReader, repository, cboClasses);
103+
104+
Map<String, ScmLogInfo> rankedLogInfosByPath =
105+
scmLogInfos.stream().collect(Collectors.toMap(ScmLogInfo::getPath, logInfo -> logInfo, (a, b) -> b));
106+
107+
List<RankedDisharmony> rankedDisharmonies = new ArrayList<>();
108+
for (CBOClass cboClass : cboClasses) {
109+
rankedDisharmonies.add(new RankedDisharmony(cboClass, rankedLogInfosByPath.get(cboClass.getFileName())));
110+
}
111+
112+
return rankedDisharmonies;
113+
}
114+
115+
private List<CBOClass> getCBOClasses(Map<String, ByteArrayOutputStream> filesToScan) {
116+
117+
CBORuleRunner ruleRunner = new CBORuleRunner();
118+
119+
log.info("Identifying highly coupled classes from files in repository");
120+
List<CBOClass> cboClasses = new ArrayList<>();
121+
for (Map.Entry<String, ByteArrayOutputStream> entry : filesToScan.entrySet()) {
122+
String filePath = entry.getKey();
123+
ByteArrayOutputStream value = entry.getValue();
124+
125+
ByteArrayInputStream inputStream = new ByteArrayInputStream(value.toByteArray());
126+
Optional<CBOClass> godClassOptional = ruleRunner.runCBOClassRule(filePath, inputStream);
127+
godClassOptional.ifPresent(cboClasses::add);
128+
}
129+
130+
return cboClasses;
131+
}
132+
133+
private Map<String, ByteArrayOutputStream> getFilesToScan(
134+
RepositoryLogReader repositoryLogReader, Repository repository) {
135+
136+
try {
137+
if (filesToScan.isEmpty()) {
138+
filesToScan = repositoryLogReader.listRepositoryContentsAtHEAD(repository);
139+
}
140+
} catch (IOException e) {
141+
log.error("Error reading Git repository contents", e);
142+
}
143+
return filesToScan;
144+
}
95145
}

cost-benefit-calculator/src/main/java/org/hjug/cbc/RankedDisharmony.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.time.Instant;
55
import lombok.Data;
66
import org.hjug.git.ScmLogInfo;
7+
import org.hjug.metrics.CBOClass;
78
import org.hjug.metrics.GodClass;
89

910
@Data
@@ -14,14 +15,15 @@ public class RankedDisharmony {
1415
private final String className;
1516
private final Integer effortRank;
1617
private final Integer changePronenessRank;
17-
private final Integer priority;
18+
private final Integer rawPriority;
19+
private Integer priority;
1820

19-
private final Integer wmc;
20-
private final Integer wmcRank;
21-
private final Integer atfd;
22-
private final Integer atfdRank;
23-
private final Float tcc;
24-
private final Integer tccRank;
21+
private Integer wmc;
22+
private Integer wmcRank;
23+
private Integer atfd;
24+
private Integer atfdRank;
25+
private Float tcc;
26+
private Integer tccRank;
2527

2628
private final Instant firstCommitTime;
2729
private final Instant mostRecentCommitTime;
@@ -34,7 +36,7 @@ public RankedDisharmony(GodClass godClass, ScmLogInfo scmLogInfo) {
3436
className = godClass.getClassName();
3537
changePronenessRank = scmLogInfo.getChangePronenessRank();
3638
effortRank = godClass.getOverallRank();
37-
priority = changePronenessRank - effortRank;
39+
rawPriority = changePronenessRank - effortRank;
3840

3941
wmc = godClass.getWmc();
4042
wmcRank = godClass.getWmcRank();
@@ -47,4 +49,18 @@ public RankedDisharmony(GodClass godClass, ScmLogInfo scmLogInfo) {
4749
mostRecentCommitTime = Instant.ofEpochSecond(scmLogInfo.getMostRecentCommit());
4850
commitCount = scmLogInfo.getCommitCount();
4951
}
52+
53+
public RankedDisharmony(CBOClass cboClass, ScmLogInfo scmLogInfo) {
54+
path = scmLogInfo.getPath();
55+
// from https://stackoverflow.com/questions/1011287/get-file-name-from-a-file-location-in-java
56+
fileName = Paths.get(path).getFileName().toString();
57+
className = cboClass.getClassName();
58+
changePronenessRank = scmLogInfo.getChangePronenessRank();
59+
effortRank = cboClass.getCouplingCount();
60+
rawPriority = changePronenessRank - effortRank;
61+
62+
firstCommitTime = Instant.ofEpochSecond(scmLogInfo.getEarliestCommit());
63+
mostRecentCommitTime = Instant.ofEpochSecond(scmLogInfo.getMostRecentCommit());
64+
commitCount = scmLogInfo.getCommitCount();
65+
}
5066
}

cost-benefit-calculator/src/test/java/org/hjug/cbc/CostBenefitCalculatorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ void testCostBenefitCalculation() throws IOException, GitAPIException, Interrupt
6060
RevCommit secondCommit = git.commit().setMessage("message").call();
6161

6262
CostBenefitCalculator costBenefitCalculator = new CostBenefitCalculator();
63-
List<RankedDisharmony> disharmonies = costBenefitCalculator.calculateCostBenefitValues(
63+
List<RankedDisharmony> disharmonies = costBenefitCalculator.calculateGodClassCostBenefitValues(
6464
git.getRepository().getDirectory().getPath());
6565

6666
Assertions.assertEquals(0, disharmonies.get(0).getPriority().intValue());

coverage/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<parent>
88
<groupId>org.hjug.refactorfirst</groupId>
99
<artifactId>refactor-first</artifactId>
10-
<version>0.3.1-SNAPSHOT</version>
10+
<version>0.4.0-SNAPSHOT</version>
1111
</parent>
1212

1313
<artifactId>coverage</artifactId>

effort-ranker/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.hjug.refactorfirst</groupId>
77
<artifactId>refactor-first</artifactId>
8-
<version>0.3.1-SNAPSHOT</version>
8+
<version>0.4.0-SNAPSHOT</version>
99
</parent>
1010

1111
<groupId>org.hjug.refactorfirst.effortranker</groupId>
@@ -20,7 +20,7 @@
2020
<dependency>
2121
<groupId>org.hjug.refactorfirst.testresources</groupId>
2222
<artifactId>test-resources</artifactId>
23-
<version>0.3.1-SNAPSHOT</version>
23+
<version>0.4.0-SNAPSHOT</version>
2424
</dependency>
2525

2626
<dependency>

effort-ranker/src/main/java/org/hjug/metrics/CBOClass.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Created by Jim on 11/16/2016.
88
*/
99
@Data
10-
public class CBOClass {
10+
public class CBOClass implements Disharmony {
1111

1212
private String className;
1313
private String fileName;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.hjug.metrics;
2+
3+
public interface Disharmony {
4+
5+
String getFileName();
6+
}

0 commit comments

Comments
 (0)