Date post: | 16-Apr-2017 |
Category: |
Software |
Upload: | olafur-andri-ragnarsson |
View: | 347 times |
Download: | 0 times |
HÖNNUN OG SMÍÐI HUGBÚNAÐAR 2015L19 Application Architecture
Agenda▪ Architecture Considerations▪ Architecture Decisions▪ Play Framework Exercise
Architecture Considerations
Three Layers▪ Presentation Layer for the User Interface▪ Domain Layer for the domain logic▪ Data Source Layer for the data access
– Separation of concern
Client
Client
Domain Data Source
Presentation Layer▪ Consideration– Separating the Presentation Logic from the Domain Logic– Simple vs. Rich user interface– Should content be editable frequently
▪ Content Management System– View templates with HTML and JS
User Interfaces▪ Clear separation of concerns is important– Define the Presentation Logic– Design the domain layer so the presentation can get the information
needed – Semantics – or the meaning of things is important
– Presentation logic must avoid making assumptions on the domain – the semantics should be a part of the domain• Use Data Transfer Objects to store semantics
Presentation Semantics Domain
Client Types▪ Native OS Applications– Windows, iOS, Android, Linux▪ Embedded– Run inside Web Browsers– Flash, Java Applets▪ Interactive Web Applications– HTML with JavaScript ▪ HTML Presentation in Browsers– Simple HTML
Client Types▪ Mobile is not a client type– It’s just smaller screen– Which 60% people hold vertically▪ People have their phones with them all the time▪ Check their phone about 110 times per day
Different user motivations
Responsive Web Design▪ Web pages that automatically adjust to the screen size
– Should be the default design▪ Problems with RWD
– Does not deal with context– What would a persons be
looking for when using a mobile phone?
– Excuse to avoid apps, when app might be a better choice
App vs. Web
Don’t ask a developer which is better - it’s a management decision
MOBILE WEB MOBILE APPUsing a mobile web browser
Downloaded, runson native hardware
PROS Content is indexable Device independent (almost) Easier/Faster development & update Easier to measure
CONS Connection Dependence Limited hardware integration Bandwidth & browser limited UX
PROS Connection independence Better hardware integration Better graphic performance & UX
CONS Content is not web indexable Device dependence More expensive development & update More complex to measure
Source: moz.com/blog/
Content Delivery▪ Native, Embedded and Interactive Web Apps– Require HTTP API call for dynamic content– For example SOAP, REST with Json or XML▪ HTML Presentation in Browsers– Server side generated
Content Type▪ Static Content such as graphic assets, doesn’t change frequently▪ Editable Content such as text, layout, mashed-up content, editable by content
owners, frequently▪ Dynamic Content stored in database and manipulated by the domain logic
Content Management Systems▪ Content is separated form the Enterprise system– Managed by CMS software with its own database– HTTP API calls for dynamic content from the enterprise system
CLIENT Web Browser
HTML JavaScript CMS
Enterprise Application
HTTP/REST/Json
OPERATOR
Editablecontent
Staticcontent
Dynamiccontent
Staticcontent
Domain Layer▪ Where is the domain logic?– Application Servers– Lightweight Containers
Application Servers▪ Domain Components are deployed on Application Servers– Distributed Multi-tiered Applications– Example:• Web Servers, EJB Servers
Lightweight Containers▪ Assemble components from different projects into a cohesive
application– Wiring is done with “Inversion of Control” - config– Provide life-cycle management of objects– Provide context
Web Browser
Native App
Web Server
Web Layercontrollers
view
Lightweight Container
DomainLayer
Data SourceLayer DB
Data Source Layer▪ How to create the mapping from the domain to the Data Source Layer– Gateways with no domain logic– Records managed with some domain logic– Data Mappers
Data Source Layer▪ Domain Model uses gateway
Domain Layer
Data Source Layer
Object Relational Mapping (ORM)▪ Use a mapping layer to map between objects and tables– Mapping a data representation from an object model to a relational
data model with a SQL-based schema▪ Mapping requires
metadata– XML▪ Authoring and maintaining
metadata is less work than maintaining SQL code
The Big Picture
Client
DomainData
Source
CMS
RESTWeb
Server DB
The Big Picture with Services
Client
DomainData
Source
CMS
RESTWeb
Server DB
DomainData
SourceREST
Web Server DB
Frameworks LibrariesShared Objects
SERVICE
SERVICE
Architecture Decisions
Advice is a dangerous gift
There are no right answers
“Use the advice to prod your thinking, but don’t use it as a replacement for your thinking” — Martin Fowler
Three Layers▪ Presentation Layer for the User Interface▪ Domain Layer for the domain logic▪ Data Source Layer for the data access
– What patterns to use?
Presentation Layer
Domain Data Source
Domain Layer▪ Transaction Script▪ Domain Model▪ Table Module
Domain Layer▪ Transaction Script– Procedural– Encapsulates the logic of each transaction– Works well for systems that are transactional in nature▪ Drawbacks– Does not handle complexity of logic– Code duplications
Domain Layer▪ Domain Model– Works nicely for any type of domain logic– Flexibility in creating an object oriented classes that use
abstractions and polymorphism– Beautiful code▪ Drawbacks– Learning curve – understanding the model– Requires skills– Doesn’t always map easily to relational database
Domain Layer▪ Table Module– Works well for data driven applications– Fits well with relational databases– Requires Record Set functionality▪ Drawbacks– Structured around the database– Needs tooling support, for example Record Set– Can become dependent on the environment
Data Source Layer▪ Data Source for Transaction Script– Fits well to use the Gateway patterns– Row Data Gateway or Table Data Gateway– Depends on the applications– If the transactions are dealing with each row per transactions, then
Row Data Gateway works– If working with tables, Table Data Gateway works
Data Source Layer▪ Data Source for Table Module– Table Module requires good support from Record Set– Table Data Gateway fits this well
Data Source Layer▪ Data Source for Domain Model– If the Domain Model is fairly simple, and maps the database, Active
Record works well– If you want to provide abstraction the gateway patterns become
better choice, Row Data Gateway and Table Data Gateway– If things get more complication and there is need to keep the model
independent from the data source, Data Mapper should be considered
Model View Controller▪ For all types MVC architectural patterns applies▪ Web Frameworks are usually implemented using some sort of
Front Controller pattern▪ Each request has an Action or a Controller▪ Views are handle by Template View
Domain Layer
The Big Picture
Presentation Layer
Service Layer
Data Source
DomainDB
Wehavearelativelysimpledomainlogicthatmapsnicelytothedataschema,andwehavegoodtoolsforRecordSethandling.WhatDomainLayerpatternwouldmakesense?
A) ServiceLayer B) DomainModel C) TransactionScript D) TableModule
QUIZ
Play Framework Exercise
Exercise▪ Design Web Application RuNews– Front page displays RSS news items– Content read with ImportContentProcess – User can sign up and login
Overview
Controller
View
Service Layer
Domain Model
Table Data Gateway
routes ApplicationConext.xml
users
SignupAs a user, I want to be able to sign up
RegistrationFields: name, username, password, email
Validation: all fields are requiredusername must be at least 4 characterspassword must be confirmed (typed in twice)
Play setup
43
▪ Project is created: RuNews– activator new RuNews– Import in IntelliJ IDEA▪ Structure– controllers– is.ru.honn.news– views
The Database▪ Table users
44
CREATE TABLE users ( id int Identity (1, 1) primary key NOT NULL, name varchar(128), username varchar(128) unique, password varchar(128), email varchar(128), )
Application.java
45
package controllers;
import play.*; import play.mvc.*;
import views.html.*;
public class Application extends Controller { public Result index() { return ok(index.render()); } }
index▪ View is views/index.scala.html
▪ Compiled: views/html/index
46
@main("RuNews") { <h2>Registration</h2> <p> Here you can sign up: </p> <p> <a class="btn" href="@routes.SignupController.blank">Sign up</a> </p>}
Routing▪ conf/routes contains the routing information
# Routes# This file defines all application routes (Higher priority routes first) # ~~~~# Home pageGET / controllers.Application.index() # Sign UpGET /signup controllers.SignupController.blank() POST /signup controllers.SignupController.submit() GET /users/:username controllers.UserController.getUser(username: String) GET /userinfo controllers.UserController.blank() # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
RuNews Example▪ User
48
public class User { protected int id; protected String name; protected String username; protected String password; protected String email;
public User() { }
public User(int id, String name, String username, String password, String email) { this.id = id; this.name = name; this.username = username; this.password = password; this.email = email; } ...
RuNews Example▪ UserService is a Service Layer interface
▪ UserServiceData contains the implementation
49
public interface UserService { public int signup(User user); public User login(String username, String password); public User getUser(String username); public void setUserDataGateway(UserDataGateway userDataGateway); }
Adding Domain and Data Layers▪ Domain Layer– Service Layer in service– Domain Model (very simple) in
domain▪ Data Source Layer– Table Data Gateway
Adding Domain and Data Layers▪ app.xml added to conf– data.xml not used
51
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="is.ru.honn.news.service.UserServiceData"> <property name="userDataGateway" ref="userDataGateway"/> </bean> <bean id="userDataGateway" class="is.ru.honn.news.data.UserData"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/> <property name="url" value="jdbc:jtds:sqlserver://hrnem.ru.is:1433"/> <property name="username" value=“###”/> <property name="password" value=“###”/> </bean></beans>
Adding Domain and Data Layers
▪ Table Data Gateway injected into service
52
public class UserServiceData implements UserService { RuDataAccessFactory factory; UserDataGateway userDataGateway;
public UserServiceData() { }
public void setUserDataGateway(UserDataGateway UserDataGateway) { this.userDataGateway = UserDataGateway; }
RuNews Example▪ SignupController is a Controller
53
package controllers; import ...import play.mvc.*; import play.data.*; import views.html.signup; import views.html.summary; import static play.data.Form.form; public class SignupController extends Controller { final static Form<UserRegistration> signupForm = form(UserRegistration.class); protected ApplicationContext ctx = new FileSystemXmlApplicationContext("/conf/app.xml"); public Result blank() { return ok(signup.render(signupForm)); }
RuNews Example▪ SignupController is a Controller
54
public Result submit() { Form<UserRegistration> filledForm = signupForm.bindFromRequest(); if (!"true".equals(filledForm.field("accept").value())) { filledForm.reject("accept", "You must accept the terms and conditions"); } ... if (filledForm.hasErrors()) { return badRequest(signup.render(filledForm)); } else { UserRegistration created = filledForm.get(); UserService service = (UserService) ctx.getBean("userService"); service.signup(created); return ok(summary.render(created)); }}
RuNews Example▪ signup.scala.html is the view
55
@(signupForm: Form[is.ru.honn.news.domain.UserRegistration]) @import helper._ @main("Signup", nav = "signup") { @helper.form(action = routes.SignupController.submit) { <fieldset> <legend>Account informations</legend> @inputText( signupForm("name"), '_label -> "Name", '_help -> "Please enter your name.", '_error -> signupForm.globalError ) @inputText( signupForm("username"), '_label -> "Username", '_help -> "Please choose a valid username.", '_error -> signupForm.globalError )
@inputText( signupForm("email"), '_label -> "Email", '_help -> "Enter a valid email address." )
RuNews Example▪ summary.scala.html displayes the user
56
@(user: is.ru.honn.news.domain.User) @main("Account created!", nav = "signup") { <h2>Your account:</h2> <p>Name: @user.getName()</p> <p>Username: @user.getUsername()</p> <p>Email: @user.getEmail()</p> }
RuNews Example▪ index.scala.html is default “/“ view
▪ All views use @main with title as parameter
57
@main("RuNews") { <h2>Registration</h2> <p> Here you can sign up: </p> <p> <a class="btn" href="@routes.SignupController.blank">Sign up</a> </p>}
RuNews Example▪ main.scala.html is layout template
58
@(title: String = "Welcome", nav: String = "")(content: Html) <!DOCTYPE html> <html> <head> <title>RuNews</title> <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/bootstrap.css")"> <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")"> <link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")"> </head>
RuNews Example▪ main.scala.html is layout template <body> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="@routes.Application.index()">RuNews</a> </div> <div> <ul class="nav navbar-nav"> <li class="@("active".when(nav == "signup"))"> <a href="@routes.SignupController.blank">Sign up</a> </li> <li class="@("active".when(nav == "details"))"> <a href="@routes.UserController.blank">User details</a> </li> </ul> </div> </div> </nav>
RuNews Example▪ main.scala.html is layout template <div class="container"> <div class="content"> <div class="page-header"> <h1>@title</h1> </div> <div class="row"> <div class="span14"> @content </div> </div> </div> <footer> <p> <a href="http://www.playframework.org">www.playframework.org</a> </p> </footer> </div> </body></html>