SlideShare ist ein Scribd-Unternehmen logo
1 von 39
Downloaden Sie, um offline zu lesen
MatteoVaccari
matteo.vaccari@xpeppers.com
(cc) Alcuni diritti riservati
Programmazione web
libera dai framework
1mercoledì 10 novembre 2010
Chi son io?
• Ho sviluppato applicazioni web in PHP, Java,
Ruby (on Rails)
• In particolare Rails,Wicket, Spring, Hibernate
• Insegno Applicazioni Web I e II all’Insubria
• Lavoro in XPeppers come consulente e
mentor
2mercoledì 10 novembre 2010
Perché usiamo i
framework?
3mercoledì 10 novembre 2010
Davvero risparmiamo
tempo?
• Dibattere su quale framework sia il migliore
• Imparare a usare il framework
• Capire come si fa a fare X
• Seguire le mailing list
• Aggiornare l’app all’ultima versione del FW
4mercoledì 10 novembre 2010
E i rischi?
• Performance insufficiente?
• Contiene errori che non sappiamo
correggere? Errori intermittenti?
• Si scopre che non supporta la feature X
• E se poi il nostro framework passa di
moda?
5mercoledì 10 novembre 2010
# controllers/employees_controller.rb
class EmployeesController < ApplicationController
def index
@employees = Employee.find(:all)
end
end
# views/employees/index.html.erb
<table>
<% for employee in @employees %>
<tr>
<td><%= employee.name %></td>
</tr>
<% end %>
</table>
# Missing objects....(pseudocodice)
controller = router.find_controller(request.uri) # un EmployeeController
action = router.find_action(request.uri) # "index"
controller.send(action)
# e ancora...
stream = OutputStream.new
view = View.new("employees/index.html.erb")
view.render_on(stream)
Gli oggetti scomparsi
6mercoledì 10 novembre 2010
Davvero, perché usiamo
i framework?
7mercoledì 10 novembre 2010
I framework
incrementano il costo,
la complessità e il
rischio
8mercoledì 10 novembre 2010
Usa la forza degli
oggetti, Luke!
9mercoledì 10 novembre 2010
// Qui ficcanasiamo troppo
cane.getCorpo().getCoda().scodinzola();
// Tell, don’t ask!
cane.esprimiContentezza();
Programmare a oggetti
Steve Freeman et al.: Mock Roles, not Objects
10mercoledì 10 novembre 2010
@Entity
@Name("user")
@Table(name="users")
public class User implements Serializable {
private String username;
private String password;
private String name;
public User(String name, String password, String username) {
this.name = name;
this.password = password;
this.username = username;
}
public User() {}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
// ...
Questo non è un oggetto...
è una struttura dati!
11mercoledì 10 novembre 2010
Il lato oscuro del DDD
E di Hibernate, JPA, EJB3...
12mercoledì 10 novembre 2010
Il domain model si riduce a
uno
schema dei dati
Procedure (non oggetti)
13mercoledì 10 novembre 2010
Contro la paura
impariamo:
• A programmare bene. A oggetti.
• Gli standard di base: HTTP, URI, HTML, CSS
• I nostri strumenti: linguaggio, web server,
database
14mercoledì 10 novembre 2010
Browser
Web
Server
My App Database
15mercoledì 10 novembre 2010
Browser
Web
Server
My App Database
ConcurrencyConcurrency
16mercoledì 10 novembre 2010
Browser
Web
Server
My App Database
State State
ConcurrencyConcurrency
17mercoledì 10 novembre 2010
Una servlet come
punto di partenza
public class MyOnlyServlet extends HttpServlet {
	 @Override
	 protected void service(HttpServletRequest request,
HttpServletResponse response) throws ... {
	 	 MainPage page = new MainPage();
	 	 page.service(request.getParameter("foo"));
	 }
}
18mercoledì 10 novembre 2010
Usare la dependency
injection
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOE
	 Connection connection = new JndiDataSource("java:comp/env/jdbc/CourseDB")
.getConnection();
	 CourseCatalogue courses = new JdbcCourseCatalogue(connection);
	 CoursesApplication app = new CoursesApplication(courses);
	 app.service(request, response);
}
19mercoledì 10 novembre 2010
The database is your friend
:o)
20mercoledì 10 novembre 2010
The database is your friend
:o)
• Transazioni
• Concorrenza
• Ricerche
We don’t need no EJBs!
21mercoledì 10 novembre 2010
Una transazione HTTP
==
Una transazione DB
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) th
	 Connection connection = null;
	 try {
	 DataSource source = new JndiDataSource("java:comp/env/jdbc/CourseDB");
connection = source.getConnection();
	 	 CourseCatalogue courses = new JdbcCourseCatalogue(connection);
	 	 CoursesApplication app = new CoursesApplication(courses);
	 	 app.service(request, response);
	 	 connection.commit();
	 } catch (Exception e) {
	 	 rollback(connection);
	 	 throw new ServletException(e);
	 } finally {
	 	 close(connection);
	 }
}
22mercoledì 10 novembre 2010
Una semplice
interfaccia al DB
public interface Database {
Map<String, Object> selectOneRow(String sql, Object ... params);
void execute(String sql, Object ... params);
List<Map<String, Object>> selectMultipleRows(String sql, Object ... params);
}
23mercoledì 10 novembre 2010
public class DatabaseCarrierRepository implements CarrierRepository {
final Database database;
@Override
public List<Channel> findAllChannels(CarrierView view) {
String query = "SELECT ID, NAME FROM CHANNEL ORDER BY NAME";
List<Map<String, Object>> rawChannels = database.selectMultipleRows(query);
List<Channel> channels = new ArrayList<Channel>();
for (Map<String, Object> map : rawChannels) {
Channel channel = new Channel(map.get("NAME").toString(),
((BigDecimal) map.get("ID")).intValue());
channels.add(channel);
}
return channels;
}
24mercoledì 10 novembre 2010
Il “routing” delle pagine
// GeometryServlet.service()
protected void service(HttpServletRequest request, HttpServletResponse response)
	 List<PageComponent> pages = new ArrayList<PageComponent>();
	 pages.add(new WelcomePage());
	 pages.add(new SquareAreaPage());
	 pages.add(new TriangleAreaPage());
	 pages.add(new SphereVolumePage());
	 GeometryApplication app = new GeometryApplication(pages);
	 app.service(request, response);	
}
// GeometryApplication.service()
public void service(HttpServletRequest request, HttpServletResponse response) thr
	 for (PageComponent component : components) {
	 	 if (component.wantsToHandle(request)) {
	 	 	 response.getWriter().print(component.toHtml());
	 	 	 return;
	 	 }
	 }	 	
	 response.sendError(404);
}
25mercoledì 10 novembre 2010
Project automation
http://technicbricks.blogspot.com/
26mercoledì 10 novembre 2010
Quick feedback
#!/bin/bash
# script/server.sh
# start app on port 8080
ant war || exit 1
java -jar lib/winstone-0.9.10.jar --warfile target/*.war $*
27mercoledì 10 novembre 2010
Server up in < 2s
$ script/server.sh
Buildfile: /Users/matteo/work/conferences/webtech/projectPortfolio/build.xml
prepare:
compile:
war:
BUILD SUCCESSFUL
Total time: 0 seconds
[Winstone 2010/11/10 00:18:04] - Beginning extraction from war file
[Winstone 2010/11/10 00:18:04] - No webapp lib folder found - /private/var/folders/Cb/CbG3BVbs
[Winstone 2010/11/10 00:18:04] - HTTP Listener started: port=8080
[Winstone 2010/11/10 00:18:04] - AJP13 Listener started: port=8009
[Winstone 2010/11/10 00:18:04] - Winstone Servlet Engine v0.9.10 running: controlPort=disabled
28mercoledì 10 novembre 2010
Dominare il database
#!/bin/bash
# script/create_databases.sh
# create and populate databases for development and test environments
echo 'Drop databases...'
mysqladmin -uroot --force drop db
mysqladmin -uroot --force drop db_test
echo 'Create databases...'
mysqladmin -uroot create db
mysqladmin -uroot create db_test
echo "grant all on db.* to db@localhost identified by 'db';" | mysql -uroot
echo "grant all on db_test.* to db@localhost identified by 'db';" | mysql -uroot
echo 'Build schema...'
cat db/*.sql | mysql -udb db -pdb
cat db/*.sql | mysql -udb db_test -pdb
echo 'Populate development...'
mysql -udb -pdb db < db/populate_db.sql
echo 'Done!'
29mercoledì 10 novembre 2010
Incremental SQL scripts
$ ls
001_create_contents.sql
002_add_columns_to_users.sql
003_add_filtri_per_operatore.sql
004_add_custom_fields.sql
005_add_publisher_issues.sql
006_add_columns_content.sql
007_add_media_parade_things.sql
008_alter_publication_issue.sql
009_create_audit_log.sql
010_create_phones.sql
011_add_media_parade_codes.sql
012_add_media_partner_codes.sql
013_add_alias_services.sql
014_delete_custom_field_name_fk_from_user.sql
015_add_indexes.sql
016_add_more_indexes.sql
...
alter table contents
add pull_downloads int,
add ivr_downloads int;
update schema_info set version = 6;
30mercoledì 10 novembre 2010
Generare HTML
public class Course {
// ...
public void renderOn(CourseView view) {
	 view.setCourseTitle(title);
	 view.setCourseDescription(description);
}
// ...
}
31mercoledì 10 novembre 2010
Testable
	 @Test
	 public void rendersCourseView() throws Exception {
	 	 Course course = new Course("A Title", "A Description");
	 	 FakeCourseView view = new FakeCourseView();
	 	
	 	 course.renderOn(view);
	 	
	 	 assertEquals("A Title - A Description", view.toHtml());
	 }
32mercoledì 10 novembre 2010
Generare HTML: template
class FreemarkerCourseView implements CourseView {
	 Map context = new HashMap();
	 public void setCourseTitle(String title) {
	 	 context.put("title", title);
	 }
	
	 public void renderOn(Writer writer) throws IOException, TemplateException {
	 	 Configuration configuration = new Configuration();
	 	 Template template = configuration.getTemplate("coursePage.ftl");
	 	 template.process(context, writer);
	 }
	 public String toHtml() {
	 	 StringWriter writer = new StringWriter();
	 	 renderOn(writer);
	 	 return writer.toString();
	 }
}
33mercoledì 10 novembre 2010
Generare HTML: oggetti
class ObjectOrientedCourseView implements CourseView {
	 private String title;
	 private String description;
	 public void setCourseTitle(String title) {
	 	 this.title = title;
	 }
	
	 public void setCourseDescription(String description) {
	 	 this.description = description;
	 }
	
	 public void renderOn(Writer writer) throws IOException, TemplateException {
	 	 HtmlDivision div = new HtmlDivision().with("id", "course");
	 	 div.add(new Display(title));
	 	 div.add(new TextBlock(description));
	 	 div.renderOn(writer);
	 }
}
34mercoledì 10 novembre 2010
Blocchi da costruzione
public class Display implements HtmlElement {
	 private String text;
	 public Display(String text) {
	 	 this.text = text;
	 }
	 public String toHtml() {
	 	 return format("<p class='display'>%s</p>", text);
	 }
}
35mercoledì 10 novembre 2010
Altri blocchi
public class Link implements HtmlElement {
	 private final String url;
	 private final String label;
	 private boolean opensInNewWindow;
	 public Link(String url, String label) {
	 	 this.url = url;
	 	 this.label = label;
	 }
	 public String toHtml() {
	 	 String attributes = opensInNewWindow ? "target='_blank'" : "";
	 	 return format("<a href='%s' %s>%s</a>", url, attributes, label);
	 }
	 public void setOpensInNewWindow() {
	 	 opensInNewWindow = true;
	 }
}
36mercoledì 10 novembre 2010
Anche form e layout
public Page getTemperatureConversionPage(Map<String, String> parameters) {
	 Display display = new Display(converter.convert(parameters.get("temp")));
	 Form form = new Form("/", "get"));
	 form.add(new TextField("Temperatura:", "temperature", parameters.get("temp")));
	 form.add(new SubmitButton("Converti"));
	 Page page = new Page();
	 page.addStylesheet("ourstyle");
	 page.addDisplay(display);
	 page.addForm(form);
	 return page;
}
37mercoledì 10 novembre 2010
In conclusione?
• Usa la forza degli oggetti
• Sfrutta i tuoi strumenti
• Sii consapevole delle conseguenze
dei framework
38mercoledì 10 novembre 2010
Grazie dell’attenzione!
Extreme Programming:
sviluppo e mentoring
39mercoledì 10 novembre 2010

Weitere ähnliche Inhalte

Andere mochten auch

Michelle Hathaway Mastery Timeline
Michelle Hathaway Mastery TimelineMichelle Hathaway Mastery Timeline
Michelle Hathaway Mastery TimelineMichelle Hathaway
 
Loosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain modelLoosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain modelFrancesca1980
 
Simple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computingSimple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computingFrancesca1980
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascriptFrancesca1980
 
ΑΠΟΓΡΑΦΗ
ΑΠΟΓΡΑΦΗΑΠΟΓΡΑΦΗ
ΑΠΟΓΡΑΦΗsteverz
 
ΚΑΤΑΣΤΑΤΙΚΟ
ΚΑΤΑΣΤΑΤΙΚΟΚΑΤΑΣΤΑΤΙΚΟ
ΚΑΤΑΣΤΑΤΙΚΟsteverz
 
ΟΚΤΩΒΡΙΟΣ 2010
ΟΚΤΩΒΡΙΟΣ 2010ΟΚΤΩΒΡΙΟΣ 2010
ΟΚΤΩΒΡΙΟΣ 2010steverz
 
Photo presentation
Photo presentationPhoto presentation
Photo presentationKalliopi1
 
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScriptPhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScriptFrancesca1980
 
Writing cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI BindingsWriting cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI BindingsFrancesca1980
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascriptFrancesca1980
 
Trabajo en equipo abierto 4hrs 23 noviembre tlc
Trabajo en equipo abierto 4hrs 23 noviembre tlcTrabajo en equipo abierto 4hrs 23 noviembre tlc
Trabajo en equipo abierto 4hrs 23 noviembre tlcCinet México
 

Andere mochten auch (19)

Michelle Hathaway Mastery Timeline
Michelle Hathaway Mastery TimelineMichelle Hathaway Mastery Timeline
Michelle Hathaway Mastery Timeline
 
Loosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain modelLoosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain model
 
Java scriptpatterns
Java scriptpatternsJava scriptpatterns
Java scriptpatterns
 
Simple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computingSimple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computing
 
Advanced JQuery
 Advanced JQuery Advanced JQuery
Advanced JQuery
 
Map meshup
Map meshupMap meshup
Map meshup
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascript
 
ΑΠΟΓΡΑΦΗ
ΑΠΟΓΡΑΦΗΑΠΟΓΡΑΦΗ
ΑΠΟΓΡΑΦΗ
 
ΚΑΤΑΣΤΑΤΙΚΟ
ΚΑΤΑΣΤΑΤΙΚΟΚΑΤΑΣΤΑΤΙΚΟ
ΚΑΤΑΣΤΑΤΙΚΟ
 
ΟΚΤΩΒΡΙΟΣ 2010
ΟΚΤΩΒΡΙΟΣ 2010ΟΚΤΩΒΡΙΟΣ 2010
ΟΚΤΩΒΡΙΟΣ 2010
 
Java scriptpatterns
Java scriptpatternsJava scriptpatterns
Java scriptpatterns
 
Finggggg
FingggggFinggggg
Finggggg
 
Photo presentation
Photo presentationPhoto presentation
Photo presentation
 
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScriptPhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
 
Writing cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI BindingsWriting cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI Bindings
 
Open Education Resources
Open Education ResourcesOpen Education Resources
Open Education Resources
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascript
 
Iss
IssIss
Iss
 
Trabajo en equipo abierto 4hrs 23 noviembre tlc
Trabajo en equipo abierto 4hrs 23 noviembre tlcTrabajo en equipo abierto 4hrs 23 noviembre tlc
Trabajo en equipo abierto 4hrs 23 noviembre tlc
 

Ähnlich wie Programmazione web libera dai framework

Py a6 python-database
Py a6 python-databasePy a6 python-database
Py a6 python-databaseMajong DevJfu
 
Sviluppo web dall'antichità all'avanguardia e ritorno
Sviluppo web  dall'antichità all'avanguardia e ritornoSviluppo web  dall'antichità all'avanguardia e ritorno
Sviluppo web dall'antichità all'avanguardia e ritornolordarthas
 
SQLite in Xamarin.Forms
SQLite in Xamarin.FormsSQLite in Xamarin.Forms
SQLite in Xamarin.FormsGuido Magrin
 
Write less do more...with jQuery
Write less do more...with jQueryWrite less do more...with jQuery
Write less do more...with jQueryXeDotNet
 
Introduzione a Node.js
Introduzione a Node.jsIntroduzione a Node.js
Introduzione a Node.jsMichele Capra
 
E suap - tecnologie client
E suap - tecnologie client E suap - tecnologie client
E suap - tecnologie client Sabino Labarile
 
Matteo Bicocchi - Introducing HTML5
Matteo Bicocchi - Introducing HTML5Matteo Bicocchi - Introducing HTML5
Matteo Bicocchi - Introducing HTML5Pietro Polsinelli
 
Abusing HTML 5 Client-side Storage
Abusing HTML 5 Client-side StorageAbusing HTML 5 Client-side Storage
Abusing HTML 5 Client-side Storageameft
 
WeWantWeb - WCF Data Services
WeWantWeb - WCF Data ServicesWeWantWeb - WCF Data Services
WeWantWeb - WCF Data ServicesDomusDotNet
 
Sviluppo di servizi REST per Android - Luca Masini
Sviluppo di servizi REST per Android - Luca Masini Sviluppo di servizi REST per Android - Luca Masini
Sviluppo di servizi REST per Android - Luca Masini Whymca
 
SVILUPPO DI SERVIZI REST PER ANDROID
SVILUPPO DI SERVIZI REST PER ANDROIDSVILUPPO DI SERVIZI REST PER ANDROID
SVILUPPO DI SERVIZI REST PER ANDROIDLuca Masini
 
breve introduzione a node.js
breve introduzione a node.jsbreve introduzione a node.js
breve introduzione a node.jsnetmeansnet
 
September 2010 - Gatein
September 2010 - GateinSeptember 2010 - Gatein
September 2010 - GateinJBug Italy
 
AngularJS: server communication
AngularJS: server communicationAngularJS: server communication
AngularJS: server communicationVittorio Conte
 

Ähnlich wie Programmazione web libera dai framework (20)

#dd12 Applicazioni a tre voci (Android e Domino)
#dd12 Applicazioni a tre voci (Android e Domino)#dd12 Applicazioni a tre voci (Android e Domino)
#dd12 Applicazioni a tre voci (Android e Domino)
 
Wcf data services
Wcf data servicesWcf data services
Wcf data services
 
Py a6 python-database
Py a6 python-databasePy a6 python-database
Py a6 python-database
 
Sviluppo web dall'antichità all'avanguardia e ritorno
Sviluppo web  dall'antichità all'avanguardia e ritornoSviluppo web  dall'antichità all'avanguardia e ritorno
Sviluppo web dall'antichità all'avanguardia e ritorno
 
SQLite in Xamarin.Forms
SQLite in Xamarin.FormsSQLite in Xamarin.Forms
SQLite in Xamarin.Forms
 
Write less do more...with jQuery
Write less do more...with jQueryWrite less do more...with jQuery
Write less do more...with jQuery
 
Introduzione a node.js
Introduzione a node.jsIntroduzione a node.js
Introduzione a node.js
 
Introduzione a Node.js
Introduzione a Node.jsIntroduzione a Node.js
Introduzione a Node.js
 
E suap - tecnologie client
E suap - tecnologie client E suap - tecnologie client
E suap - tecnologie client
 
DDive - 8.5.2 Xpages - L'evoluzione continua
DDive - 8.5.2 Xpages - L'evoluzione continuaDDive - 8.5.2 Xpages - L'evoluzione continua
DDive - 8.5.2 Xpages - L'evoluzione continua
 
Javascript
JavascriptJavascript
Javascript
 
Matteo Bicocchi - Introducing HTML5
Matteo Bicocchi - Introducing HTML5Matteo Bicocchi - Introducing HTML5
Matteo Bicocchi - Introducing HTML5
 
Abusing HTML 5 Client-side Storage
Abusing HTML 5 Client-side StorageAbusing HTML 5 Client-side Storage
Abusing HTML 5 Client-side Storage
 
WeWantWeb - WCF Data Services
WeWantWeb - WCF Data ServicesWeWantWeb - WCF Data Services
WeWantWeb - WCF Data Services
 
Sviluppo di servizi REST per Android - Luca Masini
Sviluppo di servizi REST per Android - Luca Masini Sviluppo di servizi REST per Android - Luca Masini
Sviluppo di servizi REST per Android - Luca Masini
 
SVILUPPO DI SERVIZI REST PER ANDROID
SVILUPPO DI SERVIZI REST PER ANDROIDSVILUPPO DI SERVIZI REST PER ANDROID
SVILUPPO DI SERVIZI REST PER ANDROID
 
breve introduzione a node.js
breve introduzione a node.jsbreve introduzione a node.js
breve introduzione a node.js
 
September 2010 - Gatein
September 2010 - GateinSeptember 2010 - Gatein
September 2010 - Gatein
 
AngularJS: server communication
AngularJS: server communicationAngularJS: server communication
AngularJS: server communication
 
Html5
Html5Html5
Html5
 

Programmazione web libera dai framework

  • 1. MatteoVaccari matteo.vaccari@xpeppers.com (cc) Alcuni diritti riservati Programmazione web libera dai framework 1mercoledì 10 novembre 2010
  • 2. Chi son io? • Ho sviluppato applicazioni web in PHP, Java, Ruby (on Rails) • In particolare Rails,Wicket, Spring, Hibernate • Insegno Applicazioni Web I e II all’Insubria • Lavoro in XPeppers come consulente e mentor 2mercoledì 10 novembre 2010
  • 4. Davvero risparmiamo tempo? • Dibattere su quale framework sia il migliore • Imparare a usare il framework • Capire come si fa a fare X • Seguire le mailing list • Aggiornare l’app all’ultima versione del FW 4mercoledì 10 novembre 2010
  • 5. E i rischi? • Performance insufficiente? • Contiene errori che non sappiamo correggere? Errori intermittenti? • Si scopre che non supporta la feature X • E se poi il nostro framework passa di moda? 5mercoledì 10 novembre 2010
  • 6. # controllers/employees_controller.rb class EmployeesController < ApplicationController def index @employees = Employee.find(:all) end end # views/employees/index.html.erb <table> <% for employee in @employees %> <tr> <td><%= employee.name %></td> </tr> <% end %> </table> # Missing objects....(pseudocodice) controller = router.find_controller(request.uri) # un EmployeeController action = router.find_action(request.uri) # "index" controller.send(action) # e ancora... stream = OutputStream.new view = View.new("employees/index.html.erb") view.render_on(stream) Gli oggetti scomparsi 6mercoledì 10 novembre 2010
  • 7. Davvero, perché usiamo i framework? 7mercoledì 10 novembre 2010
  • 8. I framework incrementano il costo, la complessità e il rischio 8mercoledì 10 novembre 2010
  • 9. Usa la forza degli oggetti, Luke! 9mercoledì 10 novembre 2010
  • 10. // Qui ficcanasiamo troppo cane.getCorpo().getCoda().scodinzola(); // Tell, don’t ask! cane.esprimiContentezza(); Programmare a oggetti Steve Freeman et al.: Mock Roles, not Objects 10mercoledì 10 novembre 2010
  • 11. @Entity @Name("user") @Table(name="users") public class User implements Serializable { private String username; private String password; private String name; public User(String name, String password, String username) { this.name = name; this.password = password; this.username = username; } public User() {} public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getName() { return name; } // ... Questo non è un oggetto... è una struttura dati! 11mercoledì 10 novembre 2010
  • 12. Il lato oscuro del DDD E di Hibernate, JPA, EJB3... 12mercoledì 10 novembre 2010
  • 13. Il domain model si riduce a uno schema dei dati Procedure (non oggetti) 13mercoledì 10 novembre 2010
  • 14. Contro la paura impariamo: • A programmare bene. A oggetti. • Gli standard di base: HTTP, URI, HTML, CSS • I nostri strumenti: linguaggio, web server, database 14mercoledì 10 novembre 2010
  • 17. Browser Web Server My App Database State State ConcurrencyConcurrency 17mercoledì 10 novembre 2010
  • 18. Una servlet come punto di partenza public class MyOnlyServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ... { MainPage page = new MainPage(); page.service(request.getParameter("foo")); } } 18mercoledì 10 novembre 2010
  • 19. Usare la dependency injection @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOE Connection connection = new JndiDataSource("java:comp/env/jdbc/CourseDB") .getConnection(); CourseCatalogue courses = new JdbcCourseCatalogue(connection); CoursesApplication app = new CoursesApplication(courses); app.service(request, response); } 19mercoledì 10 novembre 2010
  • 20. The database is your friend :o) 20mercoledì 10 novembre 2010
  • 21. The database is your friend :o) • Transazioni • Concorrenza • Ricerche We don’t need no EJBs! 21mercoledì 10 novembre 2010
  • 22. Una transazione HTTP == Una transazione DB @Override protected void service(HttpServletRequest request, HttpServletResponse response) th Connection connection = null; try { DataSource source = new JndiDataSource("java:comp/env/jdbc/CourseDB"); connection = source.getConnection(); CourseCatalogue courses = new JdbcCourseCatalogue(connection); CoursesApplication app = new CoursesApplication(courses); app.service(request, response); connection.commit(); } catch (Exception e) { rollback(connection); throw new ServletException(e); } finally { close(connection); } } 22mercoledì 10 novembre 2010
  • 23. Una semplice interfaccia al DB public interface Database { Map<String, Object> selectOneRow(String sql, Object ... params); void execute(String sql, Object ... params); List<Map<String, Object>> selectMultipleRows(String sql, Object ... params); } 23mercoledì 10 novembre 2010
  • 24. public class DatabaseCarrierRepository implements CarrierRepository { final Database database; @Override public List<Channel> findAllChannels(CarrierView view) { String query = "SELECT ID, NAME FROM CHANNEL ORDER BY NAME"; List<Map<String, Object>> rawChannels = database.selectMultipleRows(query); List<Channel> channels = new ArrayList<Channel>(); for (Map<String, Object> map : rawChannels) { Channel channel = new Channel(map.get("NAME").toString(), ((BigDecimal) map.get("ID")).intValue()); channels.add(channel); } return channels; } 24mercoledì 10 novembre 2010
  • 25. Il “routing” delle pagine // GeometryServlet.service() protected void service(HttpServletRequest request, HttpServletResponse response) List<PageComponent> pages = new ArrayList<PageComponent>(); pages.add(new WelcomePage()); pages.add(new SquareAreaPage()); pages.add(new TriangleAreaPage()); pages.add(new SphereVolumePage()); GeometryApplication app = new GeometryApplication(pages); app.service(request, response); } // GeometryApplication.service() public void service(HttpServletRequest request, HttpServletResponse response) thr for (PageComponent component : components) { if (component.wantsToHandle(request)) { response.getWriter().print(component.toHtml()); return; } } response.sendError(404); } 25mercoledì 10 novembre 2010
  • 27. Quick feedback #!/bin/bash # script/server.sh # start app on port 8080 ant war || exit 1 java -jar lib/winstone-0.9.10.jar --warfile target/*.war $* 27mercoledì 10 novembre 2010
  • 28. Server up in < 2s $ script/server.sh Buildfile: /Users/matteo/work/conferences/webtech/projectPortfolio/build.xml prepare: compile: war: BUILD SUCCESSFUL Total time: 0 seconds [Winstone 2010/11/10 00:18:04] - Beginning extraction from war file [Winstone 2010/11/10 00:18:04] - No webapp lib folder found - /private/var/folders/Cb/CbG3BVbs [Winstone 2010/11/10 00:18:04] - HTTP Listener started: port=8080 [Winstone 2010/11/10 00:18:04] - AJP13 Listener started: port=8009 [Winstone 2010/11/10 00:18:04] - Winstone Servlet Engine v0.9.10 running: controlPort=disabled 28mercoledì 10 novembre 2010
  • 29. Dominare il database #!/bin/bash # script/create_databases.sh # create and populate databases for development and test environments echo 'Drop databases...' mysqladmin -uroot --force drop db mysqladmin -uroot --force drop db_test echo 'Create databases...' mysqladmin -uroot create db mysqladmin -uroot create db_test echo "grant all on db.* to db@localhost identified by 'db';" | mysql -uroot echo "grant all on db_test.* to db@localhost identified by 'db';" | mysql -uroot echo 'Build schema...' cat db/*.sql | mysql -udb db -pdb cat db/*.sql | mysql -udb db_test -pdb echo 'Populate development...' mysql -udb -pdb db < db/populate_db.sql echo 'Done!' 29mercoledì 10 novembre 2010
  • 30. Incremental SQL scripts $ ls 001_create_contents.sql 002_add_columns_to_users.sql 003_add_filtri_per_operatore.sql 004_add_custom_fields.sql 005_add_publisher_issues.sql 006_add_columns_content.sql 007_add_media_parade_things.sql 008_alter_publication_issue.sql 009_create_audit_log.sql 010_create_phones.sql 011_add_media_parade_codes.sql 012_add_media_partner_codes.sql 013_add_alias_services.sql 014_delete_custom_field_name_fk_from_user.sql 015_add_indexes.sql 016_add_more_indexes.sql ... alter table contents add pull_downloads int, add ivr_downloads int; update schema_info set version = 6; 30mercoledì 10 novembre 2010
  • 31. Generare HTML public class Course { // ... public void renderOn(CourseView view) { view.setCourseTitle(title); view.setCourseDescription(description); } // ... } 31mercoledì 10 novembre 2010
  • 32. Testable @Test public void rendersCourseView() throws Exception { Course course = new Course("A Title", "A Description"); FakeCourseView view = new FakeCourseView(); course.renderOn(view); assertEquals("A Title - A Description", view.toHtml()); } 32mercoledì 10 novembre 2010
  • 33. Generare HTML: template class FreemarkerCourseView implements CourseView { Map context = new HashMap(); public void setCourseTitle(String title) { context.put("title", title); } public void renderOn(Writer writer) throws IOException, TemplateException { Configuration configuration = new Configuration(); Template template = configuration.getTemplate("coursePage.ftl"); template.process(context, writer); } public String toHtml() { StringWriter writer = new StringWriter(); renderOn(writer); return writer.toString(); } } 33mercoledì 10 novembre 2010
  • 34. Generare HTML: oggetti class ObjectOrientedCourseView implements CourseView { private String title; private String description; public void setCourseTitle(String title) { this.title = title; } public void setCourseDescription(String description) { this.description = description; } public void renderOn(Writer writer) throws IOException, TemplateException { HtmlDivision div = new HtmlDivision().with("id", "course"); div.add(new Display(title)); div.add(new TextBlock(description)); div.renderOn(writer); } } 34mercoledì 10 novembre 2010
  • 35. Blocchi da costruzione public class Display implements HtmlElement { private String text; public Display(String text) { this.text = text; } public String toHtml() { return format("<p class='display'>%s</p>", text); } } 35mercoledì 10 novembre 2010
  • 36. Altri blocchi public class Link implements HtmlElement { private final String url; private final String label; private boolean opensInNewWindow; public Link(String url, String label) { this.url = url; this.label = label; } public String toHtml() { String attributes = opensInNewWindow ? "target='_blank'" : ""; return format("<a href='%s' %s>%s</a>", url, attributes, label); } public void setOpensInNewWindow() { opensInNewWindow = true; } } 36mercoledì 10 novembre 2010
  • 37. Anche form e layout public Page getTemperatureConversionPage(Map<String, String> parameters) { Display display = new Display(converter.convert(parameters.get("temp"))); Form form = new Form("/", "get")); form.add(new TextField("Temperatura:", "temperature", parameters.get("temp"))); form.add(new SubmitButton("Converti")); Page page = new Page(); page.addStylesheet("ourstyle"); page.addDisplay(display); page.addForm(form); return page; } 37mercoledì 10 novembre 2010
  • 38. In conclusione? • Usa la forza degli oggetti • Sfrutta i tuoi strumenti • Sii consapevole delle conseguenze dei framework 38mercoledì 10 novembre 2010
  • 39. Grazie dell’attenzione! Extreme Programming: sviluppo e mentoring 39mercoledì 10 novembre 2010