본문 바로가기

Android/랜덤리즘

[랜덤리즘] 예외 처리하기, 다이얼로그보다 사용자에게 선택권을 주기

흔한 알고리즘에 대해서는 문제가 많았지만, 덱, 연결 리스트와 같이 100개 미만의 문제를 가진 알고리즘이 많다는 것을 알게되었다.

문제 수가 많은 알고리즘에 대해서만 클릭해보고 기능이 잘 되는지 확인을 해보았기때문에 뒤늦게 알게된 것이겠지 .. 싶다..

 

마주한 문제

 

위의 사진과 같이 덱 알고리즘에서 브론즈에 해당되는 문제는 존재하지 않았다.

 

 

네트워크 통신에서는 200으로 성공이었지만, 왜 문제가 보이지 않을까? 해서 주소로 접속해보았다.

일단 결과가 보내졌기 때문에 200으로 성공이 떴지만, 그 속의 내용은 문제가 존재하지 않는다는 count : 0 이 있었다!

 

count가 0인 경우에 대한 예외처리가 필요하구나를 알게되었다.

 


해결을 위해 생각한 방법

[1] count 가 0으로 전달되었을 때, 다이얼로그를 통해 메세지를 표시하고 선택을 다시 할 수 있도록 도와주기

다이얼로그를 통해 메세지를 표시하는 것은 사용자에게 명시적으로 관련된 문제가 없음을 표시하는 방법이라 좋다고 생각되었지만, 다시 선택을 하게끔 하는 것은 옳지 않다고 생각이 되었다.

옳지 않다고 생각한 이유는 기존에 선택한 예외를 발생하는 버튼과 정상적으로 작동하는 버튼에 차이점이 없기 때문에 또 다시 예외를 발생시킬 가능성이 있다고 생각되었다.

 

[2] 태그 + 레벨을 선택할 때, 존재하지 않는 문제들에 대해서 비활성화를 하여 미리 사용자에게 일러주기

예외를 발생시키는 버튼에 대해서 비활성화하게되면 회색 컬러로 표시가 되고, 버튼을 클릭해도 다음 스텝으로 넘어가지 않기때문에 예외가 발생할 상황을 제한시키는 것이 좋다고 생각되었다.

 


적용한 방법 (2번)

 

기존의 흐름이 위와 같았다면

 

 

변경한 후의 흐름은 위와 같다!

 

태그를 선택했을 때, 각각의 레벨에 대한 문제가 존재하는지 (count의 값이 0인지 아닌지) 확인하는 작업을 추가해주었다.

 

// TagViewModel.kt

fun hasProblemOfTag(tag: String) {
    viewModelScope.launch {
        try {
            val bronze = async { hasProblemOfTagUseCase.invoke(tag, 'b') }
            val silver = async { hasProblemOfTagUseCase.invoke(tag, 's') }
            val gold = async { hasProblemOfTagUseCase.invoke(tag, 'g') }
            val platinum = async { hasProblemOfTagUseCase.invoke(tag, 'p') }
            val diamond = async { hasProblemOfTagUseCase.invoke(tag, 'd') }
            val ruby = async { hasProblemOfTagUseCase.invoke(tag, 'd') }

            val result = awaitAll(bronze, silver, gold, platinum, diamond, ruby)
            _problemCountOfTag.value = result
        } catch (exception: Exception) { ... }
    }
}

 

async 를 사용해보고 싶었는데, 이번에 사용해볼 수 있었다! 모든 결과를 사용해야 하므로 awaitAll() 을 통해 값을 받아주었다.

각각의 레벨들이 하드코딩되어 있지만 ... 아무튼 위의 코드와 같이 해당 태그에 대한 각각의 레벨들이 문제가 있는지 네트워크 요청을 보냈고, 응답을 count 가 0이면 false, 0이 아니면 true 로 받기위해서 결과를 받는 변수의 타입을 Boolean 으로 선언해주었다.

 

Fragment 에서 결과를 관찰하고 있다가, 결과값이 관찰되면 해당 결과값을 BottomSheetDialog 로 전달해주었다.

 

// LevelSelectionDialog.kt

private fun initButtons(levels: BooleanArray) {
    if (!levels[0]) {
        binding.tvBronze.isEnabled = false
    }
    if (!levels[1]) {
        binding.tvSilver.isEnabled = false
    }
    if (!levels[2]) {
        binding.tvGold.isEnabled = false
    }
    if (!levels[3]) {
        binding.tvPlatinum.isEnabled = false
    }
    if (!levels[4]) {
        binding.tvDiamond.isEnabled = false
    }
    if (!levels[5]) {
        binding.tvRuby.isEnabled = false
    }
}

 

위의 함수의 파라미터로 결과값을 전달한 후에, 해당되는 레벨의 버튼을 비활성화해주었다!

 


결과 화면

모든 레벨에 대해서 문제가 존재할 때 특정 레벨에 대해서만 문제가 존재할 때

 

예외처리 끝!