0

Say I am creating an app which contains selectable components and a toolbar/action bar. Some tools work on selected components only, some work on all components together. Pretty standard stuff.

I can think of 3 approaches to go about the architecture of the relations between the toolbar and the components:

  1. Toolbar is "stupid". Made from nothing but buttons that merely throw an event on click. Event data will contain the clicked action name. The actions execution logic is defined in the components. Components listen to "onToolClick" event and decide if they should execute the action on themselves (i.e IF this.selected -> this.actions[event.actionName](this)). This approach will allow flexibility in the implementation of actions, Make it more robust, and simplify the toolbar module. Yet it will complicate the structure of the components.

  2. Toolbar is somewhat "stupid". Actions execution logic is defined in the toolbar generically (Probably delegated to an external handler). Click on buttons will throw an event, event data will contain a reference to the logic. Components listen to "onToolClick" event and decide if they should execute the action on themselves (i.e IF this.selected -> event.action(this)). This approach will keep actions logic in one designated place and simplify components structure. Yet it spreads the action handling over multiple modules.

  3. A "smart" Toolbar. Actions execution logic is defined in the toolbar generically (Probably delegated to an external handler). Toolbar will also keep a reference to all components. Click on buttons will go over the list of components, decide if action is applicable and execute on the component (i.e. FOR EACH component in components -> IF component.selected -> action(component)). Components will add themselves to the toolbar components list, and update their status. This approach encapsulate actions all together from the components and keeps it all in one place. Yet it's not scaleable in case some new components will require more specific action handling, plus it gives the toolbar direct access to components.

Is there really a "best practice" for this issue? Is it a matter of taste, or app specific? Are there any other approaches?

Thank you very much!

4
  • What kind of application is this? Desktop? Android? iOS? Single page app running in a browser? Commented May 7, 2020 at 16:51
  • Well, it was more like a generic question. Why? does it make a difference? If yes - than let's talk about a web page please. Thanks!
    – Yogev
    Commented May 7, 2020 at 16:54
  • It does make a difference. So this is a single page app then? Commented May 7, 2020 at 20:12
  • You could say so, yes.
    – Yogev
    Commented May 7, 2020 at 23:34

2 Answers 2

2

Toolbars are part of the User Interface.

Good UI's are always decoupled from the application's underlying logic. The best UI's don't even know anything about the underlying application logic; instead, they expose commands that can be subscribed to by the application through bindings.

Ergo, I prefer the "stupid" approach.

Study any of the common UI paradigms such as Model-View-Controller, Model-View-ViewModel, Model-View-Presenter etc., and you will find that they all have the same goal: to decouple the UI from the application. This is done for many reasons:

  1. Separation of Concerns
  2. Testability
  3. Maintainability
  4. Clarity of code.
2
  • Thank you Robert! I actually hold a pretty vast experience and knowledge of MVC (Not so much with the other two you have mentioned) and a big supporter in decoupling UI from logic. For this particular application I am using React.js which makes it a bit more difficult to maintain. Yet your answer did help me get in the right mind set for it. I think the right thing to do would be to have the components subscribe to the toolbar with a personal dispatcher which would trigger the corresponding reducer of each component's state. Thanks!
    – Yogev
    Commented May 7, 2020 at 23:43
  • P.S Just to be clear why: This way, dispatcher is sent to UI, reducer holds the logic and stays in the underlying app level, and can even be parted from the components themselves.
    – Yogev
    Commented May 7, 2020 at 23:51
1

I agree with Robert's answer that the toolbar itself should be stupid but would suggest that you have a look at the command pattern as a way to keep action implementation cleanly separated. Commands in a UI would basically have three methods:

  • initialize(ui) to initialize themselves in the context of an UI, for example to remember the set of selected objects to which the command should be applied

  • apply(ui) to perform the actual operation

  • undo(ui) to undo the action

This approach also allows you to implement an undo/redo stack.

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.