MVVMFX - JavaOne 2016
MVVMFX - JavaOne 2016
MVVMFX - JavaOne 2016
2016-09-21
● Custom Software Development
● Dresden, München, Berlin, Hamburg, Leipzig, Görlitz
● 200+ Employees
MODEL VIEW
VIEWMODEL
Model View ViewModel
● Based on Presentation Model Pattern
● 2005 published by Microsoft
● WPF (.NET), JavaScript (knockout.js), ...
Model
● Application model
● Independent from UI
● Backend systems etc.
Model
ViewModel
● UI state
● Presentation logic
● Communication with backend
● Preparation of model data
ViewModel
Model
View
● Display data from ViewModel
● Pass user input to ViewModel View
● Update UI state in ViewModel
ViewModel
Model
KEEP
VIEW AND
VIEWMODEL
SYNCHRONIZED?
View
ViewModel
Model
Data Binding and Properties
StringProperty = StringProperty
String Binding String
StringProperty a = new SimpleStringProperty();
StringProperty b = new SimpleStringProperty();
a.bindBidirectional(b);
a.setValue(“Hallo”);
System.out.println(b.getValue()); // “Hallo”
b.setValue(“World”);
System.out.println(a.getValue()); // “World”
Data Binding in MVVM
Data Binding in MVVM
“Max” “Wielsch”
Data Binding in MVVM
welcomeMessageProperty.set(
“Hallo Max Wielsch”
“Hallo “
+ user.getFirstName() + “ ”
ViewModel + user.getLastName());
“Max” “Wielsch”
Data Binding in MVVM
welcomeLabel.textProperty().bind(
viewModel.welcomeMessageProperty());
View
welcomeMessageProperty.set(
“Hallo Max Wielsch”
“Hallo “
+ user.getFirstName() + “ ”
ViewModel + user.getLastName());
“Max” “Wielsch”
View Hierarchies
View View
View
? ?
Benefits
● all presentation logic is located only in the ViewModel
● ViewModel is testable with unit tests
UI
Tests
→ High testability of frontend code
System Tests
→ Test-driven-development in the UI
Integration Tests
Unit Tests
Challenges of MVVM
● Communication between VMs in more complex applications
● Demands discipline to not violate visibility constraints
● More code necessary for layers of indirection
… is an open-source application framework providing necessary components for the
usage of the Model View ViewModel pattern with JavaFX.
https://github.com/sialcasa/mvvmFX
… is an open-source application framework providing necessary components for the
usage of the Model View ViewModel pattern with JavaFX.
https://github.com/sialcasa/mvvmFX
Basic Classes for MVVM
Extended FXML Loader
Dependency Injection Support
ResourceBundles
ModelWrapper
Notifications
Commands
Validation
Scopes
How to create a MVVM Component?
Component
View FXML
CodeBehind class
ViewModel
Base Classes / Interfaces
class TodolistViewModel implements ViewModel {
…
}
@InjectViewModel
private TodolistViewModel viewModel;
}
TodolistView.fxml:
...
<VBox xmlns:fx="http://javafx.com/fxml"
fx:controller="de.saxsys.mvvmfx.examples.todo.TodolistView">
<children>
...
</children>
</VBox>
But how to load a MVVM component?
URL url = getClass().getResource(“/de/saxsys/MyView.fxml”);
FXMLLoader loader = new FXMLLoader(url);
loader.load();
loader.getRoot(); // loaded node
loader.getController(); // controller class
But how to load a MVVM component?
URL url = getClass().getResource(“/de/saxsys/MyView.fxml”);
FXMLLoader loader = new FXMLLoader(url);
loader.load();
loader.getRoot(); // loaded node
loader.getController(); // controller class
View
ViewModel
Notifications
public class MyView implements FxmlView<MyViewModel> {
@InjectViewModel
private MyViewModel viewModel;
…
viewModel.subscribe(“messageKey”, (k,v) -> doSomething());
…
}
public class MyViewModel implements ViewModel {
…
publish(“messageKey”);
…
}
How to handle dependencies of components?
class MyViewModel implements ViewModel {
}
How to handle dependencies of components?
class MyViewModel implements ViewModel {
@Inject
private Service service;
}
Dependency Injection
● Inversion of Control
● No static dependency to a specific implementation, only to
interfaces
● Use mock implementations for unit tests
● Configure lifecycle of instances
Dependency Injection Support
<dependency> <dependency>
<groupId>de.saxsys</groupId> <groupId>de.saxsys</groupId>
<artifactId>mvvmfx-cdi</artifactId> <artifactId>mvvmfx-guice</artifactId>
</dependency> </dependency>
<dependency>
<groupId>de.saxsys</groupId>
<artifactId>mvvmfx-easydi</artifactId>
</dependency>
or
MvvmFX.setCustomDependencyInjector(...);
Dependency Injection Support
public class MyFxApp extends Application { … }
Component
Views need to share state
Chuck Norris
Duke
Duke
Duke
Duke
M D Master
Duke Detail
Views are hierarchical
Component
Scope
Define a Scope
@ScopeProvider(scopes=PersonScope.class})
public class PersonViewModel implements ViewModel {}
ScopeProvider
Components below can inject the same scope instance
Communication
Scenarios
MODEL
WRAPPER
ModelWrapper
The ModelWrapper optimizes reading and writing of model data.
Negative Example
public class ContactFormViewModel implements ViewModel {
@Inject
private Repository repository;
private person;
firstname.setValue(person.getFirstName());
lastname.setValue(person.getLastName());
emailAddress.setValue(person.getEmailAddress());
phoneNumber.setValue(person.getPhoneNumber());
}
public void save() {
person.setFirstName(firstname.get());
person.setLastName(lastname.get());
person.setEmailAddress(emailAddress.get());
person.setPhoneNumber(phoneNumber.get());
repository.persist(person);
}
}
public class ContactFormViewModel implements ViewModel {
// Properties and Property-Getter …
@Inject
private Repository repository;
private person;
repository.persist(person);
}
}
public class ContactFormViewModel implements ViewModel {
validationSupport.registerValidator(textField,
Validator.createRegexValidator("Wrong Number", "\\+?[0-9\\s]{3,20}", Severity.ERROR));
Validation
// ViewModel
// View
@Override
public void onViewAdded() {
notificationCenter.subscribe("something", observer);
}
@Override
public void onViewRemoved() {
notificationCenter.unsubscribe(observer);
}
}
How to Secure the
Architecture
How to verify that the pattern was adhered to?
● Advantages of MVVM only available when all developers adhere to
the pattern
● How to find mistakes and wrong usage of API?
How to verify that the pattern was adhered to?
● Advantages of MVVM only available when all developers adhere to
the pattern
● How to find mistakes and wrong usage of API?
● AspectJ compile time checking (beta)
class MyViewModel implements ViewModel {
/.../PersonsViewModel.java:34
validationSupport.registerValidator(label,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
www.mvvmfx.de
alexander.casall@saxsys.de
@sialcasa
Manuel Mauky
manuel.mauky@saxsys.de
http://lestard.eu
@manuel_mauky