SlideShare ist ein Scribd-Unternehmen logo
41. DNUG Konferenz · 11./12. November 2014 · Leipzig
www.dnug.de
Das Model-View-Controller - Pattern
Track Entwicklung 12.11.2014 13:30 – 14:15 Uhr
Bert Häßler
Leonso GmbH
www.leonso.de
bert.haessler@leonso.de
Slides und DemoDB für diesen Vortrag: www.leonso.de/dnug14
Über mich
 Bert Häßler, verheiratet, drei Kinder
 Diplom-Wirtschaftsinformatiker, Technische Universität Dresden
 1998 „Erstkontakt“ mit Notes
 Anwendungsentwicklung / Administration
 @Formula-Debugger (www.nappz.de/xfl)
 seit 2006 EntwicklerCamp, DNUG
 OO – Frameworks in Notes
 LotusScript (!!!) und Java/XPages
 2012 Gründung Leonso GmbH
18.11.2014 2www.leonso.de
Agenda
 Softwarequalität
 MVC – Was ist das?
 Model / DAO
 View
 Controller
 MVC in XPages
 Beispielimplementation
 Der Weg zum eigenen Framework
18.11.2014 3www.leonso.de
Softwarequalität – Worauf kommt es an?
18.11.2014 4www.leonso.de
Quelle: http://cdn-static.zdnet.com/i/story/61/03/001582/istock_000002369355xsmall.jpg
Softwarequalität – Worauf kommt es an?
18.11.2014 5www.leonso.de
Funktionalität
Effizienz Übertragbarkeit
Änderbarkeit
Zuverlässigkeit
Benutzbarkeit
Siehe auch: http://de.wikipedia.org/wiki/Softwarequalität
Softwarequalität – Worauf kommt es an?
18.11.2014 6www.leonso.de
Funktionalität
Effizienz Übertragbarkeit
Änderbarkeit
Zuverlässigkeit
Benutzbarkeit
Siehe auch: http://de.wikipedia.org/wiki/Softwarequalität
Softwarequalität – Worauf kommt es an?
18.11.2014 7www.leonso.de
Funktionalität
Effizienz
Änderbarkeit
Zuverlässigkeit
Benutzbarkeit
Siehe auch: http://de.wikipedia.org/wiki/Softwarequalität
Übertragbarkeit
Softwarequalität – Worauf kommt es an?
18.11.2014 8www.leonso.de
E. Rauschenbach
Deutscher Karikaturpreis 2003
Softwarequalität – Worauf kommt es an?
 Probleme bei „gewachsenen“ Notes-Anwendungen:
 Code kann überall stehen
 z.B. Buttons, Events, Agenten, Bibliotheken
 Verschiedene Sprachen (Formel, LS, einfache Aktionen, JS)
 Redundanz
 Ansatz:
 Modularisierung
18.11.2014 9www.leonso.de
„Frontend“ „Backend“
Das MVC-Pattern
 Model
 View
 Controller
18.11.2014 10www.leonso.de
Quelle: http://www.casting-power.de/images/kindermodels.jpg
Das MVC-Pattern
 Model
 View
 Controller
18.11.2014 11www.leonso.de
Quelle: http://upload.wikimedia.org/wikipedia/en/6/6a/View_From_Rock_Cottage_to_Soldiers_Bay.jpg
Das MVC-Pattern
 Model
 View
 Controller
18.11.2014 12www.leonso.de
Quelle: http://writeups.org/img/fiche/2719a.jpg
Das MVC-Pattern
 Model
 Daten
 Geschäftslogik
 View
 Darstellung
 Benutzeraktion
 Controller
 Steuerung
18.11.2014 13www.leonso.de
ModelView
Controller
MVC-Pattern für „klassische“ XPage
18.11.2014 14www.leonso.de
ModelView
Controller
FacesServlet
NSF
XPage
<HTML>
…
</HTML>
request
response
18.11.2014 15www.leonso.de
Demo
Model-Komponente
 Class Animal
 Einstiegsklasse
 „Application“
 In diesen Klassen KEINE konkreten Datenbankzugriffe
implementieren!
18.11.2014 16www.leonso.de
Zoo
getAllAnimals()
getAnimalByID()
createAnimal()
…
Animal
Species
Name
Description
save()
Model-Komponente
 DAO (Data Access Object)
 Implementiert benötigte lesende/schreibende Datenzugriffsmethoden
 CRUD (Create, Read, Update, Delete)
18.11.2014 17www.leonso.de
Dao
saveAnimal(animal)
removeAnimal(animal)
getAllAnimals()
getAnimalByID()
…
Model-Komponente
18.11.2014 18www.leonso.de
Model
Zoo
Animal
DB
DAO
Model-Komponente
18.11.2014 19www.leonso.de
public class Zoo implements Serializable {
/* Ermitteln aller Tiere in der Datenbasis<br>
* Methode wird an aktuell verwendete DAO-Instanz delegiert<br>
* nach aussen ist Zoo eine Facade, die die DAO-Ebene verbirgt */
public List<Animal> getAllAnimals() throws Exception {
return getDao().getAllAnimals();
}
/* Suche nach einem Tier ueber dessen ID */
public Animal getAnimalById(String id) throws Exception {
return getDao().getAnimalById(id);
}
// DAO-Instanz uebernimmt das Lesen und Schreiben der Daten
private Dao dao = null;
public Dao getDao() throws Exception {
if (dao == null) dao = new Dao(this);
return dao;
}
/* erzeugt ein neues Animal-Objekt */
public Animal createAnimal() throws Exception {
Animal model = getInstanceOfAnimal();
model.generateNewId(); // Initiale Werte werden gleich hier gesetzt
return model;
}
/* Factory-Methode zum Erstellen einer Animal-Instanz<br>
* alle Stellen im gesamten Code, die eine Instanz von Animal brauchen,<br>
* sollten dies nicht ueber <code>Animal a = new Animal();</code><br>
* implementieren, Factory-Pattern erlaubt flexiblere Klassenbindung! */
public Animal getInstanceOfAnimal() {
return new Animal(this);
}
}
Model-Komponente
18.11.2014 20www.leonso.de
public class Animal implements Serializable {
private static final long serialVersionUID = 1L;
private final Zoo app; // die Application als "Mutter" aller Objekte
private String id = null;
private String species = null;
private String name = null;
private String description = null;
public Animal(Zoo app) {
this.app = app;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//weitere Getter/Setter
...
/**
* speichert das Objekt<br>
* standardmaessig delegieren wir diese Methode an DAO<br>
* Damit kann die Komplexitaet (Arbeitsteilung von Model und DAO) nach
* aussen verborgen werden.
*/
public void save() throws Exception {
app.getDao().saveAnimal(this);
}
}
Model-Komponente
18.11.2014 21www.leonso.de
public class Dao implements Serializable {
private final Zoo app;
public Dao(Zoo zoo) {
this.app = zoo;
}
/* Suche nach einem bestimmten Tier */
public Animal getAnimalById(String id) throws Exception {
View view = UtilsJsf.getCurrentDatabase().getView("Animals");
Document doc = null;
Animal model = null;
try {
doc = view.getDocumentByKey(id); // Dokument suchen
if (doc != null) {
model = app.getInstanceOfAnimal(); // leeres Objekt erzeugen
readModelValuesFromDoc(doc, model); // Daten übertragen
}
} finally {
recycleDominoObjects(doc, view); // Recycling nicht vergessen
}
return model;
}
private void readModelValuesFromDoc(Document doc, Animal model {
model.setId(doc.getItemValueString("ID"));
model.setName(doc.getItemValueString("Name"));
model.setSpecies(doc.getItemValueString("Species"));
model.setDescription(doc.getItemValueString("Description"));
}
}
View-Komponente
 XPage Animal.xsp
 Class AnimalPageBean
 Code für Buttons
 Databinding
18.11.2014 22www.leonso.de
AnimalPageBean
clickSave()
clickBack()
getAnimal()
View-Komponente
18.11.2014 23www.leonso.de
 XPage Animal.xsp
 XPage ohne natives Notes-Databinding!
 Binding über PageBean bzw. Model
<?xml version="1.0" encoding="UTF-8"?>
<xp:view>
<h2>Tier</h2>
Tierart <xp:inputText value="#{page.animal.species}" />
Name <xp:inputText value="#{page.animal.name}" />
Details <xp:inputTextarea value="#{page.animal.description}" />
<xp:button value="zurück">
<xp:eventHandler event="onclick">
<xp:this.action><![CDATA[#{javascript:page.clickBack()}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button value="speichern">
<xp:eventHandler event="onclick">
<xp:this.action><![CDATA[#{javascript:page.clickSave()}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:view>
View-Komponente
18.11.2014 24www.leonso.de
public class AnimalPageBean implements Serializable {
private final Animal model; // akuell geöffnetes Objekt
public AnimalPageBean() throws Exception {
String id = UtilsJsf.getParameter("id");
// ManagedBean "app" holen
Zoo app =(Zoo) UtilsJsf.resolveVariable("app");
// Ueber die ID in der Datenbank suchen
model = app.getAnimalById(id);
}
// wird fuer Data-Binding benutzt, siehe xsp
public Animal getAnimal() {
return model;
}
// Code fuer Button "speichern"
public void clickSave() throws Exception {
// Validierung und Fehleranzeige muss noch implementiert werden
model.save();
redirectToOverview();
}
// Code fuer Button "zurueck"
public void clickBack() throws Exception {
redirectToOverview();
}
// zur Uebersichtsseite navigieren
private void redirectToOverview() throws IOException {
UtilsJsf.sendRedirect("Overview.xsp");
}
}
Diagramm Animal.xsp
18.11.2014 25www.leonso.de
Model
View
Animal.xsp
AnimalPageBean
Zoo
Animal
DB
DAO
View-Komponente
 XPage Overview.xsp
 Class OverviewPageBean
 Code für Buttons
 Anzeigefunktionen
18.11.2014 26www.leonso.de
OverviewPageBean
clickNew()
clickRemove(animal)
getUrl(animal)
getDisplayText(animal)
View-Komponente
 XPage Overview.xsp
18.11.2014 27www.leonso.de
<xp:view>
<h2>Das sind unsere Tiere</h2>
<xp:repeat
value="#{page.allAnimals}"
var="animal">
<xp:link
text="#{javascript:page.getDisplayText(animal)}"
value="#{javascript:page.getUrl(animal)}" />
<xp:button value=“löschen">
<xp:eventHandler event="onclick">
<xp:this.action><![CDATA[#{javascript:page.clickRemove(animal);}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:repeat>
<xp:button value="neu">
<xp:eventHandler event="onclick">
<xp:this.action><![CDATA[#{javascript:page.clickNew();}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:view>
View-Komponente
18.11.2014 28www.leonso.de
public class OverviewPageBean implements Serializable {
/* liefert die Tiere in alphabetischer Reihenfolge */
public List<Animal> getAllAnimals() throws Exception {
List<Animal> all = (Zoo) UtilsJsf.resolveVariable("app").getAllAnimals();
// wir erwarten von der App nicht, dass sie uns die Daten schon sortiert hat
Collections.sort(all, new Comparator<Animal>() {
// wir sortieren hier nach Tierart + Name
public int compare(Animal a1, Animal a2) {
String sortValue1 = a1.getSpecies() + " " + a1.getName();
String sortValue2 = a2.getSpecies() + " " + a2.getName();
return sortValue1.compareTo(sortValue2);
}
});
return all;
}
/* liefert den Anzeigetext fuer ein Tier */
public String getDisplayText(Animal animal) {
return animal.getSpecies() + " " + animal.getName();
}
/* Code fuer den Button "Loeschen" auf der Seite */
public void clickRemove(Animal model) throws Exception {
// hier koennten ggfs. noch Sicherheitsabfragen kommen...
model.remove();
}
/* generiert die URL fuer ein bestimmtes Model */
public String getUrl(Animal model) {
return "Animal.xsp?id=" + model.getId();
}
}
View-Komponente
 XPage ohne natives Notes-Databinding!
 Binding über PageBean oder Model
 Code so weit wie möglich in PageBean halten
 Bessere Wiederverwendung (Vererbung)
 Performance
 Anzeige von Meldungen
 Validierungsfehler
 Laufzeitfehler
 Erfolgsmeldungen
18.11.2014 29www.leonso.de
Diagramm Overview.xsp
18.11.2014 30www.leonso.de
Model
View
Overview.xsp
OverviewPageBean
Zoo
Animal
DB
DAO
Controller-Komponente
 Realisiert JSF-Lifecycle
 PhaseListener
 Bean-Management
 faces-config.xml
 Scope-Bereitstellung
 Triggert Events
 beforePageLoad(), afterPageLoad(), …
 Class ZooPhaseListener
18.11.2014 31www.leonso.de
ZooPhaseListener
beforePhase()
Controller-Komponente
18.11.2014 32www.leonso.de
public class ZooPhaseListener implements PhaseListener {
private static final long serialVersionUID = 1L;
public PhaseId getPhaseId() {
// uns interessiert nur beforeRenderResponse
return PhaseId.RENDER_RESPONSE;
}
public void beforePhase(PhaseEvent phase) {
// zu jeder XPage gibt es eine passende PageBean,
// z.B. Animal.xsp - AnimalPageBean
String url = UtilsJsf.getXSPContext().getHistoryUrl(0);
// aus '/Animal.xsp' mach 'Animal'
String page = Utils.strLeft(Utils.strRight(url, "/"), ".");
// jetzt suchen wir die passende PageBean-Klasse...
String packageName = "de.leonso.dnug.view";
String className = page + "PageBean";
Class<?> cl = Class.forName(packageName + "." + className);
Object pageBean = cl.newInstance();
// ... und als ViewScope-Variable abgespeichert
Map<String, Object> viewScope = UtilsJsf.getViewScope();
viewScope.put("page", pageBean);
}
}
Controller-Komponente
18.11.2014 33www.leonso.de
<faces-config>
<managed-bean>
<managed-bean-name>app</managed-bean-name>
<managed-bean-class>
de.leonso.dnug.model.Zoo
</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
<lifecycle>
<phase-listener>
de.leonso.dnug.controller.ZooPhaseListener
</phase-listener>
</lifecycle>
</faces-config>
View
Diagramm Demo-Applikation
18.11.2014 34www.leonso.de
Model
Animal.xsp
AnimalPageBean
Zoo
Animal
DB
DAO
Controller
FacesServlet
faces-
config.xml
instantiiert
ZooPhaseListener
Overview.xsp
OverviewPageBean
Designelemente
18.11.2014 35www.leonso.de
Änderungsanforderung
 Nicht mehr auf NSF zugreifen, sondern auf andere Datenquelle
 z.B. XML-File:
 Was ist hier zu tun?
 Neue DAO-Klasse schreiben
18.11.2014 36www.leonso.de
Änderungsanforderung
18.11.2014 37www.leonso.de
<interface>
DaoI
saveAnimal(animal)
removeAnimal(animal)
getAllAnimals()
getAnimalByID()
DaoNotes
saveAnimal(animal)
removeAnimal(animal)
getAllAnimals()
getAnimalByID()
DaoXml
saveAnimal(animal)
removeAnimal(animal)
getAllAnimals()
getAnimalByID()
18.11.2014 38www.leonso.de
Demo
Was haben wir gesehen?
 Einfache XPage-Applikation mit MVC-Struktur
 Austauschbarkeit des Datenbasis
 Datenmigration durch Implementierung von DAO-Klassen
 Nutzung der Modelklassen in verschiedenen „Frontends“
18.11.2014 39www.leonso.de
Der Weg zum eigenen Framework
 Abstraktion
 Basisklassen für Model, DAO, PageBeans
 Validierung
 Tendenziell im Model
 Und/Oder im View
 Caching
 Steigerung der Performance !!!
 Scope-Festlegung (Application, Session, View)
 Verdrängungsstrategien
 Erkennung von „dirty“-Elementen
 Daten-Formatierung und Internationalisierung
 View, Model oder ganz anders
18.11.2014 40www.leonso.de
MVC – Was bringt uns das?
 Klare Codestrukturen
 Unabhängigkeit von zugrundeliegender Datenstruktur
 Nutzung in verschiedenen „Clients“
 Browser
 REST-Services
 Periodische Hintergrundagenten (auch das gibt es noch)
 JUnit-Tests
 Wechsel zu alternativen Web-Technologien denkbar
 JSF: Apache MyFaces
 Template Engines
 Keine Angst vor „Notes-ist-tot“ – Diskussion!
18.11.2014 41www.leonso.de
Quellen / Links
 Model View Controller
http://de.wikipedia.org/wiki/Model_View_Controller
 Frostillicus Framework
http://www.notesin9.com/2014/10/10/notesin9-158-intro-to-the-
frostillicus-framework
 MVC & XPages
http://www.slideshare.net/JohnDalsgaard/mvc-and-ibm-xpages-
from-dannotes-in-korsr-dk-28-november-2013
 JAVA in Xpages
http://www.notesin9.com/2013/12/17/notesin9-132-using-java-in-
xpages-part-1/
18.11.2014 42www.leonso.de
Quellen / Links
 Head First Design Patterns
by Eric Freeman, Elisabeth Freeman,
Bert Bates, Kathy Sierra
 ISBN: 0596007124
 Publisher: O'Reilly
 www.it-ebooks.info
18.11.2014 43www.leonso.de
Leonso GmbH
Softwareentwicklung auf Basis von Java, XPages und Notes/Domino
 Fokus auf Sparkassen und Genossenschaftsbanken
 Leonso-Framework mit Schnittstelle zum Sparkassenrechenzentrum
 Produkte
 www.observer4notes.de
Notes-Datenbanken automatisch analysieren (kostenlos)
 www.qrcode4notes.de
QR-Code Generator für Notes
 www.ereignis-manager.de
Ereignissystem der Finanz-Informatik effizient nutzen
 www.leonso-transaktionstool.de
Transaktionswerkzeug für Sparkassen
18.11.2014 44www.leonso.de

Weitere ähnliche Inhalte

PPTX
E2E Tests mit PHP
PDF
Celery - eine asynchrone Task Queue (nicht nur) für Django
PDF
Dojo Und Notes
PDF
Celery eine asynchrone task queue (nicht nur) für django
PDF
Neues von XSLT 2.0 und XPath 2.0
PDF
Nutze die Macht @ IKT-Forum 09 Linz
PPTX
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan Engel
PDF
Drupal 8: TWIG Template Engine
E2E Tests mit PHP
Celery - eine asynchrone Task Queue (nicht nur) für Django
Dojo Und Notes
Celery eine asynchrone task queue (nicht nur) für django
Neues von XSLT 2.0 und XPath 2.0
Nutze die Macht @ IKT-Forum 09 Linz
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan Engel
Drupal 8: TWIG Template Engine

Was ist angesagt? (17)

PDF
Einstieg in Xpath für SEO (Campixx2021)
PPTX
Prototype 1.7
PDF
Einführung in React
PDF
Javascript auf Client und Server mit node.js - webtech 2010
PDF
IPC 2015 Zend Framework 3 Reloaded
PDF
Welches Webframework passt zu mir? (WJAX)
PDF
Python builds mit ant
PDF
Große Applikationen mit AngularJS
PDF
Powerful mostly unknown Javascript-Features
PPS
Java Design Pattern
PDF
Javascript done right
PDF
Schöne neue Welt von HTML5 - WebTech 2010 Mainz 12.10.2010
PPT
PHP: exit
KEY
Objektorientierte Programmierung mit extbase und fluid
PDF
Drupal Entities
PDF
Perl 5 Quiz Chemnitz Edition
Einstieg in Xpath für SEO (Campixx2021)
Prototype 1.7
Einführung in React
Javascript auf Client und Server mit node.js - webtech 2010
IPC 2015 Zend Framework 3 Reloaded
Welches Webframework passt zu mir? (WJAX)
Python builds mit ant
Große Applikationen mit AngularJS
Powerful mostly unknown Javascript-Features
Java Design Pattern
Javascript done right
Schöne neue Welt von HTML5 - WebTech 2010 Mainz 12.10.2010
PHP: exit
Objektorientierte Programmierung mit extbase und fluid
Drupal Entities
Perl 5 Quiz Chemnitz Edition
Anzeige

Andere mochten auch (20)

PDF
Catalogue TPS EMEA - Oct 2014 FINAL
PDF
Güdel Whitepaper tmf march_2014 (1)
PDF
Les avis clients dans l'hôtellerie restauration
PDF
Foro Albacete Smart City: Retos y Oportunidades
PDF
Kingping mag
PDF
Te escribo porque te quiero
PPSX
Emil nolde
PPT
Marketing territoriale, promozione di prodotti e servizi
PDF
Plan de Paz y Convivencia 2013-2016
PDF
Proyecto revista ConBici 2015
PDF
Herbst 2011
PDF
L2 Prestige100 - Mobile IQ 2012
PPTX
La Unión Europea
PDF
Programma Monfalcone
ODT
T2 1 daniblanco.rec2
DOCX
Noticias tecnologias ajuste texto
PPTX
Consumidor 2.0 e as Redes Sociais
PPT
La escuela-franquista-y-enlaces-para-saber-algo-de-la-actual
PDF
Lebenslauf Giuseppina Cè
DOC
Cobardes
Catalogue TPS EMEA - Oct 2014 FINAL
Güdel Whitepaper tmf march_2014 (1)
Les avis clients dans l'hôtellerie restauration
Foro Albacete Smart City: Retos y Oportunidades
Kingping mag
Te escribo porque te quiero
Emil nolde
Marketing territoriale, promozione di prodotti e servizi
Plan de Paz y Convivencia 2013-2016
Proyecto revista ConBici 2015
Herbst 2011
L2 Prestige100 - Mobile IQ 2012
La Unión Europea
Programma Monfalcone
T2 1 daniblanco.rec2
Noticias tecnologias ajuste texto
Consumidor 2.0 e as Redes Sociais
La escuela-franquista-y-enlaces-para-saber-algo-de-la-actual
Lebenslauf Giuseppina Cè
Cobardes
Anzeige

Ähnlich wie Mvc public (20)

PDF
Einführung in Puppet
KEY
Agiles Modellieren mit Domain Specific Languages
PDF
Die Zukunft der Webstandards - Webinale 31.05.2010
PPTX
Legacy Code refaktorisieren
ODP
YAFOWIL - Webformulare in Python ohne Kopfschmerzen
PDF
Testing tools
PDF
Warum ECMAScript 6 die Welt ein Stückchen besser macht
PPTX
Java Batch: Der neue Standard für‘s Stapeln
ODP
Einführung in die webOS Programmierung
PDF
Webapplikationen mit Node.js
ODP
PPT
PPTX
Microservices mit Rust
PDF
JavaServer Faces - Ein schneller Schnelleinstieg
PDF
Mögen die Tests mit dir sein
PPT
Web 2.0 Mit Der Yahoo User Interface Library
PDF
Jpgraph - eine Einführung
PDF
Einführung in React.js und Redux (Web Developer Conference 2017)
KEY
jQueryMobile mit Extbase/Fluid
PDF
Web Entwicklung mit PHP - Teil 1
Einführung in Puppet
Agiles Modellieren mit Domain Specific Languages
Die Zukunft der Webstandards - Webinale 31.05.2010
Legacy Code refaktorisieren
YAFOWIL - Webformulare in Python ohne Kopfschmerzen
Testing tools
Warum ECMAScript 6 die Welt ein Stückchen besser macht
Java Batch: Der neue Standard für‘s Stapeln
Einführung in die webOS Programmierung
Webapplikationen mit Node.js
Microservices mit Rust
JavaServer Faces - Ein schneller Schnelleinstieg
Mögen die Tests mit dir sein
Web 2.0 Mit Der Yahoo User Interface Library
Jpgraph - eine Einführung
Einführung in React.js und Redux (Web Developer Conference 2017)
jQueryMobile mit Extbase/Fluid
Web Entwicklung mit PHP - Teil 1

Mvc public

  • 1. 41. DNUG Konferenz · 11./12. November 2014 · Leipzig www.dnug.de Das Model-View-Controller - Pattern Track Entwicklung 12.11.2014 13:30 – 14:15 Uhr Bert Häßler Leonso GmbH www.leonso.de bert.haessler@leonso.de Slides und DemoDB für diesen Vortrag: www.leonso.de/dnug14
  • 2. Über mich  Bert Häßler, verheiratet, drei Kinder  Diplom-Wirtschaftsinformatiker, Technische Universität Dresden  1998 „Erstkontakt“ mit Notes  Anwendungsentwicklung / Administration  @Formula-Debugger (www.nappz.de/xfl)  seit 2006 EntwicklerCamp, DNUG  OO – Frameworks in Notes  LotusScript (!!!) und Java/XPages  2012 Gründung Leonso GmbH 18.11.2014 2www.leonso.de
  • 3. Agenda  Softwarequalität  MVC – Was ist das?  Model / DAO  View  Controller  MVC in XPages  Beispielimplementation  Der Weg zum eigenen Framework 18.11.2014 3www.leonso.de
  • 4. Softwarequalität – Worauf kommt es an? 18.11.2014 4www.leonso.de Quelle: http://cdn-static.zdnet.com/i/story/61/03/001582/istock_000002369355xsmall.jpg
  • 5. Softwarequalität – Worauf kommt es an? 18.11.2014 5www.leonso.de Funktionalität Effizienz Übertragbarkeit Änderbarkeit Zuverlässigkeit Benutzbarkeit Siehe auch: http://de.wikipedia.org/wiki/Softwarequalität
  • 6. Softwarequalität – Worauf kommt es an? 18.11.2014 6www.leonso.de Funktionalität Effizienz Übertragbarkeit Änderbarkeit Zuverlässigkeit Benutzbarkeit Siehe auch: http://de.wikipedia.org/wiki/Softwarequalität
  • 7. Softwarequalität – Worauf kommt es an? 18.11.2014 7www.leonso.de Funktionalität Effizienz Änderbarkeit Zuverlässigkeit Benutzbarkeit Siehe auch: http://de.wikipedia.org/wiki/Softwarequalität Übertragbarkeit
  • 8. Softwarequalität – Worauf kommt es an? 18.11.2014 8www.leonso.de E. Rauschenbach Deutscher Karikaturpreis 2003
  • 9. Softwarequalität – Worauf kommt es an?  Probleme bei „gewachsenen“ Notes-Anwendungen:  Code kann überall stehen  z.B. Buttons, Events, Agenten, Bibliotheken  Verschiedene Sprachen (Formel, LS, einfache Aktionen, JS)  Redundanz  Ansatz:  Modularisierung 18.11.2014 9www.leonso.de „Frontend“ „Backend“
  • 10. Das MVC-Pattern  Model  View  Controller 18.11.2014 10www.leonso.de Quelle: http://www.casting-power.de/images/kindermodels.jpg
  • 11. Das MVC-Pattern  Model  View  Controller 18.11.2014 11www.leonso.de Quelle: http://upload.wikimedia.org/wikipedia/en/6/6a/View_From_Rock_Cottage_to_Soldiers_Bay.jpg
  • 12. Das MVC-Pattern  Model  View  Controller 18.11.2014 12www.leonso.de Quelle: http://writeups.org/img/fiche/2719a.jpg
  • 13. Das MVC-Pattern  Model  Daten  Geschäftslogik  View  Darstellung  Benutzeraktion  Controller  Steuerung 18.11.2014 13www.leonso.de ModelView Controller
  • 14. MVC-Pattern für „klassische“ XPage 18.11.2014 14www.leonso.de ModelView Controller FacesServlet NSF XPage <HTML> … </HTML> request response
  • 16. Model-Komponente  Class Animal  Einstiegsklasse  „Application“  In diesen Klassen KEINE konkreten Datenbankzugriffe implementieren! 18.11.2014 16www.leonso.de Zoo getAllAnimals() getAnimalByID() createAnimal() … Animal Species Name Description save()
  • 17. Model-Komponente  DAO (Data Access Object)  Implementiert benötigte lesende/schreibende Datenzugriffsmethoden  CRUD (Create, Read, Update, Delete) 18.11.2014 17www.leonso.de Dao saveAnimal(animal) removeAnimal(animal) getAllAnimals() getAnimalByID() …
  • 19. Model-Komponente 18.11.2014 19www.leonso.de public class Zoo implements Serializable { /* Ermitteln aller Tiere in der Datenbasis<br> * Methode wird an aktuell verwendete DAO-Instanz delegiert<br> * nach aussen ist Zoo eine Facade, die die DAO-Ebene verbirgt */ public List<Animal> getAllAnimals() throws Exception { return getDao().getAllAnimals(); } /* Suche nach einem Tier ueber dessen ID */ public Animal getAnimalById(String id) throws Exception { return getDao().getAnimalById(id); } // DAO-Instanz uebernimmt das Lesen und Schreiben der Daten private Dao dao = null; public Dao getDao() throws Exception { if (dao == null) dao = new Dao(this); return dao; } /* erzeugt ein neues Animal-Objekt */ public Animal createAnimal() throws Exception { Animal model = getInstanceOfAnimal(); model.generateNewId(); // Initiale Werte werden gleich hier gesetzt return model; } /* Factory-Methode zum Erstellen einer Animal-Instanz<br> * alle Stellen im gesamten Code, die eine Instanz von Animal brauchen,<br> * sollten dies nicht ueber <code>Animal a = new Animal();</code><br> * implementieren, Factory-Pattern erlaubt flexiblere Klassenbindung! */ public Animal getInstanceOfAnimal() { return new Animal(this); } }
  • 20. Model-Komponente 18.11.2014 20www.leonso.de public class Animal implements Serializable { private static final long serialVersionUID = 1L; private final Zoo app; // die Application als "Mutter" aller Objekte private String id = null; private String species = null; private String name = null; private String description = null; public Animal(Zoo app) { this.app = app; } public String getName() { return name; } public void setName(String name) { this.name = name; } //weitere Getter/Setter ... /** * speichert das Objekt<br> * standardmaessig delegieren wir diese Methode an DAO<br> * Damit kann die Komplexitaet (Arbeitsteilung von Model und DAO) nach * aussen verborgen werden. */ public void save() throws Exception { app.getDao().saveAnimal(this); } }
  • 21. Model-Komponente 18.11.2014 21www.leonso.de public class Dao implements Serializable { private final Zoo app; public Dao(Zoo zoo) { this.app = zoo; } /* Suche nach einem bestimmten Tier */ public Animal getAnimalById(String id) throws Exception { View view = UtilsJsf.getCurrentDatabase().getView("Animals"); Document doc = null; Animal model = null; try { doc = view.getDocumentByKey(id); // Dokument suchen if (doc != null) { model = app.getInstanceOfAnimal(); // leeres Objekt erzeugen readModelValuesFromDoc(doc, model); // Daten übertragen } } finally { recycleDominoObjects(doc, view); // Recycling nicht vergessen } return model; } private void readModelValuesFromDoc(Document doc, Animal model { model.setId(doc.getItemValueString("ID")); model.setName(doc.getItemValueString("Name")); model.setSpecies(doc.getItemValueString("Species")); model.setDescription(doc.getItemValueString("Description")); } }
  • 22. View-Komponente  XPage Animal.xsp  Class AnimalPageBean  Code für Buttons  Databinding 18.11.2014 22www.leonso.de AnimalPageBean clickSave() clickBack() getAnimal()
  • 23. View-Komponente 18.11.2014 23www.leonso.de  XPage Animal.xsp  XPage ohne natives Notes-Databinding!  Binding über PageBean bzw. Model <?xml version="1.0" encoding="UTF-8"?> <xp:view> <h2>Tier</h2> Tierart <xp:inputText value="#{page.animal.species}" /> Name <xp:inputText value="#{page.animal.name}" /> Details <xp:inputTextarea value="#{page.animal.description}" /> <xp:button value="zurück"> <xp:eventHandler event="onclick"> <xp:this.action><![CDATA[#{javascript:page.clickBack()}]]></xp:this.action> </xp:eventHandler> </xp:button> <xp:button value="speichern"> <xp:eventHandler event="onclick"> <xp:this.action><![CDATA[#{javascript:page.clickSave()}]]></xp:this.action> </xp:eventHandler> </xp:button> </xp:view>
  • 24. View-Komponente 18.11.2014 24www.leonso.de public class AnimalPageBean implements Serializable { private final Animal model; // akuell geöffnetes Objekt public AnimalPageBean() throws Exception { String id = UtilsJsf.getParameter("id"); // ManagedBean "app" holen Zoo app =(Zoo) UtilsJsf.resolveVariable("app"); // Ueber die ID in der Datenbank suchen model = app.getAnimalById(id); } // wird fuer Data-Binding benutzt, siehe xsp public Animal getAnimal() { return model; } // Code fuer Button "speichern" public void clickSave() throws Exception { // Validierung und Fehleranzeige muss noch implementiert werden model.save(); redirectToOverview(); } // Code fuer Button "zurueck" public void clickBack() throws Exception { redirectToOverview(); } // zur Uebersichtsseite navigieren private void redirectToOverview() throws IOException { UtilsJsf.sendRedirect("Overview.xsp"); } }
  • 26. View-Komponente  XPage Overview.xsp  Class OverviewPageBean  Code für Buttons  Anzeigefunktionen 18.11.2014 26www.leonso.de OverviewPageBean clickNew() clickRemove(animal) getUrl(animal) getDisplayText(animal)
  • 27. View-Komponente  XPage Overview.xsp 18.11.2014 27www.leonso.de <xp:view> <h2>Das sind unsere Tiere</h2> <xp:repeat value="#{page.allAnimals}" var="animal"> <xp:link text="#{javascript:page.getDisplayText(animal)}" value="#{javascript:page.getUrl(animal)}" /> <xp:button value=“löschen"> <xp:eventHandler event="onclick"> <xp:this.action><![CDATA[#{javascript:page.clickRemove(animal);}]]> </xp:this.action> </xp:eventHandler> </xp:button> </xp:repeat> <xp:button value="neu"> <xp:eventHandler event="onclick"> <xp:this.action><![CDATA[#{javascript:page.clickNew();}]]> </xp:this.action> </xp:eventHandler> </xp:button> </xp:view>
  • 28. View-Komponente 18.11.2014 28www.leonso.de public class OverviewPageBean implements Serializable { /* liefert die Tiere in alphabetischer Reihenfolge */ public List<Animal> getAllAnimals() throws Exception { List<Animal> all = (Zoo) UtilsJsf.resolveVariable("app").getAllAnimals(); // wir erwarten von der App nicht, dass sie uns die Daten schon sortiert hat Collections.sort(all, new Comparator<Animal>() { // wir sortieren hier nach Tierart + Name public int compare(Animal a1, Animal a2) { String sortValue1 = a1.getSpecies() + " " + a1.getName(); String sortValue2 = a2.getSpecies() + " " + a2.getName(); return sortValue1.compareTo(sortValue2); } }); return all; } /* liefert den Anzeigetext fuer ein Tier */ public String getDisplayText(Animal animal) { return animal.getSpecies() + " " + animal.getName(); } /* Code fuer den Button "Loeschen" auf der Seite */ public void clickRemove(Animal model) throws Exception { // hier koennten ggfs. noch Sicherheitsabfragen kommen... model.remove(); } /* generiert die URL fuer ein bestimmtes Model */ public String getUrl(Animal model) { return "Animal.xsp?id=" + model.getId(); } }
  • 29. View-Komponente  XPage ohne natives Notes-Databinding!  Binding über PageBean oder Model  Code so weit wie möglich in PageBean halten  Bessere Wiederverwendung (Vererbung)  Performance  Anzeige von Meldungen  Validierungsfehler  Laufzeitfehler  Erfolgsmeldungen 18.11.2014 29www.leonso.de
  • 31. Controller-Komponente  Realisiert JSF-Lifecycle  PhaseListener  Bean-Management  faces-config.xml  Scope-Bereitstellung  Triggert Events  beforePageLoad(), afterPageLoad(), …  Class ZooPhaseListener 18.11.2014 31www.leonso.de ZooPhaseListener beforePhase()
  • 32. Controller-Komponente 18.11.2014 32www.leonso.de public class ZooPhaseListener implements PhaseListener { private static final long serialVersionUID = 1L; public PhaseId getPhaseId() { // uns interessiert nur beforeRenderResponse return PhaseId.RENDER_RESPONSE; } public void beforePhase(PhaseEvent phase) { // zu jeder XPage gibt es eine passende PageBean, // z.B. Animal.xsp - AnimalPageBean String url = UtilsJsf.getXSPContext().getHistoryUrl(0); // aus '/Animal.xsp' mach 'Animal' String page = Utils.strLeft(Utils.strRight(url, "/"), "."); // jetzt suchen wir die passende PageBean-Klasse... String packageName = "de.leonso.dnug.view"; String className = page + "PageBean"; Class<?> cl = Class.forName(packageName + "." + className); Object pageBean = cl.newInstance(); // ... und als ViewScope-Variable abgespeichert Map<String, Object> viewScope = UtilsJsf.getViewScope(); viewScope.put("page", pageBean); } }
  • 36. Änderungsanforderung  Nicht mehr auf NSF zugreifen, sondern auf andere Datenquelle  z.B. XML-File:  Was ist hier zu tun?  Neue DAO-Klasse schreiben 18.11.2014 36www.leonso.de
  • 39. Was haben wir gesehen?  Einfache XPage-Applikation mit MVC-Struktur  Austauschbarkeit des Datenbasis  Datenmigration durch Implementierung von DAO-Klassen  Nutzung der Modelklassen in verschiedenen „Frontends“ 18.11.2014 39www.leonso.de
  • 40. Der Weg zum eigenen Framework  Abstraktion  Basisklassen für Model, DAO, PageBeans  Validierung  Tendenziell im Model  Und/Oder im View  Caching  Steigerung der Performance !!!  Scope-Festlegung (Application, Session, View)  Verdrängungsstrategien  Erkennung von „dirty“-Elementen  Daten-Formatierung und Internationalisierung  View, Model oder ganz anders 18.11.2014 40www.leonso.de
  • 41. MVC – Was bringt uns das?  Klare Codestrukturen  Unabhängigkeit von zugrundeliegender Datenstruktur  Nutzung in verschiedenen „Clients“  Browser  REST-Services  Periodische Hintergrundagenten (auch das gibt es noch)  JUnit-Tests  Wechsel zu alternativen Web-Technologien denkbar  JSF: Apache MyFaces  Template Engines  Keine Angst vor „Notes-ist-tot“ – Diskussion! 18.11.2014 41www.leonso.de
  • 42. Quellen / Links  Model View Controller http://de.wikipedia.org/wiki/Model_View_Controller  Frostillicus Framework http://www.notesin9.com/2014/10/10/notesin9-158-intro-to-the- frostillicus-framework  MVC & XPages http://www.slideshare.net/JohnDalsgaard/mvc-and-ibm-xpages- from-dannotes-in-korsr-dk-28-november-2013  JAVA in Xpages http://www.notesin9.com/2013/12/17/notesin9-132-using-java-in- xpages-part-1/ 18.11.2014 42www.leonso.de
  • 43. Quellen / Links  Head First Design Patterns by Eric Freeman, Elisabeth Freeman, Bert Bates, Kathy Sierra  ISBN: 0596007124  Publisher: O'Reilly  www.it-ebooks.info 18.11.2014 43www.leonso.de
  • 44. Leonso GmbH Softwareentwicklung auf Basis von Java, XPages und Notes/Domino  Fokus auf Sparkassen und Genossenschaftsbanken  Leonso-Framework mit Schnittstelle zum Sparkassenrechenzentrum  Produkte  www.observer4notes.de Notes-Datenbanken automatisch analysieren (kostenlos)  www.qrcode4notes.de QR-Code Generator für Notes  www.ereignis-manager.de Ereignissystem der Finanz-Informatik effizient nutzen  www.leonso-transaktionstool.de Transaktionswerkzeug für Sparkassen 18.11.2014 44www.leonso.de