Лучшая практика для обработки нулевых типов в классах при сопоставлении классов - PullRequest
0 голосов
/ 26 декабря 2018

Я использую Kotlin 1.30.У меня есть следующие классы сущностей, которые будут заполнены из API.И некоторые свойства могут быть нулевыми в API, поэтому я объявил их, используя безопасный тип null.

Однако я сопоставлю этот класс сущностей с моим классом модели домена.И просто интересно, как лучше всего обращаться с нулевыми типами?

У меня есть 2 идеи, как это сделать, когда я сопоставляю классы.

  1. объявляем все эквивалентные свойства как безопасные нулевые типы
  2. используйте оператор elivs длявернуть либо пустую строку, либо пустой список

В следующем фрагменте я использую оператор elvis.Просто интересно, каков лучший метод для этого?

class LoginResponseDomainMapperImp : LoginResponseDomainMapper {
    override fun map(entity: LoginResponseEntity): LoginResponse {
        return LoginResponse(
            entity.token ?: "",
            mapUsers(entity.user),
            mapEnterprises(entity.enterprises ?: emptyList()),
            mapVendors(entity.vendors ?: emptyList()))
    }

    private fun mapUsers(userEntity: UserEntity?): User {
        return User(
            userEntity?.id,
            userEntity?.email,
            userEntity?.firstName,
            userEntity?.lastName,
            userEntity?.phone,
            userEntity?.address,
            userEntity?.dob,
            userEntity?.customer,
            userEntity?.enterpriseIds ?: emptyList(),
            userEntity?.vendorIds ?: emptyList())
    }

    private fun mapEnterprises(enterprisesEntity: List<EnterprisesEntity>): List<Enterprises> {
        val enterpriseList = mutableListOf<Enterprises>()

        enterprisesEntity.forEach {
            val enterprise = Enterprises(
                it.id,
                it.enterpriseName,
                it.typeLabel,
                it.country,
                it.imageId,
                it.managers,
                it.members,
                it.stripe,
                it.locations)

            enterpriseList.add(enterprise)
        }

        return enterpriseList.toList()
    }

    private fun mapVendors(vendorsEntity: List<VendorsEntity>): List<Vendors> {
        val vendorList = mutableListOf<Vendors>()

        vendorsEntity.forEach {
            val vendor = Vendors(
                it.id,
                it.vendorName,
                it.typeLabel,
                it.userRole,
                it.latitude,
                it.longitude,
                it.partner,
                it.country,
                it.imageId,
                it.stripe)

            vendorList.add(vendor)
        }

        return vendorList.toList()
    }
}

Класс сущностей, который будет заполняться из API, поэтому любой из них может быть нулевым

data class LoginResponseEntity(
    @SerializedName("token") val token: String?,
    @SerializedName("user") val user: UserEntity?,
    @SerializedName("enterprises") val enterprises: List<EnterprisesEntity>?,
    @SerializedName("vendors") val vendors: List<VendorsEntity>?)

data class UserEntity(
    @SerializedName("id") val id: String?,
    @SerializedName("email") val email: String?,
    @SerializedName("first_name") val firstName: String?,
    @SerializedName("last_name") val lastName: String?,
    @SerializedName("phone") val phone: String?,
    @SerializedName("address") val address: String?,
    @SerializedName("dob") val dob: String?,
    @SerializedName("customer") val customer: String?,
    @SerializedName("enterprise_ids") val enterpriseIds: List<String>?,
    @SerializedName("vendor_ids") val vendorIds: List<String>?)

data class EnterprisesEntity(
    @SerializedName("id") val id: String?,
    @SerializedName("enterprise_name") val enterpriseName: String?,
    @SerializedName("type_label") val typeLabel: String?,
    @SerializedName("referral_code") val referralCode: String?,
    @SerializedName("country") val country: String?,
    @SerializedName("image_id") val imageId: String?,
    @SerializedName("managers") val managers: List<String>?,
    @SerializedName("members") val members: List<String>?,
    @SerializedName("stripe") val stripe: Boolean,
    @SerializedName("locations") val locations: List<String>?)

data class VendorsEntity(
    @SerializedName("id") val id: String?,
    @SerializedName("vendor_name") val vendorName: String?,
    @SerializedName("type_label") val typeLabel: String?,
    @SerializedName("user_role") val userRole: String?,
    @SerializedName("latitude") val latitude: Float,
    @SerializedName("longitude") val longitude: Float,
    @SerializedName("partner") val partner: Boolean,
    @SerializedName("country") val country: String?,
    @SerializedName("image_id") val imageId: String?,
    @SerializedName("stripe") val stripe: Boolean)

Класс модели данных в домене, Лучше объявить их все безопасными нулевыми типами?

data class LoginResponse(
    val token: String,
    val user: User?,
    val enterprises: List<Enterprises>,
    val vendors: List<Vendors>)

data class User(
    val id: String?,
    val email: String?,
    val firstName: String?,
    val lastName: String?,
    val phone: String?,
    val address: String?,
    val dob: String?,
    val customer: String?,
    val enterpriseIds: List<String>,
    val vendorIds: List<String>)

data class Enterprises(
    val id: String,
    val enterpriseName: String,
    val typeLabel: String,
    val country: String,
    val imageId: String,
    val managers: List<String>,
    val members: List<String>,
    val stripe: Boolean,
    val locations: List<String>)

data class Vendors(
    val id: String,
    val vendorName: String,
    val typeLabel: String?,
    val userRole: String,
    val latitude: Float,
    val longitude: Float,
    val partner: Boolean,
    val country: String?,
    val imageId: String,
    val stripe: Boolean)

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Прежде всего, в Котлине нет безопасных нулевых типов.Переменная может иметь значение NULL или нет.

Если API выдает нулевые значения, либо по отсутствию, либо путем задания их явно нулевым, ваши классы данных должны отражать это так, как эти переменные могут иметь значение NULL (вопросительный знак ? сразу после типа данных).

В тот момент, когда вы сопоставляете эти классы данных с вашими сущностями (модель предметной области), вы должны правильно обработать нулевой регистр.Поскольку это допустимый случай, API-интерфейс обслуживает нулевые значения, которые вы ожидаете, вам следует обработать этот случай, назначив значение по умолчанию.

Использование оператора elvis - это всего лишь способ изящно работать с обнуляемыми типами,но если вы используете его, остается ваш выбор.

0 голосов
/ 26 декабря 2018

Если вы объявляете все свойства как nullable, это не намного лучше, чем Java, даже если вы обращаетесь к ним с нулевым оператором безопасности.Если ваши свойства JSON имеют значение null, это означает, что в вашей бизнес-логике они не всегда имеют значение, и вы несете ответственность за его обработку путем возврата к значению по умолчанию (то есть emptyList() или "")или, может быть, что-то более сложное, например, перенаправление на экран входа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...