Problems with dependency injection

11 views
Skip to first unread message

[rob desbois]

unread,
Aug 15, 2008, 12:39:27 PM8/15/08
to Test Driven Development
Hi all, only just found this group but hope I can get some people's
opinions on the following scenario.
In my case this involved hardware communications in c++ but the
question and principles aren't limited to platform or language.

I'll start with the question:
If a class C depends on an object whose construction requires
parameters you would ordinarily want to encapsulate in C, how would
you redesign this?

Now, to clarify that rather abstract question:
You have a codebase with class Serial for reading, writing, and
controlling a serial (COM) port.
You develop a new class FooDevice for controlling a particular device
over a serial port.
FooDevice therefore requires an instance of Serial.

Initially you make a Serial instance a member of FooDevice; FooDevice
passes FooDevice the baud rate on construction.
You decide to inject the dependency on Serial, which requires that you
construct it before FooDevice, and pass it as a parameter to
FooDevice's constructor.

This means that FooDevice's client code must know the baud rate of the
device, which seems to me to be breaking encapsulation.
Obviously not a problem as such, and can be dealt with in a number of
ways, but I would be interesting to see if how the rest of you deal
with this situation - do you just 'break' encapsulation and leave it
at that?

--rob

Nick Parker

unread,
Aug 15, 2008, 2:16:13 PM8/15/08
to Test-Driven...@googlegroups.com
Rob,

It seems to be a very targeted problem, where you have a device communicating with hardware.  Below I tried to markup what you may have been describing, with the adjustment that I threw an interface around your serial implementation by just defining pure virtual functions within the class.  It seems as if, and I think you are pointing this out in your question, why do I need to expose the baud rate back up to the FooDevice?  Is that correct?  If so, I would consider either augmenting what really needs to be exposed to the ISerial, or writing a separate generic adapter that FooDevice could talk to and it in turn could delegate your baud rate information back into the Serial class.

public class ISerial
{
   public virtual void SetBaudRate(int rate);
   public virtual int GetBaudRate();
};

public class Serial : ISerial { // Implementation here...};

public class FooDevice
{
    public FooDevice(ISerial *serial){  // store pointer }
}

Nick Parker
www.developernotes.com

[rob desbois]

unread,
Aug 18, 2008, 4:47:51 AM8/18/08
to Test Driven Development
Nick,

Thanks for your reply.

Although the example is targeted I don't think the general problem is.

"How can I inject a dependency which requires data from the unit/
module it is injected into?"
Seems quite a generic thing to me - but that said I can't come up with
any other cases off the top of my head.

Your suggested modification works in this case - but for situations
using an RAII design accessors may not be usable - assume for the
general case that the information is required in the *construction* of
the dependency and cannot be passed later.

Perhaps I am over-complicating this - I guess that as dependency
injection implies that the dependent is no longer responsible for the
creation of the depended-on item, that the client code therefore
*must* be responsible for it. Hence must have access to the data
required for construction of that item.
Think I'm being a little obsessive about encapsulation here?? :-D

Thanks
--rob


On Aug 15, 7:16 pm, "Nick Parker" <ni...@developernotes.com> wrote:
> Rob,
>
> It seems to be a very targeted problem, where you have a device
> communicating with hardware.  Below I tried to markup what you may have been
> describing, with the adjustment that I threw an interface around your serial
> implementation by just defining pure virtual functions within the class.  It
> seems as if, and I think you are pointing this out in your question, why do
> I need to expose the baud rate back up to the FooDevice?  Is that correct?
> If so, I would consider either augmenting what really needs to be exposed to
> the ISerial, or writing a separate generic adapter that FooDevice could talk
> to and it in turn could delegate your baud rate information back into the
> Serial class.
>
> public class ISerial
> {
>    public virtual void SetBaudRate(int rate);
>    public virtual int GetBaudRate();
>
> };
>
> public class Serial : ISerial { // Implementation here...};
>
> public class FooDevice
> {
>     public FooDevice(ISerial *serial){  // store pointer }
>
> }
>
> Nick Parkerwww.developernotes.com
>

Nick Parker

unread,
Aug 18, 2008, 9:55:39 AM8/18/08
to Test-Driven...@googlegroups.com
Rob,

I think it comes down to how you structure your object relationships.  You might take a look at the AutumnFramework, a DI library for C++.

http://code.google.com/p/autumnframework/

http://code.google.com/p/autumnframework/wiki/Manual_1_A_Sample

Nick Parker
www.developernotes.com
Reply all
Reply to author
Forward
0 new messages