<@U05SQRQ75FZ> heyy just dropping by to say I love...
# arrow
m
@Daniel Ciocirlan heyy just dropping by to say I love the contents in your channel! It's super educational and very hands on. I've actively been promoting it in my company. I've recently gave a workshop internally about type classes and composable behaviour in Kotlin and I was pleasantly surprised to see my YouTube notification this morning that you've done one! I've shared it to my colleagues. ❤️ your work!
arrow 12
🎉 5
🙌 2
❤️ 1
K 9
d
Thanks so much! ❤️ Big props to @Riccardo Cardin as well for the written version of this piece!
I highly recommend his articles on the blog, he covers more than I can shoot in a YouTube video - he’s a very talented writer and clear thinker in general
gratitude thank you 1
🫶 1
❤️ 1
s
+1, amazing work. Keep it coming ❤️
gratitude thank you 1
s
Feel free to share a link to the channel and blog post in question, I'm not sure I'm familiar with it! 😁
s

https://www.youtube.com/watch?v=Qhfiq_1eWM8&amp;feature=youtu.be

https://blog.rockthejvm.com/kotlin-type-classes/
K 4
s
Sweet, thanks! 🎉
👍 1
c
🔝
d
@Daniel Ciocirlan Nice video! The only thing that bothered me with the last technique (which seemed to be the conclusion and BEST one?) is that the process function might be different for each event... then you'd have boilerplate to redo the validation for each type of processing... OR that ugly when block for each type of event with all the cons involved with that...
r
@dave08, you usually don’t have a single function that needs to handle all types of a type class. Let’s a look at this example: https://github.com/rcardin/functional-event-sourcing-in-kotlin/blob/main/app/src/main/kotlin/in/rcard/fes/portfolio/routing.kt
Here, we have a ktor application using type classes to validate each route’s input DTO. Each route uses an instance of the validator. aka, the type class
🙌 1
m
we have a similar thing in house, we have a
Validate<T>
instance which allows us to plug-in validators
🎉 1
d
I guess I see your point @Riccardo Cardin, but there's no way to assure you've validated input by the endpoints using the compiler -- in the video, the process function requires a validator, and since there's only one for all paths, you won't forget to validate anything. Also, that humungous
respond
at the end of that file... it goes to show how that logic still needs a big when on the business layer... the validation errors that might only be related to one particular use case has to be added to that respond function, and each change in use cases need to alter it. I have another sealed interface for response types that are a bit more like the http layer and in each use case I translate the error from the data layer to what's expected in the http layer, that way the http layer doesn't depend on any use case errors, but the downside is that business logic now has to understand some kind of meta-http response type... I'm not sure how to make any of this any better though...
r
Can you make an example? Sorry, I can't follow your reasoning (it's my fault) 😥
d
Of which part?
r
The whole part🥲
d
https://github.com/rcardin/functional-event-sourcing-in-kotlin/blob/a3cdaeaee4edb9[…]2d55f7a76/app/src/main/kotlin/in/rcard/fes/portfolio/routing.kt is dependant on your use cases... some of those errors might relate to only one of them, and when you remove it or change it, the function needs to be modified... in the video, one of the things you wanted to gain was not having to alter one big validation function when adding/removing events. Here there's the same problem with returning results.
In the video the
process
function required a Validator parameter... making sure you pass one not matter which event you're running, here in Ktor an endpoint doesn't force you to use a validator... if you wouldn't validate but just call.recieve() the compiler wouldn't complain... which is another point in the video that you want the compiler to force you to validate things...
r
IMO, it’s not possible to have a unique
process
function in real-life scenarios. You always have a stack of application/business/persistence logic for each model/scenario. If you try to have something more abstract, you'll couple things that should not relate to each other. The article/video aims to show how to achieve polymorphism without subtyping.
I hope I got your point 🙂
d
It just seemed like the last method covered all the problems of the first two, I was trying to point out that not all the problems were really dealt with... but I understand now that your point was just to show a type classes, just wondering if there's any way to overcome it's problems. I guess I'll try to keep your point in mind still looking for the right use case... 😊. I still don't see the big advantage of this compared to keeping that validation logic in the class's companion object.
r
The advantage is the separation of concerns. Is it correct to bind the validation logic into a type? Usually, the modules that call the validation logic are not the same as those that use the other methods of the validated class. Using type classes, we can be more cohesive
🙌 2
Validation is just a use case of type classes. Maybe, there are other use cases that show better the separation of concerns 🤷‍♂️
d
Yeah, I guess that could be a point in the case that the same class can be valid in different ways in different contexts, but when creating a class that the logic is unique to it, then it might make more sense that it shouldn't be able to be created in a wrong state...
r
Use smart constructor in those cases
2
Validation is for objects you don't create, like in deserialization processes
👍🏼 1
1
d
That's a good point!
Maybe, there are other use cases that show better the separation of concerns
Probably, thanks for the idea itself 😃, at least when I see such a case, I'll have this technique up my sleeve!
🎉 1
🚀 2
mind blown 1
❤️ 1