All right, so let's continue with one of our favorite topic, which is dependency injection.
We talked about it this morning. As you can see, we have a lot of topics. We have even
more topics until, what time do we finish? 6.30 p.m., right? So, 6 p.m., 6.30. So, we still
have a lot of stuff coming in. But for now, please welcome Arnaud, who is going to talk
about COIN. Thank you very much. Let's talk about new COIN developer experience in COIN.
Just about me, I'm Arnaud Juliani, the lean maintainer of COIN project and also COIN GD.
COIN is a dependency injection framework, and the idea is to help you structure your application
with ease and efficiency. And this is the challenge of providing a DSL developer experience
for you to make your app very, very easy to build. I tried to explain COIN in just two
minutes to explain how finally we improved behind that. As we have a dependency injection
framework, we want a bunch of classes here, one A and B with the dependency. And we have
a DSL keyword here that make the configuration space for us. Then this is the module keyword
that introduce the way that we have definitions for the application, single keyword with a
lambda function to create what we want to, the class that we have here, and the second
one to declare the second component, and then we are done. We have declared our components
inside the COIN container. The thing here is that it's working directly with your
Kotlin code. That means that here, if you follow closely, we are using constructor directly.
And then it's not compiling. Then that means that this class B is needed a dependency to
class A. And then this is where we need the last keyword that is get. And then the challenge
was that in three keywords, I can manage to write an application configuration to manage
my dependency. The thing is that then COIN can create everything by constructor for you
and also run any kind of Kotlin code directly behind the functions. The other side of COIN
is that you can inject any field easily just by unlocking an extension with the COIN component
interface. That means that you can access to the by-inject function that helps you retrieve
a dependency out of COIN container. Then you have both components, those one that are created
directly by COIN. And when you can't have things created directly by COIN, then you
need to inject in fields. This will perhaps remind you some of the Android activity things
like you can't create activity by yourself. You can't create Android component by yourself.
You are called by a lifecycle. Then you need to retrieve things from the outside of the
container. And then that's it. You mostly have all the tools to have your dependency
injection. You need just to run and start your container. But finally, the experience
is interesting and the community raises many things like problem of verbosity. Because
sometimes in application you tend to have like dozens of dependency. I would say perhaps
look at your code, perhaps you have kind of potato effect where you can have everything
inside one component that try to gather everything. But yeah, not that great for us. This is where
the story starts for us and how we can improve this for the Kotlin developers. And then from
this really simplistic example here, what we have here is we would like to avoid our
developer to write manually the GET things. From the idea and the need of GET is that
COIN is made to be super efficient. We don't use reflection. We don't use any kind of meta
information over your code. We just run the thing. And then the configuration seems to
be a bit manual over there, but then you are manually writing the things for COIN. The
new magic way finally to write this with COIN is having a new keyword, single and single
off. That is the same semantic keyword, but it's a new function. And then instead of asking
you a lambda, we want to ask you a function directly. This is why you have the double
semicolon character. And then for us, you don't have to write things with GET. It's
still readable, still very easy to use with the COIN semantic, the sense, the meaning
of the DSL. And then also, it's consistent with changes in the meaning of, for example,
if you change the constructor of a class, your DSL can break because you didn't update
it. Then for us, it's a very great improvement to go over a DSL that is using lots of functions,
but finally not a voodoo to write those functions directly as a lambda, but directly with parentheses
and this pointer kind of pointer function stuff. The other side of COIN, of course,
is having dynamic behavior that are interesting is that you can pass that directly to a definition.
That means that in this class, we just want an ID. And what we want to do is pass this
ID dynamically to this component. COIN offers you the way to do that directly when you inject
a field by using the function parameters of. And then magically, your data is going into
the graph and then is injected in your definition directly by this function. This is very visual,
interesting, but then this compact way of having the DSL also is capable of dealing with your
lambda expression. Then you don't need lambda anymore. It's quite interesting because finally,
this was this feeling of having COIN as a really compact DSL and compact way to describe everything
without to invade your implication is that now it avoid an annoying side effect of the DSL
and then now you can just write directly your class constructor like that. There's, of course,
some warnings. If you have qualifiers, name parameters, like if you have two components
that have the same type but have not the same implementation, then you want to have the
different name for them. Then here we can guess which one you want to use directly. Function
and classes that have default values, we don't know. We don't know if we, if you want to
use the default values, if you want COIN to use this, then up to you to use again the lambda
expression thing and also any kind of complex Kotlin expression like builders. Yeah, it's
still Kotlin then for you. You can just still use the lambda when those expressions are
needed else go with this double semicolon character expression and then just use the
class and then you're done. Mostly keep the things up going in the easiest way to write
for you. It's opening a door for us like we are a framework maker, then we try to understand
what kind of DSL and options we want to offer you. For example, when you define something
in your DI, you can give it a name, a qualifier. We can say that it's created on start. For
example, the container is starting, then you can create it on start and also you can say
that it's binding another type. All of this is interesting but it's not really easy to
extend in terms of keywords and binding. For example, you don't know if there is other
keyword after the bind because we are already using some lambda, then a function to express
something. Then do we open a new lambda block after the lambda block? It's a bit weird things.
Then with this new DSL, we can open a new way to write this function. That means that
we can directly open a lambda theory for this option. Like we have a name, we have created
a start and we have bind. This is the same word but not implemented in the same DSL style.
Here this is functions directly out of the definition thing. Clearly, you see it's a
bit more readable for us also. It's clearly more maintainable and allowing us to add more
features at time. Then it's really interesting to provide a new way to write things and also
feedback of the community is super interesting for us.
One of the things also is that coin is really simple and keep the things really simple in
terms of DSL. That means that you declare anything in terms of module. You can scale
in the way you want by features, by layers, by everything. Then up to you to organize
yourself. Really, the idea is that the tool shouldn't impact your mind, shouldn't impact
your way to build your application. You should even forget that you are using coin. This
is really important for us to continue in this way.
In coin, the framework never had the need of gathering modules, other by list or by,
let's say, something more convenient by a plus operator, but it was really simplistic.
The problem is that with scaling application development, scaling around all the development,
we need really strong links between definition, between reusability of this component, this
layer and this stuff. We finally introduce something that can be seen as really simple
to add as a module is that we add the includes function that help us really understand what
kind of module we want to reuse and then flatten everything and optimize your loading at start
for you. It may be visually, it may be really easy to use, but when finally at the beginning
for coin, you only have a list of modules to play with, it's kind of really hard to reuse
and really hard to figure out where finally you can build your configuration. Then we
are unlocking a really big door that means that you can begin to reuse parent modules
with child modules and then you can begin to dive into really, really complex, big and
complex configuration things. Then for you, we are flattening all the graph, we are loading
and optimizing all the stuff for you. Then all those Kotlin multi-platform, all of these
features are Kotlin multi-platform ready and to get those superpowers, sure, you can grab
this directly in your Gradle file. It's not 3.2 versions, time is flying by 3.3 and if
you are making a Kotlin multi-platform application, use the coin core module, Gradle module and
if you are using Android, then use the coin Android module version. Coin has been made
to make your development super easy and super simple and this is why your coin configuration
should stay really simple for you. I let you meditate on this quote from Chet Hazer and
the transition for us is we are trying to use another kind of expression in terms of
framework is that until now we were really people that pushing a lot for Kotlin DSL,
stuff, et cetera. The idea of perhaps introducing annotation is also to not reproduce what you
can find in other frameworks like Dagger and other, but really point something, we want
to bring value and the problem of also the DSL is that we clearly have some limits over
that. We can't understand really what you are writing, we can't trigger any static
analyse of your code directly. That came to magic to the Kotlin compiler plugin. I won't
dive into details for that because I believe some people already talk about KSP and everything
about that, but let's say that Kotlin compiler is everything we could do for you before we
are compiling your code in Kotlin. Then we could rewrite things, we could make code generation
of course, analysis, et cetera, et cetera. What we will do with Google KSP is provide
you a way to avoid the DSL and go really straight forward with annotation and keep all the coin
semantics, all the coin API for you. We don't want to reinvent the wheel. What we want to
do here is that we want to generate what the DSL you would have to write and then it's
really, really, really a small piece of code that you would have to write. Then if we can
still avoid you to write things in your code, this is still a good experience for us to
let you understand how far we can go. In terms of definitions, what it means is that if you
have a class, then you can just add directly an annotation. You see that this is the same
keyword we have the add single on it. Then you see that we are extending an interface.
The idea is that with just one annotation, we will understand that this class is having
a constructor and then we will also bind directly the type migrate history. The idea is that
we allow you to have, not to type anything in this. We detect things for you. We detect
the code and then we can say, okay, coin, just write this definition for my repository
type with the implementation of my repository. We have another component. We target add factory.
Factory is another keyword of coin. It's the opposite of a single ton. Factory is something
you want to create. Each time you want to ask a definition for that. Then if you want
an instance of my presenter directly, you just tag it add factory and then coin will
generate the DSL and then coin will manage to go and get the definition for you. You
see finally you don't really care about the DSL and the complexity behind that. Finally,
we can detect many, many things for you. Finally, for those who are making Android development,
we have an annotation dedicated for coin that lets you understand that. Let coin understand
that. We will create an instance of view model. Then we are reaching all the dependencies.
We understand that this is a view model and then we will bind everything for you. You
see that here we don't speak about DSL. It's just that we tag something here. The idea
is that we can have automatic injection and binding. We can detect everything, all you
need here by default. We can deal with new label type. That means that if you use the
question mark in parameter construction, then we will understand that this is something
that can be new label and then for you, it's completely transparent and then it will be
taken into account. Also, as you have seen, we can tag a parameter in a function or in
a constructor as injected param. That means it will be something that come from the application
that is sending a data, a dynamic data directly to the definition. Then the natural way to
do that will be to tag a parameter as injected param. You see that finally, the experience
for us is to try really to let you write the minimum and the minimum things for you. Like
for example, with dagger hit, we still have lots of things to specify. For example, in
the spring framework, this is the kind of opposite because a spring is scanning everything
for you and making all the class pass analysis for you. Then we are in between where finally
we allow you to just tag your code with just a bunch of annotations and then you are ready
to go and you can manage any kind of tip-off injection with your constructor things.
The idea behind of the magic is that just you use annotations and you are ready to use
the standard coin API is that you can use bi-inject or bi-view model field injection
style here. Then we don't break the experience of people that are already using a coin and
then we continue, then we allow people that are using annotations directly to use those
extensions as regular extensions. For the modules, then for definition, we just
tag annotations. We annotate classes, but for modules, we can't directly tag something
in the DSL. How works KSP is that we are scanning for many classes or functions, then it will
be kind of hard to tag around the DSL. The proposal for now is to work directly with
class module to let you have an organization module for that. Then how you do that, you
declare a module and that's it. You have a module, you have a hard module and the idea
is that you put add component scan and then we will scan any kind of component that has
been tagged in your application by package. Then it's really specific in terms of scan
then that means that you can really filter by package, filter by layout, filter by features,
how you want to organize yourself and then you just have this annotation here. Also,
if you want, you can declare things directly inside a function. We will understand that
if you tag something inside your module class, it will be a definition that we can bind for
you directly. You see it's still very, very natural to use and really super compact. Then
the idea is for us to let you go super fast for your dependency injection and keep everything
aside for you. Of course, between two modules, you can have the includes of other modules
that will generate the right things for you. That means that it will use the includes function
that has been introduced just above in the new coin DSL site. Then we just need to start
coin. That means that you have your module, you have a function where you want to start
to start coin and then the idea is we just run the module with the new instance of my
module here. The only thing we want to generate for you is that it's just a simple extension
that will generate the DSL and this is where we just want to make boundaries for us. We
don't want to reinvent the wheel. We don't want to reinvent things to generate code over
code over code. We want to keep coin as it is, something that is super efficient to make
dependency injection but allow you to use the annotations. This is why with such approach,
you can mix both. You don't have to write a new project with annotations. You can already
use coin annotations inside your project and test with it. The only thing you have to
care is be sure to have the right import. That means that we are generating all your
coin contents inside our coin.ksp.generated. Then you can use both DSL module, class modules
annotated and everything, everything. Then up to you to express yourself and use the
right tools that is great for you. What is interesting for us is that we don't want to
reproduce what we have seen and why we have made coin is that we don't want to expose
you to tools that can take dozens of minutes to recompile your project. The idea is that
it should run for thousands of components really quick. The other good thing of that
is that it's cutlin behind the scene, it's cutlin generated and this is something you
can clearly debug step by step if you want. Up to you, that means that we don't want
to replace DSL by annotations. It's another way to express yourself. Ksp is a good technology
for us to help you write less, less quotes, less bugs. Then up to you to choose the right
tools and the right solution to make your app structure. To finish then about coin and
some improvement of this year, what's next? If you want to throw now about coin, we have
many tutorials on many kind of cutlin application from a cutlin, cutlin multiplatform and Android
application, also Cator if you want. This is the roadmap for 2023 where we have end
of track coin 3.2, 3.3 is the active track, this is the current application that is still
maintained before the next release where we are in 3.4, where we want to focus on compose
for the jet brains multiplatform side, be sure that we want to bring better experience
for cutlin native and we have also the verify API that is a new verification API that lets
you make a compile time verification. Of course, we are really keen of Cator and we
want to push new things about Cator. Especially today at FirstDem, and this is my first session
at FirstDem, I'm really happy to show all the people that are really sharing and contributing
to coin and I clearly want to thank them. Thank you all the community to work on coin.
I believe some of people can find themselves on this board. If you want to chat with the
coin community, then you can either find us on Twitter, on Slack, the cutlin on Slack
and also you can go on the website that is inside coin.io to find all the related sources
that you want. And also Open Source is great, but you need a strong company behind that to
help you and have support on your project that is helping with coin technology and cutlin
technology. This is why I founded Cozilla last year to work with people that are using
such technologies. Then you can find all the resources on Cozilla.io and write on time.
Thank you.
Then we have time for questions. No question there.
No, sorry. We don't have time for questions. We are so strict on timing. The next talk
will start in four minutes, actually.