본문 바로가기

웹 프레임워크/Spring

프로젝트A. 명함 관리 프로그램 코드 리뷰 및 회고 (boostcourse 웹 백엔드)

728x90

 

www.boostcourse.org/web326

 

웹 백엔드

부스트코스 무료 강의

www.boostcourse.org

 

총 두번의 평가를 받았고 Pass가 떴습니다.

 

명함 관리 프로그램을 완성 시키는 과제인데, 자료 유출을 하면 안되기 떄문에 자세한 내용은 직접 수강신청을 하여 보시면 되겠습니다.

 

리뷰 #1

첫번째 제출은 데이터베이스 검색 쿼리를 잘 못 작성하여 Fail을 맞았습니다. 처음 과제 PDF를 읽었을 때 완전 일치로 검색을 해야하는 줄 알고 작성했는데, 문제의 의도와는 다르게 이해 했었네요.

그 외에 컨벤션, 예외처리, 메소드 단위분리, 네이밍은 통과를 주셨습니다.

 

Advice

JAVA 7 이후 제네릭 유형의 인스턴스 생성시 명시적 타입 생략 가능

조언을 받은 부분을 살펴보겠습니다.

// JAVA 7 이전 스타일 
Map<String, List<String>> employeeRecords = new HashMap<String, List<String>>();
List<Integer> primes = new ArrayList<Integer>();

// JAVA 7 이후 스타일 <> 사용 
Map<String, List<String>> employeeRecords = new HashMap<>();
List<Integer> primes = new ArrayList<>();

자바7 부터는 다이아몬드 지시자(<>)를 사용할 수 있다고 합니다. 

왼쪽에 Map에 Generics를 선언할 때 오른쪽에 선언을 생략할 수 있다고 합니다. 양쪽다 생략할 시에는 컴파일에 Type safety라는 warning을 발생 시킵니다.

 

- Java Plaform Standard Edition 7 (JAVA SE)

- Java SE Development Kit 7 (JDK 7)

- Java SE Runtime Enviornment 7 (JRE 7)

 

java -version 시 "1.7.0"

 

참고링크: www.whatap.io/ko/blog/12/, durtchrt.github.io/blog/java/generics/9/ (타입 추론)

 

변수명을 지을 때 의미있는 이름을 작성하자

//  피해야 하는 경우 
List<String> titleList = new ArrayList<>();

// 배열이나 리스트 자료구조의 변수명은 복수형을 사용합니다
List<String> titles = new ArrayList<>();

 

기존에 List 타입의 인스턴스 변수명으로 businessCardList라는 이름의 변수를 지었습니다.

개발자에게 특수한 의미가 있는 list,array등 은 변수명으로 붙이지 않고, 복수형으로 이름을 짓는 것을 추천해주셨습니다.

 

- 추가로 길더라도 발음하기 쉬운코드 변수명을 사용해라,

- 클래스와 객체 이름은 동사를 피하고 명사나 명사구가 적합하다.

- 메서드 이름은 동사나 동사구가 적합하다.

등등 ..

 

참고링크: velog.io/@k7120792/클린-코드

 

 

Excellent

JDK 1.7 부터 java.lang 패키지에 try-with-resources구문이 추가 되었습니다. (JAVA 7)

해당 방식을 이용해서 JDBC를 사용해서 DB에 Connection을 실패 했을때 자동으로 리소스가 종료가 되도록 코드를 작성하였습니다.

 

import java.sql.Connection;

public class GuestbookDao {
    public List<Guestbook> getGuestbooks(){
        ... 
        try (Connection conn ...
         ...

try-with-resouces를 사용할때는 AutoCloseable 인터페이스가 있어야합니다. 

 

public interface Connection  extends Wrapper, AutoCloseable {

    /**
     * Creates a <code>Statement</code> object for sending
     * SQL statements to the database.
     * SQL statements without parameters are normally
     * executed using <code>Statement</code> objects. If the same SQL statement
     * is executed many times, it may be more efficient to use a
     * <code>PreparedStatement</code> object.
     * <P>
     * Result sets created using the returned <code>Statement</code>
     * object will by default be type <code>TYPE_FORWARD_ONLY</code>
     * and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
     * The holdability of the created result sets can be determined by
     * calling {@link #getHoldability}.
     *
     * @return a new default <code>Statement</code> object
     * @exception SQLException if a database access error occurs
     * or this method is called on a closed connection
     */
    Statement createStatement() throws SQLException;

Connection인터페이스는 Warapper와 AutoCloseable를 다중 상속받고 있습니다. AutoCloseable를 상속받았기 때문에 사용할 수 있습니다.

 

public interface AutoCloseable {
    /**
     * Closes this resource, relinquishing any underlying resources.
     * 수많은 주석...
     * @throws Exception if this resource cannot be closed
     */
    void close() throws Exception;
}

AutoCloseable 인터페이스 입니다.

 

 

알고 있는 인터페이스중에 Connection도 있는 것을 볼 수 있습니다.

 

java docs 링크: docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html

 

 

 

리뷰 #2

두번째 리뷰는 통과를 했습니다.

 

Advice

변경되면 안되는 변수명에 final을 붙이자

private static String Drive = "생략";
private static String dbUrl = "생략";
private static String dbUser = "생략";
private static String dbPasswd = "생략";

카멜 케이스로 DB연결을 위한 변수명을 작성하였습니다. 또한 static을 사용하여 클래스 생성시 메모리에 고정시키도록 하였습니다.

 

그러나 해당 정보는 변경되지 않아야 합니다. private로 외부에서 접근하지 못하도록 하였지만, 내부 클래스에서 접근하여 변경이 가능합니다. 이로 인해 나중에 다른 개발자가 해당 클래스의 내부에서 접근하여 수정을 하게 될 경우가 충분히 생길 수 있습니다.

 

 

private static final String DIRVER = "생락";
private static final String DB_URL = "생락";
private static final String DB_USER = "생락";
private static final String DB_PASSWD = "생락";

다음과 같이 수정을 권장해주셨습니다.

final 키워드를 붙여서 수정이 불가능하도록 상수로 선언하였습니다. 또한 상수이기 때문에 대문자 스네이크 표기법을 사용하였습니다.

 

같은 경로 catch 라면 try문에 넣어서 가독성을 높히자

try (조건1;
      조건2;
      조건3) {
      } catch () {
      }

같은 catch문을 사용한다면  try-with-resources 를 사용할때 두개의 catch문을 사용했었는데, 같은 예외를 처리하고 있었습니다.

중첩을 줄이기 위해 try()안에 전부 넣어 가독성을 높혔습니다.

 

 

executeUpdate의 반환값을 받아서 예외사항을 처리하자

ps.executeUpdate();

executeUpdate 메소드는 insert 또는 update 된 row수를 반환한다고 합니다. 별도의

 

insert, delete, update와 같은 DML의 경우 행의 수를 반환하고, 그렇지 않으면 0을 리턴한다고 합니다. 

 

 

참고 링크: docs.oracle.com/javase/7/docs/api/java/sql/Statement.html

 

Excellent

"SELECT * FROM bussiness_card 생략"

이번에는 검색기능을 제대로 구현을 했습니다. 해당 컬럼의 index 로 지정되어 있다면, 와일드 카드로 작성시 index를 사용하지 않아서 쿼리의 성능 좋지않다고 피드백을 해주셨습니다.

 

(인덱스에 대해 학습 후 추가 예정)

 

 

참고링크: https://grip.news/archives/1428

728x90