metaprogramación en javascript

67
Javier Vélez Reyes @javiervelezreye [email protected] Metaprogramación En JavaScript Programación Orientada a Componentes Febrero 2015

Upload: javier-velez-reyes

Post on 08-Jan-2017

488 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Metaprogramación en JavaScript

JavierVélezReyes@javiervelezreye

[email protected]

MetaprogramaciónEnJavaScript

ProgramaciónOrientadaaComponentes

Febrero2015

Page 2: Metaprogramación en JavaScript

@javiervelezreye2

AutorMetaprogramaciónEnJavaScript

Licenciadoeninformá1caporlaUPMdesdeelaño2001ydoctoren informá1ca por la UNED desde el año 2009, Javier esinves1gadorysulíneadetrabajoactualsecentraenlainnovaciónydesarrollodetecnologíasdeComponentesWeb.Ademásrealizaac1vidades de evangelización y divulgación en diversascomunidadesIT,esPolymerPolytechnicSpeakeryco-organizadordelgrupoPolymerSpainqueconformaunacomunidaddeinterésde ámbito nacional en relación al framework Polymer y a lastecnologíasdeComponentesWeb.

I.¿QuiénSoy?

II.¿AQuéMeDedico?

[email protected]

@javiervelezreye

linkedin.com/in/javiervelezreyes

gplus.to/javiervelezreyes

jvelez77

javiervelezreyes

youtube.com/user/javiervelezreyes

PolymerPolytechnicSpeaker

Co-organizadordePolymerSpain

EvangelizaciónWeb

DesarrolladorJSFullstack

ArquitecturaWeb

Formación&ConsultoríaIT

e-learning

Page 3: Metaprogramación en JavaScript

JavierVélezReyes@javiervelezreye

[email protected]

1Introducción§  QuéEsLaMetaprogramación§  PorQuéLaMetaprogramación§  ElContextoDeLaMetaprogramación§  ElProcesoDeLaMetaprogramación§  LaMetaprogramaciónComoParadigma

Introd

ucción

Metap

rogram

aciónEn

JavaScrip

t

Page 4: Metaprogramación en JavaScript

@javiervelezreye4

IntroducciónMetaprogramaciónEnJavaScript

QuéEsLaMetaprogramación

La metaprogramación es una disciplina de programación queconsiste en construir programas que generan, manipulan omodificanotrosprogramas,incluidosellosmismos.

Definición

ProgramaComoProcesodeTransformaciónDeDatos

MetaprogramaComoProcesodeTransformaciónDeProgramas

El programa toma unos datos deentradayproduceunosresultadosdesalida de acuerdo a un proceso detransformación

Elmetaprogramatomaunosdatosdeentradaquerepresentanunprogramayvaloresdeconfiguraciónparadirigirel proceso de construcción de otroprograma

Page 5: Metaprogramación en JavaScript

@javiervelezreye5

IntroducciónMetaprogramaciónEnJavaScript

QuéEsLaMetaprogramación

En términos generales se puede pensar en dos grandes familiasdetécnicasdemetaprogramación.Laprogramacióngenera1vaylaprogramaciónorientadaacomponentes.

TiposDeMetaprogramación

MetaprogramaciónGeneraUvaProgramaciónGeneraUva

MetaprogramaciónComposiUvaP.OrientadaAComponentes

La programación generaBva confec-cionacódigonuevoaparBrdedatosde configuración y elementos deprogramas

La programación orientada a compo-nenteselaboranuevoscomponentesaparBr de la combinación composiBvadeotroscomponentes

Page 6: Metaprogramación en JavaScript

@javiervelezreye6

IntroducciónMetaprogramaciónEnJavaScript

PorQuéLaMetaprogramación

Algunas compañías se especializan en la construcción de un 1po de productos dentro de undominioespecífico.Conelánimodefomentarlareu1lizaciónconvieneconstruirartefactosquecontribuyanadominioenvezdelimitarsuaplicaciónalámbitodeunproyecto.

FactoríasdeSoXware.LaConstruccióndeunDominio

Requisitos

ProyectoA

Dominio

Soluciones

Requisitos

ProyectoB

Soluciones

Variantes

ProyectoA

Dominio

Soluciones

Variantes

ProyectoB

Soluciones

Invariantes

AproximaciónClásicaContribucionesAProyecto

AproximaciónMetaprogramáUcaContribucionesADominio

La reuBlización clásicamente se enBendecomounprocesodemigraciónde códigoentreproyectos

EnlaaproximaciónmetaprogramáBcaloscomponentesseexpresancomoartefactosabstractosaniveldedominio

Page 7: Metaprogramación en JavaScript

@javiervelezreye7

IntroducciónMetaprogramaciónEnJavaScript

PorQuéLaMetaprogramación

De esta manera se consigue reducir costes de desarrollo y mantenimiento por medio de laeconomíadeescalay laeconomíadealcance.Laprimerareducecostesporelaumentode laproduccióndeunsoloproducto.Lasegundaloconsigueporelabaratamientodelaadaptaciónenproductossimilares.

LíneasdeProducto.EconomíadeEscala&EconomíadeAlcance

Una línea de producción permite elabaratamientodecostesporeldesarrolloenmasadeungrannúmerodeproductosidénBcos

La línea de variación consigue elabaratamiento de costes por laconstruccióndeproductosmuysimilares

EconomíaDeEscala EconomíaDeAlcance

Producto1 ProductoN

ProyectoA

ProyectoK

Page 8: Metaprogramación en JavaScript

@javiervelezreye8

IntroducciónMetaprogramaciónEnJavaScript

PorQuéLaMetaprogramación

En términos generales, podemos resumir en cuatro los obje1vos principales de lametaprogramación.Automa1zación, reu1lización,mantenibilidadyextensibilidad.Todosellospromueven, enmayor omenormedida, tanto la economíade alcance como la economíadeescala.

AutomaUzación,ReuUlización,Mantenibilidad&Extensibilidad

Automa;zación

Reu;lización

ExtensibilidadMantenibilidad

El uso de componentes permite unaa d e c u a d a e s p e c i a l i z a c i ó n d eresponsabilidades que fomenta lamantenibilidad por susBtución departes

La automaBzación persigue la idea deconstruirsoRwareatravésdeprocesosdeconfecciónqueminimizanlosesfuerzosdedesarrollo

El carácter adaptaBvo o generaBvo de loscomponentes les confiere una mayorcapacidad evoluBva lo que facilita laextensibilidadglobaldelsistema

La plasBcidad contractual de loscomponentes se regenera o adaptapara permiBr que estos encajenfácilmente en diversos contextos deexplotaciónarquitectónica

Page 9: Metaprogramación en JavaScript

@javiervelezreye9

IntroducciónMetaprogramaciónEnJavaScript

ElContextoDeLaMetaprogramación

Elanalistadedominioestableceunadefiniciónformalycomputabledelproductomedianteelusodelenguajesespecíficosdedominio.Estadefiniciónseusaparaconfigurarelframeworkdemetaprogramaciónquear1cularálasoluciónespecíficarequerida.

PerspecUvaDeCajaNegra

FrameworkdeMetaprogramación

Invariantesdedominio

Variantesdeproducto

EspecificacióndeProducto

describe

Analista

Dominio

DSL

Invariantesdedominio

VariantesdeProducto

ModelodeConfiguración

El cliente especifica con ayuda delenguajes específicos de dominio laspartesvariantesdelaespecificacióndesuproducto

La especificación del producto específicoadap tado a l o s r eque r im i en to sparBculares del cliente queda capturadoentre las invariantes de dominio y lasvariantesdeproducto

Page 10: Metaprogramación en JavaScript

@javiervelezreye10

IntroducciónMetaprogramaciónEnJavaScript

ElContextoDeLaMetaprogramación

Laespecificaciónde lasvariantesdeproductoseprocesaparadeterminar losmetaprogramasque deben emplearse en el proceso construc1vo. Estos metaprogramas pueden u1lizarmetacomponenentes prediseñados y aplican técnicas de composición o generación paraproducircomponentes.

PerspecUvaDeCajaBlanca

usa

FrameworkdeMetaprogramación

MetacomponentesMetaprogramasdecomposiciónogeneradores

ComponentesdeProyecto

ProyectodeCliente

crea

Invariantesdedominio

define

Especificacióndeproducto

invoca

LenguajedeProgramación

LenguajedeMetaprogramación

Orquestador

Dominio

Analista

Page 11: Metaprogramación en JavaScript

@javiervelezreye11

IntroducciónMetaprogramaciónEnJavaScript

ElContextoDeLaMetaprogramación

En la metaprogramación está1ca las fases de elaboración y ejecución se desarrollansecuencialmente mientras que en la elaboración dinámica el desarrollo de ambas fases esparalelo. Esta segunda aproximación ofrece oportunidades de reelaboración que no sonposiblesconlametaprogramaciónestá1ca.

MetaprogramaciónEstáUca&Dinámica

ElaboraciónEstáUca

usa

FrameworkdeMetaprogramación

MetacomponentesMetaprogramasdecomposiciónogeneradores

ComponentesdeProyecto

crea

LenguajedeProgramación

LenguajedeMetaprogramación

Orquestadorpasivo

Especificacióndeproducto

En la elaboración estáBca primero seelaboran los componentes de cliente yluegoselanzanaejecución

Ladesventajasesqueunavez creados los compo-nentes, éstos no puedenreadaptarse

FasedeElaboración

FasedeEjecución

Page 12: Metaprogramación en JavaScript

@javiervelezreye12

IntroducciónMetaprogramaciónEnJavaScript

ElContextoDeLaMetaprogramación

En la metaprogramación está1ca las fases de elaboración y ejecución se desarrollansecuencialmente mientras que en la elaboración dinámica el desarrollo de ambas fases esparalelo. Esta segunda aproximación ofrece oportunidades de reelaboración que no sonposiblesconlametaprogramaciónestá1ca.

MetaprogramaciónEstáUca&Dinámica

ElaboraciónDinámica

FasedeElaboración

FasedeEjecución

Enlaelaboracióndinámicalaelaboraciónde los componentes de cliente se realizaenBempodeejecución

Esto permite que loscomponentes se readap-ten dinámicamente alcontextos cambiantes deuso

usa

FrameworkdeMetaprogramación

Metacomponentes

ComponentesdeProyecto

crea

LenguajedeProgramación

LenguajedeMetaprogramación

Especificacióndeproducto

Metaprogramasdecomposiciónogeneradores

Orquestadorpasivo

Page 13: Metaprogramación en JavaScript

@javiervelezreye13

IntroducciónMetaprogramaciónEnJavaScript

ElProcesoDeLaMetaprogramación

El proceso de construcción pormetaprogramación de un compo-nente atraviesa un conjunto defases conceptuales con propósitosdiferencialesycaracterís1cos.

CicloDeElaboración Niveldedominio

Niveldeproyecto

DescomposicióndiseñadaSelección

Adaptación

Composición

Encapsulación

Metacomponentes

Componente

C.Adaptado

Colaboración

C.Encapsulado

C.Contextualizado

Contextualización

Abstracción

Análisis

Page 14: Metaprogramación en JavaScript

@javiervelezreye14

IntroducciónMetaprogramaciónEnJavaScript

ElProcesoDeLaMetaprogramación

Laselecciónconsisteendeterminarlasvariantesespecíficasdecada1podemeta-componenteque formarán parte del proceso construc1vo. La selección está1ca es aquella que se realizaenteramenteantesdel1empodeejecución.Porelcontrario,laseleccióndinámicaimplicaqueelmetaprograma inyecta lógicadenegocioparaar1cular laselecciónen1empodeejecuciónpudiendohaceréstadinámicamentecambiante.

Selección

Selección

Variantesdeproducto

SelecciónEstá;caLa selección estáBca se resuelve antes delBempo de ejecución de manera que lasvariantes seleccionadas quedan definiBva-mentefijadas

SelecciónDinámicaLa ventaja de la selección dinámica es quepermitedarsoporteaescenariosdonde lasvariantes uBlizadas pueden cambiarduranteelBempodeejecución

Page 15: Metaprogramación en JavaScript

@javiervelezreye15

IntroducciónMetaprogramaciónEnJavaScript

ElProcesoDeLaMetaprogramación

La adaptación es el proceso mediante el cual un componente se adapta para resolver lasimpedancias que presenta con el contexto arquitectónico de explotación. La adaptaciónsintác1ca se centra en adaptar el contrato del componente mientras que la adaptaciónsemán1ca persigue modificar el comportamiento del artefacto a los requerimientos delproyecto. Tanto estandarizar los componentes como trabajar con componentes proto1po anivelmetaevitafrecuentementelaadaptación.

Adaptación

Adaptaciónsintác;ca&semán;caUn ejemplo de adaptación sintácBcaconsiste en cambiar los nombres de losmétodos de un componente. La decoraciónpor aspectos del comportamiento de unmétodo es un ejemplo de adaptaciónsemánBca

Estandarización&Proto;posLaestandarizacióndecontratosycomporta-mientos evita la adaptación. Asimismocuando los metacomponentes soncomponentes directamente operaBvos seposibil ita la ausencia ocasional deadaptación

ProyectoA ProyectoB ProyectoC

Adaptación

Page 16: Metaprogramación en JavaScript

@javiervelezreye16

IntroducciónMetaprogramaciónEnJavaScript

ElProcesoDeLaMetaprogramación

La composición es un ejercicio de transformación en el que un metacomponente al quellamaremosnúcleoseenriqueceporlaadquisicióndeciertalógicaparcialqueresideenotrouotrosmetacomponentesllamadosextensiones.Enelmarcodeestarelaciónbinariaesposibleanalizarelgradodedependenciaque1enencadaunadeestaspartesentresíparacaracterizarel1podecomposición.

Composición

Composición Núcleo

Dependiente Autónomo

Dependiente

AutónomoExtensión

ComposiciónCooperaBva

ComposiciónSubordinada

ComposiciónSubordinante

ComposiciónAutónoma

ProyectoA

Page 17: Metaprogramación en JavaScript

@javiervelezreye17

IntroducciónMetaprogramaciónEnJavaScript

ElProcesoDeLaMetaprogramación

Laencapsulaciónesunprocesomedianteelcualseestablecennuevasfronterasarquitectónicasen el marco de una composición que 1enen por obje1vo aislar la misma del contexto deexplotación. Este aislamiento permite la protección de la información. Por extensiónconsideraremos que todo mecanismo que garan1ce esta protección es una forma débil deencapsulación.

Encapsulación

Encapsulación

ProyectoBProyectoA

EncapsulaciónFuerteLa encapsulación fuerte es el procesomedianteelcualselevantanunasfronterasarquitectónicas nuevas en elmarcodeunarelacióncomposiBva

EncapsulaciónDébilPor extensión, consideraremos quecualquier mecanismo que proporcioneproteccióndeinformaciónenelmarcodelacomposiciónesunaformadeencapsulacióndébil

Page 18: Metaprogramación en JavaScript

@javiervelezreye18

IntroducciónMetaprogramaciónEnJavaScript

ElProcesoDeLaMetaprogramación

La contextualización es la fase úl1ma del proceso composi1vo mediante la cual se dota alcomponente de una condiciones ambientales de contexto que condicionarán sucomportamientoduranteel1empodeejecución.Cuandoestascondicionesambientalessefijanantes del 1empo de ejecución hablamos de contextualización está1ca. La variante dinámicapermitear1cularrecontextualizacionesen1empodeejecución.

Contextualización

Contextualización ContextualizaciónEstá;caLa contextualización estáBca resuelve lascondiciones ambientales de contexto antesdequeelcomponenteentreenelBempodeejecución.

ContextualizaciónDinámicaLa contextualización dinámica permiterestablecer recurrentemente el contexto deejecución lo que ofrece mayores oportu-nidadesdeadaptación

Estado

LógicaA

B

C

Page 19: Metaprogramación en JavaScript

@javiervelezreye19

IntroducciónMetaprogramaciónEnJavaScript

LaMetaprogramaciónComoParadigma

Entornoalconceptodecomponentesepuedendescribirtresejesdimensionales.Losobje1vosdeterminanlospropósitosperseguidos,losmecanismoscaracterizanlascapacidadesna1vasdellenguajeylosprincipiosdediseñoofrecendirectricesgeneralesdeactuación.

EjesDimensionales

Principios

MecanismosC

Auto

Reut

Ctx

Ref

Ext

Sust Her

Man

Int

Del

Ext

Adap

ObjeUvos

Pol

Los objeBvos responden a quénuevas caracterísBcas estruc-turales y funcionalespersigueelparadigma

¿Que?

Los principios ofrecen directrices acercade cómo proceder para apl icaradecuadamente los mecanismos dellenguaje

¿Cómo?

Losmecanismossonlascapacidadesdel lenguaje que permiten alcanzarlosobjeBvosperseguidos

¿Conqué?

Page 20: Metaprogramación en JavaScript

@javiervelezreye20

IntroducciónMetaprogramaciónEnJavaScript

LaMetaprogramaciónComoParadigma

En torno a los tres ejes dimensionales se pueden establecer sendos planos de ac1vidad. Lastécnicasindicancómoaplicarlosmecanismosdellenguaje,lospatronespresentansolucionesaproblemas recurrentes y los modelos arquitectónicos ofrecen restricciones que determinancomoproceder.

PlanosDeAcUvidad

Principios

MecanismosC

Auto

Reut

Ctx

Ref

Ext

Sust Her

Man

Int

Del

Ext

Adap

Programadores

Diseñadores

Arquitectos

PlanoTecnológico

ObjeUvos

Patronesd

eDiseño

Pol

Los modelos y restriccionesarquitectónicas proporcionand i r e c t r i c e s gene ra l e s quedeterminan cómo construirsoluciones soRware basadas enmetaprogramación

Modelos&Restricciones

Eldiseñodefineformascanónicasdeaplicar losmecanismosdel lenguajeparaproblemasrecurrentes

PatronesdeDiseño

Las técnicas indican cómoaplicar losmecanismos del lenguaje en elproceso de metaprogramación paraalcanzarlosobjeBvos

Técnicas

Page 21: Metaprogramación en JavaScript

@javiervelezreye21

IntroducciónMetaprogramaciónEnJavaScript

LaMetaprogramaciónComoParadigma

En torno a los tres ejes dimensionales se pueden establecer sendos planos de ac1vidad. Lastécnicasindicancómoaplicarlosmecanismosdellenguaje,lospatronespresentansolucionesaproblemas recurrentes y los modelos arquitectónicos ofrecen restricciones que determinancomoproceder.

PlanosDeAcUvidad

Principios

MecanismosC

Auto

Reut

Ctx

Ref

Ext

Sust Her

Man

Int

Del

Ext

Adap

Programadores

Diseñadores

Arquitectos

PlanoTecnológico

ObjeUvos

Patronesd

eDiseño

Pol

Capítulo1

}

}Capítulo2

}

Capítulo3

Capítulo4 }

Page 22: Metaprogramación en JavaScript

JavierVélezReyes@javiervelezreye

[email protected]

2JavaScript como Lenguaje De Metaprogramación

§  Introducción§  Delegación&HerenciaEnLaComposición§  Polimorfismo&AbstracciónEnLaComposición§  Contextualización&ReflexiónEnLaComposición

JavaScrip

tCom

oLeng

uajeDeMetap

rogram

ación

Metap

rogram

aciónEn

JavaScrip

t

Page 23: Metaprogramación en JavaScript

@javiervelezreye23

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

Introducción

Elespaciodeposiblesopcionescuandoabordamosproblemasdemetaprogramaciónesmuyamplio.Nuestrofocodeatenciónaquíen primer lugar será discu1r problemas en el marco de lacomposiciónynode lageneración.Enestecapítuloveremos lasprincipales caracterís1cas del lenguaje que permiten ar1cularprocesosdeconfeccióncomposi1va.

MetaprogramaciónComposiUva

A

B

Porotro ladonoscentraremosenescenariosde composición dinámica donde la fase deelaboración y ejecución coexisten durante el1empodeproduccióndelasoluciónso`ware.Comoveremosesto requierequeel lenguajede metaprogramación y programacióncoincidan y frecuentemente se entre-mezclarán técnicas propias de ambosnivelesdedesarrollo.

ComposiciónDinámica

FasedeElaboración

FasedeEjecución

Page 24: Metaprogramación en JavaScript

@javiervelezreye24

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

Introducción

Como discu1remos, JavaScript es un buen candidato comolenguaje para cubrir las necesidades propias de los procesos demetaprogramación. En efecto, su carácter dinámico, su sistemade1pificacióndébily susistemadeclasesbasadoenproto1posconfierenalosartefactosconstruidosunaltogradodeplas1cidadadapta1vaquefacilitalosprocesosdemetaprogramación.

CapacidadesDelLenguaje

Sin embargo, aquí restringiremos nuestros estudio alas capacidades del lenguaje en el marco de unmodelode componentesbasadoenobjetos. Enestesen1docomprobaremosquelasálgebras deobjetosresultan muy flexibles y potentes para ar1cularprocesos de metaprogramación. Quedan fuera lascapacidades del lenguaje v inculadas a laprogramación funcional que fomentan un es1lomásgenera1voquecomposi1vo.

ModeloDeObjetos

TipificaciónDébil

ProtoUpos

Dinamicidad

JavaScript

ModelodeObjetos

ModelodeFunciones

DelegaciónHerenciaPolimorfismoLigaduraDinámica

OrdenSuperiorClausurasEvaluaciónParcial

Page 25: Metaprogramación en JavaScript

@javiervelezreye25

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

CapacidadesDeJavaScriptEnElModeloDeObjetos

Losobjetossonelciudadanodeprimeracategoríadentrodeestemodelo. En JavaScript un objeto es un mero agregador depropiedades organizado como un diccionario cuyos valorespueden ser 1pos primi1vos o funciones que ejecutan en elcontextodelobjeto.

LosObjetosEnLaComposición

ObjetosAbiertosvar o = { };

var o = { x : 1, y : 1, z : 1 };

var o = { x : 1, y : 1 };

o.x = 1; o.y = 1; o.z = 1;

delete o.z Podemosampliary reducir lacargasemánBcadel objeto a través de operaciones demodificaciónsobreelmismo

El objeto en JavaScript es unmero agregadordecaracterísBcasfuncionalesydeestadoperonoconsBtuyeunclasificadorestricto

Objetoscomoagregadores

Objetosabiertos

o{ p1: v1, ... pn: vn, m1: function (){}, ... mn: function (){} }

Page 26: Metaprogramación en JavaScript

@javiervelezreye26

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

CapacidadesDeJavaScriptEnElModeloDeObjetos

Por medio de la delegación se ar1culan esquemas decolaboración entre objetos de manera que los algoritmos sedistribuyen entre el ecosistema de objetos par1cipantes. Estopermitear1cularunaadecuadadivisiónde responsabilidadesenlasfasespreliminaresdediseño.

LaDelegaciónEnLaComposición

DynamicBinding

var a = { d: b, m: function (){ d.n(); } };

var b = { n: function (){ ... } }

b.n = function () { ... };

El enlace dinámico permite resolver lalocalizacióndelmétodollamadojustoantesdelainvocaciónloquesealineaconelmodelodeobjetosabiertos

var b = { };

Enlacedinámico

b{ n: function (){ ...; } }

Elesquemadedelegaciónimponeunaparte estáBca, que determina elnombre del método a invocar y otradinámica que informa del objetodonderesidedichométodo

a{ d: B, m: function (){ d.n(); } }

Delegación

Page 27: Metaprogramación en JavaScript

@javiervelezreye27

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

CapacidadesDeJavaScriptEnElModeloDeObjetos

Otrarelacióndedelegación implícitaentreobjetossemarcapormediode lacadenadeproto1pado.Todoobjetosevinculaaunproto1poenelquedelegalabúsquedadeunapropiedadcuandoésta no se encuentra en el propio objeto. Las clases sonproto1posdeobjetosconloqueesteconceptoseconvierteenunrol.

LaHerenciaEnLaComposición

Dado que las clases se representan comoobjetosprotoBpo,laspropiedadesanterioresseaplicanalarelacióndeherencia

Proto;pos

En JavaScript la herencia es un Bpoespecial de delegación. Dado que lasclasesserepresentancomoprotoBposlos conceptos de clase y objeto sonmeros roles en tornoa la relacióndeherencia

Herencia

o{ n: function (){ this.m(); } }

p[[prototype]]

{ m: function (){ ... } }

LaherenciaesunaformadedelegaciónfuerteatravésdelacadenadeprotoBpado.Debidoalcarácterabiertode los protoBpos es la forma más dinámica dedelegación

HeredaresDelegar

var p = { m: function (){ ... } }

p.m = function () { ... };

var p = { }; var o = Object.create(p);

o.n = function (){ this.m(); };

ProtoUposcomoClases

Page 28: Metaprogramación en JavaScript

@javiervelezreye28

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

CapacidadesDeJavaScriptEnElModeloDeObjetos

En JavaScript el polimorfismo sólo puede interpretarse entérminos de la conformidad a un contrato establecido porconvenio. A diferencia de otros lenguajes, esta conformidadpuedesertotaloparcial.

ElPolimorfismoEnLaComposición

DuckTyping

Para garanBzar que o es compaBble con elprotocolo de c, se debe imponer la existenciade un método m en o. La metaprogramaciónpuedetransformaroenestesenBdo

DuckTyping

Losobjetosaybresultanconformesauncontratodefinidopor laexistenciadelmétodom. Esto es una forma depolimorfismo débil que no estáarBculada a través de herencia ni dedefinicióndeinterfaces

ConformidadContractual

b{ m: function () {}, y: function () {} }

var o = { }; c.m(o);

var c = { m: function (o){ o.m(); } };

var o = { m: function () {} }; c.m(o);

o.m = function () { ... };

a{ m: function () {}, x: function () {} }

Page 29: Metaprogramación en JavaScript

@javiervelezreye29

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

CapacidadesDeJavaScriptEnElModeloDeObjetos

A travésdel polimorfismodébil queofrece JavaScript esposiblealcanzarcotasdeexpresividaddemayorabstracción.Estoesunapropiedadmuyconvenienteparaladefinicióndemetaprogramasquedebenoperaren términosdealtageneralidad. El siguienteejemplomuestraunesquemaqueoperaanivelabstracto.

LaAbstracciónEnLaComposición

Abstracción

Losalgoritmossepuedenexpresarentérminosabstractos asumiendo que cada objetoparBcipanteincluiráunaversiónpolimórficadelosmétodosimplicados

Abstracción

Losobjetosaybresultanconformesaun contrato que incluye los métodosmyn.Elobjetocesunartefactoconconformidad parcial a dicho contratoque sin embargo no puede usarse enaquellosprotocolosdondeserequieram.

ConformidadParcial

a{ m: function () {}, n: function () {} }

os[2].m = function () { ... };

var os = [a, b, c]; app.all (os);

var app = { all: function (os){ for (o in os) o.m(); } };

var os = [a, b, c]; app.all (os);

b{ m: function () {}, n: function () {} }

c{ m: function () {}, }

Page 30: Metaprogramación en JavaScript

@javiervelezreye30

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

CapacidadesDeJavaScriptEnElModeloDeObjetos

Los métodos del modelo de objetos se diferencian de lasfunciones en el uso de un parámetro implícito – this – quereferencia al contexto donde dicho método debe ejecutarse.Dicho contexto puede ser alterado por diversos mecanismosexplícitosoimplícitosdellenguaje.

LaContextualizaciónEnLaComposición

PunteroImplícitothis

Las capacidades de recontextualización queofrece JavaScript permiten arBcular diversosesquemas de conexión composiBva quecondicionan la variante funcional que se va ainvocarencadacaso

Recontextualizaciónbind permite especificar que elmétodo m debe ejecutarse en elcontexto del objeto b. Esto Benerepercusiones acerca de a quienafecta el código dentro de m ypermite arBcular composicionesinteresantes

Contextualización

os[2].m = function () { ... };

var os = [a, b, c]; app.all (os);

var app = { all: function (os){ for (o in os) o.m(); } };

var os = [a, b, c]; app.all (os);

a{ m: function () { return this.n(); }.bind (b) }

b{ n: function () {} }

Page 31: Metaprogramación en JavaScript

@javiervelezreye31

JavaScriptComoLenguajeDeMetaprogramaciónMetaprogramaciónEnJavaScript

CapacidadesDeJavaScriptEnElModeloDeObjetos

Lamayoría de losmetaprogramas hacen uno de las capacidades reflexivas del lenguaje. Unaarquitectura reflexiva es aquella queofrece al programador ciertosmetadatos para permi1rledescubrir las caracterís1cas de los elementos del entorno de ejecución. A con1nuaciónresumimoslascapacidadesesencialesdereflexiónenJavaScript.

LaReflexiónEnLaComposición

A

B{ p1: v1, ... pn: vn, m1: function (){}, ... mn: function (){} }

Object.keys (o), Object.getOwnPropertyNames (o), Object.freeze (o) Object.seal (o) Object.preventExtensions (o) Object.isFrozen (o) Object.isSeal (o) Object.isExtensible (o)

ReflexividadaNiveldeObjeto

Object.defineProperty (o, p, {}) Object.defineProperties (o, {}) Object.getOwnPropertyDescriptor (o, p) o.hasOwnProperty (p) o.propertyIsEnumerable (p)

ReflexividadaNiveldePropiedad

Object.getPrototypeOf (o) o1.isPrototypeOf (o2) o.prototype o.constructor o.__proto__

ReflexividadaNiveldeProto;po

Page 32: Metaprogramación en JavaScript

JavierVélezReyes@javiervelezreye

[email protected]

3Técnicas De Metaprogramación Compositiva

§  TécnicasdeAdiciónComposi1va§  TécnicasdeExtensiónComposi1va§  TécnicasdeIntercesiónComposi1va§  TécnicasdeDelegaciónComposi1va

TécnicasDeMetap

rogram

acionCo

mpo

si;v

a

Metap

rogram

aciónEn

JavaScrip

t

Page 33: Metaprogramación en JavaScript

@javiervelezreye33

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

Introducción

Lametaprogramacióncomposi1vasecaracterizaporelhechodeque man1ene la estructura esencial de los componentes. Todoejercicio metaprogramá1co en este sen1do se reduce a unconjunto de ac1vidades de intervención puntual que pretendenadaptar,conectarocontextualizarcódigodeloscomponentes.

LaMetaprogramaciónComposiUvaComoIntervención

El conjunto potencial de intervenciones sobre unmodelo de componentes queda impuesto por lascapacidades metaprogramá1cas del lenguaje y elmodeloseleccionado.A lo largodeestecapítulonoscentraremos en objetos aunque es fácil hacer unaadaptación de los metaprogramas para que operensobre las álgebras funcionales. Diremos que cadapunto de intervención dentro de un componente esun code holder mientras que el conjunto de todosellos conforman el contrato de composición sobremodeloelcomponente.

CodeHolders&ContratosDeComposición

TransformaciónrestringidaIntervención

puntual

Contratodecomposición

Codeholderopuntodeintervención

Componente

Page 34: Metaprogramación en JavaScript

@javiervelezreye34

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

Introducción

Sobre los puntos de intervención definidos por cada uno de loscodeholdersesposiblerealizarac1vidadesdemetaprogramaciónrelacionadasconlainyeccióndecódigo.Lasposiblesvariantesdeinyección de código se describen a par1r de la definición de unconjunto de operadores o primi1vas de composición propias decada1podecodeholder.

InyecciónDeCódigo&PrimiUvasDeComposición

Losprogramasencargadosdellevaracaboelprocesode inyección de código sobre cada uno de los codeholders del modelo de componentes se llamanmetaprogramas. Estos algoritmos u1lizan losoperadores de composición para garan1zar que losprocesos de intervención son conformes con losdiferentes 1pos de code holders. A lo largo de estecapítulodescribiremosloscodeholdersenJavaScriptsobre el modelo de objetos y las operación decomposiciónvinculadasaellos.

Metaprogramas&Intervención

Códigoinyectado

MetaprogramacomposiUvo

Procesodeinyeccióndecódigo

Page 35: Metaprogramación en JavaScript

@javiervelezreye35

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

Introducción

A diferencia de lo que ocurre en otras aproximaciones decomposición, en JavaScript se impone que el modelo decomponente y metacomponente coincidan. Es decir, unmetacomponente es en realidad un componenteconvencional que funciona como ejemplar protocpico paraconfeccionar componentes opera1vos al nivel deprogramación.

MetacomponentesComoComponentesProtoUpo

En el campo de la metaprogramación composi1va, losmeta-programassecaracterizanporrecibircomoentradacada una de las partes par1cipantes en el procesocomposi1vo – núcleo y extensiones. El código delmetaprogramaoperasobreestoselementos demaneraexógena. Es decir, éste no se incluye dentro de losmismos. En aproximaciones genera1vas el código delmetaprograma coincide con el del componenteresultante. Este 1po de meta-programación se conocecomoendógena.

MetaprogramaciónExógenaMetaprogramacomposiUvo IN

OUT

NiveldeMetaprogramación

Metacomponente Componente

=NiveldeProgramación

Page 36: Metaprogramación en JavaScript

@javiervelezreye36

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorAdición

Las técnicas adi1vas persiguen ampliar la lógica de uncomponente con nueva funcionalidad. De esta manera elcomponente se adapta a nuevos contextos arquitectónicosdondelalógicaadicionadaesrequerida.

Definición

Los puntos de intervención en este casoreflejanelcarácterabiertodelosobjetosenJavaScript con lo que es posible alterar elconjuntodecaracterís1casdelosmismos.

CodeHolders

Componenteoriginal

AdiciónmetaprogramáBca

Objeto{ p1: v1, ... pn: vn, m1: function (){}, ... mn: function (){} }

HoldersdePropiedad

HoldersdeMétodomiembro

Page 37: Metaprogramación en JavaScript

@javiervelezreye37

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorAdición

Los operadores de composición fundamentales que hacenusodetécnicasadi1vaspermitenañadir,borrar,actualizaryrenombrar lascaracterís1cas–métodosypropiedades–deunobjeto.

OperadoresDeComposiciónPorAdición

Losoperadoresfundamentalessecentranenoperar sobre el conjunto de caracterísBcasde un componente que funciona comonúcleo.

OperadoresfundamentalesdeAdición

mp.add (o, 'x', 1); mp.remove (o, 'x') mp.update (o, 'x', 1); mp.add (o, 'x', 1); mp.rename (o, 'x', 'y'); mp.update (o, 'x', 5);

{} { x: 1 } {} {} { x: 1 } { y: 1 } { y: 5 }

Operador o

mp.add = function add (core, key, value) { core[key] = value; }; mp.remove = function remove (core, key) { delete core[key]; }; mp.update = function update (core, key, value) { if (core[key]) mp.add (core, key, value); }; mp.rename = function rename (core, oldKey, newKey) { mp.add (core, newKey, core[oldKey]); mp.remove (core, oldKey); };

Page 38: Metaprogramación en JavaScript

@javiervelezreye38

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorAdición

Como extensión a los operadores de adición se puedenincluirprimi1vasquepermiten copiar ymoverpropiedadesde un objeto a otro o extender un objeto core con lascapacidadesdeotrocomoextensión.

OperadoresDeComposiciónPorAdición

Los operadores fundamentales se comple-mentanconotroconjuntodeoperadoresqueimplicanunnúcleoyunaextensión

OtrosoperadoresdeAdiciónmp.copy = function copy (core, ext, key) { mp.add (core, key, ext[key]); }; mp.move = function move (core, ext, key) { mp.copy (core, ext, key); mp.remove (core, key); }; mp.extend = function extend (core, ext) { var keys = Object.getOwnPropertyNames (ext); keys.forEach (function (key) { mp.copy (core, ext, key); }); };

mp.copy (o2, o1, 'y'); mp.remove (o2, 'y'); mp.move (o2, o1, 'x'); mp.extend (o1, o2);

{ y: 5 } {} { y: 5 } { y: 5 } { y: 5 } {} {} { y: 5 } {x: 0} {y: 0} {x: 0, y: 0} {y: 0}

Operador o1 o2

Page 39: Metaprogramación en JavaScript

@javiervelezreye39

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorExtensión

Las técnicas extensivas 1enen por objeto reformular lascapacidades funcionales del componente por medio de laespecializaciónsemán1ca.Este1podetécnicasseencuentraestrechamentevinculadoa laherenciaporproto1poscomomecanismodellenguaje.

Definición

Sobreuna jerarquíadeherencia es posiblealterarlaposiciónrela1vadeloselementoso reescribir la semán1ca de los métodosmiembrosdelhijo.Ademássepuedeoperarsobre los enlaces de la cadena de proto-1pado.

CodeHolders

Componenteoriginal

ExtensiónmetaprogramáBca

Objeto{ p1: v1, ... pn: vn, m1: function (){}, ... mn: function (){} }

HoldersdeMovimiento

Holdersdesobrescritura

ProtoUpo

[[Prototype]]

HolderdeEnlaceaProtoBpo

Page 40: Metaprogramación en JavaScript

@javiervelezreye40

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorExtensión

Los operadores fundamentales que hacen uso de técnicasextensivasestánrelacionadosconlaalteracióndelacadenadeproto1pado.Esposibleañadir,borraroinver1relsen1dodeestarelación.

OperadoresDeComposiciónPorExtensión

Mediante estrategias reconstrucBvas esposible cambiar dinámicamente el valor delarelacióndeprotoBpadoentreobjetos

OperadoresfundamentalesdeExtensiónmp.setPrototype = function (core, proto) { var ch = Object.create (proto); mp.extend (ch, core); return ch; }; mp.removePrototype = function (core) { return mp.setPrototype (core, null); }; mp.reversePrototype = function (core) { var proto = Object.getPrototypeOf (core); return mp.setPrototype (proto, core); };

mp.setPrototype(o, p); mp.removePrototype (o); mp.reversePrototype (o);

o -> p o o <- p

Operador o p

Page 41: Metaprogramación en JavaScript

@javiervelezreye41

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorExtensión

Los operadores de copia y movimiento por metaprogra-mación permitenmover y copiar ascendente y descenden-tementecaracterís1caspresentesentreunproto1poycadaunodesusobjetoshijos.

OperadoresDeComposiciónPorExtensión

Las operaciones de copia y movimiento decaracterísBcaspor lacadenadeprotoBpadopermitenalterarlasemánBcadefinidaporlarelaciónjerárquicaentreobjetos

OperadoresfundamentalesdeExtensión

Operador o p

mp.copyUp = function (core, key) { var proto = Object.getPrototypeOf (core); if (proto) mp.add (proto, key, core[key]); }; mp.copyDown = function (core, key, child) { mp.add (child, key, core[key]); }; mp.moveUp = function (core, key) { mp.copyUp (core, key); mp.remove (core, key); }; mp.moveDown = function (core, key, child) { mp.add (child, key, core[key]); mp.remove (core, key); };

mp.copyUp (o, 'x'); mp.copyDown (p, 'x', o); mp.moveUp (o, 'x'); mp.moveDown (p, 'x', o);

o{x} -> p, o{x} -> p{x} o -> p{x}, o{x} -> p{x} o{x} -> p, o -> p{x} o -> p{x}, o{x} -> p

Page 42: Metaprogramación en JavaScript

@javiervelezreye42

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorIntercesión

La intercesión permite inyectar lógica de decoración demaneraentrelazadaconel códigooriginaldel componente.Elpropósitodeeste1podetécnicasesampliarlasemán1cadelmismosinextendersucontrato.

Definición

Encuantoapropiedadessepuede inyectarcódigoparaqueseejecuteantesydespuésde acceder a las mismas tanto para sulectura como para su escritura. En losmétodos, existe similarmente decoraciónanterior y posterior a la invocación, peroademás tambiénesposible inyectarcódigoque se ejecutará cuando el métodoexplícitamentelodemande.

CodeHolders

Componenteoriginal

IntercesiónmetaprogramáBca

Objeto{ p1: v1 , pn: vn ,

m: function (){ <<code>> } }

Holderbeforedeacceso

Holderbeforedeinvocación

HolderaRerdeinvocación

Holderarounddeinvocación

HolderaRerdeacceso

Page 43: Metaprogramación en JavaScript

@javiervelezreye43

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorIntercesión

Los operadores de intercesión fundamentales permitendecorar la invocación de métodos inyectando lógicafuncionalqueseejecutaantesodespuésdelaac1vacióndelmétodo.

OperadoresDeComposiciónPorIntercesión

Los operadores fundamentales de intercesiónpermiten inyectar lógica funcional que seejecutaráantesodespuésdelmétodo

OperadoresfundamentalesdeIntercesión

Operador o

mp.before = function before (core, key, ext) { var fn = core[key]; core[key] = function () { ext.apply (this, arguments); return fn.apply (this, arguments); }; }; mp.after = function after (core, key, ext) { var fn = core[key]; core[key] = function () { var r = fn.apply (this, arguments); ext.apply (this, arguments); return r; }; };

mp.before (o, 'f', g); mp.after (o, 'f', g);

{f: function() {...} } f, g g, f

Page 44: Metaprogramación en JavaScript

@javiervelezreye44

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorIntercesión

Adicionalmente, y como una especialización de losoperadores anteriores, se puede decorar un método enbefore para condicionar el su ejecución en función delresultadoemi1doporunaextensióndeguarda.

OperadoresDeComposiciónPorIntercesión

LosoperadoresdeguardauBlizan técnicasdeintercesiónparacondicionarlaejecucióndeunmétodo en función del resultado emiBdo porciertopredicadológico

OperadoresfundamentalesdeIntercesión

Operador o

mp.provided = function provided (core, key, ext) { var fn = core[key]; core[key] = function () { if (ext.apply (this, arguments)) return fn.apply (this, arguments); }; }; mp.except = function except (core, key, ext) { var fn = core[key]; core[key] = function () { if (!ext.apply (this, arguments)) return fn.apply (this, arguments); }; };

mp.provided (o, 'f', p); mp.except (o, 'f', p);

{f: function() {...} } f sii p es true f sii p es false

Page 45: Metaprogramación en JavaScript

@javiervelezreye45

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorIntercesión

Asimismoesposibleconcederaunmétodoelcontrolacercadecuandoseejecutaráciertadecoraciónproporcionadaporelclienteenelcontextodesuesquemaalgorítmico.

OperadoresDeComposiciónPorIntercesión

En este caso el código core, f, manBenereferencias explícitas a una función dedecoración, r, pasada por convenio comoprimerargumento

OperadorexplícitodeIntercesión

Operador o

mp.around = function around (core, key, ext) { var fn = core[key]; core[key] = function () { var args = [].slice.call(arguments); args = [ext.bind(this)].concat(args); return fn.apply (this, args); }; };

Enejecución,enelesquemadedecoración se susBtuye rporg

La extensión, g, se anteponecomo primer parámetro a losargumentos de la funcióndecoradaf mp.around (o, 'f', g);

{f: function(r) { r(); ... r (); } } g, ..., g

Page 46: Metaprogramación en JavaScript

@javiervelezreye46

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorIntercesión

Los operadores de acceso a propiedades para lectura yescritura en before permiten inyectar código que seejecutaráantesdelaccesoalaspropiedades.

OperadoresDeComposiciónPorIntercesión

Se decoran los métodos de acceso ymodificación a propiedades get y set y semanBeneunavariableocultaparasoportarelestadodelapropiedad.

OperadorexplícitodeIntercesión

Operador o

La extensión, g, se anteponecomo primer parámetro a losargumentos de la funcióndecoradaf

mp.beforeGetAtt = function (core, key, ext) { Object.defineProperty (core, '_' + key, { value: core[key], enumerable: false, ... }); Object.defineProperty (core, key, { get: function () { ext.call (this, arguments); return core['_' + key]; } }); }; mp.beforeSetAtt = function (core, key, ext) { Object.defineProperty (...); Object.defineProperty (core, key, { set: function (v) { ext.call (this, v); core['_' + key] = v; } }); };

mp.beforeGetAtt (o, 'x', f) mp.beforeSetAtt (o, 'x', f)

{x: 0} o.x -> f, 0 o.x = 3 -> f, {x: 3}

Page 47: Metaprogramación en JavaScript

@javiervelezreye47

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorIntercesión

Similarmente, losoperadoresdeaccesoapropiedadesparalecturayescrituraena`erpermiten inyectarcódigoqueseejecutarádespuésdelaccesoalaspropiedades.

OperadoresDeComposiciónPorIntercesión

Se decoran los métodos de acceso ymodificación a propiedades get y set y semanBeneunavariableocultaparasoportarelestadodelapropiedad.

OperadorexplícitodeIntercesión

Operador o

La extensión, g, se anteponecomo primer parámetro a losargumentos de la funcióndecoradaf

mp.afterGetAtt = function (core, key, ext) { Object.defineProperty (core, '_' + key, { value: core[key], enumerable: false, ... }); Object.defineProperty (core, key, { get: function () { var r = core['_' + key]; ext.call (this, arguments); return r; } }); }; mp.afterSetAtt = function (core, key, ext) { Object.defineProperty (...); Object.defineProperty (core, key, { set: function (v) { core['_' + key] = v; ext.call (this, v); } }); };

mp.afterGetAtt (o, 'x', f) mp.afterSetAtt (o, 'x', f)

{x: 0} o.x -> 0, f o.x = 3 -> {x: 3}, f

Page 48: Metaprogramación en JavaScript

@javiervelezreye48

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorDelegación

Las técnicas basadas en delegación ar1culan estrategiascomposi1vasquepermitendispersarlalógicadeunservicioentrevarioscomponentesconiden1dadpropiadentrodelaarquitectura pero estableciendo fachadas de desacopla-miento.

Definición

Los puntos de intervención en esta familiade técnicas coinciden con los de laintercesión. La diferencia estriba en estecaso en que los metaprogramas inyectancódigo dirigido a establecer esquemasdelega1vosaotralógica.

CodeHolders

Objeto{ p1: v1 , pn: vn ,

m: function (){ <<code>> } }

Holderbeforedeacceso

Holderbeforedeinvocación

HolderaRerdeinvocación

Holderarounddeinvocación

HolderaRerdeacceso

Componenteoriginal

DelegaciónmetaprogramáBca

Page 49: Metaprogramación en JavaScript

@javiervelezreye49

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorDelegación

Este 1po de operadores ar1culan procesos de composiciónpor delegación interna y externa mediante la construccióndemétodosproxyañadidosalcore.

OperadoresDeComposiciónPorDelegación

Ladelegación internapermitegenerarunmétodo de proxy que delega en otrométodo del mismo objeto. La delegaciónexterna se produce entre objetosdiferentes

OperadorfundamentalesdeDelegación

Operador o1 [o2]

mp.innerDelegate = function (core, oKey, nKey, ctx) { var context = ctx || core; core[nKey] = function () { return core[oKey].apply (context, arguments); }; }; mp.outerDelegate = function (core, ext, key, ctx) { var context = ctx || ext; core[key] = function () { var r = ext[key].apply (context, arguments); return r === ext ? this : r; }; };

mp.innerDelegate(o1,'f','g') mp.outerDelegate(o1,o2,'f')

{f} {g:function(){o1.f()} f} {} {f} {f:function(){o2.f()}} {f}

Page 50: Metaprogramación en JavaScript

@javiervelezreye50

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorDelegación

A par1r de los operadores anteriores se definen losoperadores de forwarding y proxy en forwarding quecontextualizanlainvocacióneneldelegado.

OperadoresDeComposiciónPorDelegación

El forwarding es una modalidad dedelegación débil contextualizada en eldelegado. Es lo que se conocer pordelegaciónconvencionanen los lenguajesdeOOP

OperadorfundamentalesdeDelegación

Operador o1 [o2]

mp.forward = function (core, ext, key) { mp.outerDelegate (core, ext, key, ext); }; mp.forwardProxy = function (core, ext) { if (typeof(ext) === 'string') ext = core[ext]; if (ext) { var keys = Object.keys (ext); keys.forEach (function (key) { if (typeof (ext[key]) === 'function') mp.forward (core, ext, key); }); } };

mp.forward (o1,o2,'f') o1.f()

{x:1}{x:3, f(){return this.x}} 3

Page 51: Metaprogramación en JavaScript

@javiervelezreye51

TécnicasDeMetaprogramacionComposi1vaMetaprogramaciónEnJavaScript

TécnicasDeMetaprogramaciónPorDelegación

Similarmente, los operadores fundamentales puedenu1lizarse para ar1cular técnicas de delegación contextual-lizadasenelcore.

OperadoresDeComposiciónPorDelegación

La delegación es la forma más fuerte ydinámica de vinculación composiBva. Enellael contextodeevaluaciónpermaneceenelobjetocore

OperadorfundamentalesdeDelegación

Operador o1 [o2]

mp.delegate = function (core, ext, key) { mp.outerDelegate (core, ext, key, core); }; mp.delegateProxy = function (core, ext) { if (typeof(ext) === 'string') ext = core[ext]; if (ext) { var keys = Object.keys (ext); keys.forEach (function (key) { if (typeof (ext[key]) === 'function') mp.delegate (core, ext, key); }); } };

mp.delegate (o1,o2,'f') o1.f()

{x:1}{x:3, f(){return this.x}} 1

Page 52: Metaprogramación en JavaScript

JavierVélezReyes@javiervelezreye

[email protected]

4Modelos Arquitectónicos De Composición

§  ModelosArquitectónicosBasadosenAdición§  ModelosArquitectónicosBasadosenIntercesión§  ModelosArquitectónicosBasadosenDelegación

Mod

elosArquitectón

icosDeCo

mpo

sición

Metap

rogram

aciónEn

JavaScrip

t

Page 53: Metaprogramación en JavaScript

@javiervelezreye53

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

Introducción

Existen diversos modelos arquitectónicos de metaprogramación composi1va que basan suimplementación en cadaunode las cuatro técnicas descritas en el capítulo anterior. En estecapítulodescribimosdichosmodelos.

ModelosArquitectónicosSegúnTécnicasComposiUvas

MixinsBasedProgramming

TraitsBasedProgramming

Adición

AspectOrientedProgramming

Intercesión

RoleProgramming

ComposiBonFilters

Delegación

Adap1veProgramming

SubjectOrietedProgramming

Extensión

LayeredObjects

Page 54: Metaprogramación en JavaScript

@javiervelezreye54

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnAdición

Losmixins son extensiones que describen abstracciones dedatosparcialesparaserañadidosauncore.Ellosagreganelestadoalespaciodedichocore.

Mixins

var john = { first: 'John', last : 'Doe' };

var isAuthor = { books: [], addBook: function (name) { this.books.push(name); return this; }, getBooks: function () { return this.books; } };

var isParent = { children: [], addChild: function (name) { this.children.push(name); return this; }, getChildren: function () { return this.children; } };

mp.mixin (john,isAutor) mp.mixin (john,isParent)

MixinA

MixinB

CoreAdición Adición

s

mp.mixin = function (core, ext) { var keys = Object.getOwnPropertyNames(ext); keys.forEach (function (key) { mp.copy (ext, core, key); }); };

Page 55: Metaprogramación en JavaScript

@javiervelezreye55

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnAdición

Los mixins generan problemas potenciales de colisión deestado ya que varios mixins pueden u1lizar los mismosatributosdesoporte.Encapsularelestadopermiteevitarlo.

Mixins.ColisióndeEstado

var john = { first: 'John', last : 'Doe' };

mp.mixin (john,isAutor)

MixinA

MixinB

CoreAdición Adición

{s}

var isAuthor = { data: [], addBook: function (name) { this.data.push(name); return this; }, getBooks: function () { return this.data; } };

var isParent = { data: [], addChild: function (name) { this.data.push(name); return this; }, getChildren: function () { return this.data; } };

mp.mixin = function (core, ext) { var context = Object.create (null); var keys = Object.getOwnPropertyNames(ext); keys.forEach (function (key) { if (typeof (ext[key]) === 'function') { mp.copy (core, ext, key); mp.bind (core, key, context); } else mp.copy (context, ext, key); }); };

mp.mixin (john,isParent)

Page 56: Metaprogramación en JavaScript

@javiervelezreye56

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnAdición

En los mixins con estado protegido existe la necesidad dereferiralcoredesdeelcuerpodesusmétodos.Ellorequieremeterunareferenciaalcore–self–enelcontexto.

Mixins.Self&ThisMixinA

MixinB

CoreAdición Adición

{s}

var john = { first: 'John', last : 'Doe' };

var isAuthor = { data: [], addBook: function (name) { this.data.push(name); return this; }, getBooks: function () { return this.data; } description: function () { return 'Books:' + this.getBooks (); } };

mp.mixin (john,isAutor)

this.self.getBooks ();

mp.mixin = function (core, ext) { var context = { self : core }; var keys = Object.getOwnPropertyNames(ext); keys.forEach (function (key) { if (typeof (ext[key]) === 'function') { mp.copy (core, ext, key); mp.bind (core, key, context); } else mp.copy (context, ext, key); }); };

Page 57: Metaprogramación en JavaScript

@javiervelezreye57

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnAdición

En los mixins con estado protegido existe la necesidad dereferiralcoredesdeelcuerpodesusmétodos.Ellorequieremeterunareferenciaalcore–self–enelcontexto.

Mixins.ColisióndeMétodosMixinA

MixinB

CoreAdición Adición

{s}

mp.mixin (john,isAutor)

mp.mixin (john,isParent)

var john = { first: 'John', last : 'Doe' };

var isAuthor = { init: function () { this.books = []; }, addBook: function (name) { this.books.push(name); return this; }, getBooks: function () { return this.books; } };

var isParent = { init: function () { this.children = []; }, addChild: function (name) { this.children.push(name); return this; }, getChildren: function () { return this.children; } };

mp.mixin = function (core, ext, policy) { var context = { self : core }; var decorate = policy || mp.after; var keys = Object.getOwnPropertyNames(ext); keys.forEach (function (key) { if (typeof (ext[key]) === 'function') { if (core[key]) { decorate (core, ext, key); mp.bind (core, key, context); } else { mp.copy (core, ext, key); mp.bind (core, key, context); } } else mp.copy (context, ext, key); }); };

Page 58: Metaprogramación en JavaScript

@javiervelezreye58

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnAdición

Para resolver los problemas de colisión de nombres entremétodosdediferentesmixinssepuedeaplicarunavariedadde polí1cas de ges1ón de colisiones. Estás polí1cas aplicanen esencia técnicas de entrelazado funcional entre losmétodos en conflicto. A con1nuación mostramos aquellasmásprotocpicas.

Mixins.PolíUcasdeResolucióndeConflictos

mp.override = function (core, key, ext) { core[key] = function () { return ext.apply (this, arguments); }; }, mp.discard = function (core, key, ext) { var fn = core[key]; core[key] = function () { return fn.apply (this, arguments); }; }, mp.before = function before (core, key, ext) { var fn = core[key]; core[key] = function () { ext.apply (this, arguments); return fn.apply (this, arguments); }; };

mp.after = function after (core, key, ext) { var fn = core[key]; core[key] = function () { var r = fn.apply (this, arguments); ext.apply (this, arguments); return r; }; }; mp.around = function around (core, key, ext) { var fn = core[key]; core[key] = function () { var args = [].slice.call (arguments); args = [ext.bind (this)].concat(args); return fn.apply (this, args); }; };

MixinA

MixinB

Core

Adición PolíBca

Adición

Page 59: Metaprogramación en JavaScript

@javiervelezreye59

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnAdición

Dado que los métodos sinónimos se resuelven porintercesión es necesario discriminar qué parámetroscorrespondenacadamétodoenconflictotraslaintercesión.Paraellopasamosaunesquemanominal.

Mixins.ColisióndeParámetros MixinA

MixinB

CoreAdición Adición

{defaults}

{defaults}

var john = { first: 'John', last : 'Doe' };

var isAuthor = { init: function (bks) { this.books = bks || []; }, addBook: function (name) { this.books.push(name); return this; }, getBooks: function () { return this. Books; } };

mp.mixin (john,isAutor) mp.mixin (john,isParent)

var isParent = { init: function (chs) { this.children = chs || []; }, addChild: function (name) { this.children.push(name); return this; }, getChildren: function () { return this.children; } };

init: function (defaults) { defaults = defaults || {}; this.children = defaults.children || []; },

init: function (defaults) { defaults = defaults || {}; this.books = defaults.books || []; },

Page 60: Metaprogramación en JavaScript

@javiervelezreye60

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnAdición

Cuandosecreanproto1pospormixturaelestadoprivadosecomparte entre todos los hijos. Para solucionar esteproblema debemos modificar el metaprograma para crearunestadoencadahijo.

Mixins.AdiciónsobreProtoUpos

MixinA

O1

{s} {s}

Prototype

O2

var john = { first: 'John', last : 'Doe' };

var isAuthor = { init: function () { this.books = []; }, addBook: function (name) { this.books.push(name); return this; }, getBooks: function () { return this. Books; } };

var isParent = { init: function () { this.children = []; }, addChild: function (name) { this.children.push(name); return this; }, getChildren: function () { return this.children; } };

mp.mixin = function (core, ext, policy) { var context = mp.key (); core[context] = { self: core }; var decorate = policy || mp.after; var keys = Object.getOwnPropertyNames(ext); keys.forEach (function (key) { if (typeof (ext[key]) === 'function') { if (core[key]) decorate (core, key, ext[key]); else mp.outerDelegate (core, ext, key, core[context]); } else mp.copy (core[context], ext, key); }); };

var Person = Object.create (null) mp.mixin (Person, isAutor) mp.mixin (Person, isParent) var john = Object.create (Person)

Person

Page 61: Metaprogramación en JavaScript

@javiervelezreye61

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnIntercesión

Los aspectos son abstracciones funcionales encapsuladasqueseaplicantransversalmentealosmétodosmiembrosdeuncore.Lapolí1cadeintercesiónempleadaformapartedelaencapsulación.

Aspectos.IntercesiónEstáUca

AspectA

MixinB

IntercesiónIntercesión

Corevar checkable = { add: { when: 'before', advice: function (id, v) { if (typeof (v) !== 'number') throw 'Invalid Type'; } } };

var loggable = { add: { when: 'before', advice: function (id, value) { console.log ('Adding', id); } }, find: { when: 'after', advice: function (id) { console.log ('Find', id); } } };

var manager = { data : {}, find : function (id) { return this.data[id]; }, add : function (id, value) { this.data[id] = value; } };

mp.aspect (manager, checkable); mp.aspect (manager, loggable);

mp.sAspect = function (core, ext){ var ks = Object.getOwnPropertyNames(ext); ks.forEach (function (key) { var m = ext[key]; mp[m.when](core, key, m.advice); }); };

Page 62: Metaprogramación en JavaScript

@javiervelezreye62

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnIntercesión

Los aspectos son abstracciones funcionales encapsuladasqueseaplicantransversalmentealosmétodosmiembrosdeuncore.Lapolí1cadeintercesiónempleadaformapartedelaencapsulación.

Aspectos.IntercesiónDinámica

mp.dAspect = function (core, ext){ var ks= Object.getOwnPropertyNames (ext); ks.forEach (function (key) { if (!core[key].isAdvisable) mp.advisable (core, ext, key); var m = ext[key]; m[ext[key].when](ext[key].advice); }); };

mp.advisable = function (core, ext, key) { var core[key] = function () { var args = [].slice.call (arguments); method.befores.forEach (function (fn) { fn.apply (this, args); }); method.body.apply (this, args); method.afters.forEach (function (fn) { fn.apply (this, args); }); } core[key].isAdvisable = true; core[key].befores = []; core[key].body = core[key]; core[key].afters = []; core[key].before = function (fn) { this.befores.unshift (fn); }; method.after = function (fn) { this.afters.push (fn); }; core[key] = method; };

AspectA

MixinB

IntercesiónIntercesión

Core

Page 63: Metaprogramación en JavaScript

@javiervelezreye63

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnDelegación

El modelo arquitectónico de filtros composi1vos persigueenriquecer cada objeto por intercesión para ar1culardelegacionesqueges1onenentratamientodemensajes.

FiltrosdeComposición

{pn}

f

g

{s}

El tratamiento que hacen losfiltrosdelosmensajesconsisteenarBcularunadelegacióninternaoexterna a otros componentesp resenten en e l contex toarquitectónico

DelegaciónInternayExterna

Cada método se decora con filtrossecuenciales de intercesión en before yaRerquepersiguenalterarlasemánBcadel mismo gesBonando el tratamientodelosmensajes

FiltrosdeEntradaySalida

Los filtros determinan las accionesdegesBóndemensajesarealizarenfunc ión de c i e r to e s tado ypredicadosdecontrolqueseañadenalcomponente

E s t a d o yPredicados

Page 64: Metaprogramación en JavaScript

@javiervelezreye64

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnDelegación

Los aspectos son abstracciones funcionales encapsuladasqueseaplicantransversalmentealosmétodosmiembrosdeuncore.Lapolí1cadeintercesiónempleadaformapartedelaencapsulación.

FiltrosdeComposiciónDB0

DB1DB2

replicar

delegar

replicar

delegar

var fRound = function (j, dbs){ return { state: { active: false, dbs: dbs, next: (j+1) % dbs.length }, advices: { get: { when: 'provided', advice: function (id) { if (this.active) { this.active = false; this.dbs[this.next].active = true; return true; } else { this.dbs[this.next].get(id); return false; } ... };

var fCopy = function (j){ return { state: { }, advices: { set: { when: 'before', advice: function (id, obj) { if (j < this.dbs.length - 1) this.dbs[j+1].set(id, obj); } } } }; };

Page 65: Metaprogramación en JavaScript

@javiervelezreye65

ModelosArquitectónicosDeComposiciónMetaprogramaciónEnJavaScript

ModelosArquitectónicosBasadosEnDelegación

Los aspectos son abstracciones funcionales encapsuladasqueseaplicantransversalmentealosmétodosmiembrosdeuncore.Lapolí1cadeintercesiónempleadaformapartedelaencapsulación.

FiltrosdeComposición.ColaboraciónentreFiltrosDB0

DB1DB2

replicar

delegar

replicar

delegar

var db = { get: function (id){...}, set: function (id, obj){...} }; var dbs = [Object.create (db), Object.create (db), Object.create (db)]; dbs.forEach (function (db, i, dbs) { mp.filter (db, fRound (i, dbs)); mp.filter (db, fCopy (i)); });

[1][1][1] [1,2][1,2][1,2] [1,2,3][1,2,3][1,2,3] Getting 1 from DB0... Delegating Get to DB1... Getting 2 from DB1

Se inicializa el array deba se s de da to s y s eestablecenlosfiltros

Construcción

SiempreseatacalabasededatosDB0.Cadaoperación set propaga una replica a lasiguientebasededatos.LagesBóndequeriesseresuelveenroundrobin

Funcionamientodbs[0].active = true; dbs[0].set (1, 1); dbs[0].set (2, 2); dbs[0].set (3, 3); dbs[0].get (1); dbs[0].get (2);

mp.filter = function (core, ext) { mp.extend (core, ext.state); mp.sAspect (core, ext.advices); };

Page 66: Metaprogramación en JavaScript

@javiervelezreye66

PreguntasMetaprogramaciónEnJavaScript

JavierVélezReyes@javiervelezreye

[email protected]

TécnicasdeComposición

MecanismosdeComposición

ModelosArquitectónicos

Page 67: Metaprogramación en JavaScript

JavierVélezReyes@javiervelezreye

[email protected]

MetaprogramaciónEnJavaScript

ProgramaciónOrientadaaComponentes

Febrero2015