seminario interessante - fabiovitali.it · informatica per il management ... capacità di...
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.
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
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
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.).
[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);
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.
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