seminario interessante - fabiovitali.it · informatica per il management ... capacità di...

60
Seminario interessante Lunedì 7 Maggio alle ore 9 nell’aula 2.4 (Ingegneria) Ing. Primiano Tucci “Chrome's development process: life of a line of code” Chrome and Android are amongst the largest open source projects funded by Google and currently shipped to over a billion users. Chrome alone counts more than 18 millions line of code and its codebase grows at a pace of nearly 300 commits per day. Working in such an extremely large and active project poses major challenges, in term of complexity, code scalability, engineering productivity and release process. This talk will first briefly introduce the overall company culture, then introduce the key aspects of Chromium's open source project, covering the major opportunities and challenges. The talk will also deep dive into Chrome's development process, tracking the life of a line of code from the bug tracker to production Primiano Tucci (PhD) is a Tech Lead Manager at Google UK. He has worked for the last five years on Chrome and Android internals and is currently leading platform- wide performance analysis and optimisation projects for Chrome and Android.

Upload: dokien

Post on 17-Feb-2019

212 views

Category:

Documents


0 download

TRANSCRIPT

SeminariointeressanteLunedì7Maggioalleore9nell’aula2.4 (Ingegneria)

Ing.PrimianoTucci“Chrome's development process:lifeofalineofcode”

Chrome andAndroid areamongst thelargest opensourceprojects funded byGoogleandcurrently shipped tooverabillion users.Chrome alonecounts morethan 18millions lineofcodeandits codebase grows at apaceofnearly 300commits perday.Working insuch anextremely largeandactive project posesmajorchallenges,interm ofcomplexity,codescalability,engineering productivityandreleaseprocess.This talkwill firstbriefly introducetheoverall companyculture,then introducethekey aspects ofChromium's opensourceproject,covering themajoropportunities andchallenges.Thetalkwill also deep diveintoChrome's development process,tracking thelifeofalineofcodefromthebugtracker toproductionPrimianoTucci(PhD)is aTech LeadManagerat GoogleUK.Hehas worked forthelastfive years onChrome andAndroid internals andis currently leading platform-wideperformanceanalysis andoptimisation projects forChrome andAndroid.

AggiornamentisuAlphaTube

Lalistadipartenza

• Inunsistemarealetuttiivideoassumononaturalmenteunastoriadivisualizzazionisullabasedellaqualebasarelaraccomandazione.

• Noisiamopochieabbiamopocotempo,eperdimostrarecheilsistemafunzionadobbiamocreareunasituazionefittiziadivideomoltocommentati.

• Laclasseinteradevequindiselezionare40-50videomusicali,daspecificaresuun'appositapaginadelwiki,sucuisiconcentrerannoglisforziinizialidelprogetto.

• Suggerimento:sceglietebranimusicalimoltodiversitraloropergenere,artistaedepocastorica(includeremusicaclassica,jazz,musicheetniche?)

• L'utentepuòselezionarequalunquevideodiYouTube,mainprimapaginal'esaminatorepuòaccedereadunodei40-50videodipartenzascegliendolodaunappositavocedelmenùemostrareisuggerimentisuquesticomepartenza.

Aggiornamentisulprogetto

Lalistadipartenzadefinitivaèdisponibilea

http://site1825.tw.cs.unibo.it/video.json

APIdipopolaritàglobale(1)

• Lapopolaritàglobalerichiedecheiousileinformazionidituttiiprogettidelcorso.Quindièindispensabileaccederealleinformazionidinavigazioneditutti.

• Vienequindipropostaun'APIperaccedereliberamentealleinformazionidipopolaritàdelpropriosistema.

• Ogniteamprimadiconsegnareilprogettoinserisceilproprioindirizzoinfondoadunalistainunapaginadelwiki.

• OgnigruppocheconsegnadopoDEVE utilizzareidatidipopolaritàdituttiigruppipresentinellalistaprimadelproprioindirizzo.

• Sonopiùfortunatiiprimiprogetti,piùsfortunatigliultimi.

APIdipopolaritàglobale(2)UnprogettodisponibilepressositeXXXX.tw.cs.unibo.it devemettereadisposizioneunservizioall'indirizzo:

https://siteXXXX.tw.cs.unibo.it/globpop?id=YYYYYY

taleche:– IlservizioèaccessibiledaqualunqueindirizzoinGET– YYYYYYèl'IDdiunvideodiYouTube– LarispostaèundocumentoJSONcomeilseguente:{

"site": "siteXXXX.tw.cs.unibo.it","recommender": "YYYYYY","lastWatched": "Mon, 09 Apr 2018 09:03:39 GMT","recommended": [{

"videoId": "ZZZZZZ","timesWatched": 7,"prevalentReason": "ArtistSimilarity","lastSelected": "Mon, 09 Apr 2018 11:05:27 GMT"

},{"videoId": "WWWWWW","timesWatched": 3,"prevalentReason": "GlobalPopularity","lastSelected": "Mon, 07 Apr 2018 19:21:13 GMT"

},...]}

Unodi:• Random• Search• Related• Recent• Fvitali• LocalPopularity• GlobalPopularity• ArtistSimilarity• GenreSimilarity• BandSimilarity

Recommender fvitali

• Serveperpermettereaiprimigruppidiaverequalchedato,eaisuccessiviperfaredebugging senzacaricaretroppoglialtrigruppi.

• E'un'APIidenticaaquelladellapopolaritàglobale,disponibilealprimoindirizzodellalistadeigruppipubblicatasulwiki.

• Saràmessaadisposizioneappenacompletatalalistainizialedivideo.

• Leinformazionidiquestalistanonvannomescolate aquelledeglialtrirecommender (saràprobabilmenteunalistastatica).

Aggiornamentisulprogetto

Ilrecommender fvitali èdisponibileall'indirizzo:http://site1825.tw.cs.unibo.it/TW/globpop

E'possibiletestarloall'indirizzohttp://www.fabiovitali.it/TW/2018/es/video.html

Framework Javascript

Prima parte

Fabio VitaliCorsi di laurea in Informatica e Informatica per il ManagementAlma Mater – Università di Bologna

Oggiparleremodi…

Alcuniframework:– JQuery– Node +Express– Angular– React– Vue

IframeworkAjaxSonolibrerieJavascript chesemplificanolavitanellacreazionediapplicazioniAjaxanchecomplesse.Hannotrescopifondamentali– Astrazione:gestisconoledifferenzetraunbrowserel'altroefornisconounmodellodiprogrammazioneunico(oquasi)chefunzionaMOLTOPROBABILMENTEsututtiomoltibrowser.

– Strutturadell'applicazione:fornisconounmodellodiprogettodell'applicazioneomogeneo,indicandoconesattezzacomeedovefornirelecaratteristicheindividualidell'applicazione

– Libreriadiwidget:fornisconouna(piùomeno)riccacollezionedielementidiinterfaccialiberamenteassemblabilipercrearevelocementeinterfaccesofisticateemodulari

Caratteristichecomuni(1/2)

AccessoalDOM– Navigazionesull’alberodeldocumento– Selezionedielementipernome,id,classe,path– Modifichedinamichealcontenutodeglielementi– ModifichedinamicheallostileCSSdeglielementi

• Posizione• Comparsa/sparizione• Caratteristichetipografiche

Comunicazioniasincroneconilserver(Ajax)– Gestioneasincronicità ecallback– Gestionesuccessoeerrori– ConversionedaeperJSON

Caratteristichecomuni(2/2)

Gestioneeventi– Selezionedell’eventoeassociazioneadelementiarbitrari

– Bubbling deglieventi– Riccastrutturadatidell’evento

Libreriadiwidget– Layoutcomplessivodellapagina– Elementideiform– Animazioni– Tabelleintelligentiealberi– Templating

ContentDeliveryNetwork(CDN)Inbreve,unaretefortementedistribuitadicomputerchecollaboranotraloroperdistribuireinmanieraomogeneacontenutidigrandesuccessosenzainutiliduplicazionidioccupazioneetrasmissionedifile.UnusocorrettodeiCDNpermettedisfruttarealmeglioanchelecapacitàdicaching dellemacchineend-user odeinodiintermedidellarete.Adesempiounutentechenavigasutresitiweb,ciascunodeiqualiusalibreriecomeTwitter BootstrapeJQuery manonfausodiCDN,devescaricaretrevolteglistessiidenticifile.SequestitresitifannoriferimentoalibreriepresentisullostessoCDN,invece,lerelativelibrerieverrannoscaricateunavoltasolaerimarrannoincacheancheperglialtrisiti.

URIcheinizianocon//• UnURIreference puòiniziareconunnomedominio,deltipo:

//www.sito.com/dir1/dir2/fig1.gif• EssadeveessererisoltainunURIassolutoutilizzandoleparti

mancantidell'URIbase,cheinquestocasosarebbelapaginaHTMLospitanteiltag <img>.

• Quindiquestosignifica:"carical'immaginefig1.gifutilizzandolostessoprotocollodellapaginaHTML:HTTPsesiamofuoridall'ariaprotettaeHTTPSsesiamodentrol'areaprotetta".

• EccoquindicheèprassiutilizzarequestotipodiURInellechiamateCDN:

//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.j

s

jQuery

jQueryhttp://www.jquery.com

Inassolutoilframework Ajaxpiùusatoalmondo.Nel2017l'89%delmilionedisitiwebconmaggioretrafficoincludejQuery nellesuepagine.Natonel2006,haunalicenzaopensourcemoltoaperta.E’ moltoleggero(78Kb)eveloce.ForniscesupportoperlanavigazioneelamodificadelDOM,gestionedieventiel’usodicomunicazioniasincroneconilserver(Ajax).Estendibileattraversolacreazionediplug-in.Nonhalibreriediwidget proprie,mailprogettoparallelojQueryUIfornisceunaprimalibreriadiwidget (conl’aggiuntadialtrelibrerie)

jQuery:l’oggetto$

jQuery haunapeculiaritàsintattica,l’usodellakeyword$perognicomandodellalibreria:

$("a").click(function(){alert("Helloworld!");})Ilcarattere$inJavascript èusabilenegliidentificatori.jQuery definiscealloraunafunzione$()cheèunaliasdelcostruttorejQuery(),ehacomeparametrounselettoreDOM.IlcodicejQuery èimmediatamenteidentificabilecometalegrazieaquestoausiliosintattico.

jQuery:usarelalibreria(1)

<html><head><script type="text/javascript" src="jquery.js"></script> <script type="text/javascript”>

// codice personale</script>

</head><body><p> parte HTML </p>

</body></html>

jQuery:usarelalibreria(2)

<html><head><script type="text/javascript" src="jquery.js"></script> <script type="text/javascript” srf="mycode.js"></script>

</head><body><p> parte HTML </p>

</body></html>

Quandovengonoeseguitigliscript?Immediatamente!

• Tuttigliscriptvengonoeseguitisubitodopoillorocaricamento.– Adesempio,gliscriptstannotipicamentedentroall’headdiHTML,che

vienecaricatoprimadelbodyemoltoprimadituttelerisorseesternecomeleimmagini.

• Cisonoduemomentispecificiapartiredaiqualisipossonoattivaregliscript:– document.ready:ilDOMècaricato,prontoeinizializzato.Eventualirisorse

esterne(comeleimmagini)possonoancoranonesserepronte,mailloropostonelDOMègiàriservato.

– window.load:ilDOMècaricatoepronto,etuttelerisorseesterne(comeleimmaginisonopronteecaricate.

• Perlamaggiorpartedellesituazioni,loscriptpuòpartirealready.SeavetebisognodiinformazioniaggiuntivenonpresentinelDOM(adesempio,ladimensioneinbytediun’immagine)allorabisognaaspettareilload.

jQuery,eventireadyeload• jQuery metteadisposizioneduecallback associateaglieventidireadyeload.– $(document).ready(function(){

// codice da eseguire al ready})

– $(window).load(function(){// codice da eseguire al load

})

• Tipicamentesimettetuttoilcodicedentroa$(document).ready.

• N.B.:E’ equivalentescrivere:– $(document).ready( function() { … } )– $(document).ready = inizio;…function inizio() { … }

Scorciatoia$(function() {

// codice del ready}

jQuery:accederealDOMIlparametrodelcostruttore$() èunselettorejQuery.SonoselettorijQuery tuttiiselettoriCSS3,piùalcunispecificidijQuery.

– $(‘p’) restituisceunarraydituttiip deldocumento– $(‘.pippo’) restituisceunarraydituttiglielementidiclasse‘pippo’– $(‘#pluto’) restituisceunarraychecontienel’elementodiid=‘pluto’.– $(‘:selected’) restituisceunarraydituttiglielementiselected– $(‘:visible’) restituisceunarraydituttiglielementivisibili– $(‘p[id^=“basic”]’) restituisceunarraydituttiip ilcuiidiniziacon la

parola‘basic’– …

Adesempio:– $("a").click(function() {

alert("Hello world!");});

jQuery:modificareilDOMjQuery metteadisposizionemoltefunzionidimodificadelDOM.Esseagisconoosututtol’arrayidentificatodalselettore,osulprimoelementodiquestoarray

– $("p").addClass(”importante”),$("p").removeClass(”importante”):aggiunge otoglie laclasse CSSaogni elemento dell’array

– $(’h2').before(’<p>Capitolo</p>'),$(’h2').after(’<hr/>'):aggiungecontenuto primaodopo ogni elemento dell’array.

– $(‘h2’).css("background-color”),$(‘h2’).css("background-color”,"#FF0000"):restituisce/cambiail valore della proprietà CSSspecificata delprimoelemento dell’array selezionato.

– $(‘h2’).html(),$(‘h2’).text():restituisceilcodiceHTMLoiltestocontenutoinognielementodell’arrayselezionato.

– $(‘h2’).html(‘<b>Untitolo</b>’),$(‘h2’).text(‘Unnuovotitolo’):sostituisceilcodiceHTMLoiltestocontenutoinognielementodell’arrayselezionato.

jQuery:effettieanimazioni

E’ possibileattivareeffettieanimazioniaglielementideldocumento.Questieffettivengonoeseguitisubitoodopoundelay.Perattivareglieffettiinseguitoadunevento(adesempiounclicksuunbottone)ènecessariospecificarel’animazionedentroall’handler dell’eventodesiderato.

– $(’#target').hide();$(’#target').show();nascondeemostral’elementoconid=‘target’,assegnandolaproprietàCSSspecifica(cheèdiversaneivaribrowser).

– $(’img.mostra').fadeIn('slow’);$(’img.nascondi').fadeOut('slow’):falentamenteapparire osparire ogni elemento dell’array selezionato.

– $(’img.mostra').slideDown('slow’);$(’img.nascondi').slideUp('slow’):falentamenteapparire,conmovimento dall’alto albassoodalbassoinalto,ogni elemento dell’array selezionato.

jQuery:eventi(1/2)

jQuery permettedispecificareunafunzionedicallback daassociareaglieventidelDOM.• $(‘input’).mouseover(function() {

alert(‘mouseover’); })

• $(‘input’).keypress(function(e) { alert(e.which);

})• $(‘a’).click( function(e) {

document.href=“http://www.google.com”; e.preventDefault() ;

})

e.preventDefault()bloccal'esecuzionedelcomportamentodidefault(inquestocaso,lanavigazioneversoilcontenutooriginariodell'href).

jQuery:eventi(2/2)Inrealtà,click(),mouseover(),ecc.derivanodaunsolometodo:

$(‘input’).mouseover(f1) è equivalente a$(‘input’).on('mouseover',f1) $(‘a’).click(f3) è equivalente a$(‘a’).on('click',f3)

Questo portaadun'immediataecomodissima estensione:$(‘body').on('click', 'a', f3) estende$(‘a’).on('click',f3)– Ilsecondoparametro,facoltativo,èunsecondoselettoreCSS,cheindicaa

qualidiscendentidelselettoreprimarioassociarelacallback.– Inentrambiicasi,lacallback siapplicaaglielementi<a>,enona<body>.– Normalmente,ilbinding dellacallback all’eventoavvienesolosuelementigià

esistentinelDOM.Quindi$(‘a’).on('click',f3) siapplicasoloaglielementidelDOMpresenti,adesempio,aldocument.ready.

– Sevoglioassociareuneventoaelementichepotrebberoesserecreatiinseguitoalbinding,debbodelegareadunelementosempreesistente(adesempio,<body>)diassociareilcallback all'elementogeneratodinamicamente.

jQuery:AjaxUnasingolafunzionesioccupadituttalacomunicazioneasincronausandoXMLHttpRequest (XHR):

$.ajax({url: ’app.php’,success: function(data) {

$('.result').html(data);alert(’Caricamento effettuato');

},error: function(data) {

alert(‘Caricamento impossibile’);}

})

IlparametrounicodellafunzioneèunJSONdicuiimembriurl esuccesssonoobbligatori.Alcunefunzioniequivalenti($.get(),$.post()e $.put())sonodisponibilipermaggiorerapidità.Lefunzionisuccess() eerror() vengonochiamateappenalaconnessioneHTTPsièconclusaedunquereadystate =4(loaded).

jQuery:asincroniaepromesse

Unaalternativaalcall-backèusarelepromesse.Ilselettore$() ègiàunapromessa,percuisipossonocrearecatenedifunzionithen() condueparametri,lafunzionedachiamareincasodisuccessoequellaincasodiinsuccesso:

var good = function(data) {$('.result').html(data);alert(’Caricamento effettuato');

};var bad = function(data) {

alert(‘Caricamento impossibile’);};$.get(’http://www.server.it/server’).then(good, bad);

jQuery:conclusioni

jQuery sicomportainmanieramoltoconservativaneiconfrontideldocumentoHTMLdipartenza,aggiungendodinamicamentecomportamentiestiliadelementicherimangonoquellioriginali.Lasemplicitàd’usoelaleggerezzadellalibrerialarendonoidealeperpiccolicompitidianimazioneeattivazionedielementiinpaginechesonogiàbenstrutturateegraficamentecomplete.jQuery nonèfattoperprogettareinterfacce,maperdescriverecomportamentidinamicisualcunielementiparticolaridipaginewebtradizionali(form,link,menu,ecc.).

Node.js, npm ed Express.js

[XXX]acrossthestack• Lostack èl'insiemedegliambientidicuiunprogettistaweb

devetenercontoperrealizzareun'applicazione,edeilinguaggidiprogrammazionedaconoscere.

• Javaacross thestack:– GoogleWebToolkit:ambienteintegratoclient-server,incuilaparte

clientvienecompilatainJavascript daunsorgenteJava• Javascript across thestack:

– ASP epoiASP.NET:soluzioneMicrosoftperIIS.ASPerasoloJavascript,mentreASP.NETpermettedisceglieretramoltilinguaggi,inclusoC#,VBAeJavascript.

– GoogleApps Script:soluzioneGoogleperfornirecomportamentisofisticatiaisitirealizzaticonGoogleSites.

– MongoDB,CouchDB:databaseNoSQL fornisconomeccanismidiinterrogazioneegestionedeidativiaJavascript

– NodeJS:ambientediesecuzioneserver-sidediapplicazionisofisticate(ancheindipendentementedaHTTP).

MEANstack

• UnterminecheadessoèMOLTOdimodaèMEANstack:– MongoDB:undatabaseNoSQL cheforniscepermanenzaaidatidelle

applicazioni– ExpressJs:unframework perapplicazioniweb– AngularJs:unframework MVCperlacreazioneditemplate sofisticatidi

pagineHTML– NodeJs:unapiattaformasoftwareperapplicazioniserver-side

• Loscopoevidentedellostack MEANèdiripetereilsuccessoesostituirsiallostack LAMPchehacostituitoilsetfondamentaleditecnologieperlosviluppodiapplicazioniwebneglianni2000.

NodeJSenpm

Creaturadiunapersonasola,RyanDahl (2009),perfornirebi-direzionalitàalleapplicazioniweb(tecnologiapush).Un'applicazionenativaserver-side,chepermettedifarechiamateI/Oguidatedaeventi,non-bloccanti.Peruniformarelarealizzazionediapplicazionimisteserver/client,decidediusareunmotoreJavascript ancheserver-side

– Nonèlaprimavolta,giàMicrosoftconASPusaJavascript server-side– UtilizzauninterpretediJavascript moltopotente,V8diGoogle

Adessovieneaggiuntounpackagemanager,npm,chepermettediinstallarevelocementelibrerieepacchettiassociati.

Single-thread non-blocking execution

Invecedidedicareunthread adogniconnessionericevutadallarete,l'applicazionenodeJS utilizzaunsolothread incuituttelerichiestericevonoattenzionecondivisa.

– Inun'applicazioneWebtradizionaleunthread puòaverecirca2Mbdimemoriaassociati,quindiunamacchinacon8GBhaunmassimoteoricodi4000richiesteconcorrenti.

– Mantenendotuttoinununicostack,NodeJS arrivaadunmassimoteoricodi1milionedirichiesteconcorrenti.

Poichéognirichiestapuòrichiederetempivariabili,èprassiinserirerichiesteoneroseinfunzioniasincrone,non-bloccanti,conunafunzionedicallback alcompletamento.

– Questopermettealthread principale(main loop)dirimaneremoltosnelloeveloce.

– Percontro,èfacilissimoinchiodareNodeJS facendoeseguirepartionerosedelcodicedirettamentedentroalmainloop.

NodeJScomemotoreHTTP

NodeJS puòelegantementesostituirePHP,Python,Perl eognialtroapprocciocgi-bintradizionale.Diseguitounesempiodiun'applicazionecherestituisceunframmentoHTML:

var http = require('http');

http.createServer(function (request, response) {

response.writeHead(200, {'Content-Type': 'text/html'});response.end('<h1>Hello World</h1>');

}).listen(8000);

NodeJSconaltriprotocolli

NodeJS puòporsiinascoltosuqualunqueportaeimplementareancheprotocollidiversidaHTTP:

var net = require('net');net.createServer(function (stream) {stream.write('hello\r\n');stream.on('end',function () {stream.end('goodbye\r\n');

});stream.pipe(stream);

}).listen(8000);

Event Loophttp://i.stack.imgur.com/zYgcr.png

Asincroniaefunzionicallback

• Node.js è quasiesclusivamente basato su funzioniasincrone ecallback.

• Laconvenzione dinode.js suggerisce dicrearefunzioni che accettano una funzione callbackasincrona comeultimoparametro

• Lafunzione callbackperconvenzione usa lasintassi error-firstfs.readFile('test.txt', function(err, data) {

if(err) {console.log('Error: '+error.message);return;

}doSomething(data);

});

Imodulidinode.js• Node.js è estremamente modulare.E'possibile mettere codice

indipendente infilejavascript ed eseguirlo secondonecessità.• Ilmeccanismo dicaricamento dimodulidiNode.js è semplice:

– unmoduloè unfileJavascript.– Quando si richiede unmodulo,esso viene cercato localmente o

globalmente secondounmodello preciso.

• Imodulivengono caricati conrequire().

http = require("http")

fs = require(”redis")

require("./greetings.js")

console.log("You just loaded a lot of modules! ")

Modulo core built-in

dipendenza(da installare con npm)

file locale

Creare unmodulo

greetings = require("./greetings.js")

greetings.hello()

greetings.ciao()

hello = function() {

console.log("\n Hello! \n")

}

ciao = function() {

console.log("\n Ciao! \n")

}

module.exports.hello = hello;

module.exports.ciao = ciao;

greetings.js

npm

• Imodulidinode.js vengonodistribuitiedinstallaticonnpm (node packagemanager)

• npm vieneeseguitoviacommand-lineeinteragisceconilregistronpm.– meccanismorobustopergestiredipendenzeeversionidei

pacchetti(moduli)– sempliceprocessodipubblicazionedipacchettiecondividerlicon

altriutenti.

• Inpiù:unapiattaformaperrepository pubbblici eprivati,servizienterprise (integraticonfirewallaziendali),integrazioneconaltrepiattaforme,ecc.

Express.js

• Expressèunmodellodiserverwebpernode.js– Open-source,licenzaMIT– moltousatoemoltosupportatodallacomunità– moltosempliceemoltoespandibileconplugin

• Expresssidedicaalrouting,allagestionedellesessioni,all'autenticazionedegliutenti,emoltialtriprincipifondantidelleconnessioniHTTP.

• Natonel2010,acquistatonel2015daIBM,poiregalatodaIBMallaNode.js Foundation.

Basicserver

express = require("express")app = express()

docs_handler = function(request, response){var docs = {server : "express”}response.json(docs);

}

app.get("/docs", docs_handler);

app.listen(8099, function(){console.log("\nExpress is running!!! \n")

})

Routing

Expressfornisceunasempliceinterfacciaperfarerouting:app.method(path, function(request, response) { ... })

dove– method èunodeimetodiHTTP(get,post,put,delete,ecc.)– path èillocal path dell'URIrichiestoalserver– function(req,res)èunhandler daeseguirequandovienerichiestoil

path.Idueparametricontengonogliobject dellarichiestaHTTP(uri,intestazioni,parametri,dati,ecc.)edellarispostaHTTPinviadirestituzione(intestazioni,dati,ecc.)

Ogniroute gestisceunaopiùhandler anchesuglistessipath.app.post('/', function (req, res) {

res.send('<p>Richiesta POST');});

AccedereaidatidiunPOST

• Lalibreria bodyparser (integrata conexpress)permettediaccedere alcorpo dei dati spediti dalPOSTnel bodydella richiesta.

• Questi middlewaresi occupano direcuperare eelaborare i dati sottomessi daunformviaposteliconvertono inoggetti accedibili dall'applicazione.

• Idati delPOSTsi accedono come:<request>.body.<post_variable>

POSTdata

var express = require("express")var bodyParser = require('body-parser');

app = express()

app.use(bodyParser());

app.post('/login',function(request,response){console.log("Username:" + request.body.user)console.log("Password:" + request.body.pwd)

// Continue and do authentication….});

‘user’/‘pwd’:nomidegliinputusatinelform

Expressmiddleware stack• Expresshapochissimefunzionalitàproprie(routing),ma

utilizzaungrandenumerodilibreriemiddlewaregrandementepersonalizzabiliinunostack diserviziprogressivamentepiùcomplessi.

• Peraggiungereunmiddleware allostack:app.use(<middleware>)

• Un'applicazioneExpressèalloraessenzialmenteunasequenzadichiamatefunzionidimiddleware tralarichiestaelarisposta.

• Ilmiddleware può– accedereaglioggettidirichiestaerisposta– cambiarliedeseguiredelcodicedimodifica– chiamarelaprossimafunzionedelmiddleware (next() )– usciredalcicloemandarelarisposta.

L'esercizio Javascript del compito

Formatodell'esercizioJSdelcompito

Lastrutturadell'esercizioJSdelcompitoèsemprelastessa– Vienefornita(osuggeritaimplicitamente)unapaginaHTMLcondei

widget rilevanti– Vienedescrittal'APIdiunservizioserver-sideconURI,metodiHTTPe

struttureXMLoJSONpiùomenocomplesse.– Inalternativa,vienerichiestodidescrivereun'APIditaliservizi

descrittiaparole– Bisognaassociareaglieventidialcuniwidget lainterrogazione

asincronaaiservizi.– Bisognasempregestireilcasodisuccessodellacomunicazione(che

tipicamentevaariempiredeidivdellapaginaHTML).Bisognaspessogestireilcasod'errore(tipicamenteunalert informativo)

– Spessobisognaarricchirealtriwidget coneventiassociatiadaltrechiamateAJAX.

Unesercizio(1/4)

• Nelsistemainformativodiunamensascolasticasivuolesperimentareunsistemachepermettaaisingoliscolaridiscegliereilpropriomenùdelpranzo.

• Allamattinaloscolarooungenitoreaccedealsistemainformativo,inseriscelepropriecredenzialiesitrovadifronteadun'interfacciacheglipermettedisceglieretraivaripiattioffertiquelgiorno.

• Ognimenùècompostodaprimo,secondoconcontornoedessert(fruttaodolce).

• IlmenùèinterrogabiletramitemetodoGETall'indirizzohttp://www.menuscolastico.it/mandamenu.php?date=[XXX],dove[XXX]èunadatainformatoYYYYMMDD.

Unesercizio(2/4)

Datalamolteplicitàdietniepresentinellescuolepubblicheitalianeel'incrementodiallergieeintolleranzealimentarineibambini,alcunicibidebbonoessereesclusiperchénonadattiallacultura,allareligioneoallasalutedelsingolostudente.Poichénonsipuòrichiederechesiailbambinostessoadevitarediscegliereicibiinadatti(potrebbeignorareidettamidellapropriadietaovolerlisfidare),ènecessariocheilsistemaescludaautomaticamenteicibiinadatti.Incasodisuccessodell'operazionedilogin,dunque,ilsistemafornisceunoggettoJSON(nonmodificabile,stabilitoinfasediregistrazionedellostudente)comeilseguente:

{nome: 'Andrea',cognome: 'Rossi',classe: '3',sezione: 'A',restrizioni: ['vegetariano','celiaco']

}

Unesercizio(3/4){

"giorno": "2018-05-15","menu": {

"primi": [{"nome": "Tagliatelle al ragù","ingr": ["pasta all'uovo", "manzo", "salsa pomodoro", "spezie"]},{"nome": "Pasta al pomodoro","ingr": ["pasta secca", "salsa pomodoro", "spezie"]}, ... ],

"secondi": [{"nome": "Scaloppina ai funghi","ingr": ["manzo", "funghi secchi", "besciamella"]},{"nome": "Stracchino e grissini","ingr": ["formaggio fresco", "grissini"]}, ... ],

"dessert": [{"nome": "fiordilatte","ingr": ["latte", "zucchero", "aromi naturali"]

},{"nome": "Kiwi","ingredienti": ["kiwi"]

}, ... ]}

}

DopotalerichiestailsistemaspedisceunJSONcomesegue:

Unesercizio(4/4)SiassumacheesistagiàfornitaunafunzionepuòMangiare(R,I),cherestituisceTrueoFalseasecondacheunapersonaconlarestrizioneR possaconsumareomenol'ingredienteI,perognicompatibilitàpossibile,perognitipodirestrizioneedogniingrediente.Scrivere:

a) LafunzionechiediMenu(D) cherichiedeilmenudelladataD(YYYYMMDD)b) LafunzionerestringiMenu(AR,M),cherestituisceinformatoJSONilmenùrisultante

dall'eliminazionedeicibichecontengonoingredientiincompatibiliconlerestrizioni,doveARèunarraydirestrizionieMèunmenuinJSON.

c) LafunzionemostraScelte(M),chevaacreareunform pervisualizzareidatidelmenuMgiàristrettocomesegue:perognicategoria(primo,secondo,dessert):selacategoriacontieneunsolocibo,visualizzailtestocorrispondente;selacategoriacontienedueopiùcibi,visualizzaunmenuatendinaconunelementoperognicibo.Diognicibovienemostratoilnomeegliingredientineltestoalternativo.

d) LafunzionespedisciMenu(),chesicollegaconcollegamentoAjaxemetodoPOSTall'indirizzohttp://www.menuscolastico.it/mandamenu spedendoivaloridituttiicampidelform,emostrandoincasodisuccessoilmessaggio"Indicazionidelmenùricevutecorrettamente",eincasodiinsuccessoilmessaggio"C'èstatounerrorenellaspedizionedelleindicazionidimenù.Percortesiariprova."

Tracciadellasoluzione(1/??)

• LafunzionechiediMenu(D) èunwrapper dichiamataAjax.Incasodisuccessobisognapopolareilform.Quindilafunzionesuccessodeveprimarestringereilmenuepoimostrarelescelte.Nonsiparladiinsuccesso.

• LafunzionerestringiMenu(AR,M) èunconfrontotraarray.Bisognapensareadunalgoritmo.

• LafunzioneMostraScelte(M) èunmodificatoredellapaginavisualizzata.Bisognaselezionarel'elementogiusto,ecrearedelDOMalsuointernopertrestringheotremenuatendinaconrelativaetichettapiùilpulsantedisubmit.

• LafunzionespedisciMenu() èunwrapper dichiamataAjaxassociataalclickdelpulsantedisubmit.AttenzionecheèunPOST,enonunGET.

Appuntiperunasoluzione(1/4)Assumocheilform abbiaid="formMenu".Hoduevariabiliglobali:var url = "http://www.menuscolastico.it/mandamenu.php"var utente = {

nome: 'Andrea',cognome: 'Rossi',classe: '3',sezione: 'A',restrizioni: ['vegetariano','celiaco']

}

DichiarocheusojQuery escrivo:Domandaa)function chiediMenu(D) {

$.ajax({url: url + "?date="+D.format("YYYYMMDD"), (*)success: function(datiString){var dati = JSON.parse(datiStringa)var menuRistretto = restringMenu(utente.restrizioni, dati.menu);mostraMenu(menuRistretto)

}})

}(*):E'accettabiledescrivereaparoleDate.format(formato).

Appuntiperunasoluzione(2/4)

Domandab)function restringiMenu(restrizioni,menu) {for (var i in menu) { //cioè primo, secondo, dessertvar categoria = menu[i]for (var j=0; j<categoria.length; j++) {var ricetta = categoria[j]for (var k=0; k<ricetta.ingredienti.length; k++) {var ingrediente = ricetta.ingredienti[k]for (var l=0; l<restrizioni.length; l++) {var restrizione = restrizioni[l]if (!puoMangiare(restrizione,ingrediente)) {remove(categoria,j) (**)

}}

}}

}return menu

}(**):E'accettabiledescrivereaparoleremove(array,posizione).

Appuntiperunasoluzione(3/4)Domandac)function mostraMenu(menu) {var html = ""for (var i in menu) { //cioè primo, secondo, dessertvar cat = menu[i]html += "<p class='menu'>"+ i +": ";if (cat.length==0) {} // nessun cibo in questa categoriaif (cat.length==1) {var ricetta = cat[0]html += "<span title='"+ricetta.ingredienti.join(", ")+"'>"html += ricetta.nome + "</span>"

} else {html += "<select>"for (var j=0; j<cat.length; j++) {var ricetta = cat[j]html += "<option>"+ricetta.nome+"</option>"

}html += "</select>"

}html += "</p><button onclick='spedisciMenu()'>Spedisci</button>"

}$("formMenu").html(html)

}

Appuntiperunasoluzione(4/4)

Domandad)function spedisciMenu() {var formData = $("formMenu").getAllData() (***)$.ajax({url: url,method: 'POST',data: formData,success: function(datiString, status, richiesta){alert("Indicazioni del menù ricevute correttamente")

},error: function(err) {alert("C'è stato un errore. Per cortesia riprova")

}})

}

(***):E'accettabiledescrivereaparolegetAllData().

www.unibo.it

Fabio Vitali

Dipartimento di Informatica – Scienze e IngegneriaAlma mater – Università di Bologna

[email protected]