2021-gpu-is-mine icon indicating copy to clipboard operation
2021-gpu-is-mine copied to clipboard

Job 도메인 설계에 대해 고민해본다.

Open wannte opened this issue 3 years ago • 4 comments

이슈 설명

도메인 구조에 대해 다시 한 번 고민해 본다.

패키지 간에 도메인 그래프를 그려보고 서로의 의존관계를 그래프로 그려보고 방향성에 대해 고민해 본다.

지금 당장 수정한다라기보다는, 구조에 대해 고민해보는 것.

이번 이슈는 Job에 대해서만으로 한정한다.

참고자료 조영호님 우아한 객체지향 발표

wannte avatar Oct 21 '21 00:10 wannte

@Transactional
public Long save(Long memberId, JobRequest jobRequest) {

    //패키지간의 의존 관계를 끊어야 한다.

    // A라는 패키지의 로직을 수정했을 때, B를 수정해야됨, A를 수정해야 됨, B를 수정해야 됨.
    // job을 이루는 서버한테 이 Member가 이 서버쓸수 있어? 라고 메시지를 보내야 한다.
    // Service에서 모든 로직을 처리하고 있는 느낌.
    memberService.checkMemberOfServer(memberId, jobRequest.getGpuServerId());

    Long serverId = jobRequest.getGpuServerId();
    // server의 상태체크 로직이 필요
    Job job = jobRequest.toEntity(findBoardByServerId(serverId), findMemberById(memberId));

    jobRepository.save(job);
    return job.getId();
}

wannte avatar Oct 21 '21 12:10 wannte

GET /api/labs/1/jobs/1 HTTP/1.1

Hibernate: 
    select
        administra0_.id as col_0_0_ 
    from
        administrator administra0_ 
    where
        administra0_.email=? limit ?
Hibernate: 
    select
        member0_.id as id1_5_,
        member0_.created_at as created_2_5_,
        member0_.updated_at as updated_3_5_,
        member0_.email as email4_5_,
        member0_.lab_id as lab_id8_5_,
        member0_.member_type as member_t5_5_,
        member0_.name as name6_5_,
        member0_.password as password7_5_ 
    from
        member member0_ 
    where
        member0_.email=?
Hibernate: 
    select
        lab0_.id as id1_4_0_,
        lab0_.created_at as created_2_4_0_,
        lab0_.updated_at as updated_3_4_0_,
        lab0_.name as name4_4_0_ 
    from
        lab lab0_ 
    where
        lab0_.id=?
Hibernate: 
    select
        member0_.id as id1_5_,
        member0_.created_at as created_2_5_,
        member0_.updated_at as updated_3_5_,
        member0_.email as email4_5_,
        member0_.lab_id as lab_id8_5_,
        member0_.member_type as member_t5_5_,
        member0_.name as name6_5_,
        member0_.password as password7_5_ 
    from
        member member0_ 
    where
        member0_.email=?
Hibernate: 
    select
        lab0_.id as id1_4_0_,
        lab0_.created_at as created_2_4_0_,
        lab0_.updated_at as updated_3_4_0_,
        lab0_.name as name4_4_0_ 
    from
        lab lab0_ 
    where
        lab0_.id=?
Hibernate: 
    select
        member0_.id as id1_5_0_,
        member0_.created_at as created_2_5_0_,
        member0_.updated_at as updated_3_5_0_,
        member0_.email as email4_5_0_,
        member0_.lab_id as lab_id8_5_0_,
        member0_.member_type as member_t5_5_0_,
        member0_.name as name6_5_0_,
        member0_.password as password7_5_0_,
        lab1_.id as id1_4_1_,
        lab1_.created_at as created_2_4_1_,
        lab1_.updated_at as updated_3_4_1_,
        lab1_.name as name4_4_1_ 
    from
        member member0_ 
    left outer join
        lab lab1_ 
            on member0_.lab_id=lab1_.id 
    where
        member0_.id=?
Hibernate: 
    select
        job0_.id as id1_3_0_,
        job0_.created_at as created_2_3_0_,
        job0_.updated_at as updated_3_3_0_,
        job0_.completed_time as complete4_3_0_,
        job0_.expected_time as expected5_3_0_,
        job0_.gpu_board_id as gpu_boa10_3_0_,
        job0_.member_id as member_11_3_0_,
        job0_.meta_data as meta_dat6_3_0_,
        job0_.name as name7_3_0_,
        job0_.started_time as started_8_3_0_,
        job0_.status as status9_3_0_,
        gpuboard1_.id as id1_1_1_,
        gpuboard1_.created_at as created_2_1_1_,
        gpuboard1_.updated_at as updated_3_1_1_,
        gpuboard1_.gpu_server_id as gpu_serv7_1_1_,
        gpuboard1_.is_working as is_worki4_1_1_,
        gpuboard1_.model_name as model_na5_1_1_,
        gpuboard1_.performance as performa6_1_1_,
        gpuserver2_.id as id1_2_2_,
        gpuserver2_.created_at as created_2_2_2_,
        gpuserver2_.updated_at as updated_3_2_2_,
        gpuserver2_.disk_size as disk_siz4_2_2_,
        gpuserver2_.is_on as is_on5_2_2_,
        gpuserver2_.lab_id as lab_id9_2_2_,
        gpuserver2_.last_response as last_res6_2_2_,
        gpuserver2_.memory_size as memory_s7_2_2_,
        gpuserver2_.name as name8_2_2_,
        lab3_.id as id1_4_3_,
        lab3_.created_at as created_2_4_3_,
        lab3_.updated_at as updated_3_4_3_,
        lab3_.name as name4_4_3_,
        member4_.id as id1_5_4_,
        member4_.created_at as created_2_5_4_,
        member4_.updated_at as updated_3_5_4_,
        member4_.email as email4_5_4_,
        member4_.lab_id as lab_id8_5_4_,
        member4_.member_type as member_t5_5_4_,
        member4_.name as name6_5_4_,
        member4_.password as password7_5_4_,
        lab5_.id as id1_4_5_,
        lab5_.created_at as created_2_4_5_,
        lab5_.updated_at as updated_3_4_5_,
        lab5_.name as name4_4_5_ 
    from
        job job0_ 
    left outer join
        gpu_board gpuboard1_ 
            on job0_.gpu_board_id=gpuboard1_.id 
    left outer join
        gpu_server gpuserver2_ 
            on gpuboard1_.gpu_server_id=gpuserver2_.id 
    left outer join
        lab lab3_ 
            on gpuserver2_.lab_id=lab3_.id 
    left outer join
        member member4_ 
            on job0_.member_id=member4_.id 
    left outer join
        lab lab5_ 
            on member4_.lab_id=lab5_.id 
    where
        job0_.id=?

wannte avatar Oct 21 '21 13:10 wannte

field가 많아짐에 따라, getter/setter, null 체크 로직이 많아지기 때문에, 도메인 로직을 확인하기 어려움 존재

고민하는 문제

  1. Controller에서 Member객체를 굳이 받아야 할까?, memberId만 받아도 충분하지 않을까? -> 컨트롤러에서 member의 종류에 따라서 보여주는 로직이 달라지는 경우는 유용하겠지만, 지금의 우리 서비스에서 member객체를 바로 쓴느 경우는 드문 것으로 보인다.
  2. CUD작업에서는 검증이 필요하겠지만, 조회 로직에서도 서비스 단에 검증로직을 추가해야 할까?
  3. Enum으로 관리하는 Exception은 확장에 취약한 것으로 보임. (동일한 로직이 별도의 서비스에서 동시에 정의되어 있고, 각각 다른 에러메시지를 내보내는 부분을 통일시켜주기 위해 Enum을 도입했지만, 공통 로직을 도메인 단으로 옮겨왔을 때, 문제가 해결될 수 도 있을 거라 생각)

wannte avatar Oct 21 '21 16:10 wannte

모든 Job관련 서비스가 GpuServer.isOn=false 인 경우 정상적으로 등록할 수 있게끔 테스트 코드가 짜여 있었음. RestAssured에서는 우선 Worker측에서 Gpu상대 변경을 진행한 후 테스트를 진행하도록 수정

JobStatus.Waiting이 기본 상태가 아니라, 예약을 하는 시점에서 상태를 정해지도록 수정 (생성시 null) -> 테스트 코드의 많은 수정 필요. 객체를 생성하는 시점이 아닌 예약이 가능한 상황인지 검증이 이루어지고 나서야 예약상태로 변경되어야 된다고 판단.

    @DisplayName("사용자의 Job 접근 권한을 확인한다.")
    class CheckPermissionOnJob {

이 테스트는 도메인에서의 검증으로 대체


Entity의 equals(), hashcode() 의 구현은 그 의미가 퇴색됨. 영속성 컨텍스트에서 관리되는 객체들은 reference로 같음을 제공하기 때문에, id만을 equals의 기준으로 삼는 지금의 구현은 테스트 코드의 복잡성만을 야기한다고 판단.


DB 제약 조건 이름 명시적으로 알아볼 수 있도록 수정하면 좋을듯! Screenshot from 2021-10-22 02-51-36

wannte avatar Oct 21 '21 16:10 wannte