Models d’aplicacions web Toni Navarrete Enginyeria del Software II – UPF 2006
Problema Les aplicacions basades en JSPs sovint barregen en un únic JSP totes les capes, i per exemple, llegeixen dades d’un formulari, accedeixen a la base de dades, escriuen la resposta, generen missatges d’error... Objectiu: Separar clarament els aspectes de presentació, de l’accés al repositori de dades, i també de la lògica de negoci
Esquema Model 1 L’accés a la BD i part de la lògica de negoci està encapsulada mitjançant una sèrie de classes (JavaBeans) Encara hi ha una barreja de HTML i Java que dificulta la lectura i manteniment: no separació entre lògica i presentació
Esquema Model 2 Un Servlet rep les peticions i instancia una o més classes que seran les que accedeixen a la BD El resultat final del procés és un JSP que s’envia al client Model 2 és en realitat una adaptació del MVC per a sistemes web
Patró d’arquitectura Model-View-Controller (MVC) Podem veure qualsevol sistema amb una divisió en 3 àrees: Controlador (controller), que manega l’entrada que canvia el sistema Exemple: el volant, l’accelerador, la palanca de marxes,... Model, que són les dades o el model del sistema Exemple: el motor, suspensió, transmissió,... Vista (view), que és la presentació de les dades, ja sigui de forma textual, gràfica... Exemple: el comptaquilòmetres, indicadors lluminosos, ... MVC és típic en desenvolupaments GUI A la web, la connexió “stateless” entre servidor i client no permet que un controller notifiqui els canvis al view de forma fàcil, com sí passa en una GUI “típica”
MVC en entorns web (Model 2 o MVC 2) Estructura d’una aplicació web seguint MVC2: Un servlet controller recull les dades necessàries típicament des d’un formulari Hi ha una sèrie de classes (model) que fan una sèrie d’operacions relacionades amb la lògica del negoci, normalment accedint a una BD. És el servlet controller l’encarregat d’instanciar i inicialitzar aquestes classes També el servlet controller centralitza la lògica de dispatching: selecció de la següent vista (un JSP), segons els paràmetres d’entrada i estat de l’aplicació Això fa que hi hagi una separació entre els JSPs de vista i el servlet de control A més, s’evita que les vistes tinguin referències d’altres vistes En resum, les aplicacions són més fàcils de mantenir i d’extendre
MVC en entorns web (Model 2 o MVC 2)
Estructura del controller: Identificació de les operacions a realitzar 3 opcions: Amb una variable oculta de formulari (POST) Amb un paràmetre d’URL (GET) http://host/app/servlet?operacio=1 Amb mappings (definint noms virtuals) <servlet-mapping> <servlet-name>myServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> (típic amb frameworks)
Estructura del controller: Invocació dels mètodes del model Una forma simple: if (op==1) { User u = new User( request.getAttribute("user"), request.getAttribute("pass")); } else if (op==2) { ... } ...
Estructura del controller: Invocació dels mètodes del model Patró Command: Es defineix una classe abstracta Action, per representar una acció, amb un mètode perform, per delegar-hi peticions Es creen tantes subclasses com operacions concretes s’hagin identificat El controller té una taula, on per cada operació, s’indica quina subclasse li correspon
Estructura del controller: Invocació dels mètodes del model // Action.java: public abstract class Action { protected Model model; public Action(Model model) this.model = model; } public abstract String getName(); public abstract Object perform(HttpServletRequest req);
Estructura del controller: Invocació dels mètodes del model // CreateUserAction.java: public class CreateUserAction extends Action { public CreateUserAction(Model model) super(model); } public String getName() return "createUser"; public Object perform(HttpServletRequest req) return model.createUser(req.getAttribute("user"), req.getAttribute("pass"));
Estructura del controller: Invocació dels mètodes del model public class ControllerServlet extends HttpServlet { private HashMap actions; public void init() throws ServletException { actions = new HashMap(); CreateUserAction cua = new CreateUserAction(model); actions.put(cua.getName(), cua); // ... (més accions) } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { // llegir “op” des de la URL // el mètode getOperation() estaria definit a altre lloc String op = getOperation(req.getRequestURL()); // troba i executa l’acció corresponent Action Action action = (Action)actions.get(op); Object result = null; try { result = action.perform(req); } catch (NullPointerException npx) { ... } //determina la següent vista (lògica de distpatching) ...
Estructura del controller: Lògica de dispatching Per despatxar una petició a una vista des del servlet controller s’utilitza: RequestDispatcher d = getServletContext().getRequestDispatcher(URLVista); // retorna un objecte RequestDispatcher //que actua com a un wrapper de la vista (a una URL concreta) //Normalment la vista és un JSP d.forward(request,response); // passa la petició a la vista NOTA: el servlet que fa el forward d’una petició no ha d’escriure res a la sortida, o en cas contrari es produirà una excepció D’aquesta forma el Controller està lligat a la vista (necessitem el path)
Estructura del controller: Lògica de dispatching Per evitar-ho, el dispatcher pot estar separat del servlet controller. El controller delega la selecció de la següent vista en el dispatcher. Patró Dispatcher View També és freqüent que una vista sigui múltiple, en el sentit de què és la composició de vàries vistes Patró Multiple View o Composite View
Dispatcher i CompositeView Model
Dispatcher i CompositeView Model
Observació El controller (Action) és qui típicament crearà les instàncies que calgui del model i li passarà a les vistes Aquestes només criden a mètodes de get d’aquestes instàncies Els mètodes de modificació/inserció típicament es criden des del controller
Estructura del Controller Podem tenir un controller únic per a tot el sistema o un per a cada cas d’ús Per exemple, en un framework com Struts només n’hi ha un únic servlet controller que ens el dóna el propi framework i que és configurable mitjançant fitxers XML Nota: sovint es parla de Front Controller per parlar del servlet controller (és el nom d’un patró J2EE)
Estructura del Model El model de classes de domini és la base per al Model Al disseny cal assignar a les classes les responsabitats de dur a terme les operacions identificades en els SSD: SSD: Diagrama de Seqüència de Sistema, on vegem com cada usuari interactua amb el sistema (representat com si fos un objecte) per a cada cas d’ús concret Hem d’acabar creant els diagrames d’interacció per cada operació del SSD o bé un diagrama per a tot el cas d´ús Utilitzem els patrons GRASP (i altres) per a l’assignació de responsabilitats Patrons GRASP: Patterns of General Principles in Assigning Responsabilities. Els 3 més comuns: Information Expert (o Expert) Creator Controller (ja explicat anteriorment en el context web)
Exemples de diagrama de casos d’ús i SSD per al cas d’ús “Processar venda”
Exemple de diagrama de classes de domini
Objectius de l’assignació de responsabilitats: 1. Baix acoblament Low coupling (baix acoblament) L’acoblament és una mesura de com de fortament un element està connectat a, té coneixement de, o està relacionat amb altres elements Un element amb baix acoblament no depèn de molts altres elements No són desitjables classes amb alt acoblament perquè tenen els següents problemes: Els canvis en classes relacionades forcen canvis locals És difícil d’entendre aïlladament És difícil de reutilitzar, ja que requereix altres classes
Objectius de l’assignació de responsabilitats: 2. Alta cohesió High cohesion (alta cohesió) La cohesió és una mesura de com fortament estan relacionades les responsabilitats que té un element Si un element ha de fer moltes coses diferents entre elles, és poc cohesionat, la qual cosa no és desitjable Els elements amb baixa cohesió tenen els següents problemes: Difícil de comprendre Difícil de reutilitzar Difícil de mantenir Patiran canvis constants
Patrons GRASP: Information Expert Principi general d’assignació de responsabilitats: Assignar la responsabilitat al “Information Expert”, la classe que té la informació necessària per a dur a terme la responsabilitat
Patrons GRASP: Information Expert Un exemple Qui ha de ser el responsable de saber el total d’una venda? Venda sap el total de la venda: Afegim l’operació getTotal() a Venda LíniaVenda sap el subtotal: Afegim l’operació getSubtotal() a LíniaVenda Producte sap el preu del producte getPreu() a Producte
Patrons GRASP: Information Expert Una excepció Una excepció a Information Expert és quan treballem amb bases de dades No convé afegir els mètodes per connectar amb la base de dades a cada una de les classes Això donaria problemes de baixa cohesió i duplicació Millor separar la capa de “negoci” de la capa de la base de dades
Patrons GRASP: Creator Qui és el responsable de crear una nova instància d’una classe? Assignar a la classe B la responsabilitat de crear una instància de la classe A si una o més de les següents condicions es compleix: B agrega objectes A B conté objectes A B guarda objectes A B usa objectes A B té les dades d’inicialització que s’han de passar a A per poder crear una instància (és a dir B és un expert respecte a la creació d’A)
Patrons GRASP: Creator Un exemple Qui ha de ser el responsable de crear una instància de LíniaVenda? Resposta: Venda
Patrons GRASP: Controller Qui ha de ser el responsable de manegar un esdeveniment d’entrada al sistema? Assignar la responsabilitat de rebre o manegar un esdeveniment de sistema a una classe que compleixi una de les següents alternatives: Representa el sistema complet o un subsistema: Patró Façade Representa un controlador d’un escenari d’un cas d’ús. :VendaJFrame Interface Layer System event Domain Layer ???
Patrons GRASP: Controller Un exemple Qui gestiona els esdeveniments de sistema ferNovaVenda introduirExemplar finalitzarVenda controlarPagament Dues opcions: ProcessarVendaController Façade (que gestiona tots els casos d’ús)
Altres patrons GRASP Pure Fabrication Indirection Problema: a vegades Information Expert no és adequat (exemple: Base de dades) Solució: s’assignen un conjunt de responsabilitats a una classe artificial que no representa cap concepte del domini Exemples GoF: Adapter, Command, Strategy ... Indirection Problema: a vegades no ens interessa acoblar dos elements determinats Solució: s’assigna la responsabilitat a un objecte intermedi que media entre elements per tal de què no estiguin directament acoblats La majoria dels Indirection són Pure Fabrications Exemples GoF: Adapter, Bridge, Facade, Observer, Mediator
Estructura del Model És convenient separar els mètodes d’accés a la BD de les classes de domini. En JDO, l’accés a la BD és transparent En EJB, hi ha la possibilitat de què els EJBs d’entitat ho encapsulin tot Solució: Patró Data Access Object (DAO) Un DAO abstreu i encapsula tots els accessos al magatzem de dades. El DAO gestiona la connexió amb el magatzem i les operacions de selecció i modificació de dades 1 DAO per tot el sistema, o per a cada cas d’ús 1 DAO per classe (on tots els DAO hereten d’una classe abstracta DAO general que té els mètodes per establir la connexió a la BD): el més habitual
Estructura del Model: Patró DAO En realitat DAO és un Adapter entre l’objecte de “negoci” i el magatzem de dades
Estructura del Model: DAO i Factory Es pot emprar un Factory que construeixi diferents DAOs en funció del tipus de magatzem de dades: major flexibilitat front a canvis del tipus de magatzem (canvi de gestor o de paradigma)
Model 2 web application frameworks Els anomentats web application frameworks (o web-tier frameworks) simplifiquen la implementació d’aplicacions basades en MVC2: J2EE BluePrints Web Application Framework (WAF) Apache Structs, és el més conegut JavaServer Faces Inclouen un servlet controller configurable, i aporten unes classes abstractes que poden ser exteses per manegar la lògica de dispatching Alguns frameworks inclouen un llenguatge de macros o altres eines per simplificar la construcció de l’aplicació
Unes notes sobre arquitectura... Arquitectura basada en capes Capa de presentació Capa de “negoci” Capa de dades No confondre les capes d’arquitectura amb la separació entre model-vista-controlador Esquemes d’arquitectura general de l’aplicació: D’una capa De dues capes De tres capes “Mitja capa” (cas típic: 2,5 capes)
Arquitectura d’una capa Browser Capa de presentació Capa de negoci Capa de dades File system Web server
Arquitectura de dues capes Browser HTTP Capa de presentació Capa de negoci Web server+CGI o Web server+servlet engine JDBC Capa de dades File system Base de dades
Arquitectura de tres capes Browser HTTP Capa de presentació Web server CORBA/RMI/ Web Services/... Capa de negoci Application server: components distribuïts JDBC Capa de dades File system Base de dades
Arquitectura de dues capes i mitja Browser JavaScript HTML dinàmic Capa de presentació HTTP Web server+servlet engine JDBC File system Capa de dades
Factors de determinació d’arquitectures de dues o tres capes Complexitat de l’aplicació Mantenibilitat Aplicacions de 2 capes Aplicacions de 3 capes Pressió de la planificació Experiència de l’equip de desenvolupament
Algunes particularitats de les aplicacions web Aspectes tecnológics de l’ES per web Tecnologies HTML Llenguatges de script Cookies XML CGIs, NSAPI, ISAPI, Servlets Pàgines amb codi incrustat (ASP, JSP, PHP) EJB i altres models de components Web-services Arquitectura Models de capes Servidors web Servidors d’aplicacions Clients thick i clients thin
Se li dóna molta importància a la interfície d’usuari Algunes particularitats de les aplicacions web Especificació de requeriments Se sol basar en un model de casos d’ús (se solen utilitzar mètodes use-case driven) Se li dóna molta importància a la interfície d’usuari Existeixen mètodes específics centrats en la interfície La navegació pot ser un aspecte important de la interfície. Hi ha mètodes centrats en la navegació Es habitual utilitzar prototipus no funcionals de la interfície (amb pàgines estàtiques o imatges)
Cal decidir el model de l’arquitectura Algunes particularitats de les aplicacions web Especificació de requeriments Cal decidir el model de l’arquitectura nombre de capes clients thin o thick
Algunes particularitats de les aplicacions web Disseny Decidir la tecnologia per a les vistes: Pàgina estàtica HTML Swing (en applets) Servlets JSP Usant XML/XSL ... Extensió UML per aplicacions web
Algunes particularitats de les aplicacions web Estensió web d’UML Estereotips per modelar Server Page Client Page Form Frameset Target ClientScript Object Web Page ASP Page JSP Page Servlet Script Library
Algunes particularitats de les aplicacions web Estensió web d’UML Algunes particularitats de les aplicacions web Estensió web d’UML. Exemples d’estereotips Pàgina web Formulari Script de client Llibrería de scripts JSP Servlet
Algunes particularitats de les aplicacions web Estensió web d’UML Algunes particularitats de les aplicacions web Estensió web d’UML. Un exemple
Algunes particularitats de les aplicacions web Disseny Decidir la tecnologia per a les classes entitat (persistència) JDBC, EJB amb BMP o CMP, JDO, altres frameworks ... Gestor de connexions a la BD (si és el cas): Un DAO global Un DAO per classe Controller: servlet (frameworks MVC com Struts o Java Server Faces) Views: JSP
Algunes particularitats de les aplicacions web Proves El model de contingut de l’aplicació web és revisat per descobrir errors El model de disseny per l’aplicació web és revisat per descobrir errors de navegació S’apliquen proves d’unitat als components de procés seleccionats i a les pàgines web Es construeix l’arquitectura, es realitzen les proves d’integració L’aplicació web ensamblada es prova per a aconseguir una funcionalitat global i un contingut L’aplicació web s’implementa en una varietat de configuracions diferents d’entorns; cal comprovar la compatibilitat amb cada configuració L’aplicació web es prova amb una població d’usuaris finals controlada i monitoritzada
Més informació: patrons J2EE J2EE Patterns Catalog http://java.sun.com/blueprints/patterns/catalog.html Core J2EE Patterns. Best Practices and Design Strategies http://www.corej2eepatterns.com/index.htm J2EE Best Practices http://www.middleware-company.com/ Designing Enterprise Applications with the J2EETM Platform, Second Edition http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/index.html
Més informació: Struts Web d’Apache Struts http://struts.apache.org/ Curs de Struts a coreservlets.com http://courses.coreservlets.com/Course-Materials/struts.html Llibre (en castellà) Chuck Cavanness: Jakarta Struts. Anaya Multimedia - O’Reilly, 2005
Més informació: ES per web Pressman: Ingeniería del Software, un enfoque práctico. 5ª edición. McGraw Hill, 2002.