프로그래밍 언어/Spring

<Spring>LMS 프로젝트 3. 학생 출결 로직 작성(1) 로직 작성

창조적생각 2021. 10. 29. 11:37

 

*본 프로젝트는 JSP 팀 프로젝트로 만들었던 Learning Management System을 Spring으로 이식하는 과정입니다.

**본 프로젝트는 김영한 선생님의 인프런 강의 스프링 핵심원리 - 기본편

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 개발자가 되어보세요! 📣 확인해주

www.inflearn.com

을 바탕으로 실습하는 과정입니다. 스프링에 대해서 배우고 싶으시다면 이 강의를 들어보시는 것도 좋을 것입니다.

 

개발 환경

IDK : intelliJ

JDK : 자바 11

의존성은 김영한 선생님의 강의 순서대로 하기 위해 아무것도 넣지 않고 시작한다.

 

배운 것을 바탕으로 학생의 출결 정보를 출력하는 로직을 작성한다.

학생의 출석 시간과 퇴실시간을 입력받아 출석, 지각, 조퇴, 결석을 판별하여 출력한다.

 

 

*다이어그램은 UML방식에 아직 완전히 숙달되지 않아 임의적으로 그리는 것입니다. 양해바랍니다.

 

출석 정보는 후에 저장소를 만들어 저장하기로 한다.

1. 클라이언트가 학생 ID와 입실시간, 퇴실시간을 전송하면,

2. AttendService에서 그 값을 받아서 출결을 판별한다.

 

조건은

1) 입실시간이 9:00 이전이고 퇴실시간이 16:50 - 24:00 사이라면 정시출석으로 인정한다.

2) 입실시간이 9:00 - 12:00 사이이고 퇴실시간이 16:50 - 24:00 사이라면 지각으로 처리한다.

3) 입실시간이 9:00 - 12:00 사이이고 퇴실시간이 16:50 이전이라면 조퇴로 처리한다.

4) 결석은 이후에 관리자가 하루가 지난 후 수정을 통해 일괄처리한다.

 

기타 자세한 조건은 Memory저장소가 아닌 외부 데이터저장소를 사용할 때 지정하고 기본적인 로직만 규칙에 맞게 작성하기로 한다.

 

 

1.Attend 엔티티 작성하기

 

<Enum AttendStandard>

1
2
3
4
5
6
7
8
9
package eleven.lms.attend;
 
public enum AttendStandard {
    present,
    late,
    earlyLeave,
    absence
}
 
cs

출석,지각,조퇴,결석을 열거형 AttendStandard 안에 넣어둔다.

 

<Class MemberAttend>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package eleven.lms.attend;
 
import java.util.Date;
 
public class MemberAttend {
    private String memberId;
    private AttendStandard attendStandard;//출석,지각,조퇴,결석
    private Date inTime;//입실 시간
    private Date outTime;//퇴실 시간
 
    public MemberAttend(String memberId, Date inTime, Date outTime) {
        this.memberId = memberId;
        this.inTime = inTime;
        this.outTime = outTime;
    }
 
    public String getMemberId() {
        return memberId;
    }
 
    public void setMemberId(String memberId) {
        this.memberId = memberId;
    }
 
    public AttendStandard getAttendStandard() {
        return attendStandard;
    }
 
    public void setAttendStandard(AttendStandard attendStandard) {
        this.attendStandard = attendStandard;
    }
 
    public Date getInTime() {
        return inTime;
    }
 
    public void setInTime(Date inTime) {
        this.inTime = inTime;
    }
 
    public Date getOutTime() {
        return outTime;
    }
 
    public void setOutTime(Date outTime) {
        this.outTime = outTime;
    }
 
    @Override
    public String toString() {
        return "MemberAttend{" +
                "memberId='" + memberId + '\'' +
                ", attendStandard=" + attendStandard +
                ", inTime=" + inTime +
                ", outTime=" + outTime +
                '}';
    }
}
cs

 

1)회원의 ID로 검색을 하기 위해 회원의 memberID, 출결을 판별하기 위한 Date 타입의 자료 InTime, OutTime, 그리고 출결 판별을 위해 AttendStandard를 선언해주고 getter setter를 작성한다.

 

2)테스트를 위해 Intime, OutTime 그리고 memberId를 매개변수로 하는 생성자를 작성해준다.

 

3)결과를 보기 위한  toString 도 작성해준다.

 

2. 출결 판별 로직 작성하기

 

<Interface AttendPolicy>

 

반환타입이 AttendStandard이고 매개변수는 MemberAttend인 출석판별 메서드 JudgeAttend를 선언한다.

1
2
3
4
5
6
7
8
9
package eleven.lms.attendrule;
 
import eleven.lms.attend.AttendStandard;
import eleven.lms.attend.MemberAttend;
 
public interface AttendPolicy {
    AttendStandard JudgeAttend(MemberAttend memberAttend);
}
 
cs

<Class OneDayPolicy>

AttendPolicy를 구현하는 OneDayPolicy를 작성한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package eleven.lms.attendrule;
 
import eleven.lms.attend.AttendStandard;
import eleven.lms.attend.MemberAttend;
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class OneDayPolicy implements AttendPolicy{
    SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss");
    Date startTime = dateFormat.parse("09:00:00");
    Date endTime = dateFormat.parse("16:50:00");
 
    public OneDayPolicy() throws ParseException {
    }
 
    @Override
    public AttendStandard JudgeAttend(MemberAttend memberAttend) {
        if (memberAttend.getInTime().compareTo(startTime)<=0 && memberAttend.getOutTime().compareTo(endTime)>=0){
            return AttendStandard.present;
        }
        if (memberAttend.getInTime().compareTo(startTime)>0 && memberAttend.getOutTime().compareTo(endTime)>=0){
            return AttendStandard.late;
        }
        if (memberAttend.getOutTime().compareTo(endTime)<=0){
            return AttendStandard.earlyLeave;
        }
        else return AttendStandard.absence;
    }
}
cs

1) SimpleDateFormat을 이용하여 시간 형식을 지정한다. 지금은 간단하게 로직이 돌아가는 것만 확인하기 위해

"hh:mm:ss" 시분초만을 입력하기로 한다.

 

2) startTime 은 오전 9시로 지정하고 endTime은 16:50으로 지정하여 기준 시간을 작성해 준다.

 

3)JudgeAttend를 구현한다.

  (1) 입실시간이 9:00 이전이고 퇴실시간이 16:50 - 24:00 사이라면 정시출석으로 인정한다.

  (2) 입실시간이 9:00 - 12:00 사이이고 퇴실시간이 16:50 - 24:00 사이라면 지각으로 처리한다.

  (3) 입실시간이 9:00 - 12:00 사이이고 퇴실시간이 16:50 이전이라면 조퇴로 처리한다.

  (4) 그 외에는 결석 처리를 한다.

 

위의 로직을 util.Date 안의 compareT0()를 사용하여 작성한다.

 

3. 로직을 통해 판별한 출석상태를 AttendMember에 추가하기

 

<Interface AttendService>

출결상태를 AttendMember에 추가하는 메서드 createAttend를 작성한다.

1
2
3
4
5
6
7
8
package eleven.lms.attend;
 
public interface AttendService {
    public void CreateAttend(MemberAttend memberAttend);
 
    public String findById(String MemberId);
}
 
cs

 

<Class AttendServiceImpl>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
public class AttendServiceImpl implements AttendService {
    AttendPolicy attendPolicy = new OneDayPolicy();
 
    public AttendServiceImpl() throws ParseException {
    }
 
    @Override
    public void CreateAttend(MemberAttend memberAttend) {
        memberAttend.setAttendStandard(attendPolicy.JudgeAttend(memberAttend));
    }
 
    @Override
    public String findById(String MemberId) {
        return null;
    }
}
 
cs

AttendPolicy의 구현체로 OneDayPolicy를 선택해줍니다.

CreateAttend 메서드를 작성해줍니다.

memberAttend에 AttendStandard에 judgeAttend메서드를 사용하여 AttendStandard를 지정해줍니다.

 

<class AttendServiceTest>

 

잘 작동하는지 테스트 클래스를 만들어 테스트해봅니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package eleven.lms.attend;
 
import eleven.lms.attendrule.AttendPolicy;
import eleven.lms.attendrule.OneDayPolicy;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import static org.junit.jupiter.api.Assertions.*;
 
class AttendServiceTest {
 
    @Test
    void createAttend() throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss");
        Date start = dateFormat.parse("08:56:00");
        Date end = dateFormat.parse("16:00:00");
        MemberAttend memberAttend = new MemberAttend("memberA",start,end);
        AttendPolicy attendPolicy = new OneDayPolicy();
 
        memberAttend.setAttendStandard(attendPolicy.JudgeAttend(memberAttend));
 
       Assertions.assertThat(memberAttend.getAttendStandard().equals(AttendStandard.earlyLeave));
        System.out.println(memberAttend);
 
 
    }
}
cs

MemberAttend에 ("MemberA","08:56:00","16:00:00")을 넣고 어떻게 출력이 되는지 봅니다.

*아직 Assertions를 정확하게 잘 몰라서 주석처리했습니다.

**모든 출석상태와 비교해도 다 통과가 잘되서 이것은 조금 더 공부를 해봐야할 것같습니다.

 

<출력결과>

잘 적용이 되어 있는 것을 볼 수 있습니다만... 테스트로는 글쎄요...

4. 출결정보가 추가된 MemberAttend 메모리저장소에 추가하기

 

<Interface AttendRepository>

1
2
3
4
5
6
7
8
package eleven.lms.attend;
 
public interface AttendRepository {
    void save(MemberAttend memberAttend);//출결정보 저장
 
    MemberAttend findById(String memberId);//출결정보 검색
}
 
cs

 

<Class MemoryMemberRepository>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package eleven.lms.attend;
 
 
import java.util.HashMap;
import java.util.Map;
 
public class MemoryAttendRepository implements AttendRepository{
    private static Map<String, MemberAttend> store = new HashMap<>();
 
    @Override
    public void save(MemberAttend memberAttend) {
        store.put(memberAttend.getMemberId(),memberAttend);
    }
 
    @Override
    public MemberAttend findById(String memberId) {
        return store.get(memberId);
    }
}
cs

 

출결정보를 hashmap store에 저장하는 save 메서드를 작성한다.

그리고 그 안에서 저장된 정보를 id 로 찾을 수 있는 findById메서드를 작성한다.

 

<MemoryAttendRepositoryTest>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package eleven.lms.attend;
 
import eleven.lms.attendrule.AttendPolicy;
import eleven.lms.attendrule.OneDayPolicy;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import static org.junit.jupiter.api.Assertions.*;
 
class MemoryAttendRepositoryTest {
 
    @Test
    void save() throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss");
        //given
        Date start = dateFormat.parse("08:56:00");
        Date end = dateFormat.parse("16:00:00");
        MemberAttend memberAttend = new MemberAttend("memberA",start,end);
        AttendPolicy attendPolicy = new OneDayPolicy();
        AttendService attendService = new AttendServiceImpl();
        AttendRepository attendRepository = new MemoryAttendRepository();
        //when
        attendService.CreateAttend(memberAttend);
        attendRepository.save(memberAttend);
        MemberAttend findMember = attendRepository.findById("memberA");
        //then
        Assertions.assertThat(findMember).isEqualTo(memberAttend);
 
 
 
    }
}
cs

<실행결과>

테스트결과 잘 저장됨을 볼 수 있다

5. 실행파일 작성

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package eleven.lms.attend;
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class AttendApp {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss");
        Date start = dateFormat.parse("08:56:00");
        Date end = dateFormat.parse("16:00:00");
 
        MemberAttend memberAttend = new MemberAttend("MemberA",start,end);
        AttendService attendService = new AttendServiceImpl();
        AttendRepository attendRepository = new MemoryAttendRepository();
 
        attendService.CreateAttend(memberAttend);
        attendRepository.save(memberAttend);
        
        System.out.println(memberAttend);
    }
}
 
cs

 

<실행결과>

 

*간단하게 출결 로직을 만드는 부분은 끝이 났다.

이제 작성한 코드를  좋은 객체지향 설계의 5원칙에 따르게 수정하는 일이 남았다.

 

 

 

 

728x90