Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einleitung
2 Die Basis der Objektorientierung
3 Die Prinzipien des objektorientierten Entwurfs
4 Die Struktur objektorientierter Software
5 Vererbung und Polymorphie
6 Persistenz
7 Abläufe in einem objektorientierten System
8 Module und Architektur
9 Aspekte und Objektorientierung
10 Objektorientierung am Beispiel: Eine Web-Applikation mit PHP 5 und Ajax
A Verwendete Programmiersprachen
B Literaturverzeichnis
Stichwort
Ihre Meinung?

Spacer
 <<   zurück
Objektorientierte Programmierung von Bernhard Lahres, Gregor Rayman
Das umfassende Handbuch
Buch: Objektorientierte Programmierung

Objektorientierte Programmierung
2., aktualisierte und erweiterte Auflage, geb.
656 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1401-8
Pfeil 8 Module und Architektur
  Pfeil 8.1 Module als konfigurierbare und änderbare Komponenten
    Pfeil 8.1.1 Relevanz der Objektorientierung für Softwarearchitektur
    Pfeil 8.1.2 Erweiterung von Modulen
  Pfeil 8.2 Die Präsentationsschicht: Model, View, Controller (MVC)
    Pfeil 8.2.1 Das Beobachter-Muster als Basis von MVC
    Pfeil 8.2.2 MVC in Smalltalk: Wie es ursprünglich mal war
    Pfeil 8.2.3 MVC: Klärung der Begriffe
    Pfeil 8.2.4 MVC in Webapplikationen: genannt »Model 2«
    Pfeil 8.2.5 MVC mit Fokus auf Testbarkeit: Model-View-Presenter


Rheinwerk Computing - Zum Seitenanfang

8.2 Die Präsentationsschicht: Model, View, Controller (MVC)  Zur nächsten ÜberschriftZur vorigen Überschrift

Ein sehr erheblicher Teil der Funktionalität auch von objektorientierten Systemen spielt sich bei der Interaktion mit dem Anwender von Software ab. Für die Modellierung dieser Interaktion in der Präsentationsschicht gibt es verschiedene Ansätze. Am weitesten verbreitet ist dabei der sogenannte MVC-Ansatz (Model-View-Controller).

Mit Model-View-Controller (MVC) wird ein Interaktionsmuster in der Präsentationsschicht von Software beschrieben. MVC ist wohl einer der schillerndsten Begriffe im Bereich der objektorientierten Programmierung. Viele Varianten haben sich herausgebildet, teilweise einfach aufgrund eines falschen Verständnisses des ursprünglichen MVC-Musters, teilweise als Weiterentwicklung oder Anpassung an neue Anwendungsfälle.

Da es sich bei MVC nach wie vor um das wichtigste und verbreitetste Muster für die Präsentationsschicht von objektorientierten Anwendungen handelt, gehen wir in diesem Kapitel ausführlich darauf ein.


Rheinwerk Computing - Zum Seitenanfang

8.2.1 Das Beobachter-Muster als Basis von MVC  Zur nächsten ÜberschriftZur vorigen Überschrift

Eine ganz zentrale Art von Information in objektorientierten Systemen ist die Information darüber, dass ein Objekt seinen Zustand geändert hat.

Interaktionen in der Präsentationsschicht

Die Interaktionen, die hierbei entstehen, können komplex sein. Nach dem Prinzip einer Verantwortung sollten Sie aber vermeiden, dass die betroffenen Objekte sich gegenseitig kennen müssen. Für derartige Fälle bietet es sich an, das Entwurfsmuster »Beobachtetes–Beobachter« anzuwenden. Das Muster wird auch kurz Beobachter-Muster genannt. In Abschnitt 5.4, »Mehrfachvererbung«, hatten wir es bereits an einem Beispiel vorgestellt. Abbildung 8.1 zeigt die bei der Anwendung des Musters beteiligten Klassen noch einmal in der Übersicht für den allgemeinen Fall.

Abbildung 8.1    Beobachter und beobachtete Objekte

In der Abbildung ist zu sehen, dass sich die Beobachter über die Operation anmelden() registrieren können. Wenn sie das getan haben, werden sie über Änderungen des Zustands im beobachteten Objekt informiert. Dies geschieht darüber, dass dieses Objekt nach Änderungen seine eigene Operation benachrichtigen() aufruft. Diese wird alle registrierten Beobachter durchgehen und deren Operation aktualisieren() aufrufen. Damit haben alle Beobachter die Möglichkeit, auf die Zustandsänderung zu reagieren.

Innerhalb von MVC wird das Muster verwendet, um Änderungen an einem Modell an die Objekte zu kommunizieren, die das Modell darstellen, die sogenannten Views. Dabei sollen die Modelle nichts darüber wissen müssen, von welchen Objekten sie denn nun dargestellt werden.


Rheinwerk Computing - Zum Seitenanfang

8.2.2 MVC in Smalltalk: Wie es ursprünglich mal war  Zur nächsten ÜberschriftZur vorigen Überschrift

Für einen Überblick beginnen wir direkt am Anfang: MVC wurde zusammen mit der objektorientierten Programmiersprache Smalltalk eingeführt. Bei MVC handelte es sich ursprünglich um ein Konzept, das die Interaktionen eines Benutzers (vor allem über Mausaktionen) sauber von den dadurch veränderten Daten und deren Darstellung trennen sollte.

Controller: Verarbeitung von Eingaben

Dabei ist der Controller für die Verarbeitung der Eingaben (zum Beispiel Mausklicks) zuständig und für deren Kommunikation an das Modell. Das Model ist passiv, es wird vom Controller befragt und modifiziert. Der View [Es ist gängig, den englischen Begriff View für eine Darstellungskomponente zu verwenden. Allerdings herrscht Uneinigkeit darüber, ob der Artikel nun als »der View« oder »die View« zu wählen ist. Wir verwenden im Folgenden die Version »der View«. ] befragt das Modell, um auf dieser Grundlage seine Darstellung anzupassen.

Wie aus Abbildung 8.2 hervorgeht, ist die Beziehung zwischen View und Controller klar definiert: Sie treten immer als Paar auf, und jeder kennt den jeweils anderen. Ein Modell kann aber von beliebig vielen View-/Controller-Paaren betreut werden, was die Möglichkeit von verschiedenen Sichten auf dasselbe Modell eröffnet.

Abbildung 8.2    Beziehung zwischen Model, View und Controller in Smalltalk

Die Interaktion über das Beobachter-Muster findet zwischen Model und View statt. In Abbildung 8.3 ist dargestellt, wie das Muster für die Zusammenarbeit dieser beiden Bestandteile eingesetzt wird.

Abbildung 8.3    Beobachter-Muster in MVC

Im dargestellten Beispiel werden Änderungen am einem KundenModell an alle beteiligten Views kommuniziert. In diesem Fall hat ein Kunde lediglich einen Namen zugeordnet. Bei Änderungen an diesem Namen ruft das Modell die Operation aktualisieren auf. Wenn sich KundenHtmlView beim Modell durch Aufruf der Operation anmelden() als Beobachter registriert hat, wird dieser mit benachrichtigt und kann in der Methode aktualisieren() die Anzeige des Namens anpassen.


Rheinwerk Computing - Zum Seitenanfang

8.2.3 MVC: Klärung der Begriffe  Zur nächsten ÜberschriftZur vorigen Überschrift

Obwohl die ursprünglich in Smalltalk eingeführte Trennung in Model, View und Controller recht eindeutig ist, werden wir in Diskussionen sehr unterschiedliche Verständnisse dessen antreffen, was denn nun ein Modell und was ein Controller ist.

Das rührt unter anderem daher, dass uns bestimmte Aufgaben, für die zum Beispiel ein Controller in Smalltalk zuständig war, mittlerweile ganz selbstverständlich abgenommen werden. Deshalb klären wir hier zunächst einmal, was denn mit Model, View und Controller gemeint ist.

Was ist denn nun eigentlich ein Controller?

Ein Controller hat in MVC eine recht generische Aufgabe: Er muss die Interaktionen eines Benutzers über die verschiedenen Eingabemöglichkeiten wie Tastatur oder Maus entgegennehmen und in konsolidierter Form weiterleiten.


Icon Hinweis Controller in MVC (Eingabe-Controller)

Ein Controller hat in der MVC-Variante von Smalltalk die Aufgabe, die Anwendung von den Komplexitäten der Eingabemechanismen abzuschotten. Zum Beispiel ist er dafür zuständig, Mausereignisse einem konkreten Bildschirmbereich zuzuordnen.

Die Funktionalität des Controllers ist mittlerweile meist recht selbstverständlich in grundlegende Bibliotheken integriert, die Anwendungsprogrammierer in der Regel gar nicht mehr zu Gesicht bekommen.


Sie benötigen eben in der Regel keinen explizit angegebenen Controller mehr, um einen Mausklick auch einem konkreten Eingabeelement eines Views zuzuordnen. Diese Dinge werden Ihnen meist durch Module abgenommen, die in Betriebssystem oder Basisbibliotheken integriert sind.

Wir verwenden für diese Art von Controller den Begriff Eingabe-Controller. Ein Anwendungsentwickler muss sich aber nur noch selten direkt mit Eingabe-Controllern beschäftigen.

Sie sollten den Eingabe-Controller auch möglichst klar unterscheiden von einem Applikations-Controller, der Abläufe innerhalb einer Applikation steuert. Zum Beispiel ist dieser dafür zuständig, einen Folgedialog aufgrund einer Benutzereingabe zu ermitteln. Dies hat aber mit der ursprünglichen Verwendung in MVC nur wenig zu tun. MVC ist nämlich auch in Smalltalk nie ein komplettes Architekturmodell gewesen, sondern eine Lösung für eine ganz bestimmte Teilaufgabe: die Interaktionen in der Präsentationsschicht sauber zu trennen.

Was ist denn nun eigentlich ein Modell?

Auch in Bezug auf das Modell innerhalb von MVC gibt es hin und wieder Unklarheiten. Möglicherweise kommt das auch daher, dass gerade in Smalltalk praktisch jedes Objekt als Modell agieren kann.

Das heißt aber lediglich, dass zumindest in der Theorie jedes Smalltalk-Objekt darstellbar ist und auf Nachrichten reagieren kann, die möglicherweise eine Zustandsänderung bewirken. Entscheidend dabei ist aber, dass das Modell den Zustand des gesamten Konstrukts verwaltet und als Referenz für die Darstellung dient.

In der Regel wird das Modell zwar weitere Komponenten in Anspruch nehmen, die dann die fachliche Funktionalität umsetzen, das Modell selbst ist aber nur durch die oben genannten Eigenschaften definiert.


Icon Hinweis Modell in MVC

Ein Modell in MVC muss also folgende Eigenschaften aufweisen:

  • Es muss einen Zustand verwalten können.
  • Es muss darstellbar sein.
  • Es muss auf Aufforderungen zu Änderungen reagieren können.

Damit hat ein Modell zunächst überhaupt nichts mit der Logik in der Domäne zu tun, auch nicht unbedingt mit Persistenz.


Und schließlich noch der View

Views im MVC-Modell sind die Komponenten, die für die Darstellung des Modells verantwortlich sind. Die Darstellungsarten sind dabei nicht eingeschränkt. Grundsätzlich könnte ein View die Daten des Modells auch durch die Nutzung eines Sprachgenerierungsmoduls vorlesen. Allerdings erscheint für diesen Fall die Bezeichnung View nicht mehr völlig adäquat.

Views sollten sich ausschließlich mit der Darstellung beschäftigen und möglichst keine fachliche Logik enthalten. Allerdings werden in einigen Fällen Funktionen des Controllers mit im View integriert.

View und Controller zusammengefasst

Controller erledigen in der Regel sehr gleichförmige Aufgaben. Schon bei Smalltalk gibt es einen kleinen Satz von Standard-Controllern, deren Exemplare dann jeweils einem View und einem Modell zugeordnet werden.

Sowohl bei den Microsoft Foundation Classes (MFC) als auch bei der Java-Oberflächenbibliothek Swing ist denn auch der Controller keine eigenständige Entität mehr. Bei Microsoft nennt sich das Ganze dann Document-View, bei Swing wird das Verfahren hin und wieder auch Model-Delegate genannt.

Auch wenn die Begriffe hier schon wieder etwas verwirrend sind, es handelt sich doch in beiden Fällen um eine Modellierung, bei der View und Controller zusammenfallen. Bei Microsoft eben im View, bei Swing im Delegate – der Oberflächenkomponente, die für die Anzeige und für die Behandlung von Benutzereingaben zuständig ist.

Vorsicht, Falle Nummer 1: MVC ist kein Schichtenmodell

Wir haben in der Praxis und in der Literatur schon häufiger eine Interpretation von MVC vorgefunden, die unserer Meinung nach einfach falsch ist.

MVC ist ein Muster für Interaktionen in der Präsentationsschicht. Es setzt damit bereits voraus, dass wir uns grundsätzlich auf eine Architektur eingelassen haben, die Schichten vorsieht und die Präsentation vom Rest der Anwendung trennt.

MVC ist keine komplette Architektur.

In der Praxis und in der Literatur haben wir aber häufiger eine Interpretation von MVC gesehen, die dieses Muster zur kompletten Architektur für eine Applikation erhoben hat. Außerdem wird häufig auch die Rolle des Modells überdehnt, indem diesem die Verantwortung für Geschäftslogik, Persistenz oder andere zentrale Aspekte zugeschoben wird.

Sie sollten auf keinen Fall MVC mit der Schichtenarchitektur verwechseln. Das Modell ist nämlich nicht für die Umsetzung der Schicht der Anwendungslogik zuständig. Natürlich können beide Aufgaben (Bereitstellung der Anwendungslogik und Darstellbarkeit in der Präsentationsschicht) in der Praxis von denselben Objekten übernommen werden. So können Sie natürlich eine Enterprise Java Bean als Modell verwenden, um diese direkt über die Präsentationsschicht darzustellen. Die Modell-Eigenschaft ist dabei aber nach wie vor völlig unabhängig von den anderen Eigenschaften der EJB, wie z. B. die Fähigkeit, Daten persistent zu machen.

Vorsicht, Falle Nummer 2: Nicht jeder View braucht eine eigene Controllerklasse

Durch die bestehende 1:1-Verbindung zwischen Views und Controllern in MVC könnte man leicht auf die Idee kommen, dass diese Beziehung nicht nur für die Exemplare, sondern auch für die Klassen gelten könnte.

Dies ist aber schon bei der ursprünglichen Version von MVC in Smalltalk nie so geplant gewesen. Dort bekommt zwar jeder View sein spezielles und eigenes Exemplar eines Controllers zugewiesen, da auch ein Controller einen Zustand besitzt, der direkt mit dem View zusammenhängt. Aber in Smalltalk gab es eine kleine Anzahl von Controller-Klassen, und deren Exemplare wurden zusammen mit den jeweiligen spezifischen Views erzeugt.

Auch waren in Smalltalk die Controller für Aufgaben zuständig, die Sie heute in der Regel bei der Entwicklung einer Applikation gar nicht mehr als Aufgabe wahrnehmen, weil sie von Bibliotheken übernommen werden, die wir mittlerweile ganz selbstverständlich voraussetzen. Sie müssen sich eben in der Regel nicht mehr damit beschäftigen, wie Sie aus den Koordinaten eines Mausklicks darauf schließen könnten, welches Element der Oberfläche davon nun wie betroffen ist. Das war aber eine der Aufgaben von Controllern im ursprünglichen MVC.


Rheinwerk Computing - Zum Seitenanfang

8.2.4 MVC in Webapplikationen: genannt »Model 2«  Zur nächsten ÜberschriftZur vorigen Überschrift

Mit Bezug auf Webapplikationen wird ebenfalls von einer Verwendung des MVC-Musters gesprochen. Sun hat in frühen Versionen der J2EE-Spezifikation zwei Varianten des empfohlenen MVC-Musters eingeführt, die Model 1 und Model 2 genannt wurden. [Auszusprechen als Model One und Model Two. ] Diese Begriffe haben sich gehalten, obwohl sie in der Spezifikation mittlerweile nicht mehr enthalten sind.

Model 1

Model 1 ist dabei eine sehr einfache Variante, bei der Zugriffe auf Modelle (meist Java Beans) direkt aus JSP-Seiten [JSP (Java Server Pages) sind ein standardisierter Mechanismus, wie Java-Code in HTML-Seiten integriert werden kann. Eine JSP-Seite ist ein HTML-Dokument, das bei seiner Anzeige dynamisch modifiziert und mit Daten angereichert wird. ] heraus erfolgen. Die folgende Abbildung zeigt eine Interaktion auf Basis dieses Modells.

Abbildung 8.4    Model 1 für Webapplikationen

Model 1 ist sehr einfach und überschaubar, allerdings nur für relativ kleine Anwendungen zu empfehlen. Änderungen an der Navigationsstruktur durch die verschiedenen Seiten sind nur mit großem Aufwand durchzuführen, da dafür direkt in die JSP-Seiten eingegriffen werden muss.


Icon Hinweis Model 1 für Webapplikationen

Model 1 ist eine einfache Architektur für die Interaktion mit der Präsentationsschicht von Webapplikationen. Es existiert keinerlei Controller, sondern der View (eine JSP-Seite) kommuniziert direkt mit dem Modell. Das Modell wird dabei in der Regel durch eine sogenannte Java Bean repräsentiert. Java Beans sind einfache Java-Klassen, die sich an Konventionen für die Namen von Operationen halten, die auf ihre Daten zugreifen.

Bei Verwendung von Model 1 liegt die Entscheidung darüber, welche Folgeseite angezeigt wird, alleine bei der aktuellen JSP-Seite. Als Reaktion auf eine bestimmte Benutzereingabe wird direkt dort über die in der Folge zu präsentierende JSP-Seite entschieden.


Model 2

Model 2 für Webapplikationen lagert die Entscheidung darüber, welche Folgeseiten aufgerufen werden, in eine eigene Komponente aus und erlaubt damit mehr Flexibilität.


Icon Hinweis Model 2 für Webapplikationen

Beim Model 2 für Webapplikationen erfolgt die Steuerung für die Dialogabfolge durch eine eigene Komponente, den sogenannten Controller. Der Controller übernimmt dabei Aufgaben, die gegenüber der ursprünglichen Variante in MVC angepasst sind. Die Aufgabenverteilung ist bei Verwendung von Model 2 damit die folgende:

  • Der View: Eine JSP-Seite, die Daten darstellt und Dateneingaben vom Benutzer annimmt. Diese Seite kann Logik enthalten, allerdings entscheidet sie nicht darüber, welche JSP als Folgeseite angezeigt wird.
  • Der Controller: Ein Servlet, das grundsätzlich von JSP aus aufgerufen wird und aufgrund der vorgenommenen Eingaben entscheidet, welche Aktion ausgeführt werden soll und welche Folgeseite aufgerufen wird.
  • Das Modell: Ein Objekt, das die darzustellenden Daten hält, meist eine Java Bean.

Eine Umsetzung der Model 2-Variante von MVC bietet das verbreitete Framework Jakarta Struts. In Abbildung 8.5 ist dargestellt, wie eine Interaktion auf Basis dieses Modells erfolgt.

Abbildung 8.5    Model 2 für Webapplikationen

Hier wird ersichtlich, dass der Controller gegenüber Smalltalk weitere Aufgaben bekommen hat: Er steuert einen Teil der Applikationslogik, ist also nicht mehr nur für die Kommunikation der Benutzerinteraktion an Modell und View zuständig. Sie haben es hier mit einer Erweiterung des MVC-Musters zu tun.

Icon Beispiel Online-Banking in Struts

Als Beispiel stellen wir im Folgenden den Auszug einer kleinen Banking-Anwendung vor, die zur Anmeldung die Eingabe einer PIN erfordert. Zunächst einmal gibt es bei Struts einen zentralen Controller (ein Servlet), der die Reaktion auf Benutzereingaben (in der Regel der Klick auf einen Button) auswertet. Dabei entscheidet das Servlet auf der Grundlage einer Konfiguration in XML, was als Reaktion auf die Eingabe als Nächstes passieren soll. Diese Entscheidung wird auf der Grundlage einer Beschreibung getroffen, wie sie als Beispiel in Listing 8.1 aufgeführt ist.

... 
<struts-config> 
    <form-beans>  
          <form-bean name="logonForm" 
                  type="banking.logon.LogonForm"/> 
          <form-bean name="transferAmountForm" 
                 type="banking.transfer.TransferAmountForm"/> 
    </form-beans> 
    <action-mappings>  
    <!-- Karteneingabe --> 
        <action path="/logon" 
               type="banking.logon.LogonAction" 
               name="logonForm"> 
                  <forward name="cardsuccess" 
                   path="/logon/PIN_Kontoservice.jsp" /> 
        </action> 
        <!-- PIN-Eingabe --> 
        <action path="/pinentry"  
        type="banking.logon.PinEntryAction" 
        name="logonForm">         
        <forward name="wrongpin" 
                  path="/logon/reenterpin.jsp"> 
        <forward name="lastwrongpin" 
                  path="/logon/retaincard.jsp"> 
        <forward name="success"  
                  path="/kontoservice/Kontoservice.jsp"/> 
        </action> 
<!— Weitere Aktionen --> 
        ... 
    </action-mappings> 
</struts-config>

Listing 8.1    Ablaufbeschreibung für Struts-Anwendung

In Listing 8.1 wird also festgelegt, welche JSP-Seiten als Folgeseiten aufgerufen werden. In Zeile wird dabei zunächst bestimmt, welche Eingabemasken und welche Klassen für deren Datenhaltung verwendet werden. In Zeile beginnen die sogenannten Action-mappings, die festlegen, welche JSP-Seiten nach einer Aktion angezeigt werden sollen. Die Aktion, die als Reaktion auf die PIN-Eingabe ausgelöst wird, ist in Zeile definiert. Ausgeführt wird die Aktion, die über die Klasse PinEntryAction festgelegt wird. Diese wiederum entscheidet über ihren Status (success, wrongpin oder lastwrongpin) mittelbar, welche JSP-Seite als Nächstes angezeigt wird. In Zeile ist zum Beispiel festgelegt, dass bei erfolgreicher PIN-Eingabe die JSP-Seite Kontoservice.jsp angezeigt wird.

In Listing 8.2 ist die Umsetzung der Aktion aufgeführt, die nach Eingabe einer PIN aufgerufen wird.

package banking.logon; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 
 
import banking.base.BankingSession; 
import banking.base.SecurityInfo; 
 
import org.apache.struts.action.*; 
public class PinEntryAction extends Action 
{ 
 
  public ActionForward perform( ActionMapping mapping, 
        ActionForm form, 
        HttpServletRequest request, 
        HttpServletResponse response) 
  { 
  LogonForm theForm = (LogonForm) form; 
  // Die Pin ist enthalten im übergebenen Formular 
  String encodedpin = theForm.getEncodedPin(); 
        // Die verschlüsselte Version der PIN speichern 
        HttpSession session = request.getSession(); 
        BankingSession bankingsession = 
        (BankingSession)session.getAttribute("bankingsession"); 
        SecurityInfo securityInfo = 
           bankingsession.getSecurityInfo(); 
        securityInfo.setEncodedPin(encodedpin);  
        return mapping.findForward("success");  
  } 
}

Listing 8.2    Aktion bei PIN-Eingabe

Die Klasse PinEntryAction aus Listing 8.2 merkt sich also die verschlüsselte Version der PIN (Zeile ) und signalisiert dann den Erfolg der PIN-Eingabe (Zeile ). Eventuelle Fehlersituationen und andere Rückgabewerte sind der Einfachheit halber im Code nicht dargestellt.

Modell: einfache Java Bean

Unser Modell sieht in diesem Fall ganz einfach aus, es handelt sich um eine simple Java Bean, welche die Daten aufnehmen kann, die im View (der entsprechenden JSP-Seite) eingesammelt werden. In Listing 8.3 ist das Modell aufgeführt, von dem die Daten zur PIN-Eingabe gehalten werden.

package banking.logon; 
import org.apache.struts.action.ActionForm; 
public class LogonForm extends ActionForm { 
 
protected String track2; 
protected String track3; 
protected String encodedpin; 
public String getTrack2() { return track2; } 
public String getTrack3() { return track3; } 
public String getEncodedPin() { return encodedpin; } 
 
public void setTrack2(String track2){this.track2=track2;} 
public void setTrack3(String track3){this.track3=track3;} 
public void setEncodedPin(String encodedpin) 
          {this.encodedpin = encodedpin; } 
 
}

Listing 8.3    Modell für die Eingabe

Das Modell dient hier zur Aufnahme der Eingaben, die in diesem Fall die Daten der PIN und der verwendeten Bankkarte umfassen. Die Angaben über die PIN werden durch die zugeordnete Aktion in die Session übernommen und können bei späteren Überprüfungen erneut verwendet werden.


Rheinwerk Computing - Zum Seitenanfang

8.2.5 MVC mit Fokus auf Testbarkeit: Model-View-Presenter  topZur vorigen Überschrift

Ein Aspekt, der in der Regel bei der Modellierung der Präsentationsschicht nur unzureichend betrachtet wird, ist die Testbarkeit der resultierenden Applikation.

Tests von Oberflächen sind schwierig.

Es ist ein Erfahrungswert, dass Tests unter Beteiligung von grafischen Benutzeroberflächen wesentlich schwieriger zu automatisieren sind als Tests von Softwarekomponenten, die ohne eine grafische Darstellung auskommen.

Es gibt eine ganze Reihe von Produkten, die versuchen, dieses Problem durch automatisierte Tests unter Beteiligung von grafischen Oberflächen zu lösen. Besser ist es aber, bereits beim Design unserer Software sicherzustellen, dass der überwiegende Teil ohne Beteiligung von grafischen Benutzeroberflächen getestet werden kann. Ein Muster in der Präsentationsschicht, welches das Problem angeht, wurde von Martin Fowler kategorisiert und nennt sich Model-View-Presenter.

Grundgedanke ist es dabei, die eigentliche Darstellung (den View) komplett von technischer und fachlicher Logik freizuhalten.

Je direkter eine Applikation mit den Darstellungskomponenten gekoppelt ist, desto schwieriger wird es, sie komplett zu testen.

Abbildung 8.6    Beziehung Model-View-Presenter

Beim Ansatz des Model-View-Presenters werden Ereignisse direkt vom View verarbeitet. Aber der View delegiert diese direkt weiter an die Presenter-Klasse. Diese wiederum gibt möglicherweise Rückmeldungen an den View. Warum ist es nun aber sinnvoll, in der Kommunikation zwischen View und Presenter eine Abstraktionsschicht über eine Schnittstellenklasse einzuziehen?

Abstraktion über eine Schnittstellenklasse

Nun, eine Möglichkeit ist die Wiederverwendung von Presenter-Klassen, wenn ein Presenter mit mehreren verschiedenen Views zusammenarbeiten soll, die lediglich dasselbe Interface implementieren. Dieser Fall ist in der Praxis aber eher selten.

Viel wichtiger ist die daraus entstehende Möglichkeit, den View für Testzwecke durch ein Ersatzobjekt (ein sogenanntes Mock Object) zu ersetzen. Damit haben Sie die Möglichkeit, sämtliche Logik Ihres Programms weitgehend automatisiert zu testen. Lediglich die konkrete Darstellung bleibt außen vor, aber diese ist in der Regel weniger fehleranfällig als andere Teile. Sie können durch einen Test der Presenter-Klasse zum Beispiel auch feststellen, ob Querabhängigkeiten zwischen Oberflächenelementen korrekt ausgewertet werden.

Diskussion: Ist MVP zu viel Aufwand?

Gregor: Testbarkeit schön und gut. Aber ist das jetzt nicht etwas übertrieben? Überleg mal: Für jeden Dialog, jedes Fenster in unserer Anwendung müssen wir nun noch einmal ein Interface definieren und auch noch eine zusätzliche Presenter-Klasse, die wir uns eigentlich auch schenken könnten.

Bernhard: O.k., ich gebe zu, dass das nach unnötiger Komplexität aussieht. Ich denke auch nicht, dass es für alle Softwaresysteme Sinn macht. Aber meine Erfahrung ist einfach, dass oft eine ganze Menge Aufwand in GUI-spezifische Anwendungsteile versenkt wird, weil diese nicht vernünftig testbar sind.

Gregor: Aber ist denn nicht der Einsatz von GUI-spezifischen Testtools genau für solche Fälle gedacht? Wir werfen da Rational Robot oder unseren Test-Director an, der testet das ganze System mit den GUI-Komponenten zusammen durch.

Bernhard: Das ist nicht das Gleiche. Regressionstests sind nach meiner Erfahrung viel einfacher zu erstellen und auch zu pflegen, wenn sie sich nur mit Source-Code beschäftigen. Sobald ich Makros dazu schreiben, mich auf Beschriftungen in Dialogen verlassen und ein externes Tool (anstelle eines simplen von mir geschriebenen Testprogramms) anwerfen muss, wird das ganze Verfahren selbst schon sehr kompliziert und fehleranfällig.

Gregor: Na gut, zugegeben, das Testen wird einfacher. Aber ob damit der zusätzliche Aufwand in der Implementierung wettgemacht wird, davon bin ich noch nicht komplett überzeugt. Und warum überhaupt eine zusätzliche Klasse, die View-Klasse selbst würde doch völlig ausreichen, warum teste ich nicht diese direkt?

Bernhard: Ja, das ist ein guter Punkt. Allerdings sind in der Praxis die View-Klassen eben oft stark mit der ganz konkreten Darstellung verbunden und lassen sich eben nicht davon unabhängig verwenden. Genau diese Trennung versuchen wir mit unserer neu eingezogenen Schnittstelle erst zu erreichen.

Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

 <<   zurück
  Zum Rheinwerk-Shop
Neuauflage: Objektorientierte Programmierung






Neuauflage:
Objektorientierte Programmierung

Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Java ist auch eine Insel






 Java ist auch
 eine Insel


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: Einstieg in Python






 Einstieg in Python


Zum Rheinwerk-Shop: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern