우아한형제들/우아한테크코스

[우아한테크코스] 6주차후기 - 점진적 리팩토링과 데이터베이스 적용

Jay Tech 2019. 6. 22. 14:27
반응형

6주차 후기

날짜 TODO 추가 공부
6/10(월) 프로그래밍 (로또) 졸업시험
6/11 (화) 강의 (프로젝트의 요소와 리팩토링)  
6/12 (수) 프로그래밍 (로또) 학교과제
6/13 (목) 프로그래밍 (로또) 학교과제
6/14 (금) (동생졸업식)  
6/15 (토)    
     

프로젝트 3요소

이번 강의는 "프로젝트 3요소인 비용, 일정, 품질 을 다 좋게할 수 있을까?"에 대한 캡틴의 짧은 언급이 있었다. 일정과 품질에 대해 생각해 볼 수 있는 좋은 기회였다. 많은 경우에서 일정이 품질보다 우선시 되는 경우가 있다고 한다. 그렇다면 일정 > 품질 이라는 것이 나쁜 일 인가라는 의문이 들 수 도 있다. 그렇다고 품질에 집중해서 일정을 놓치면 안된다. 왜냐하면 품질에 대한 명확한 기준이 없기 때문이다. 클린코드를 구현한 프로젝트의 절대적인 점수를 매길 수는 없는 노릇아닌가.

프로젝트의 3박자를 잘 맞추는 것이 프로젝트의 숙명이라고 할 수 있겠다.

점진적 리팩토링

캡틴은 또한 점진적 리팩토링에 대해서 말씀하셨다. 실제 동작하는 코드를 바꾸는 행위는 "달리는 자동차의 바퀴를 간다"라는 표현으로 비유하였다. 그만큼 어렵고 위험한 작업임을 알 수 있다. 그리고 바퀴를 갈아보는 방법에 대해서 간단한 언급이 있었다.

동작하는 코드를 리팩토링 하려고 함수의 인자나 반환형 혹은 무언가를 한 곳 바꾸게 된다면 빨간 줄과 함께 컴파일 에러가 난무할 것이다. 이에 캡틴은 컴파일 에러 없이 리팩토링 하는 법을 보여주었다.

방법은 바로 바꾸려는 부분을 새롭게 만드는 것이었다. 메서드를 바꿀 때는 (예를들어, copy and paste하고 메서드의 이름뒤에 2를 붙이면서 새로 만듦) 일정 기간동안 같은 기능을 하는 코드가 공존하게되는 과도기적 시간이 존재하게 된다.그리고 바꾼 함수가 동작을 하게 된다면 기존의 함수를 삭제를 하고 바꾼 함수의 이름을 기존 함수 이름으로 rename을 하게된다 .이 방법은 시간을 길게 두고 리팩토링을 하는 것이 아니라 짬을 내서 잠깐씩 할 수 있는 방법이다.

이렇게 한다면 컴파일 에러 없이 안전하게 리팩토링을 할 수 있게 된다.

데이터베이스 설계

로또 게임을 웹 UI에 적용하는데에 있어 데이터베이스를 활용하기 위해 먼저 데이터베이스를 설계하였다. 실제로 포워드 엔지니어링 (데이터베이스에 직접 때려넣는 행위) 을 하기 때문에 밑에 표시 해놓은 Domain 영역도 모두 정의를 해놓아야 관리하기 편하다. 일단은 약식으로 해보기로... (자료형을 신경쓰지 않았음)

오타 정정!! W_LOTTO 테이블의 pk 물리 네이밍은 id가 아니라 round_id 이다. 그리고 테이블 앞에 T를 안 붙이는 것으로 변경!

물리모델

물리모델 (실제 테이블에 들어가는 형식)

왼쪽 초록색 실선이 식별관계를 의미한다. 식별 관계란 부모테이블의 키로 지정된 컬럼(로또 회차 아이디) 이 자식 테이블의 기본 키로(당첨 로또 아이디) 연결된 경우를 의미한다. 오른쪽 빨간 점선은 비 식별 관계를 의미한다. 비 식별 관계란 부모테이블의 키가(로또 회차 아이디) 자식테이블의 일반 컬럼(round_id) 으로 연결된 경우를 의미한다.

 

논리모델

논리모델 (사람이 보기 쉽게 개념설계를 엔티티별로 구체화시키고 정규화를 진행)

참고로 구매이력 테이블의 회차 번호와 유저아이디는 회차와 유저 테이블의 PK를 가져온 것인데 둘을 이용하여 구매이력 테이블의 한 ROW를 식별할 수 없다!

부연 설명을 하자면, 슈퍼 키 라는 것이 있다. 슈퍼 키는 테이블에서 튜플을 식별할 수 있는 Unique 한 Attribute의 집합이다. 예를 들어, 학생정보를 관리를 하는데 학번과 주민등록 번호로 한 명의 학생 (한 ROW)를 식별할 수 있다. 그렇다면 학번과 주민등록 번호는 슈퍼 키이다. 하지만 학번 하나만으로 한 ROW를 식별할 수 있다. 즉 한 ROW를 구분할 수 있는 최소한의 키를 후보키라고 한다.

이 설명을 한 이유는 아까 구매이력 테이블을 설명하기 위해서이다. 구매이력 테이블은 회차번호와 유저 아이디로는 한 ROW를 식별할 수 없다. 한 사람이 같은 로또 번호로 여러 장 구매할 수 있기 때문이다. 만일 같은 번호로 구매할 수 없다는 조건이 게임에 걸려 있다면 회차번호와 유저아이디는 키가 될 것이다. 하지만 저 둘을 키로 잡을 수 없다. 그래서 테이블 아이디를 pk로 두었다.

참고로 이 설계는 Exerd라는 이클립스 플러그인으로 진행하였다. 사용법은 예전에 정리해놓은것들이 있는데 아래 링크를 참조하자.

 

https://pjh3749.tistory.com/162?category=668899

 

[ERD] eXERD 설치와 회원가입 모델링 하는 법

eXERD 는 경력자 뿐만 아니라 초보자도 데이터베이스 설계를 직관적이고, 쉽고, 빠르게 하도록 개발된 이클립스 기반 지능형 모델링 도구이다. 여러 DBMS를 지원한다. Oracle, MS SQL, IBM DB2, PostgreSQL, MySQL..

pjh3749.tistory.com

https://pjh3749.tistory.com/159?category=668899

 

데이터베이스 모델링과 회원가입 설계

■ 모델링의 정의 모형, 축소형의 의미 사람이 살아가면서 나타날 수 있는 다양한 현상에 대해서 일정한 표기법에 의해 포현해 놓은 모형 사람,사물,개념 등 -> 모델을 만들어가는 일 추상화(모형과,가설적) : 현..

pjh3749.tistory.com

다음으로 실제로 MySQL에 넣어보고 Reverse Engineering을 통해 제대로 됐는지 확인할 수 있다.

 

리버스 엔지니어링

 

리버스 엔지니어링 결과물

그림은 그닥 예쁘진 않지만 아까 설계 플러그인으로 설계한 모습과 동일함을 알 수 있다.

일급 컬렉션으로의 변경

무의식적으로 getter의 사용이 반복되었다. 이것을 없애기 위해 구조를 바꾸어야 했다. getter를 사용했을 때 문제점은 외부에서 객체 내부의 중요 값을 바꿔버릴 수 있다는 것이다.

 

문제의 코드

 

 

LottoTicket 이라는 인터페이스를 정의한다.

public interface LottoTicket {
    boolean contains(LottoNumber lottoNumber);
    int matchCount(Lotto lotto);
}

그리고 Lotto는 LottoTicket을 구현한다.

public class Lotto implements LottoTicket {
// 중략
}

이렇게 되면 로또 구매리스트인 (LottoBuyList)에서 로또를 get을 하지만 로또를 절대 변경할 수 없다.

도메인의 역할

로또 프로그램을 만들면서 받은 전체적인 피드백 내용이다.

 

피드백 내용

내 코드의 문제점에서는 실제 도메인의 상세 구현들이 컨트롤러-서비스 계층에서 구현되는 부분들이 존재하였다. 로직들은 전부 도메인에 넣는것으로 리팩토링 하였고 컨트롤러 쪽에서는 결과만 받는 것으로 변경하였다.

반응형