Hello `Koliners` I want ask about `SecurityByDesig...
# announcements
m
Hello
Koliners
I want ask about
SecurityByDesign
if there better setup how to create the classes https://gist.github.com/marzelwidmer/6aa9733c919f2a8dc6aa84116fe4a580 what I don’t like is…
invoke
function is available
Copy code
data class Customer (val firstName: FirstName, val lastName: LastName, val gender: Gender)
// Domain Primitive
data class FirstName private constructor(val value: String) {
    companion object {
        // Create Object
        operator fun invoke(value: String) = FirstName(validate(value = value))
        private fun validate(value: String): String {
            check(value.isNotEmpty()) { "value must be non-empty" }
            check(value.trim().length >= 2) { "wrong value length" }
            check(value.trim().length <= 20) { "wrong value length" }
            return value
        }
    }
}
n
why even have an invoke method? just use the constructor.
👍 2
(with an init block that does the validation)
d
You can run validation in
init
Block of a data class:
Copy code
data class FirstName(val value: String) {
  init {
    require(value.isNotEmpty()) { ... }
  }
}
👍 1
m
Copy code
@ParameterizedTest(name = "{index} test gender {0}")
    @ValueSource(chars = ['f', 'F', 'm', 'M'])
    fun `Customer creation test - it must have a valid gender fF 👧 or mM 🧔`(input: Char) {
        Customer(firstName = FirstName(Faker().name.firstName()), lastName = LastName(Faker().name.lastName()), gender = Gender(input))
    }
I it posible to hide it
d
Also consider using
require
instead of
check
, as it throws
IllegalArgumentException
👍 1
👆 2
🙏 1
😎 1
n
also I'd be careful about making these data classes...I always forget if it's possible to safeguard the
copy
method
m
Btw, I’ve used a similar pattern before but it didn’t scale well. Validation logic cannot always be specified on the type in a static way. It may be dynamic (depend on other input) and/or have complex business logic. So I ended up removing all length checks and alike from these types.
copy
is guarded by
init
afaik.
d
init
can never be bypassed (unless you hack the JVM)
m
Also, static validation on the type tends to be problematic when (de)serializing and when migrating data. Validation logic may change over time which makes it super hard to reuse those classes. You also may re-run expensive validation in cases where data is known to be valid, e.g. when coming from DB.
n
@diesieben07 all the more reason to use init instead of a factory method then :)
m
The
init
setup I like …
muchos gracias
🙂 @Marc Knaup what U mean
to reuse those classes
I am working in a
a like microservice
setup… was planing to validate the
Bounded Context
with this. how U do it then with the validations ?
m
If it’s just a small microservice it may actually be fine. I have a validation behind separate interfaces, not part of the data model. My data model is used multiplatform and for serialization (API & database). Having the validation logic involved in all of those turned out to be problematic 😁
👍 1
Let’s say you limit
FirstName
to 20 chars (which is ridiculous btw 😉) and store such data to DB. In the future you want to limit to 19 chars, so you change the validation. What happens to old users loaded from DB? They may have 20 chars.
m
Is more foucs at REST layer (for web and mobile clients) this is just a PoC setup with DB basically we have to send it later to external system and other services in our domain. and at the moment we can’t trust (;) all the client calls 😉 and have to some how protect the (external system) to also don’t get many issues who is for difficult to analyse then
m
Is it a public API? How do you communicate the validation failures to the API client?
m
no is private corporate API
the communication on rest level. we use the https://github.com/zalando/problem
m
So in that case it’s probably okay to communicate the
IllegalArgumentException
message to the client :)
m
yes.. i think so… important is to don’t pass it (if something missing on first place) to other service in special to the Backend of the company
with this I mean what leave our product team (owned services)
m
Makes sense 👍