Mvc public

438 Aufrufe

Veröffentlicht am

0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Keine Downloads
Aufrufe
Aufrufe insgesamt
438
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
6
Aktionen
Geteilt
0
Downloads
1
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Mvc public

  1. 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. 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. 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. 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. 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. 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. 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. 8. Softwarequalität – Worauf kommt es an? 18.11.2014 8www.leonso.de E. Rauschenbach Deutscher Karikaturpreis 2003
  9. 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. 10. Das MVC-Pattern  Model  View  Controller 18.11.2014 10www.leonso.de Quelle: http://www.casting-power.de/images/kindermodels.jpg
  11. 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. 12. Das MVC-Pattern  Model  View  Controller 18.11.2014 12www.leonso.de Quelle: http://writeups.org/img/fiche/2719a.jpg
  13. 13. Das MVC-Pattern  Model  Daten  Geschäftslogik  View  Darstellung  Benutzeraktion  Controller  Steuerung 18.11.2014 13www.leonso.de ModelView Controller
  14. 14. MVC-Pattern für „klassische“ XPage 18.11.2014 14www.leonso.de ModelView Controller FacesServlet NSF XPage <HTML> … </HTML> request response
  15. 15. 18.11.2014 15www.leonso.de Demo
  16. 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. 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() …
  18. 18. Model-Komponente 18.11.2014 18www.leonso.de Model Zoo Animal DB DAO
  19. 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. 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. 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. 22. View-Komponente  XPage Animal.xsp  Class AnimalPageBean  Code für Buttons  Databinding 18.11.2014 22www.leonso.de AnimalPageBean clickSave() clickBack() getAnimal()
  23. 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. 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"); } }
  25. 25. Diagramm Animal.xsp 18.11.2014 25www.leonso.de Model View Animal.xsp AnimalPageBean Zoo Animal DB DAO
  26. 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. 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. 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. 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
  30. 30. Diagramm Overview.xsp 18.11.2014 30www.leonso.de Model View Overview.xsp OverviewPageBean Zoo Animal DB DAO
  31. 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. 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); } }
  33. 33. 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>
  34. 34. 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
  35. 35. Designelemente 18.11.2014 35www.leonso.de
  36. 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
  37. 37. Ä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()
  38. 38. 18.11.2014 38www.leonso.de Demo
  39. 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. 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. 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. 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. 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. 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

×