refactoring : long function - split loop

This commit is contained in:
haerong22
2022-02-26 15:55:30 +09:00
parent 0a2b13f4a7
commit 99e370ebc8
3 changed files with 220 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
package com.example.refactoring._03_long_function._12_split_loop;
import java.util.HashMap;
import java.util.Map;
public record Participant(String username, Map<Integer, Boolean> homework) {
public Participant(String username) {
this(username, new HashMap<>());
}
public double getRate(double total) {
long count = this.homework.values().stream()
.filter(v -> v == true)
.count();
return count * 100 / total;
}
public void setHomeworkDone(int index) {
this.homework.put(index, true);
}
}

View File

@@ -0,0 +1,126 @@
package com.example.refactoring._03_long_function._12_split_loop;
import org.kohsuke.github.GHIssue;
import org.kohsuke.github.GHIssueComment;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class StudyDashboard {
private final int totalNumberOfEvents;
private final List<Participant> participants;
private final Participant[] firstParticipantsForEachEvent;
public StudyDashboard(int totalNumberOfEvents) {
this.totalNumberOfEvents = totalNumberOfEvents;
participants = new CopyOnWriteArrayList<>();
firstParticipantsForEachEvent = new Participant[this.totalNumberOfEvents];
}
public static void main(String[] args) throws IOException, InterruptedException {
StudyDashboard studyDashboard = new StudyDashboard(15);
studyDashboard.print();
}
private void print() throws IOException, InterruptedException {
checkGithubIssues(getGhRepository());
new StudyPrinter(this.totalNumberOfEvents, this.participants).execute();
printFirstParticipants();
}
/**
* 하나의 반복문 안에 여러 작업을 수행하는 경우 각 작업을 따로 분리할 수 있다.
*/
private void checkGithubIssues(GHRepository ghRepository) throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(8);
CountDownLatch latch = new CountDownLatch(totalNumberOfEvents);
for (int index = 1 ; index <= totalNumberOfEvents ; index++) {
int eventId = index;
service.execute(new Runnable() {
@Override
public void run() {
try {
GHIssue issue = ghRepository.getIssue(eventId);
List<GHIssueComment> comments = issue.getComments();
checkHomeWork(comments, eventId);
Participant first = findFirst(comments);
firstParticipantsForEachEvent[eventId - 1] = first;
latch.countDown();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
});
}
latch.await();
service.shutdown();
}
private Participant findFirst(List<GHIssueComment> comments) throws IOException {
Date firstCreatedAt = null;
Participant first = null;
for (GHIssueComment comment : comments) {
Participant participant = findParticipant(comment.getUserName(), this.participants);
if (firstCreatedAt == null || comment.getCreatedAt().before(firstCreatedAt)) {
firstCreatedAt = comment.getCreatedAt();
first = participant;
}
}
return first;
}
private void checkHomeWork(List<GHIssueComment> comments, int eventId) {
for (GHIssueComment comment : comments) {
Participant participant = findParticipant(comment.getUserName(), this.participants);
participant.setHomeworkDone(eventId);
}
}
private void printFirstParticipants() {
Arrays.stream(this.firstParticipantsForEachEvent).forEach(p -> System.out.println(p.username()));
}
private GHRepository getGhRepository() throws IOException {
GitHub gitHub = GitHub.connect();
GHRepository repository = gitHub.getRepository("whiteship/live-study");
return repository;
}
private Participant findParticipant(String username, List<Participant> participants) {
return isNewParticipant(username, participants) ?
createNewParticipant(username, participants) :
findExistingParticipant(username, participants);
}
private Participant findExistingParticipant(String username, List<Participant> participants) {
Participant participant;
participant = participants.stream().filter(p -> p.username().equals(username)).findFirst().orElseThrow();
return participant;
}
private Participant createNewParticipant(String username, List<Participant> participants) {
Participant participant;
participant = new Participant(username);
participants.add(participant);
return participant;
}
private boolean isNewParticipant(String username, List<Participant> participants) {
return participants.stream().noneMatch(p -> p.username().equals(username));
}
}

View File

@@ -0,0 +1,71 @@
package com.example.refactoring._03_long_function._12_split_loop;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Comparator;
import java.util.List;
public class StudyPrinter {
private int totalNumberOfEvents;
private List<Participant> participants;
public StudyPrinter(int totalNumberOfEvents, List<Participant> participants) {
this.totalNumberOfEvents = totalNumberOfEvents;
this.participants = participants;
}
public void execute() throws IOException {
try (FileWriter fileWriter = new FileWriter("participants.md");
PrintWriter writer = new PrintWriter(fileWriter)) {
this.participants.sort(Comparator.comparing(Participant::username));
writer.print(header(this.participants.size()));
this.participants.forEach(p -> {
String markdownForHomework = getMarkdownForParticipant(p);
writer.print(markdownForHomework);
});
}
}
private String getMarkdownForParticipant(Participant p) {
return String.format("| %s %s | %.2f%% |\n", p.username(), checkMark(p, this.totalNumberOfEvents),
p.getRate(this.totalNumberOfEvents));
}
/**
* | 참여자 (420) | 1주차 | 2주차 | 3주차 | 참석율 |
* | --- | --- | --- | --- | --- |
*/
private String header(int totalNumberOfParticipants) {
StringBuilder header = new StringBuilder(String.format("| 참여자 (%d) |", totalNumberOfParticipants));
for (int index = 1; index <= this.totalNumberOfEvents; index++) {
header.append(String.format(" %d주차 |", index));
}
header.append(" 참석율 |\n");
header.append("| --- ".repeat(Math.max(0, this.totalNumberOfEvents + 2)));
header.append("|\n");
return header.toString();
}
/**
* |:white_check_mark:|:white_check_mark:|:white_check_mark:|:x:|
*/
private String checkMark(Participant p, int totalEvents) {
StringBuilder line = new StringBuilder();
for (int i = 1 ; i <= totalEvents ; i++) {
if(p.homework().containsKey(i) && p.homework().get(i)) {
line.append("|:white_check_mark:");
} else {
line.append("|:x:");
}
}
return line.toString();
}
}