arrow-exact
arrow-exact copied to clipboard
Feature: Using Exact for data class / class with multiple properties
I have the following requirement in one of my productive applications using Either for exeption handling.
I have a domain model that consists of multiple properties and it should only be possible to create valid objects. A valid object depends on a validation that includes multiple of the properties. To achieve this with a data class I have an implementation similar to below (simplified for better overview):
sealed interface Topic {
val id: UUID
val name: String
val title: String
val category: String
companion object {
operator fun invoke(id: UUID, name: String, title: String, category: String): Either<Failure, Topic> {
return TopicModel.create(id, name, title, category)
}
}
private data class TopicModel private constructor(
override val id: UUID,
override val name: String,
override val title: String,
override val category: String,
) : Topic {
companion object {
fun create(id: UUID, name: String, title: String, category: String): Either<Failure, Topic> {
return either {
ensure(category.length > 5) {
Failure.ValidationFailure("The category must be longer than 5 characters!")
}
ensure(name.isNotEmpty() || title.isNotEmpty()) {
Failure.ValidationFailure("Either name or title must not be empty!")
}
TopicModel(
id = id,
name = name,
title = title,
category = category
)
}
}
}
}
}
The complexity comes from the fact that I don't want to expose the copy - constructor.
For this requirement I can also use Exact but only by providing a kind of DTO object as constructor parameter. This does not feel great.
I used a class instead of a data class because the implementation is simpler.
class TopicDto(
val id: UUID,
val name: String,
val title: String,
val category: String
)
class Topic private constructor(
val id: UUID,
val name: String,
val title: String,
val category: String,
) {
companion object : Exact<TopicDto, Topic> {
override fun Raise<ExactError>.spec(raw: TopicDto): Topic {
ensure(raw.category.length > 5)
ensure(raw.name.isNotEmpty() || raw.title.isNotEmpty())
return Topic(
id = raw.id,
name = raw.name,
title = raw.title,
category = raw.category
)
}
}
}
I would like to have a solution to either use the spec - function with multiple parameters.
Is this a valid requirement or is the usage of Exact only intended for single parameter types like value classes and compose complexer types out of it (no longer contain own validation)?