[우테코] 1주차 과제 피드백 정리

코드 리뷰 스터디에 참여하고 있다.

많이 늦었지만… 스터디원들의 피드백 중 기억해야할 내용을 정리해본다.

1. |, & vs. ||, && 연산자 선택

    if (page1 < 1 | page1 > 400 | page2 < 1 | page2 > 400)
    // 리팩터링
    if (page1 < 1 || page1 > 400 || page2 < 1 || page2 > 400)
  • 연산자
    • 피연산자을 int 형으로 변환할 수 있는 경우에는 Bitwise OR 연산
    • 피연산자가 boolean 형일 경우에는 Logical inclusive OR 연산
      • Conditional OR 연산자인   를 사용할 때와 결과가 같음
      • 하지만, 는 short-circuit이 발생하지 않음
  • 참고자료

2. 변수 지정 최소화

// Case.1
private int getSum(int page) {
    int sum = 0;
    while (page > 0) {
        int q = page / 10;
        int r = page % 10;
        sum += r;
        page = q;
    }
    return sum;
    }
// 리팩터링
private int getSum(int page) {
    int sum = 0;
    while (page > 0) {
        sum += page % 10;
        page = page / 10;
    }
    return sum;
}

// Case2.
String answer = Decoder.decoding(cryptogram);
return answer;
// 리팩터링
return Decoder.decoding(cryptogram);

3. StringBuilder 활용

  • String은 불변 속성 객체(immutablie)
    • +연산을 사용하는 경우 더해진 새로운 문자열이 새로운 메모리 구역에 저장
    • 이때 기존 문자열은 참조되지 않음
      • 이후 가비지 콜렉터에 의해 정리
    • String에 +연산을 많이 사용하는 코드의 경우 heap 메모리 부족이 일어날 수도
  • 문자열 추가, 삭제가 잦은 경우 StringBuilder를 사용 권장

  • 참고 블로그

4. 불변값 변수 처리

    for (int i = 0; i < n_str.length(); i++)
  • n_str.length()의 값은 변하지 않음
    • 반복문의 시작과 동시에 (혹은 시작하기 전에) 변수로 선언해 주는 게 바람직
    • for loop이 돌 때마다 같은 값을 반복해서 계산하는 비효율성

5. 클래스 내 코드 컨벤션 준수

class Withdrawal {
    private static Withdrawal withdrawal = new Withdrawal();

    static Withdrawal getInstance() {
        return withdrawal;
    }

    private List<Integer> money_array = new ArrayList<>(9);
    private Withdrawal() {
        setMoney_array(this.money_array);
    }

// refactoring
class Withdrawal {
    // 클래스 변수
    private static Withdrawal withdrawal = new Withdrawal();
    // 인스턴스 변수
    private List<Integer> money_array = new ArrayList<>(9);
    // 생성자
    private Withdrawal() {
        setMoney_array(this.money_array);
    }
    // 메서드
    static Withdrawal getInstance() {
        return withdrawal;
    }

6. 객체를 객체답게

  • final Map<String, List> friends_map; 을 제외하고는 받은 인자값을 그대로 Recommendation 클래스에 전달하는 모습
    • 객체를 만들었다라는 코드라고 생각되지 않음
  • 객체를 생성하고자는 목표로?
    • Friend 객체와 Visitor 객체를 만들기
    • Firend 객체에서 setFriendScore(), makeFriendsMap()를 처리
    • Visitor 객체에서 setVisitorScore부터 나머지를 처리하는 방식으로 권유
    • visitor 객체에서 쓰이는 Friend 관련된 데이터들은 Firend 객체에서 메서드 만들어서 불러오고 방식으로
package onboarding;

import java.util.Collections;
import java.util.List;
import java.util.*;

public class Problem7 {
    public static List<String> solution(String user, List<List<String>> friends, List<String> visitors) {
        List<String> answer = Collections.emptyList();
        Recommendation rec = new Recommendation(user, friends, visitors);
        List<String> answer = rec.returnResult();
        return answer;
    }
}

class Recommendation {
    final String user;
    final List<List<String>> friends;
    final List<String> visitors;
    final Map<String, List<String>> friends_map;

    Recommendation(String user, List<List<String>> friends, List<String> visitors) {
        this.user = user;
        this.friends = friends;
        this.visitors = visitors;
        this.friends_map = makeFriendsMap(friends);
    }

    List<String> returnResult() {
        List<String> result = new ArrayList<>();
        Map<String, Integer> friend_score = setFriendScore();
        Map<String, Integer> visitor_score = setVisitorScore(friend_score);
        Map<String, Integer> user_score = setUserScore(visitor_score);
        Map<String, Integer> fltr_user_score = filterUserScore(user_score);
        List<Map.Entry<String, Integer>> sorted_user_entryList = sortUserScore(fltr_user_score);
        int i = 0;
        while (i < 5 & i < sorted_user_entryList.size()) {
            result.add(sorted_user_entryList.get(i).getKey());
            i += 1;
        }
        return result;
    }

    private List<Map.Entry<String, Integer>> sortUserScore(Map<String, Integer> user_score) {
        List<Map.Entry<String, Integer>> entryList = new LinkedList<>(user_score.entrySet());
        entryList.sort(Map.Entry.comparingByKey());
        entryList.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));
        return entryList;
    }

    private Map<String, Integer> filterUserScore(Map<String, Integer> user_score) {
        for (String key : user_score.keySet()) {
            if (user_score.get(key) == 0) {
                user_score.remove(key);
            }
        }
        return user_score;
    }

    private Map<String, Integer> setUserScore(Map<String, Integer> user_score) {
        // user key에 대한 친구 목록이 없는 경우 빈 array 반환
        List<String> array = new ArrayList<>();
        List<String> user_friends = friends_map.getOrDefault(user, array);
        for (String friend : user_friends) {
            user_score.remove(friend);
        }
        return user_score;
    }

    private Map<String, Integer> setVisitorScore(Map<String, Integer> user_score) {
        for (String visitor : visitors) {
            user_score.put(visitor, user_score.getOrDefault(visitor, 0) + 1);
        }
        return user_score;
    }

    private Map<String, Integer> setFriendScore() {
        Map<String, Integer> user_score = new HashMap<>();
        // user key에 대한 친구 목록이 없는 경우 빈 array 반환
        List<String> array = new ArrayList<>();
        List<String> friend_list = friends_map.getOrDefault(user, array);
        for (String friend : friend_list) {
            List<String> cross_friend_list = friends_map.get(friend);
            for (String cross_friend : cross_friend_list) {
                if (cross_friend.equals(user)) {
                    continue;
                }
                user_score.put(cross_friend, user_score.getOrDefault(cross_friend, 0) + 10);
            }
        }
        return user_score;
    }

    private Map<String, List<String>> makeFriendsMap(List<List<String>> friends) {
        Map<String, List<String>> friends_map = new HashMap<>();
        for (List<String> friend_list : friends) {
            for (int i = 0; i <= 1; i++) {
                String friend1 = friend_list.get(i);
                String friend2 = friend_list.get(1 - i);
                List<String> array = new ArrayList<>();
                List<String> friend1_friend_list = friends_map.getOrDefault(friend1, array);
                friend1_friend_list.add(friend2);
                friends_map.put(friend1, friend1_friend_list);
            }
        }
        return friends_map;
    }
}

기타