1
votes

I am currently building a complex marionette application and have been follow a great book as a reference. However, I am a sucker for reusable code and like to keep things flexible as possible.

My application has various screens and modules, one of which is a dashboard. The dashboard has its own set of responsibilities, so I made the conclusion that it should be a sub-app.

The dashboard is split 50/50 and there are two components inside. I have identified that each of these components (lets say compA and compB) each have their own set of responsibilities aswell and should be their own sub apps. However, I will have the use case where compA will be used in another area of the application.

My first thought with re-use in mind was to simply re-use the views and create a new module where ever this particular view was needed. However, the unique events and actions that come with this view are stored in the controller and API to interact with the module.

So I have ended up with the following structure:

    application.js
    apps
    --dashboard
    --compA
    --compB

and I have implemented something like the following to reuse functionality from compA

Controller = {
    getView: function () {
        return new Show.MyView();
    }
}

API = {
    getMyView: function () {
        return Controller.getView();
    }
}

App.reqres.setHandler('compa:get:view', function () {
    return API.getMyView();
});

Doing this allows me to request a new instance of the view to display and keep the same action logic. However, this means that there is no separation between each section (compA in the dashboard, and compa in another section of the app). So if I were to stop the compa module it would not have the desired results.

Is there a better approach to re-usable modules with minimal duplication of code?

My thought was to extract the Controller logic into a controller object that I can extend, and then creating a new 'sub app' when I would like to re-use the features.

    application.js
    apps
    --dashboard
    --compA-dashboard // new instance of Controller
    --compA-somewhereelse // new instance of Controller
    --compB

It seems as though I may be over-complicating my design pattern.

1

1 Answers

1
votes

Allow me to rename your "component" as "widget" at first. In my opinion "component" is better for things more general than the widgets in your case.

I would arrange those widgets as following:

app.js
/app
  /dashboard
    /show
      show_controller.js
    dashboard_app.js
  /other
/components
  /widgets
    /widgetA
      widgetController.js
      widgetView.js
    /widgetB 

Since widgetA is dependent from dashboard and is supposed to be use elsewhere, it should be fully decoupled from dashboard.

The 'show' View of Dashboard should have a Layout to define where to show widgetA and widgetB.

Then, in your DashBoardApp, set an appRoute to respond to some route, and then call the controller.

The controller will initialize the Layout.

The Layout will ask for show of RegionA and RegionB.

Listen to 'show' events of RegionA and RegionB, to ask for an App wide request

this.listenTo(regionA, 'show', function(){
  App.request 'widget:a:show'
});

Then in Widget module, respond to the App events and deliver the view

App.reqres.setHandler('widget:a:show, function(){
  API.getWidgetAView();
});

The later part of my answer is a bit vague with less code. The basic idea is, DashBoardApp should finish his job by sending App request. And then it's components job to deliver the view upon App request, which is fully decoupled.