0

I am looking for help with my MVC design where am I going wrong and if at all it makes sense the way that I'm slowly progressing.

I am trying to create something like this: enter image description here

Many gauges that would work in their own threads, my issue is with properly dividing this program into views and models.

Here is what I came up with so far:

Controllers
           DashboardController
Models
           BarGaugeModel
           CircularGaugeModel
Views
           Components
                   BarGauge
                   CircularGauge
           DashboardView
ViewModels
           DashboardViewModel
Main
           Main

BarGaugeModel.java

public class BarGaugeModel {
    private int speed;

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
}

DashboardViewModel.java (would consist of all models)

public class DashboardViewModel {
    BarGaugeModel fuelGauge = new BarGaugeModel();

    public BarGaugeModel getFuelGauge() {
        return fuelGauge;
    }
}

BarGauge.java

public class BarGauge extends JPanel {
    private JLabel speed = new JLabel();


    public int getSpeed() {
        return Integer.parseInt(speed.getText());
    }

    public void setSpeed(int speed) {
        this.speed.setText(speed+"");
    }
}

DashboardView.java (would create all view components and add to this jframe)

public class DashboardView extends JFrame {
    BarGauge barGauge = new BarGauge();

    public void DashBoardView(){
        this.setSize(new Dimension(100,100));
        this.add(barGauge);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}

Main.java

public class Main {

    public static void main(String[] args) {
        DashboardView dashboardView = new DashboardView();
        DashboardViewModel dashboardViewModel = new DashboardViewModel();
        DashboardController dashboardController = new DashboardController(dashboardView, dashboardViewModel);

        dashboardView.setVisible(true);
    }
}

Each of those gauges would also have a manual input for user to type in which I'm also not too sure where should that input be contained in which view or maybe in completely separate one.

Higeath
  • 109
  • 7

1 Answers1

2

First of all, in a pure MVC, the model and view know nothing about each other, this is all controlled by the controller which acts as a router between them, listening to changes and forwarding those updates backwards and forwards between the view and the model.

As a general piece of advice, you should start by defining the contracts which need to be maintained by the model, controller and view in order for them to work together, personally, I start with interfaces as this decouples the implementation details and forces you to focus on what "really" needs to be done and not what you "can" do because the of implementation side effects (the controller been able to add/remove components from the view for example)

This should also include all the observer patterns/listeners, which are needed in order to provide the notification channels for the communication to occur

You will probably also want to define what is thread safe and what is not, for example, while your "ultimate" design might need the models to be getting information from different threads, should updates be generated on the same threads or should they be synced back to a single thread? Whose responsibility is it to actually do that anyway (hint, in most cases, it's the views)

Through this process you should be looking for overlapping details, which can be further reduced down into common functionality (no point having two distinct models which have public int getValue() when the can be distilled down into a single common interface ... in most cases)

I'd also be careful about converting "data" when you don't need, for example in your BarGauge class, you take the speed, which is given as a int, but turn it into a String, personally, I'd leave it as an int and simply change the way you present it, it saves a lot of trouble and the views responsibility should be to present the state, so I'd tend to leave it in it's raw format and only convert it for presentation when needed.

When doing something like this, one of the things I try and do, is focus on who is responsible for what, for example...

When an update comes from the thread, it goes to the model, the model updates its state based on the input from the thread, it notifies the controller, which notifies the view which is then updated

Thread -> Model -> Controller -> View

When the user inputs data, the data passes through the view to the controller, which notifies the model, which updates its state, this in turn may generate a return trip so the view can update itself based on what the model has decided to do with the input (ie reject it or modify it or because it's updated some other state of the model)

User -> View -> Controller -> Model {-> Controller -> View}

dividing into smaller views and then putting this back together does it make sense to create view components as JPanels as simple gauges and then combine them into one view in JFrame as I have shown in the question?

Generally, yes, but one thing you need to get your head around is the idea that a view can act as controller for other controllers - this means you could have a "control panel" view, which is actually a container for other gauge controls (assuming that you allow the controller to expose the view and model)

What I would do, is start with a basic concept of a Controller (and probably a View)

public interface View {
    public JComponent getView();
}

public interface Controller<M, V extends View> {
    public M getModel()
    public V getView();
}

this means that I can pass any number of "controllers" to my "control pane" view and it can get each "view" and add them to itself for displaying ... as a basic idea.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you for response, I know I didn't add listeners yet since I wasn't sure I'm even moving in the right direction. The main issue that I can't fully understand is dividing into smaller views and then putting this back together does it make sense to create view components as JPanels as simple gauges and then combine them into one view in JFrame as I have shown in the question? When it comes to turning my int into string in barGauge it is simply because JLabel takes string. – Higeath Feb 28 '17 at 22:25
  • *"dividing into smaller views and then putting this back together does it make sense to create view components as JPanels as simple gauges and then combine them into one view in JFrame as I have shown in the question?"* - Generally, yes, but one thing you need to get your head around is the idea that a view can act as controller for other controllers - this means you could have a "control panel" view, which is actually a container for other other gauge controls (assuming that you allow the controller to expose the view and model) – MadProgrammer Feb 28 '17 at 22:33
  • @MadProgrammer I'm still struggling with fully understanding this design I have had quite a lot of experience with MVC in .net but here it seems completely different. The thing that I can't fully picture is should I have actionlisteners in my components which should call the action listener in my dashboardview which then would be executed in controller or should I have actionlistener only in component and then in my controller I could have view.getGaugeComponent.addSpeedListener... – Higeath Mar 01 '17 at 13:12
  • @Higeath One of the problems you'll have is Swing is a form of MVC (albeit M-VC), so it's sometimes hard to know where things should go. My personal opinion is, don't expose ui components to layers that have no responsibility modifying them, this suggests that the View's contract would have one or more observers which describes what the events the View is capable of generating, this way, the controller doesn't care about how they are generated, only they can – MadProgrammer Mar 01 '17 at 18:49