Pergunta

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!

Foi útil?

Solução

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.

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
scroll top