Neues Design-Pattern für JavaFX-Anwendungen

mvvmFX: Model-View-ViewModel mit JavaFX

Alexander Casall, Manuel Mauky
mvvmfx

© Saxonia Systems AG

Das Framework mvvmFX bietet Hilfsmittel zur Umsetzung des Model-View-ViewModel-Design-Patterns mit JavaFX und wurde nach einem Jahr Entwicklung in der ersten stabilen Version 1.0.0 veröffentlicht.

Das Design-Pattern „Model-View-ViewModel“ wurde ursprünglich von Microsoft für .NET-Anwendungen entwickelt und findet mittlerweile auch in anderen Technologien wie JavaScript-Frameworks Verwendung. Wie bei alternativen MV*-Ansätzen ist die Trennung zwischen der Struktur der Oberfläche und der (Anzeige-)Logik das Ziel. Bei MVVM existiert dazu ein ViewModel, das den UI-Zustand abbildet. Das ViewModel selbst kennt die View nicht und hat keine Abhängigkeiten zu konkreten UI-Elementen.

Stattdessen wird die View, die die UI-Elemente, aber keine UI-Logik enthält, per Data-Binding mit dem ViewModel verknüpft.

Ein simples Beispiel ist die Aufbereitung eines Willkommens-Textes im ViewModel:

mvvmfx

 

Einer der Vorteile dieser Struktur ist, dass der vollständige UI-Zustand sowie die UI-Logik in einem UI-unabhängigen Modell (ViewModel) gekapselt sind.

Was ist UI-Logik?

Aber was ist eigentlich UI-Logik? Die UI-Logik definiert, wie die Oberfläche auf Eingaben des Nutzers oder andere Einflüsse, wie zum Beispiel Änderungen im Fachmodell zu reagieren hat. Zum Beispiel wann ein Button aktiv ist oder nicht.

Durch die UI-Unabhängigkeit kann das ViewModel mit Unit-Tests getestet werden. Komplizierte Integrationstests, bei denen die tatsächliche Programmoberfläche gestartet und vom Testwerkzeug ferngesteuert werden müsste, kann man sich in vielen Fällen sparen. Das erleichtert maßgeblich eine testgetriebene Entwicklung.

JavaFX ist durch die Verfügbarkeit von Properties und Data-Binding ideal für dieses Pattern geeignet. mvvmFX ergänzt Hilfsmittel zur effizienten und sauberen Umsetzung des Patterns.

Das folgende Beispiel gibt einen Eindruck vom Vorgehen nach MVVM. Ein Log-in-Button soll erst anklickbar sein, sobald sowohl Nutzername als auch Password eingegeben wurden. Zunächst wird, getreu nach TDD, mit einem Unit-Test für das ViewModel begonnen.

@Test
public void test(){
  	LoginViewModel viewModel = new LoginViewModel();

  	assertThat(viewModel.isLoginButtonDisabled()).isFalse();

  	viewModel.setUsername("mustermann");
 	assertThat(viewModel.isLoginButtonDisabled()).isFalse();

        viewModel.setPassword("geheim1234");
        assertThat(viewModel.isLoginPossible()).isTrue();
}

Anschließend wird das ViewModel implementiert:

public class LoginViewModel implements ViewModel {

        private StringProperty username = new SimpleStringProperty();
        private StringProperty password = new SimpleStringProperty();
        private BooleanProperty loginPossible = new SimpleBooleanProperty();

        public LoginViewModel() {
		loginButtonDisabled.bind(username.isEmpty().or(password.isEmpty());
        }

  	// getter/setter
}

Nun muss dieses ViewModel nur noch mit der View verknüpft werden. Die View ist bei mvvmFX eine Kombination aus einer fxml-Datei und der zugehörigen Controller-Klasse. Wichtig hierbei ist, dass der JavaFX-Controller zur View zählt und keine Logik enthält. Er dient lediglich dazu, die Verbindung zum ViewModel herzustellen.

public class LoginView implements FxmlView {
        @FXML
  	public Button loginButton;

  	@FXML
  	public TextField username;

  	@FXML
  	public PasswordField password;

  	@InjectViewModel //wird von mvvmFX bereitgestellt
  	private LoginViewModel viewModel;

	//wird von JavaFX aufgerufen, sobald das FXML bootstrapping abgeschlossen ist
        public void initialize(){
        username.textProperty()
                .bindBidirectional(viewModel.usernameProperty());
        password.textProperty()
                .bindBidirectional(viewModel.passwordProperty());

        loginButton.disableProperty()
                .bindBidirectional(viewModel.loginPossibleProperty());
  	}
}

Wichtig ist, dass die generische View mit dem zugehörigen ViewModel getypt ist. Dadurch kann mvvmFX die Verwaltung des View-Lifecycles sicherstellen.

Weitere Funktionen

mvvmfx

Das hier gezeigte Beispiel benutzt FXML zur Deklaration der Oberflächenstruktur. Dies ist der empfohlene Weg. mvvmFX unterstützt aber auch Views, die auf herkömmliche Weise mittels Java-Code geschrieben wurden.

Ein weiterer zentraler Punkt bei der Entwicklung war die Integration von Dependency-Injection-Frameworks. Dies ist notwendig, da der Lebenszyklus von Views und ViewModels sonst von Hause aus von mvvmFX selbst verwaltet wird.

Gegenwärtig werden Zusatz-Module für die Integration von Google Guice und JBoss Weld/CDI angeboten, die einen unkomplizierten Start mit den Frameworks ermöglichen. Es können aber auch beliebige andere DI-Frameworks eingebunden werden.

mvvmFX ist vor Kurzem in einer ersten stabilen Version 1.0.0 erschienen. Es wird gegenwärtig bei der Saxonia-Systems AG in ersten Projekten eingesetzt. Die Entwicklung findet als Open-Source-Projekt (Apache-Lizenz) auf Github statt. Die Autoren freuen sich über Feedback, Anregungen und Kritik.

Für die zukünftige Entwicklung stehen vor allem Features auf dem Plan, die für größere Projekte mit komplexeren Oberflächen notwendig sind.

Dazu zählt ein Mechanismus, mit dem mehrere ViewModelle auf gemeinsame

Daten zugreifen können, ohne jedoch eine gegenseitige Sichtbarkeit und damit Abhängigkeit zu schaffen (Scopes). Des Weiteren stehen Hilfsmittel für die Navigation zwischen Views und die Steuerung von Master-Detail-Ansichten auf der To-do-Liste. Inspirationsquelle bei der Entwicklung ist Microsofts Framework PRISM, welches als Application Framework alle notwendigen Werkzeuge zur Anwendungserstellung bereitstellt.

Geschrieben von
Alexander Casall
Alexander Casall
Alexander Casall hat 2011 seinen Master in Informatik abgeschlossen und arbeitet seitdem bei der Saxonia Systems AG als Softwareentwickler. Sein Fokus liegt auf der Implementierung moderner Multi-Touch-Applikationen mit JavaFX. U.a. arbeitet er an Kollaborationswerkzeugen zur verteilten, agilen Entwicklung. In seiner Freizeit entwickelt Alexander native iOS Apps (www.buildpath.de), veröffentlicht Artikel in Fachzeitschriften, oder hält Vorträge auf Konferenzen (JavaOne, JAX, W-JAX) und User Groups.
Manuel Mauky

Manuel Mauky (www.lestard.eu) arbeitet seit 2010 als Softwareentwickler bei der Saxonia Systems AG in Görlitz. Er beschäftigt sich dort vor allem mit Java Enterprise und der UI-Entwicklung, seit einiger Zeit auch mit JavaFX. Er ist einer der Organisatoren der Görlitzer Java User Group (http://www.jug-gr.de) und steuert dazu regelmäßig eigene Vorträge bei. Seit 2013 ist er neben der Arbeit wieder Student und holt seinen Masterabschluss in Informatik nach.

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.