0xf1f1
02/17/2024, 8:27 PMRiccardo Cardin
02/18/2024, 8:28 AMEither type on your public interface. I mean, will you ever build an instance of UserType alone? If yes, then the factory of the type must return an Either. If the public interface is the User type, then the Either must go only of the UserFactory. The DDD purist would say you need Either only on your aggregate.
Btw, use EitherNel instead of Either with a list.
Try to have a look also at the smart constructor pattern.0xf1f1
02/18/2024, 6:44 PMRiccardo Cardin
02/18/2024, 6:46 PMbind method of arrow. Please, check this article for further details: https://blog.rockthejvm.com/functional-error-handling-in-kotlin-part-2/Riccardo Cardin
02/18/2024, 6:47 PMRiccardo Cardin
02/18/2024, 6:48 PMRiccardo Cardin
02/18/2024, 6:48 PMUlrich Schuster
02/19/2024, 4:48 PM0xf1f1
02/19/2024, 7:43 PM0xf1f1
02/19/2024, 7:46 PMRiccardo Cardin
02/19/2024, 7:47 PM0xf1f1
02/19/2024, 8:11 PMimport arrow.core.Either
import arrow.core.raise.either
import arrow.core.raise.ensure
interface Prob
sealed interface HouseRoomProblem: Prob {
data object HasNoName: HouseRoomProblem
}
object HouseRoom {
data class Room(val name: String)
fun *create*(name: String): Either<HouseRoomProblem, Room> = _either_ *{*
ensure(name._*isNotEmpty*_()) *{*
HouseRoomProblem.HasNoName
}
*Room*(name)
}
}
object House {
data class House(val room: HouseRoom)
fun *create*(): Either<List<HouseRoomProblem>, House> = _either_ *{*
*House*(
room = HouseRoom.*create*("room1").bind()
)
}
}Riccardo Cardin
02/19/2024, 8:48 PMinterface Prob
sealed interface HouseRoomProblem: Prob {
data object HasNoName: HouseRoomProblem
}
object HouseRoom {
data class Room(val name: String)
fun create(name: String): Either<HouseRoomProblem, Room> = either {
ensure(name.isNotEmpty()) {
HouseRoomProblem.HasNoName
}
Room(name)
}
}
object House {
data class House(val room: HouseRoom.Room)
fun create(): Either<HouseRoomProblem, House> = either {
House(
room = HouseRoom.create("room1").bind()
)
}
}Riccardo Cardin
02/19/2024, 8:49 PMList<HouseRoomProblem>, but with the fact that you don’t use/create the list at all 😅0xf1f1
02/19/2024, 8:50 PM0xf1f1
02/19/2024, 8:53 PMRiccardo Cardin
02/19/2024, 8:55 PM0xf1f1
02/19/2024, 9:05 PMRiccardo Cardin
02/20/2024, 8:01 AMobject House {
data class House(val room: HouseRoom.Room)
fun create(): Either<List<HouseRoomProblem>, House> = either {
House(
room = HouseRoom.create("room1").mapLeft { listOf(it) }.bind()
)
}
}
Otherwise, you should use the zipOrAccumulate function if you want to accumulate all the validation errors.0xf1f1
02/20/2024, 8:56 AMRiccardo Cardin
02/20/2024, 11:23 AMLeft instance, you always have a non-empty list of errors. So, you can use the EitherNel, which uses a NonEmptyList to accumulate errors.Riccardo Cardin
02/20/2024, 11:23 AM0xf1f1
02/20/2024, 8:05 PMRiccardo Cardin
02/20/2024, 8:50 PMcontext(NonZero<T>)
fun <T : Number> T.nonZero(fieldName: String): EitherNel<ZeroFieldError, T> =
either {
ensure(nonZero()) { nonEmptyListOf(ZeroFieldError(fieldName)) }
this@nonZero
}Riccardo Cardin
02/20/2024, 8:51 PMbind() works like a charm with EitherNel since this last type is only a type alias for Either<NonEmptyList<E>, A>Riccardo Cardin
02/20/2024, 8:52 PM0xf1f1
02/20/2024, 9:19 PM