Language/Dart

[Exercism] Scrabble Score #가독성 있는 코드란?2

paran21 2022. 8. 18. 16:45

https://exercism.org/tracks/dart/exercises/scrabble-score

 

Scrabble Score in Dart on Exercism

Can you solve Scrabble Score in Dart? Improve your Dart skills with support from our world-class team of mentors.

exercism.org

 

이전 Leap랑 같이 가독성 있고, 수정하기 좋은 코드에 대해 얘기를 나눌 수 있었던 문제!


처음에 내가 문제를 풀었던 방식은 1) 단어별 점수 조건을 Map으로 만들고 + 2) 주어진 단어를 List로 변환해서

이중 for문을 사용해서 점수를 구했다.

 

여기서 또 알게된 재밌는 사실은, 다트는 .dart 파일마다 반드시 class를 선언하지 않아도 된다.

그래서인지 기본 컨벤션은 자바와 동일하게 camel인데, 파일명은 snake를 사용한다.

final Map<String, int> _letterValues = {
  'AEIOULNRST' : 1,
  'DG' : 2,
  'BCMP' : 3,
  'FHVWY' : 4,
  'K' : 5,
  'JX' : 8,
  'QZ' : 10};
  
int score(String word) {
  int _answer = 0;
  List<String> characters = word.toUpperCase().split('');
  for (String character in characters) {
    for (String letters in _letterValues.keys) {
      if (letters.contains(character)) {
        _answer += _letterValues[letters]!;
        break;
      }
    }
  }
  return _answer;
}

 

일단 먼저 들었던 고민은, "2중 for문을 사용하지 않는 방법은 없을까?" 였는데 일단 점수표를 Map으로 구현한 이상 다른 방법이 없는 것 같다.

대신 메서드로 분리하는 방법이 있다.

 

점수를 얻는 방법을 getValues로 분리하였다.

그리고 switch를 사용해서 해당되는 점수를 return하였는데, 이렇게 하면 분명 코드는 길어진다.

(모든 알파벳마다 점수가 다르니 당연하다!)

그렇지만 _getValues를 private 메서드로 분리하고 나면, 점수를 얻는 score는 매우 간결해진다.

List를 만들고 forEach로 character마다 얻은 값을 더하면 된다.

 

또, 점수 조건을 수정한다면 switch문을 수정해야 하는데 위에 Map으로 선언한 것 보다 수정이 쉬울 수 있다.

 

int score(String word) {
  int _answer = 0;
  List<String> characters = word.toUpperCase().split('');
  characters.forEach((character) => _answer += _getValues(character));
  return _answer;
}

int _getValues(String char) {
  switch(char) {
    case 'A':
    case 'E':
    case 'I':
    case 'O':
    case 'U':
    case 'L':
    case 'N':
    case 'R':
    case 'S':
    case 'T':
      return 1;
    case 'D':
    case 'G':
      return 2;
    case 'B':
    case 'C':
    case 'M':
    case 'P':
      return 3;
    case 'F':
    case 'H':
    case 'V':
    case 'W':
    case 'Y':
      return 4;
    case 'K':
      return 5;
    case 'J':
    case 'X':
      return 8;
    case 'Q':
    case 'Z':
      return 10;
    default:
      return 0;
  }
}