1

I'm a bit confused about how to organize code in JavaFX (assuming I intend to go the MVVM way).

Consider the following diagram of a standard 4-layers architecture:

enter image description here

Where does the "model" in MVVM sit? Is it inside the "User Interface" layer or is it what's on "Application/Domain-Layer"? I would imagine the MVVM's model to be a representation (projection) of the back-end's model suited for the current view, but I'm not sure from what I've seen around floating on the net.

As an example:

I have a simple ice cream application. Its Application Layer exposes the methods:

  • IceCreamService.iceCreams(): List<String>;
  • IceCreamService.flavours(iceCream: String): List<String>.

The UI will have a combobox with a list of icecreams and based on the user selection will allow him to then pick some flavors. There's then a button to submit the order.

The questions are:

What do we consider to be the model here? Is this IceCreamService what we call the model OR the model would be a class created by us at the UI level consisting of properties / observable objects? If the later, who is responsible for filling up this model with data? The "controller" (ViewModel) or should it be smart enough to do it itself (that is, it has a reference to IceCreamService?)

Thanks!

Community
  • 1
  • 1
devoured elysium
  • 101,373
  • 131
  • 340
  • 557

1 Answers1

3

MVC and its derived design patterns always have the "10 people would find 12 ways to implement it" issue, so I would briefly point out a few "popular" implementations.

So far, what remains common is that your "User Interface" definitely maps to "View" in MVVM. Then it gets a little debatable from here on.

ViewModel is the brain

One popular way to implement MVVM is that the the "ViewModel" is the brain of the whole application. In this case, "Application" maps to "ViewModel" and "Domain" kind of maps to "Model." The ViewModel controls (and decides) what and how to get the data, and also what and how it wants to expose to the View. Most of the time "Model" is just a plain POJO class (e.g. IceCream class).

For JavaFX, you would let all properties in the Model and ViewModel be represented by some kind of Property implementation (i.e. something that implements that interface). If you are not using API like "mvvmFX", then most likely your View would have properties bound to other properties in the ViewModel. If you are using "mvvmFX" (which I didn't use), then you would (most likely) be binding View properties to ViewModel via the property name (which is what WPF does).

In this approach, ViewModel is responsible to get the list of ice creams. IceCreamService could be considered a separate Service layer, or you could assume that it's part of the ViewModel (it itself isn't a ViewModel but it belongs to ViewModel). If you want to update this list, ViewModel is the one who decides that.

Model as the Domain

Another implementation is make the Model do data management, pretty much like what hibernate does in Spring. Model classes continue to represent data (or entities etc), but it comes with own persistence logic. This means that if you update value of a Model object (e.g. changes flavor of an IceCream instance), the Model would know that it is "dirty", and would push the change to the repository for example.

MVCVM

I also read of another approach. In short, it is similar to the first approach, but it moves IceCreamService class into a brand new layer called "Controller."

Your example

Based on your example, this is the sample illustrating how it could be implemented in JavaFX.

class IceCreamSelectionView { // The FXML controller class used as MVVM View class
    @FXML ComboBox<String> iceCreams;
    @FXML ComboBox<String> flavors;

    private final IceCreamSelectionViewModel vm; // The corresponding ViewModel

    @FXML private void initialize() {
        Bindings.bindContent(iceCreams.getItems(), vm.getIceCreams());
        Bindings.bindContent(flavors.getItems(), vm.getFlavors());
        vm.selectedIceCreamProperty().bind(iceCreams.valueProperty());
        vm.selectedFlavorProperty().bind(flavors.valueProperty());
    }
}

class IceCreamSelectionViewModel {
    /*
     * The properties
     */

    public final ObservableList<String> getIceCreams() { return iceCreams; }
    public final ObservableList<String> getFlavors() { return flavors; }
    public final StringProperty selectedIceCreamProperty() { return selectedIceCream; }
    public final StringProperty selectedFlavorProperty() { return selectedFlavor; }

    private updateIceCreams() {
        iceCreams.setAll(iceCreamService.getIceCreams());
    }
}

// There is no Model class because both "iceCream" and "flavor" cannot be further broken down.
Community
  • 1
  • 1
Jai
  • 8,165
  • 2
  • 21
  • 52
  • Hi. Thanks for the long answer! The issue I raise is: in modern applications following the hexagonal architecture (for instance), what will happen is that the layers (Infrastructure / Domain / Application) will be a given, and it's just up to some team to build one or more front-ends (the "User-Interface" on the diagram, on top of that (they can be a desktop-ui, or a REST API, or a web-site, or a rabbit-mq API interface, etc). – devoured elysium Jan 14 '19 at 06:48
  • My question is then, in that perspective, how would things unfold? The FXML is part of the view, of course, then the Controller would still be considered as part of the View, plus the ViewModel would then connect to the bottom layers? – devoured elysium Jan 14 '19 at 06:53
  • Another question: is the ViewModel supposed to be completely UI-controls agnostic? Is that a good heuristic to follow? – devoured elysium Jan 14 '19 at 06:54
  • @devouredelysium If you are using RESTful using Spring, that would be an MVC design. In my opinion, all the clients connecting to the web service would be the "View" in the MVC design. Then if you are planning to use JavaFX as the front-end to consume the web service, you *could* have a MVVM design there. This means that it is an MVVM inside the broader MVC design. Personally, I have tried this approach, and it has its own sets of problems. – Jai Jan 14 '19 at 07:03
  • If you still want to have a JavaFX MVVM front-end, you could start off looking at how mvvmFX works. Personally, I have tried to do custom implementation for MVVM and I would say it's a lot of work with lots of issues. In general yes, FXML+FXML Controllers are going to be the View, and you would have separate ViewModel classes which could be doing the logic, then you would have Model classes representing the entities (e.g. `Person`, `Employee` etc). – Jai Jan 14 '19 at 07:08
  • I've looked yesterday into mvvmFX and I couldn't really get from their documentation / examples what's it's really offering? – devoured elysium Jan 14 '19 at 07:18
  • Btw, you seem to indicate that given the overall architecture of my application maybe MVVM is not a best fit? If not, how should I do it? – devoured elysium Jan 14 '19 at 07:22
  • @devouredelysium By my own experience, Spring MVC as overall architecture + JavaFX MVVM on the "View" isn't great. You have 2 places that contain your application logic, and it is hard to implement access-control stuff on your JavaFX front-end. For example, based on user rights, the logged in user has access to A, B and E, but it is hard to show *only* the 3 navigation on the front-end, unless you are hard-coding a lot of the functions and access-right stuff at the JavaFX application. I'm not really an architecture guy, but perhaps a web-based *could* be better, depending on your application. – Jai Jan 14 '19 at 08:11