Automatic Dependency Injection in Scala - Just the Type System!

แชร์
ฝัง
  • เผยแพร่เมื่อ 18 ก.ย. 2024
  • GitHub: github.com/sca...
    Learn ZIO: rockthejvm.com...
    In this video we will demonstrate a technique for automatic dependency injection in pure Scala with no other libraries or frameworks. Here, instances are passed automatically just by the structure of the types in question, without relying on macros, annotations, reflection or any runtime behavior. The technique is based on an example from Martin Odersky after an informal discussion (shared with his permission).
    We'll cover
    - a scenario where dependency injection is useful
    - how explicit dependency injection is done
    - how the ZIO library manages dependency injection with ZLayers
    - how we can use givens, match types and a minimum of type-level programming to make the compiler automatically infer which instances need to be injected in which place
    Follow Rock the JVM on:
    LinkedIn: / rockthejvm
    X: x.com/rockthejvm
    Blog: blog.rockthejv...
    -------------------------------------------------------------------------
    Home: rockthejvm.com
    -------------------------------------------------------------------------

ความคิดเห็น • 32

  • @rockthejvm
    @rockthejvm  หลายเดือนก่อน +3

    Please write your impressions of this approach in the comments! If you like it, it's not impossible that it may become a core Scala library or module.

  • @HelloForeignWorld
    @HelloForeignWorld หลายเดือนก่อน +12

    A couple of potential issues come to my mind:
    1. Config loading based on some condition - e.g. loading different config file based on environment variable or some CLI argument, which will not be possible if the dependencies are resolved entirely on the type level. Usually you have your config as a very first dependency which is fed in the services.
    2. Disposing of resources (e.g. acquire and release) is not under our control.
    3. Using fresh instance of a layer (e.g. to avoid global uniqueness for a particular layer)
    To be honest all of the above issues might very well be solvable and this could be a good lightweight DI approach. I really like the clever type level programming and that you managed to mention "Odersky" and "ZIO" in a single video 🙂
    Thank you for sharing this interesting idea!

  • @brieuckaisin7742
    @brieuckaisin7742 หลายเดือนก่อน +4

    This is BRILLIANT, thanks! Tuples as heterogeneous lists and match types are real game changers in Scala 3!

  • @yiannig7347
    @yiannig7347 หลายเดือนก่อน +6

    need a big cup of coffee and go over this, but it looks cool

  • @DoctorPiss1
    @DoctorPiss1 หลายเดือนก่อน +2

    What you can do with the Scala 3 compiler is amazing. I have mixed feelings about this kind of automated dependency injection. I do like that it can result in a lot less code written by the programmer but every time I have worked with something like this I have had to spend a lot of time figuring out all of the magic that is going on under the hood. I do like that this solution is built with plain Scala. No macros or reflection. Interesting stuff

  • @DavidePavan
    @DavidePavan หลายเดือนก่อน +1

    Finally, an example of using type-level programming in Scala. The simplicity and elegance are impressive. Having worked for years with Java and Spring, I appreciated doing dependency injection explicitly when using Scala. Therefore, I don't think I would use this technique in my own project, but I would be very interested in seeing more examples of how to leverage this technique.

  • @chiquiflautro
    @chiquiflautro หลายเดือนก่อน +1

    I was actually thinking of trying to implement something like this the other day. Nice to see you doing a video about it and Oderdky coming up with it

  • @darrenkim8301
    @darrenkim8301 หลายเดือนก่อน +1

    It was very helpful for me understaing Auto DI using pure scala3. Thank you!

  • @MrDejvidkit
    @MrDejvidkit หลายเดือนก่อน +1

    This is a very nice trick, and I love it. It could be useful for simple programs, which is really nice. I would use this in subsets of a bigger project, but I like the ZIO approach much better because it has more advanced and feature-rich options, like repeatability, configurations, etc., which the compile-time constructor can't work with. At least, I think so. Also, this has no error handling, which is something I really love with Zio-type. Safe error handling is really important in big projects.

  • @chiquiflautro
    @chiquiflautro หลายเดือนก่อน +2

    wouldn't it work also with multiple implicits rather than a single using clause with a provider of a tuple

  • @jay-hinddoston8364
    @jay-hinddoston8364 หลายเดือนก่อน +1

    Need to try this but its awesome

  • @pawesado8782
    @pawesado8782 หลายเดือนก่อน

    Comparing types using match types can run you into a problems.
    Personally I think it is an anti pattern.
    It's because of disjointness checks which is required to advance to remaining cases.
    With simple types - everything works well, but problems arise when you want to match against covariant/contravariant generics, or match types.
    Consider example below:
    type IsSame[A,B] =A match
    case B => true
    case _ => false
    summon[IsSame[Option[Int],Option[String]] =:= false]
    It doesn't compile
    The worst thing is that everything seems to be fine until you start using some more sophisticated types

  • @MrMikeJones1477
    @MrMikeJones1477 หลายเดือนก่อน +1

    Is there a public RFC for this feature?

  • @MrDejvidkit
    @MrDejvidkit หลายเดือนก่อน +1

    Yeey new Scala video, finally :)

  • @bishbashboshjt
    @bishbashboshjt หลายเดือนก่อน

    I’d be interested to see conditional dependency injection like Zio layers support - might be possible with an auxiliary data structure that’s indexed like a tuple but the element can be optional/error type

  • @Thomas-yh6nx
    @Thomas-yh6nx หลายเดือนก่อน +1

    No magic, I like it!

    • @sulikszabolcs
      @sulikszabolcs หลายเดือนก่อน

      Except the extra traits, types, the implicit mechanism and the scala.compiletime package. Other than that, nothing, really.

  • @butcherless
    @butcherless หลายเดือนก่อน

    Odersky is doing a magnificent job and I have no doubt that he will make the language disappear. However, it is always comforting to learn by watching Daniel's videos.

  • @sulikszabolcs
    @sulikszabolcs หลายเดือนก่อน

    In my practice writing the wiring logic is the smallest possible problem. And the compiler helps me by checking the *explicit* types in the constructors.
    I don't see the benefit of the extra compiletime magic to get the same results. Generally I don't see the benefit of any magic at all.

  • @flatmapper
    @flatmapper หลายเดือนก่อน +1

    Can we do DI without frameworks?

    • @HelloForeignWorld
      @HelloForeignWorld หลายเดือนก่อน

      it all depends on the level of ergonomics you are ready to sacrifice :D

  • @hubstrangers3450
    @hubstrangers3450 หลายเดือนก่อน

    Thank you....could you kindly provide the transcript for the above video, need to read to support your thoughts....thx

  • @alanliu6126
    @alanliu6126 หลายเดือนก่อน

    Excuse me, how to benchmark scala apps, could it be used in production?

  • @orlandocastellanos9263
    @orlandocastellanos9263 23 วันที่ผ่านมา

    Can we use spark with kotlin?

    • @rockthejvm
      @rockthejvm  21 วันที่ผ่านมา

      Yes, with the Java API - but completely unrelated to the video, no?

  • @tuxjumale4197
    @tuxjumale4197 หลายเดือนก่อน

    t.b.h. this all looks to me like just a good theoretical exercise, but in my daily work I wouldn't choose neither this nor ZIO-layers over the good old macwire "lazy val userSubscription = wire[UserSubscription]". And even if not relying on the macwire - then still I would rather wire everything manually "lazy val userSubscription = UserSubscription(userService, db)", than having to write those unnecessary layers/providers/etc

  • @EmilioRodo
    @EmilioRodo หลายเดือนก่อน

    As interesting as the mechanism is, I'm still not groking how is this or Zlayer more ergonomic that simply instantiating one's dependencies and wiring them via constructor injection. Both approaches require boilerplate in the companion object (and therefore a dependency on the di library). Could you elaborate on that? I am legit terrified I'm being an old man shouting at the clouds here, I'd love to understand this!😂

    • @rockthejvm
      @rockthejvm  หลายเดือนก่อน

      You don't have to manually build your instances, you don't care where they come from, you don't need to keep track of which piece requires which instance

    • @EmilioRodo
      @EmilioRodo หลายเดือนก่อน

      ​@@rockthejvmhow would it work if you had several instances of the same type (different implementations of the same interface)? Assuming that you need to control which implementation is passed where

  • @galberger8415
    @galberger8415 หลายเดือนก่อน

    I love Scala, I really do. But at the risk of sounding like a hater - this solves an issue that nobody had a problem with.
    I have a mere 6 years of Scala under my belt and so far the companies I know that use Scala in production either do not use its full power OR (and worse) shifting away from it. It is hard enough to find a good Scala programmer, let alone an advanced one, so please, let's stop making things more complex.
    And to top it all, if I did understand the explanation well, it is not available in Scala 2 due to the lack of type matching which makes this feature a major block for most of the industry.

  • @abelgerli
    @abelgerli หลายเดือนก่อน +1

    Ok TLP is needed .. to support it, but not to use it. So i am able to use it without wearing a real black belt 😊

  • @haroonalishah1940
    @haroonalishah1940 หลายเดือนก่อน +1

    From simple DI to complex, extra code ZIODI, NO THANK YOU.