metaprogramación en javascript
TRANSCRIPT
JavierVélezReyes@javiervelezreye
MetaprogramaciónEnJavaScript
ProgramaciónOrientadaaComponentes
Febrero2015
@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?
@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
JavierVélezReyes@javiervelezreye
1Introducción§ QuéEsLaMetaprogramación§ PorQuéLaMetaprogramación§ ElContextoDeLaMetaprogramación§ ElProcesoDeLaMetaprogramación§ LaMetaprogramaciónComoParadigma
Introd
ucción
Metap
rogram
aciónEn
JavaScrip
t
@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
@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
@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
@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
…
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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é?
@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
@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 }
JavierVélezReyes@javiervelezreye
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
@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
@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
@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 (){} }
@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
@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
@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 () {} }
@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 () {}, }
@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 () {} }
@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
JavierVélezReyes@javiervelezreye
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
@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
@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
@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
@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
@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); };
@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
@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
@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
@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
@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
@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
@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
@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
@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}
@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
@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
@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}
@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
@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
JavierVélezReyes@javiervelezreye
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
@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
@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); }); };
@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)
@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); }); };
@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); }); };
@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
@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 || []; },
@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
@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); }); };
@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
@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
@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); } } } }; };
@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); };
@javiervelezreye66
PreguntasMetaprogramaciónEnJavaScript
JavierVélezReyes@javiervelezreye
TécnicasdeComposición
MecanismosdeComposición
ModelosArquitectónicos
JavierVélezReyes@javiervelezreye
MetaprogramaciónEnJavaScript
ProgramaciónOrientadaaComponentes
Febrero2015