woniper

Stopwatch Class는 무슨일을 할까? 그리고 메소드 네이밍과 책임. 본문

Spring

Stopwatch Class는 무슨일을 할까? 그리고 메소드 네이밍과 책임.

woniper 2016.08.04 18:25

  앞서 SpringApplication Class를 보면서 run 메소드 안에 StopWatch라는 클래스를 본적이 있다. 클래스 명만 보고 그냥 StopWatch 기능을하는 클래스구나하고 넘어갔는데, 오늘 문뜩 그 클래스가 생각이나서 한번 봤는데 역시나다. (java-doc 문서)


SpringApplication 클래스에서 StopWatch에 사용되는 메소드는 start, stop 를 사용하고 객체를 StartupInfoLogger.logStarted 메소드에 파라미터로 넘긴다.


start

1
2
3
4
5
6
7
8
public void start(String taskName) throws IllegalStateException {
    if (this.running) {
        throw new IllegalStateException("Can't start StopWatch: it's already running");
    }
    this.running = true;
    this.currentTaskName = taskName;
    this.startTimeMillis = System.currentTimeMillis();
}
cs

  자바에서 기본으로 제공하는 System.currentTimeMillis 메소드로 시작 시간을 변수에 저장하는 것을 볼 수 있다.


stop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void stop() throws IllegalStateException {
    if (!this.running) {
        throw new IllegalStateException("Can't stop StopWatch: it's not running");
    }
    long lastTime = System.currentTimeMillis() - this.startTimeMillis;
    this.totalTimeMillis += lastTime;
    this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
    if (this.keepTaskList) {
        this.taskList.add(lastTaskInfo);
    }
    ++this.taskCount;
    this.running = false;
    this.currentTaskName = null;
}
cs

  단순하다 start에서 저장한 시작 시간과 stop 메소드가 호출된 시간을 계산해서 저장한다. task 설명은 생략(클래스 보면 자바 개발자라면 누구나 이해 할 수 있을 정도로 쉽다.)


메소드 네이밍과 책임

  사실 이 메소드를 보다가 메소드명을 보고 메소드명으로 책임을 어떻게 가져가야할까 문뜩 떠 오른 부분이 있다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public String prettyPrint() {
    StringBuilder sb = new StringBuilder(shortSummary());
    sb.append('\n');
    if (!this.keepTaskList) {
        sb.append("No task info kept");
    }
    else {
        sb.append("-----------------------------------------\n");
        sb.append("ms     %     Task name\n");
        sb.append("-----------------------------------------\n");
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMinimumIntegerDigits(5);
        nf.setGroupingUsed(false);
        NumberFormat pf = NumberFormat.getPercentInstance();
        pf.setMinimumIntegerDigits(3);
        pf.setGroupingUsed(false);
        for (TaskInfo task : getTaskInfo()) {
            sb.append(nf.format(task.getTimeMillis())).append("  ");
            sb.append(pf.format(task.getTimeSeconds() / getTotalTimeSeconds())).append("  ");
            sb.append(task.getTaskName()).append("\n");
        }
    }
    return sb.toString();
}
cs

  StopWatch 클래스에 prettyPrint라는 메소드를 보고 문뜩 spring에서 controller test 코드 작성 시 사용했던 MockMvcResultHandlers.pinrt()가 생각났다. 단순히 메소드명에 print가 들어갔기 때문에 생각났다.

  print라는 단어가 들어간 메소드는 어떤 역할을 하고 있을지 궁금했기 때문이다. 위 코드를 보면 보다 시피 prettyPrint 메소드는 어디에도 데이터를 출력하는 부분이 없다. 그런데 MockMvcResultHandlers.print 메소드는(소스는 생략) 실제로 출력하는 책임도 담당하는데, print라는 단어가 포함된 메소드는 실제로 데이터를 출력하는게 맞는것인가 아니면 출력할 문자열을 반환하는게 맞는것인가? 정답은 모르겠다. 일단 고민거리 하나 던지고 마무리.

4 Comments
  • 프로필사진 BlogIcon 나모찾기 2019.03.19 12:22 신고 prettyPrint() 의 역할은 출력을 예쁘게(pretty) 위한 유틸리티성 클래스일 것 같아요. 찍을 위치는 호출하는 사람에게 위임을 하고 단순히 문자열로 반환을 받은 것이지요.
    Stopwatch는 스프링 부트 애플리케이션이 실행할 때 수행 시간을 계산하는 용도로 쓰이지요.

    run 메서드 내부에서 애플리케이션을 초기화하여 가동시키고 콘텍스트를 새로고침(refreshContext) 후에 시간 측정을 멈추죠.

    refreshContext(context);
    afterRefresh(context, applicationArguments);
    stopWatch.stop();
    if (this.logStartupInfo) {
    new StartupInfoLogger(this.mainApplicationClass)
    .logStarted(getApplicationLog(), stopWatch);
    }

    스프링 부트 애플리케이션을 수행하면
    "Started ...Application in 1.323 seconds" 와 비슷한 메세지가 나오는데 여기서 1.323 seconds 라는 내용이 StopWatch에 의해 계산되었다고 보시면 됩니다.
  • 프로필사진 BlogIcon woniper 2019.03.20 09:30 신고 의견 주셔서 감사합니다.

    저는 print 메소드는 출력을하는데, prettyPrint는 단순히 문자열을 이쁘게 만들어 반환하는데 print라는 메소드명이 포함되어야하나 생각이 들었습니다.

    댓글 달아주시고 의견주셔서 다시 한번 감사합니다.
  • 프로필사진 BlogIcon 나모찾기 2019.03.20 09:37 신고 저도 print라는 이름보다는 getPrettyMessage정도가 좋지 않을까 생각하네요.
  • 프로필사진 BlogIcon woniper 2019.03.20 09:38 신고 네 저도 동감합니다 ㅎㅎ
댓글쓰기 폼