NF1 - Estructures definides pel Programador - Funcions

De wikiserver
Dreceres ràpides: navegació, cerca

Funcions

Comprovació i Depuració

Crear conjunts de proves efectius per al codi sempre és important, per això ho tractem ara, abans de continuar amb les funcions. En Javascript no solament ens trobem amb els típics problemes per garantir la qualitat sinó que també ens trobem amb obstacles a l'hora de determinar si el nostre codi funciona en tots els navegadors amb els quals hem decidit ser compatibles.

Hi ha dos importants enfocaments per depurar Javascript: el registre i els punts de parada. Tots dos són útils per respondre a la pregunta crucial, "Què està passant amb el meu codi?".

Registre

Les declaracions de registre, com les quals fem en executar console.log(), són part del codi (encara que sigui de forma temporal) i resulten pràctiques en un entorn multinavegador. Les consoles del navegador han millorat molt el procés de registre mes allà de la tècnica d'afegir una alerta. Podem escriure totes les nostres declaracions de registre en la consola i accedir a elles de forma immediata o amb posterioritat sense afectar al flux normal del programa, alguna cosa que no és possible amb alert().

El registre és perfecte per buscar quin pot ser l'estat de les coses mentre s'està executant el codi però, en algunes ocasions, volem detenir l'acció i fer un cop d'ull. Aquí és on apareixen els punts de parada.

Punts de parada

Detenen l'execució d'un comando en una línia de codi concreta, detenint el navegador. Això ens permet investigar sense presses l'estat de tot tipus de coses en el punt de parada, incloent totes les variables accessibles, el context i la cadena d'abast.

Generació de proves

Les bones proves exhibeixen tres importants característiques:

  • Repetibilitat: Els resultats han de ser molt fàcils de reproduir. Les proves que s'executen en repetides ocasions sempre haurien de produir exactament els mateixos resultats. Les proves no depenen de factors externs com la xarxa o la CPU.
  • Simplicitat: Les proves han de centrar-se a comprovar un únic element. Hem de llevar el CSS i l'HTML com sigui possible sense afectar la intenció del cas de prova.
  • Independència: Les proves han d'executar-se en solitari. Cal evitar que els resultats d'una prova depenguin d'una altra.

Enfocaments per crear proves:

  • Deconstructius: El codi existent es descompon per aïllar un problema, eliminant alguna cosa que no està relacionat amb la qüestió.
  • Constructius: Comencem a partir d'un cas reduït ben conegut i creguem fins que som capaços de reproduir l'error en qüestió.

Exemple de cas de prova DOM emplear per comprovar JQuery:

<script src="dist/jquery.js"></script>
<script>
  $(document).ready(function() {
    $("#test").append("test");
  });
</script>
<style>
  #test { width: 100px; height: 100px; background: red; }
</style>
<div id="test"></div>

Entorns de comprovació

Aquesta eina serveix a una necessitat única: mostrar els resultats de les proves, fent que sigui més fàcil determinar quins han sortit bé i quins han fallat. Els entorns de comprovació ens ajuden a aconseguir aquest objectiu sense haver de preocupar-nos per una altra cosa que no sigui crear les proves i organitzar-les en conjunts. Els entorns de comprovació única de Javascript solen proporcionar alguns components clau:

  • un executor de proves,
  • agrupacions de proves i
  • aserveraciones.

Alguns ofereixen a més l'habilitat d'execució asincrónica.

QUnit

És l'entorn que va ser creat per provar jQuery. Ha sobrepassat les seves metes inicials i ara s'ha convertit en una utilitat independent. QUnit es va dissenyar bàsicament per ser una solució senzilla, proporcionant una API mínima però fàcil d'utilitzar. Característiques:

  • API senzilla
  • compatible amb la comprovació asincrónica.
  • No es limita a jQuery

web: http://qunitjs.com/

Exemple d'ús:

Primer creem un còpia del codi a testar. Per exemple creem el fitxer exercici5.js on tenim la solució del exercici 5 de la unitat anterior. L'exercici consisteix a posar al revés un text donat.

--- Contingut del fitxer exercici5.js ---
function posarReves(opcio, text) {
	var separador = " ";
	if(opcio == 0){
		separator = "";
	}
	return text.split(separator).reverse().join(separator);
}

Segon creem un joc de proves per aquest exercici. Per exemple podem crear un fitxer anomenat jocProvesEx5.js El contingut del fitxer pot ser el següent:

test("Conjunt de Tests", function() {
	equal(posarReves("333", "hola a tots"), false);
	equal(posarReves("huksi", "hola a tots"), false);
	equal(posarReves(-2, "hola a tots"), false);
	equal(posarReves(0, "hola, a tots"), "stot a ,aloh");
	equal(posarReves(0, "hola a tots"), "stot a aloh");
	equal(posarReves("dead", "hola a tots"), false);
	equal(posarReves(1, "hola, a tots"), "tots a hola,");
	equal(posarReves(1, "hola a tots"), "tots a hola");
});

Tercer creem el HTML on combinem el codi a provar, els tests i les llibreries de QUnit.

<!DOCTYPE html>
<html>
	<head> 
		<meta http-equiv="Content-Type" content="text/html" charset=utf-8" />
		<title>Tests per al exercici 5</title>		
		<link href="qunit-1.12.0.css" type="text/css" rel="stylesheet" />
		<script src="qunit-1.12.0.js"></script>
		<script src="jocProvesEx5.js"></script>
		<script src="exercici5.js"></script>
	</head>
	<body>
		<div id="qunit"></div>	
	</body>
</html>

Gràcies a aquest conjunt de proves podem veure que ens fa falta una funció de detecció d'errors més acurada sobre la variable opcio.

YUI Test

És un entorn de comprovació creat per Yahoo! Proporciona un nombre impressionant de característiques i funcionalitats que garanteixen la cobertura de qualsevol cas de comprovació única. Es distingeix per:

  • Àmplia i exhaustiva funcionalitat
  • És compatible amb la comprovació asincrónica
  • Bona simulació d'esdeveniments.

web : http://yuilibrary.com/projects/yuitest/

JsUnit

És el més antic en termes d'edat de la base de codi i qualitat. Ve del popular entorn de comprovació Java JUnit per Javascript. L'entorn no s'ha actualitzat molt recentment i per això pot ser que no sigui la millor opció per treballar amb els navegadors moderns. web: https://github.com/pivotal/jsunit Existeix una versió que s'està implementant per donar suport als nous navegadors que es diu Jasmine: web: https://github.com/pivotal/jasmine

Exercicis

Exercici 1

Crea un joc de proves per al Exercici 3 DNI. Canvia els alerts de comprovació, si tens, per console.log(). Utilitza el framework QUnit.

Exercici 2

Crea un joc de proves per al Exercici 7 Nombres Romans.Canvia els alerts de comprovació, si tens, per console.log(). Utilitza el framework QUnit.

Exercici 3

Unifica els dos jocs de proves anteriors en un mateix fitxer. Es a dir, només has de tindre els següents fitxers: Fitxer HTML, Fitxer qunit-1.12.0.css, Fitxer qunit-1.12.0.js, Fitxer JocProvesUnificat.js, Fitxer Exercicis.js

Les Funcions son fundamentals

Les funcions, en Javascript, són objectos de primera classe, és a dir, coexisteixen amb qualsevol altre objecte i poden tractar-se com un d'ells. Igual que els tipus més mundans de Javascript, les variables poden fer referència a elles, es poden declarar amb literals i fins i tot passar-se com a paràmetres d'altres funcions.

La funció és la principal unitat modular d'execució. Vol dir que excepte els comandos incrustats en el codi que s'executen mentre es evalua les etiquetes, tot la resta de les nostres pàgines està dins d'una funció.

Les funcions com a objectes de primera classe

Els objectes tenen les següents capacitats:

  • Es creen a través de literals.
  • S'assignen a variables, entrades de matriu i propietats d'altres objectes.
  • Es poden passar com a arguments per a funcions.
  • Es retornen com a valors a partir de funcions.
  • Tenen propietats que poden creés i assignar-se de forma dinàmica.

Les funcions tenen totes aquestes capacitats, a més tenen la capacitat que poden invocar-se.

Declaracions

Les funcions es declaren usant una funció literal que crea un valor de la mateixa manera que un literal numèric. Les funcions són valors que poden emprar-se en el llenguatge igual que altres valors, com les cadenes o els nombres. Les funcions literals es componen de quatre parts:

  • 1. La paraula clau function
  • 2. Un nom opcional que, si s'especifica, ha de ser un identificador vàlid.
  • 3. Una llista separada per comes de noms de paràmetres entre parèntesis. La llista pot estar buida, però els parèntesis han d'estar presents.
  • 4. El cos de la funció. Una sèrie d'instruccions entre claus.

El fet que el nom de la funció sigui opcional pot ser una sorpresa. Si no tenim necessitat de fer referència a elles pel seu nom, no hem de donar-li-ho. Quan se li posa un nom a una funció, és vàlid en tot l'àmbit en el qual aquesta es declara. Si una funció es declara amb nom el nivell superior, es crea una propietat usant el nom de la funció en l'objecte window. Finalment, totes les funcions tenen una propietat anomenada name que emmagatzema el nom de la funció com una cadena. Estarà buida en el cas que no li posem nom. Sintaxi d'una funció Javascript:

function nomFuncio()
{
	var x=5;
	return x;
}

Anem a provar tot el que hem dit anteriorment amb un exemple. Utilitzarem un joc de proves per veure si realment les funcions són objectes de primera clase:

// --- fitxer on posem les declaracions de funcions ---
function lleugera() {
	return true;
}
var sensenom = function(){return true;};
window.esVeritat = function(){return true;};
function externa(){
	function interna(){}
}
var una_funcio = function una_altre_funcio(){return true;};

Joc de proves:

test("Conjunt de Tests per a funcions", function() {
	equal(typeof window.lleugera === "function", true);
	equal(lleugera.name === "lleugera", true);
	equal(lleugera.name === "lleugera", true);
	equal(typeof window.sensenom === "function", true);
	equal(sensenom.name === "", true);
	equal(typeof window.esVeritat === "function", true);
	equal(typeof window.externa === "function", true);
	equal(typeof window.interna === "function", false);
	equal(window.una_funcio.name === "una_altre_funcio", true);
});

Que demostra el joc de proves?

  • Les funcions s'afegeixen com a propietats del objecte window.
  • Les funcions tenen una propietat anomenada name
  • Que window.sensenom es defineix com una funció demostrant que les variables globals, fins i tot les que contenen funcions, terminen en window.
  • Que window.esVeritat es defineix com una funció.