3

I am trying to improve my programming skills and knowledge and I have been doing some reading about various design patterns and youtubing videos etc. One subject I thought was interesting was about Singletons being an Anti-pattern which has lead me on to a problem that I am not quite sure how to solve. Allow me to explain. Lets say I have created a GPS class library. In the library I have a class called GpsSensorUtil. This class does everything to do with processing GPS data such as working out speed, distance etc and fires events with this information. So now I'm thinking hey, maybe I want to see the GPS info visually. So I create a UserControl in the library which will listen to the events of the GpsSensorUtil.

The issue I am thinking about is how can I wire up the GpsSensorUtil to the UserControl so that the UserControl can listen to Events from the GpsSensorUtil? In a normal application I would be looking into DependancyInjection maybe with Unity, but then I would need to find a way of initialising and configuring the UnityContainer as there is no entry point in a class library. I did think of creating like a singleton to be a static reference for the container but as I have been reading, this is not a good thing.

In my head the following needs considering.

  1. GpsSensorUtil does not know of the UserControl and does not need too.
  2. UserControler does not need to know of the GpsSensorUtil, only the events it fires.
  3. Anyone could use this library so I don't want to constrain to one IoC like unity.

What's the best way to approach something like this?

  • Have a look at IoC in class library. Where to bootstrap on Stack Overflow. – Robert Harvey Jun 13 '16 at 17:05
  • 1
    Also, what prevents you from supplying constructors in your library with parameters that conform to some interface, and letting your library user worry about providing the DI container? – Robert Harvey Jun 13 '16 at 17:06
  • @RobertHarvey Please see my comment to Telastyn's answer. – Gaz83 Jun 13 '16 at 17:55
4

If you're making a UI for the GPS data, it will invariably have a dependency on GPS data of some sort. Having that coupling isn't bad - quite the opposite. By having your user control depend on an explicit interface, you're letting the compiler be able to tell you when it's missing and you're telling your users what it needs to work.

By making it an interface though, you're effectively decoupling your control from the implementation of the GPS data provider allow it to change freely. How the dependency gets supplied is up to the user, who could even use their own data source if they wanted to. No need for accursed IoC containers if they're not warranted.

  • I'm just thinking about yours and @RobertHarvey comment. I get what you are both saying, I guess my issue now is how to inform the developer/compiler that the UserControl requires a 'GpsSensorUtil'. I can't put the parameter in the constructor of the control because if you drag and drop the control in the designer it causes exceptions. – Gaz83 Jun 13 '16 at 17:54
  • @Gaz83: The user control doesn't require a GpsSensorUtil object. Rather, it requires that the user supply an object that conforms to your IGpsSensor Interface. – Robert Harvey Jun 13 '16 at 18:03
  • Are you not trying to solve the wrong problem? Since the OP wrote the UI control is already decoupled from the GpsSensorUtil by events, why should he make things more complicated and introduce an additional interface? – Doc Brown Jun 13 '16 at 18:10
  • 1
    @Gaz83, check out this answer to another question. You may be able to remove the need for your component to have a concrete implementation of the IGpsSensorUtil interface passed to it at design time. – David Arno Jun 13 '16 at 18:34
4

Since your UserControl is already decoupled from GpsSensorUtil by events, there is no need for dependency injection by interfaces, that would only complicate things without any additional benefit. However, if there are lots of events which must be wired up in a specific way together between those two components, it is a good aproach not to let this handle each user of your library by himself, but provide a feature in your lib which does this for him. And since you do not want to let you UserControl know of GpsSensorUtil, or vice versa, the only meaningful place is an additional class.

So in your lib, provide a class like UserControlBuilder or UserControlFactory which takes a GpsSensorUtil object, creates a UserControl object and does the wiring of the events. The users of your lib can then utilize this, so they don't need to write the wiring code by themselves (but they will still be able to use GpsSensorUtil and UserControl fully independently from each other).

There is no need to make UserControlBuilder a singleton, just the fact a user of your lib will typically just need only one object of that class does not mean your lib needs to enforce that there will be not more objects of that class.

If you want to separate the construction of UserControl from the event wiring, for example, to make it easier to use UserControl in your graphical UI designer, you still need an additional class for the wiring code. For this case, just call the class UserControlInitializer or something like that, and pass the previously constructed UserControl and GpsSensorUtil into the provided wiring function of that class.

  • Interesting idea, was watching a few videos last night on Factory Pattern and Builder Pattern. Will have a look at this but my first thought is how do I deal with DesignTime issues? i.e. if a user wants to drag and drop the control. – Gaz83 Jun 13 '16 at 19:09
  • @Gaz83: I guess you are talking of a situation where you add the UserControl to a form, maybe using Visual Studio and the WinForms designer? To support this case, your UserControl needs to be initialized separately after construction. Instead of a UserControlBuilder you could provide a UserControlInitializer object with a method WireUp(UserControl, GpsSensorUtil). – Doc Brown Jun 13 '16 at 19:26
1

Keep it simple. GpsSensorUtil should have an event property, and ControlUtil should have a public event handler. Then, in your main code that creates the two, you should have a line like gpsSensorUtilInstance.GPSEvent += controlUtilInstance.OnGPSEvent;. No frameworks, no containers, no direct dependency between the two classes.

0

The way to communicate between classes that have no knowledge of each other is via message passing. Usually there is a bus or some other form of master routing mechanism that each class registers with. From that point on, each class sends messages to the bus without any regard if another class is going to be reading them.

So here, your lib is firing events and your UI is reading them. Neither need know anything other than the type of event messages they will receive. No need for interfaces or any explicit wiring between them, they only need to know how to read and write messages to the bus.

Works well for distributed systems too, so your GPS lib could send data to a remote terminal, if your bus handled the transmission of the messages across a network instead of locally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.