Damiano Petrungaro
04/02/2022, 12:22 AMKirill Grouchnikov
04/02/2022, 1:52 AMStephan Schroeder
04/02/2022, 8:51 AMDamiano Petrungaro
04/02/2022, 10:27 AMStephan Schroeder
04/02/2022, 11:18 AMInvalidEmail
could be a Singleton
object InvalidEmailException: IllegalArgumentException(""Email must be a valid email address"")
• isn't Email.isEqual
identical to the autogenerated equals-method!? 🤔 (is it meant to be override fun equals
?? )
• you definitely have a very functional style, you avoid throwing exceptions by using Either all the time, but the code is definitely less concise because of it. E.g. this is what Email
would look like in a non-functional style
private val validEmailFormat =
"""(?:[a-z0-9!#${'$'}%&'*...\x0c\x0e-\x7f])+)\])""".toRegex()
@JvmInline
value class Email(val s: String) {
init {
require(!validEmailFormat.matches(s)) {"Email must be a valid email address"}
}
override fun toString(): String = s
}
• if you overwrite toString()
only because you want to be able to access your private wrapped value, i'd suggest make the value public and drop your toString()
• you could just use `runCatching{...}`to wrap the instanciation of value types (if you go my path so that instanciating them would throw an IllegalArgumentException) and getting a functional Result
type
So yeah, the code looks good, maybe a little much of ceremony, but that might just come with Arrow (which I haven't used yet).Damiano Petrungaro
04/02/2022, 12:14 PM.let
which I feel can be simplified maybeStephan Schroeder
04/04/2022, 8:38 AMval evenNumbers = listOf("2", "5", "13", "28", null).filterNotNull().map{it.toInt()}.filter{it%2==0}
If that's what you're interested, take a look at the functions on the Collection-Interface: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/#functions
I haven't much experience with Ktor, so no tips there.Damiano Petrungaro
04/04/2022, 8:41 AMStephan Schroeder
04/04/2022, 8:56 AMEither
, but you do have Pair
and Triple
. I've never used Triple
but Pair
is used implicitly all the time thanks to the to
-function which returns one
val pair: Pair<String, Int> = "one" to 1
// or more common hidden in
val map = mapOf(
"one" to 1,
"two" to 2,
)
For other sum types you'd just construct them via sealed classes/interfaces. (Which comes probably from Java's nominal typing over structural typing aka "it's better to give structures a name")
• plus the 1class-methods/lambdas and collection-api I already mentioned
• nudge to immutability via val
(next to var
), immutable Collection-Interfaces and -one level up- completly immutable collections via https://github.com/Kotlin/kotlinx.collections.immutableDamiano Petrungaro
04/07/2022, 5:42 PMStephan Schroeder
04/08/2022, 9:18 AMdependencies {
implementation("io.ktor:ktor-auth:1.6.8")
implementation("io.ktor:ktor-auth-jwt:1.6.8")
implementation("io.ktor:ktor-server-core:1.6.8")
implementation("io.ktor:ktor-server-netty:1.6.8")
implementation("io.ktor:ktor-serialization:1.6.8")
...
testImplementation("org.jetbrains.kotlin:kotlin-test:1.6.8")
testImplementation("io.ktor:ktor-server-test-host:1.6.8")
}
you used the ktor-version so much, that you also used it for kotlin-test
but it seems to use the same version as kotlin itself and there isn't an kotlin-version 1.6.8
, you most likely want 1.6.10
because that's the version you use for kotlin in the plugins block.
There are several approaches to versioning variables (for versions that appear more than once), the easiest of which would be to define one within the dependency block:
dependencies {
val ktorVersion = "1.6.8"
implementation("io.ktor:ktor-auth:$ktorVersion")
implementation("io.ktor:ktor-auth-jwt:$ktorVersion")
implementation("io.ktor:ktor-server-core:$ktorVersion")
implementation("io.ktor:ktor-server-netty:$ktorVersion")
implementation("io.ktor:ktor-serialization:$ktorVersion")
...
testImplementation("org.jetbrains.kotlin:kotlin-test:1.6.10")
testImplementation("io.ktor:ktor-server-test-host:$ktorVersion")
}
This works nicely for single module projects but you can't share these variables with the plugin block, which is a shame, because a shared val kotlinVersion = "1.6.10"
surely would be useful here.
For that you'd need a buildSrc-folder/approach, but it's more tricky to setup, but you can check out this demo project here: https://github.com/simon-void/ktor_serialization_demo
Within the buildSrc-folder you define a singleton containing all the dependency info you need:
object Deps {
const val kotlinVersion = "1.6.10"
}
which you than can use throughout your gradle-config
plugins {
application
kotlin("jvm") version Deps.kotlinVersion
id("org.jetbrains.kotlin.plugin.serialization") version Deps.kotlinVersion
}
dependencies {
...
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:${Deps.kotlinVersion}")
}