Dependency injection in Erlang (Disgression from: Longstanding issues: structs & standalone Erlang)
Mikael Karlsson
mikael.karlsson@REDACTED
Mon Feb 27 21:48:22 CET 2006
Romain LENGLET wrote:
> ...
>
> I think that you and I went too fast.
> Let's not try not to transpose as-is conceptual models and APIs
> such as Fractal's, that were designed for object-oriented
> programming languages. And let's use precise and standard terms.
Thanks for the terminology intro.
..
>
> If for you "contract checking" equals Meyer's "Design by
> Contract(TM)", then I think that is wrong in the context of
> Erlang.
[terminology stuff cut]
I had that in mind, but maybe more from the practical point of checking things
at runtime. UBF contracts are another example.
> Therefore, all what you want is simply to restrict the possible
> message transmissions between Erlang processes, and to check at
> runtime that such a restriction is respected.
Yes, that is all I want.
> You don't need to introduce interface types (i.e. signatures) to
> do that, unlike in Fractal or ErlCOM, and you don't need to
> introduce server interface names, etc. Let's keep it simple,
> stupid.
OK.
> In the engineering viewpoint, this kind of checking is the role
> of interceptors, in bindings (cf. RM-ODP part 3, clause
> 8.2.1.4). You can do that already with the simple API I
> proposed: an interceptor is simply a filter.
..
Nice example.
> Instead of directly binding a client process to a server process,
> just bind the interceptor in between:
> gen_server:call(Client, {setdep, service, Interceptor}),
> gen_server:call(Interceptor, {setdep, intercepted, Server}),
>
> Need anything else? :-)
Not really. :-)
But I want to be able to do it the other way too, even if it is more
restrictive. I do recognize that a framework should not impose my style on
others. If a dependency injection framework is limited to what you suggest
(setdep/getdep) that would be possible.
..
> > This could be
> > quite interesting, the Erlang Corba idl compiler for instance
> > generates interface modules with methods for idl specified
> > metods like:
> >
> > ping(OE_THIS, NeededArguments) ->
> > corba:call(OE_THIS, ping, [NeededArguments], ?MODULE).
>
> And then, what would be the interface and interrogation
> signatures corresponding to:
> - client side: Pid ! "hello".
> - server side: receive Msg -> io:format("~s~n", [Msg]).
There would not be any for this. I would not send an untagged message in
my application, but be more restrictive.
messy_interface:msg(PiD, "hello").
module messy_interface:
mgs(Ref, Message) ->
gen_server:cast(Ref,{messy_interface,msg, Message)
But again this should be left out of any dependency injection framework.
> Introducing interface signatures and interaction signatures does
> not fit Erlang, and introduce unnecessary arbitrary restrictions
> that would make reuse of existing Erlang programs very hard.
Yes, but if I write new programs that are restricted to OTP behaviours I might
come out OK.
..
> > One problem with ErlCOM, if I understood it right, was that
> > you could not have a many clients - one server relationship?
>
> No, I doesn't have such a limitation.
OK, maybe I should be more specific, I thought you only could bind one ErlCOM
interface to one ErlCOM receptor. If this is not the case I think it is a bit
too complicated for me to understand anyway....
...
> That is one big problem with Design by Contract(TM): if you want
> interesting behaviour specifications, you end up disclosing all
> the internal state of objects, hence you break encapsulation.
> See papers on JML (Java Modelling Language) for a discussion
> about that problem, and possible solutions.
> But again, DbC is not the only way to specify and check things
> that can be agreed upon about behaviours. It is only one of the
> most well-known.
>
> Sometimes, writing control code is better. That is one of
> Fractal's mottos: "programmable control". Why invent a
> specification language, when you can already specify control
> things in your favorite programming language (cf. above the
> myinterceptor implementation).
> It is just as concise and powerful as formal specification
> languages. And Erlang has pattern matching, etc. that make it
> very usable to implement behaviour checking.
Oh yes, and as designers we still can have the freedom of choosing to
implement it in an interceptor process or in a module.
> > One problem with a gen_server is that it will kill your client
> > if you do not get a response within the Timeout time, 5
> > seconds default I think. This is not acceptable if you bind
> > many components together expecting them to last for a long
> > time. I think it could be a good idea to consider a fractal
> > component behaviour, gen_fc ?, overriding the gen_server
> > behaviour, making life, or at least the development, easier
> > for developers.
>
> I'm not sure if this is necessary, but why not?
OK, I think this should be done only if necessary, which I ( too ) am not so
sure of anymore.
> I also agree that we don't necessarily need gen_server to
> implement Dependency Injection. My proposal was one example of
> implementation.
True. Actually if one was to implement a general dependency injection
framework that would do all the "wiring" stuff, the binding operations would
have to be in Erlang messages and not in gen_server calls in order not to
leave out ordinary erlang processes or any other process types.
In the gen_server, the dependency injection operations could be captured in
the handle_info section anyway.
Regards
Mikael
More information about the erlang-questions
mailing list