스팀 앱 개발기 #33 - 추가 리팩토링: 데이터 모듈의 데이터 클래스의 필드들에 nullable 적용

시작하며...

바로 다음 단계로 진행하고 싶었지만요... 빼먹은 리팩토링이 있었습니다. 그것마저 해야 다음 단계로 넘어가야 하는 거지요. 그냥 넘어가도 다음 거 개발해도 되기는 되지만요. 잘못된 코드가 나중에 발목을 잡는 불상사가 생길 수 있습니다. 초반에 잘못된 코드는 바로 잡고 넘어가는 것이 좋습니다.

이와 같이 개발은 간단한 것도 쉽게 넘어가는 법이 없습니다. 스팀 앱을 개발하는 과정에서 기능이 추가되는 과정도 보여드리고 싶지만, 시행착오로 인해 리팩토링 하는 과정도 같이 보여주고 싶습니다.


리팩토링 - 데이터 모듈의 데이터 클래스들의 필드들에 nullable 적용

API 연동시 서버로부터 받을 데이터들이 DTO 클래스들에 속하죠. 이들의 필드는 모두 nullable이어야 합니다. 왜냐면 서버로부터 일부 데이터는 받지 못할 수도 있기 때문입니다. 초반에 이걸 간과하고 코드를 만들었습니다. 다행히 유닛 테스트에서 오류가 발생하지는 않았지만, 이를 그대로 두면 나중에 언제라도 null로 인해 앱이 죽는 불상사가 발생할 수도 있습니다.

데이터 모듈의 데이터 클래스들의 필드들에 nullable을 적용한 결과는 다음과 같습니다. 선언한 필드들의 데이터 타입의 뒤에 물음표(?)를 추가하면 됩니다.

data class GetAccountsResponseDTO(
    val jsonrpc: String?,
    val result: Array<SteemitAccountDTO>?,
    val id: Int?
)

data class SteemitAccountDTO(
    val id: String?,
    val name: String?,
    val owner: SteemitKeyDTO?,
    val active: SteemitKeyDTO?,
    val posting: SteemitKeyDTO?,
    val memo_key: String?,
    val json_metadata: String?,
    val posting_json_metadata: String?,
    val proxy: String?,
    val last_owner_update: String?,
    val last_account_update: String?,
    val created: String?,
    val mined: Boolean?,
    val recovery_account: String?,
    val last_account_recovery: String?,
    val reset_account: String?,
    val comment_count: Int?,
    val lifetime_vote_count: Int?,
    val post_count: Int?,
    val can_vote: Boolean?,
    val voting_manabar: ManabarDTO?,
    val downvote_manabar: ManabarDTO?,
    val voting_power: Int?,
    val balance: String?,
    val savings_balance: String?,
    val sbd_balance: String?,
    val sbd_seconds: String?,
    val sbd_seconds_last_update: String?,
    val sbd_last_interest_payment: String?,
    val savings_sbd_balance: String?,
    val savings_sbd_seconds: String?,
    val savings_sbd_seconds_last_update: String?,
    val savings_sbd_last_interest_payment: String?,
    val savings_withdraw_requests: Int?,
    val reward_sbd_balance: String?,
    val reward_steem_balance: String?,
    val reward_vesting_balance: String?,
    val reward_vesting_steem: String?,
    val vesting_shares: String?,
    val delegated_vesting_shares: String?,
    val received_vesting_shares: String?,
    val vesting_withdraw_rate: String?,
    val next_vesting_withdrawal: String?,
    val withdrawn: String?,
    val to_withdraw: String?,
    val withdraw_routes: Int?,
    val curation_rewards: Long?,
    val posting_rewards: Long?,
    val proxied_vsf_votes: Array<Any>?,
    val witnesses_voted_for: Int?,
    val last_post: String?,
    val last_root_post: String?,
    val last_vote_time: String?,
    val post_bandwidth: Int?,
    val pending_claimed_accounts: Int?,
    val vesting_balance: String?,
    val reputation: String?,
    val transfer_history: Array<Any>?,
    val market_history: Array<Any>?,
    val post_history: Array<Any>?,
    val vote_history: Array<Any>?,
    val other_history: Array<Any>?,
    val witness_votes: Array<Any>?,
    val tags_usage: Array<Any>?,
    val guest_bloggers: Array<Any>?
) {

    fun toSteemitWallet(): SteemitWallet {
        val spToBeWithdrawn = try {
            "${to_withdraw?.toDouble() ?: 0} VESTS"
        }
        catch (e: NumberFormatException) {
            "0 VESTS"
        }

        return SteemitWallet(
            name ?: "",
            balance ?: "0 STEEM",
            sbd_balance ?: "0 SBD",
            savings_balance ?: "0 STEEM",
            savings_sbd_balance ?: "0 SBD",
            vesting_shares ?: "0 VESTS",
            delegated_vesting_shares ?: "0 VESTS",
            received_vesting_shares ?: "0 VESTS",
            vesting_withdraw_rate ?: "0 VESTS",
            spToBeWithdrawn
        )
    }

}

data class SteemitKeyDTO(
    val weight_threshold: Int?,
    val account_auths: Array<Any>?,
    val key_auths: Array<Array<Any>>?
)

data class ManabarDTO(
    val current_mana: String?,
    val last_update_time: Long?
)

toSteemitWallet 메소드에서는 추가로 코드를 수정한 게 있습니다. 왜냐면요. SteemitWallet 객체 생성시 SteemitAccountDTO 객체의 일부 필드 값이 null일 수 있기 때문입니다. 이 경우, 다른 대안의 값을 대신 대입하도록 했습니다.


SteemRepositoryImpl 클래스 추가 수정

SteemClient.apiService.getAccounts 메소드 실행 후, 서버로부터 받은 GetAccountsResponseDTO 객체의 result 필드는 null일 수 있습니다. result의 필드에 접근할 때, 그것에 ?를 추가해야 합니다. 수정한 코드 내용은 다음과 같습니다.

class SteemRepositoryImpl: SteemRepository {

    override fun readSteemitWallet(account: String): Flowable<Array<SteemitWallet>> {
        val getAccountParams = GetAccountsParamsDTO(
            params = arrayOf(arrayOf(account)),
            id = 1
        )

        return SteemClient.apiService.getAccounts(getAccountParams).map { responseDTO ->
            when (responseDTO.result?.size) {
                1 -> arrayOf(responseDTO.result[0].toSteemitWallet())
                else -> arrayOf()
            }
        }
    }

}

GitHub Commits


지난 스팀 앱 개발기

Sort:  
 2 years ago 

[광고] STEEM 개발자 커뮤니티에 참여 하시면, 다양한 혜택을 받을 수 있습니다.

Upvoted! Thank you for supporting witness @jswit.

Coin Marketplace

STEEM 0.18
TRX 0.14
JST 0.029
BTC 57849.42
ETH 3122.29
USDT 1.00
SBD 2.43