1

I am working on a program that has several frontends. The main application has a GUI that allows a lot of manual user interaction. The second one is more like a script that just runs a default work flow.

At some point questions to the user may appear. These are most often related to ambiguous input data, where the user must decide on one of the possibilities. The ambiguities often originate from the data format of an external program, so just getting rid of them is not an option.

The easiest way to get the user input would be to just open a message box with the available options. I would however prefer to have several classes handling that. One that creates a GUI dialog, one that asks for the options on CLI and one that just answers from prerecorded decisions (e.g. for testing).

The two possibilities I see are having a singleton that stores an object of the desired class or passing it through the whole call hierarchy for every tiny class that may raise a question.

Are there any design patterns or best practices on how to solve this issue? It seems like a standard problem to me.

3
  • Possible duplicate of Choosing the right Design Pattern
    – gnat
    Oct 16, 2017 at 8:53
  • 1
    @gnat My primary problem is not, that I do not know how to choose between the two possible solutions I saw (I know what I would consider the lesser of those two evils). I am trying to find out if I am missing some third way that is usually used to solve the problem.
    – Tim
    Oct 16, 2017 at 8:58
  • @gnat: did you check if this question makes more sense to you when replacing the term "design pattern" by "approach" before voting to close? It would be really nice if you did so.
    – Doc Brown
    Oct 17, 2017 at 6:16

1 Answer 1

5

This problem is a good fit for the Strategy Pattern:

several classes handling that. One that creates a GUI dialog, one that asks for the options on CLI and one that just answers from prerecorded decisions (e.g. for testing).

You would have an AskUserForChoice interface, and various UI strategies implementing it. When the application is started, it is configured with an appropriate strategy.

So how do we get the strategy implementation to the place where it is used?

The two possibilities I see are having a singleton that stores an object of the desired class or passing it through the whole call hierarchy for every tiny class that may raise a question.

Singletons are generally considered to be an anti-pattern. They obscure the actual dependencies of your code and make testing more difficult.

Explicitly passing dependencies through all function calls makes all dependencies very explicit. This is initially a viable strategy.

However, different parts of the code have different responsibilities. You should not have to explicitly pass a GUI strategy through business-level code. Instead, I would introduce an User Interface object. This object offers methods to business-logic code that achieve a particular business-layer objective, i.e. ui.resolveAmbiguity(a, b, c) not ui.showOptionDialog("Please select one option to resolve the ambiguity:", a, b, c). Internally, the User Interface object may be configured with a particular strategy to display these choices. As all UI operations have been grouped into a single class, passing this dependency around is fairly manageable.

If you don't want to manage dependencies explicitly by passing objects as function parameters or constructor arguments, it is best to use an existing dependency injection framework that auto-wires the necessary dependencies. While such frameworks may use singletons internally, they may also have tooling and features to reduce their drawbacks and avoid unexpected “action at a distance”.

But for small applications, manual dependency management through a clean design is often entirely sufficient, no framework needed.

1
  • 1
    Good answer. I would like to add that accessing the whole UI through an interface whilst having a separate "presenter" class holding the business logic to control the UI through this interface is a pattern on its own, it is called Model-View-Presenter.
    – Doc Brown
    Oct 17, 2017 at 6:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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