-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
1405 lines (1083 loc) · 121 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[NN.blog.last()]]></title>
<link href="http://nnombela.github.com/atom.xml" rel="self"/>
<link href="http://nnombela.github.com/"/>
<updated>2018-05-02T12:31:24+02:00</updated>
<id>http://nnombela.github.com/</id>
<author>
<name><![CDATA[Nicolas Nombela]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Fonética Inglesa. Monoptongos]]></title>
<link href="http://nnombela.github.com/blog/2013/09/30/fonetica-inglesa-monoptongos/"/>
<updated>2013-09-30T12:46:00+02:00</updated>
<id>http://nnombela.github.com/blog/2013/09/30/fonetica-inglesa-monoptongos</id>
<content type="html"><![CDATA[<p>El inglés tiene fama de tener un sistema vocálico endiablado, y ciertamente lo tiene, más teniendo en cuenta que tiene decenas de dialectos que fundamentalmente se diferencian en la pronunciación de las vocales.</p>
<p>Pero el problema para un hispanohablante que está aprendiendo inglés no es tanto la complejidad del sistema vocálico del Inglés como la simplicidad del sistema vocálico de su idioma materno: el Castellano. Éste está considerado como uno de los más simples que existe dentro de los idiomas más hablados, sino el más simple, y literalmente define el sistema canónico de vocales. Hasta donde yo sé sólo el Rumano se le parece en simplicidad, con las 5 vocales canónicas y dos vocales centrales (una de ellas el Schwa de la que hablaremos más tarde). De hecho si alguna vez te has preguntado por qué los rumanos tienen tanta facilidad para aprender el Castellano ya tienes la respuesta, a los hispanohablantes les costaría un poco más hablar Rumano pero desde luego mucho menos que hablar Inglés, mala suerte.</p>
<p>Ahora bien si conseguimos hacernos más o menos con el sistema vocálico del Inglés nuestro nivel del idioma va a pegar un fuerte estirón, se va a colocar en un nuevo nivel desde donde es mucho más fácil progresar. Claro que mucha gente opina que la pronunciación es la parte más difícil del Inglés, yo al contrario opino que es de la más fáciles.</p>
<!-- more -->
<p>Sorprendentemente el estudio de las vocales del Inglés se puede hacer utilizando un simple diagrama cartesiano, con sólo dos dimensiones más una característica añadida. Demasiado bueno para ser verdad, porque la realidad es que se trata de una representación idealizada, no encontrarás dos diagramas iguales de un idioma simplemente porque no existe uno correcto, lo que no implica que conocer uno sea extremadamente útil para entender y aprender un montón de cosas. Yo voy a utilizar una representación mía propia, donde hago alguna trampilla que luego explicaré pero con el único objetivo de resaltar algunos aspectos que considero interesantes.</p>
<p>Las dos dimensiones del diagrama son:</p>
<ol>
<li><p>Eje X. <strong>Posición de la lengua</strong> (Tongue backness: <code>front</code>, <code>central</code>, <code>back</code>): Articulación de la vocal dentro de la cavidad bucal. La lengua es un músculo que según la forma que adopta determina donde se “siente” que se genera la vocal: en la parte frontal, central o posterior</p></li>
<li><p>Eje Y. <strong>Apertura de la boca</strong> (Mouth height or closeness: <code>open</code>, <code>mid</code>, <code>close</code>): Altura de la lengua con respecto al paladar, no sólo la forma sino la altura es lo que determina el tamaño de la cavidad donde se produce la vocal y su sonido.</p>
<p> Y la otra característica que hay que tener en cuenta es:</p></p></li>
<li><p><strong>Redondeado de los labios</strong> (Lip roundedness: <code>rounded</code>, <code>unrounded</code>). Si se redondean los labios o no. La forma de los labios determina también el sonido vocálico.</p></li>
</ol>
<blockquote><p><strong>Nota</strong>: En vez del redondeado de labios yo voy a utilizar otro parámetro más sencillo y más preciso: <strong>La tensión de la comisura de los labios</strong>, si las separamos hacia atrás como en la <span class="vowel red">/i/</span> (los labios se estiran) o si las juntamos hacia adelante como en la <span class="vowel red">/u/</span> y los labios se comprimen (redondeándose). Voy a utilizar este parámetro porque es mucho más preciso, me permite distinguir entre 3 posibilidades: tensión para separarlos (frecuente en vocales frontales), tensión para juntarlos (frecuente en vocales posteriores) y no tensión (frecuente en las centrales).</p></blockquote>
<p>Antes de ver qué pinta tienen los diagramas vocálicos del Castellano y del Inglés, comentar que las vocales en cualquier idioma tienen tendencia a moverse en el diagrama cardinal con el tiempo y a lo largo de su historia, la mayor parte de las veces por influencias externas, y el Inglés ha estado muy sometido a influencias externas y experimentado muchos cambios, algunos muy recientes, y actualmente está experimentándose de forma muy acusada debido fundamentalmente a dos fenómenos: la internacionalización del Inglés como idioma global y también, más recientemente, por el uso de Internet.</p>
<p>Ahora bien en su movimiento más o menos errático por el diagrama tienen tendencia a seguir algunos principios de simetría y encontrar zonas de equilibrio, estos son:</p>
<ol>
<li><strong>Equidistancia</strong>. Las vocales tienden a gravitar dejando distancias equidistantes entre ellas. De esa forma son más fácilmente distinguibles</li>
<li><strong>Congruencia</strong>. Las vocales tienen tendencia a asociarse en parejas contrapuestas según el eje X (lugar donde se produce la vocal).</li>
<li><strong>Ocupamiento de bases</strong>. El diagrama define para todos los idiomas 5 zonas o bases: <code>a-base</code>, <code>e-base</code>, <code>i-base</code>, <code>o-base</code> y <code>u-base</code>, hay una tendencia a ocupar todas las bases con al menos una vocal</li>
</ol>
<p>Estas reglas te indican que cuando una vocal se mueve se mueven todas las demás para reorganizarse, es lo que le ocurrió al Inglés recientemente con lo que se ha llamado “The Great Vowel Shift” (que desgraciadamente ha complicado todo el sistema vocálico del Inglés)</p>
<p>Veamos primero el diagrama para el Castellano:</p>
<p><img class="center" src="http://nnombela.github.com/images/fonetica/Monoptongos-Castellano.png"></p>
<p>El Castellano es pura perfección, cumple perfectamente las 3 reglas que hemos comentado, define un sistema canónico, formando una <strong>V</strong> casi perfecta. Tiene 5 vocales separadas equidistantemente, dos parejas congruentes <code>i-u</code> y <code>e-o</code> y cada vocal ocupa una base.</p>
<p>Casi no se puede mejorar, y ahí está el problema, es tan perfecto que parece que no pueda haber otro, hay que romper una barrera mental: Los idiomas puede tener y suelen tener más de 5 vocales, es una barrera mental que cuesta bastante romper.</p>
<p>Ahora veamos el diagrama del Inglés, que es el dialecto Americano o GenAm (General American), escojo GenAm por varias razones: es el que mejor conozco y el que más influencia tiene sobre los demás.</p>
<p>Veamos ahora el diagrama para el Inglés GenAm:</p>
<p><img class="center" src="http://nnombela.github.com/images/fonetica/Monoptongos-Ingles.png"></p>
<blockquote><p><strong>Nota 1</strong>: Sólo vamos a ver los monoptongos, que son los difíciles, los diptongos no presentan tantos problemas.</p>
<p><strong>Nota 2</strong>: Para la caracterización fonética he utilizado la notación IPA, que utiliza símbolos latinos y griegos. Es muy muy aconsejable familiarizarse con esta notación.</p></blockquote>
<p>Hay varias cosas que notamos a simple vista si lo comparamos con el diagrama del Castellano.</p>
<ol>
<li>Hay una explosión de vocales, hay muchas más, más del doble.</li>
<li>La forma en <strong>V</strong> del Castellano parece que se ha escindido en dos <strong>U</strong>es separadas</li>
<li>Hay una vocal central: el Schwa <span class="vowel blue">/ə/</span> presente en muchos idiomas pero no en el Castellano.</li>
<li>Hay dos grupos de 6 vocales: uno que parece muy pegado a la periferia del diagrama y que llamaremos Periféricas porque parecen que definen los límites del propio diagrama, y otro grupo más central que llamaremos Centrales</li>
<li>La regla de ocupación de bases se cumple y el de congruencia (parejas contrapuestas) parece que también <code>i-u</code>, <code>ɪ-ʊ</code>, etc..)</li>
</ol>
<p>Lo interesante del diagrama es que hay muchas simetrías, que si las entendemos nos pueden ayudar muchísimo a identificar las vocales y a entenderlas un poco mejor.</p>
<p>Para mi lo más interesante es que las vocales se agrupan en dos grandes grupos con características opuestas, que son</p>
<p>A) <strong>Las vocales Periféricas</strong>: Lo más interesante es darse cuenta que son vocales que están muy en la periferia, casi en los límites de las posibilidades de vocalización. Es por eso que lo más distintivo es que son muy exageradas, incluso un pelín forzadas. Son o muy cerradas, o muy abiertas; y están o muy atrás o muy delante.</p>
<p>Son <span class="vowel blue">/i/</span>, <span class="vowel blue">/ɛ/</span>, <span class="vowel blue">/æ/</span>, <span class="vowel blue">/ɑ/</span>, <span class="vowel blue">/ɔ/</span>, <span class="vowel blue">/u/</span>. Son todas vocales más periféricas que las del Castellano, necesitan serlo ya que se tienen que diferenciar claramente de las otras vocales, las centrales. El error más común al pronunciarlas es no exagerarlas (especialmente las frontales) con lo cual a oído de un angloparlante se pueden confundir con las centrales.</p>
<p>B) <strong>Las vocales Centrales</strong>: Al contrario que las otras lo distintivo es que son mucho más neutras, más relajadas, incluso en ocasiones cuando están en una sílaba sin énfasis se pronuncian como la vocal central (el Schwa, que es una especie de vocal comodín). Son la <span class="vowel blue">/ɪ/</span>, <span class="vowel blue">/ɜ/</span>, <span class="vowel blue">/ə/</span>, <span class="vowel blue">/ʌ/</span>, <span class="vowel blue">/o/</span>, <span class="vowel blue">/ʊ/</span>. Es importante entender que son más neutras y relajadas que las vocales del Castellano</p>
<p><strong>El Schwa</strong> <span class="vowel blue">/ə/</span>. Es la vocal totalmente central y es la auténtica vocal comodín del Inglés, es la vocal más común con diferencia, incluso sustituyendo a las otras dependiendo del énfasis, hablaremos más adelante de ella en mayor profundidad.</p>
<p>Otras cosas interesantes del diagrama:</p>
<ol>
<li>Las bases tienen a rellenarse con 2 vocales (una periférica y otra central), excepto la a-base que al ser la base base (valga la redundancia) del diagrama puede albergar 3 vocales (dos periféricas y una central).</li>
<li>La vocales de las dos bases de arriba (i-base y u-base) forman una diagonal de 135º, mientras que las de las bases de enmedio (e-base y o-base) forman una diagonal en 90º. La base de abajo (a-base) acomoda las 3 vocales con forma de triángulo.</li>
<li>Se respeta bastante bien la ley de congruencia y las vocales se pueden emparejar en parejas contrapuestas <code>i,u</code>, <code>ɪ, ʊ</code>, <code>ɛ, ɔ</code>, <code>æ, ɑ</code></li>
</ol>
<p>Para resumir, a la hora de pronunciar una vocal podemos forzar el mecanismo vocálico (lengua, mandíbula y boca) o al contrario podemos relajarlo y pronunciarla de forma más neutra, cuando relajamos el mecanismo vocálico la vocal se centraliza. Una vez que tenemos esta noción clara y adquirimos la habilidad de “sentir” las vocales el sistema vocálico del Inglés emerge sin mucha dificultad.</p>
<p><strong>Interferencias de Identidad</strong>. Para un español tanto forzar como relajar una vocal es algo “poco natural”, existen graves interferencias de identidad que impide que lo hagamos (nos hace sentir raros y ridículos y sólo lo hacemos cuando parodiamos a alguien). A mi por ejemplo me ocurre que cuando estoy hablando Inglés con un nativo no tengo muchas problemas de identidad pero cuando hablo Inglés con un español me aparecen y tengo tendencia a españolizar las vocales y a pronunciarlas mal. Esto tipo de interferencias son muy difíciles de superar.</p>
<p>Reforzar la identidad personal y de grupo es la segunda función de un idioma, después de obviamente de la de comunicar, es una función social y es la mayor responsable de la explosión de dialectos y acentos de un idioma, tanto por motivos geográficos como sociales. Desafortunadamente esta segunda función de un idioma es también uno de los grandes obstáculos para aprender correctamente un nuevo idioma.</p>
<blockquote><p><strong>¿Por qué el inglés tiene 2 grupos vocálicos tan diferentes?</strong> Bien en mi opinión tiene mucho que ver con el ritmo y la entonación del Inglés (el otro apartado importante de la Fonética Inglesa). El Inglés tiene un ritmo de tipo <code>stress-timed</code>, con mucha importancia en el énfasis, con “golpes” fuertes seguidos de uno o varios “golpes” suaves dejando el mismo tiempo entre los golpes fuertes, mientras que el Castellano es <code>syllable-timed</code>, menos importancia del énfasis, con una cadencia más monótona, más aburrida, dejando el mismo tiempo entre sílabas. De todo esto hablaré en el segundo de las tres entradas que quiero hacer de Fonética Inglesa, pero quiero señalar que creo hay una conexión entre ambos aspectos fonológicos.</p></blockquote>
<p>Bien, vamos a ir ahora base por base, poniendo ejemplos y dando pistas de cómo pronunciar las vocales.</p>
<blockquote><p><strong>Nota</strong>: Para no confundirlas las vocales inglesas van a ir en azul y las vocales del Castellano van a ir en rojo.</p></blockquote>
<h2>i-base</h2>
<p><img class="left" src="http://nnombela.github.com/images/fonetica/base-i.png"></p>
<p>Empezamos por una sencilla que además nos va a permitir entender la mecánica que hay que seguir con las siguientes. En inglés hay dos vocales en esta base: <span class="vowel blue">/i/</span> y <span class="vowel blue">/ɪ/</span> .</p>
<p>La vocal <span class="vowel red">/i/</span> del Castellano está enmedio, además ocurre una cosa curiosa mientras que es la <span class="vowel blue">/i/</span> inglesa la que nosotros percibimos como más cercana a la <span class="vowel red">/i/</span> del Castellano, ocurre lo contrario, un angloparlante percibe la <span class="vowel red">/i/</span> como su <span class="vowel blue">/ɪ/</span> central, y esa es la razón por la cual hay que tener especial cuidado con algunas palabras como <span class="vowel blue">beach</span>, <span class="vowel blue">sheet</span> o <span class="vowel blue">scene</span>. Conocí a un español que aún después de llevar 30 años viviendo en Canadá me confesó que eran palabras que había eliminado de su vocabulario.</p>
<p>¿Cúal es el truco para pronunciarlas correctamente? Especialmente la <span class="vowel blue">/i/</span> (la que parece más fácil pero que en la práctica es la que más problemas da). Bueno la <span class="vowel blue">/i/</span> inglesa es muy gestual, al ser tan frontal y cerrada tienes que notar que la comisura de los labios se separan mucho y los labios se estiran al mismo tiempo, si no haces ese gesto exagerando la vocal probablemente la <span class="vowel blue">/i/</span> no va a salir bien.</p>
<p>Por el contrario la <span class="vowel blue">/ɪ/</span> central es un vocal totalmente relajada, los labios quedan neutros y apenas se estiran, la lengua también se relaja un poco, quizás probando te salga más bien una <span class="vowel red">/e/</span> pero eso es porque para tu memoria gestual es algo nuevo y se confunde, fuerza el sonido <code>i-base</code> y repítelo hasta que lo tengas memorizado y te salga natural. Como ejercicio puedes probar a incluso juntar un poco la comisura de los labios y redondear la <span class="vowel blue">/ɪ/</span> y te saldrá una bonita <span class="vowel green">/y/</span> francesa, que no viene al caso, pero que ayuda a entender la mecánica de lo que queremos conseguir.</p>
<p>Algunos pares mínimos (palabras que en su pronunciación sólo se diferencian en la vocal) son:</p>
<ul>
<li><span class="vowel blue">sheet - shit</span></li>
<li><span class="vowel blue">beach - bitch</span></li>
<li><span class="vowel blue">scene - sin</span></li>
<li><span class="vowel blue">sheep - ship</span></li>
<li><span class="vowel blue">eat - it</span></li>
</ul>
<p>Otro ejercicio interesante es repetir varias veces seguidas <span class="vowel blue">eat it</span>, tienes que notar que la comisura de los labios se estiran hacia atrás en la primera <span class="vowel blue">/i/</span> y luego se relajan rápidamente hacia adelante en la segunda <span class="vowel blue">/ɪ/</span> para luego volverse a estirar, si no sientes ese movimiento en la comisura de los labios lo estás haciendo mal.</p>
<h2>u-base</h2>
<p><img class="left" src="http://nnombela.github.com/images/fonetica/base-u.png"></p>
<p>Seguimos con una base cerrada, pero ahora las vocales en vez de pronunciarse en la parte de delante se pronuncia el la parte de detrás en la cavidad bucal.</p>
<p>De nuevo en Inglés hay dos vocales la <span class="vowel blue">/u/</span> y la <span class="vowel blue">/ʊ/</span>, que resulta que, no sorpresivamente, son congruentes (contrarias) a la <span class="vowel blue">/i/</span> y a <span class="vowel blue">/ɪ/</span> respectivamente, ahora ocurre lo contrario en cuanto a la percepción: la <span class="vowel red">/u/</span> del Castellano la percibe un angloparlante como su <span class="vowel blue">/u/</span> y ahora la que da problemas es la otra la <span class="vowel blue">/ʊ/</span>.</p>
<p>De nuevo el truco para pronunciar la <span class="vowel blue">/u/</span> es juntar la comisura de los labios, esta vez cerrando y redondeando los labios aún más que con la <span class="vowel red">/u/</span> del Castellano, un poco más.</p>
<p>Pero la díficil es la otra la <span class="vowel blue">/ʊ/</span>, pero si hemos sido capaces de sacar la <span class="vowel blue">/ɪ/</span> nos va resultar fácil sacarla, los labios apenas se redondean, quedan casi neutros, relajados, relajamos también un poco la lengua, si lo hacemos así de forma natural la vocal se mueve desde la parte posterior a la zona central.</p>
<p>Para practicar podemos utilizar esta frase <span class="vowel blue">Look is Luke!</span>, y repetirla una y otra vez, de nuevo tenemos que sentir de nuevo que la comisura de los labios se mueven, en la primera Look se usa la <span class="vowel blue">/ʊ/</span> y los labios quedan casi neutros (un pelín redondeados) y en la segunda Luke se usa <span class="vowel blue">/u/</span> y los labios se cierran y redondean mucho más.</p>
<p>Algunos pares mínimos son:</p>
<ul>
<li><span class="vowel blue">would - wood</span></li>
<li><span class="vowel blue">look - Luke</span></li>
<li><span class="vowel blue">full - fool</span></li>
<li><span class="vowel blue">pull - pool</span></li>
</ul>
<h2>e-base</h2>
<p><img class="left" src="http://nnombela.github.com/images/fonetica/base-e.png"></p>
<p>Si has llegado aquí es porque te ha ido bien con las dos anteriores, me alegro, porque se va a ir complicando hasta que lleguemos a la última: la <code>a-base</code>, que es la más difícil.</p>
<p>De nuevo e-base tiene 2 vocales monoptongas en Inglés, no debería extrañar, la <span class="vowel blue">/ɛ/</span> y <span class="vowel blue">/ɜ/</span> no se utiliza el símbolo <span class="vowel blue">/e/</span> porque este símbolo se utiliza para un sonido más canónico, en Inglés existe y se utiliza en el diptongo (pero sólo estamos viendo los monoptongos que son lo difíciles).</p>
<p>Bien, si eres cordobés o de la zona estás de suerte, ya las tienes, estas dos son muy parecidas a las <span class="vowel red">/e/</span> de la pronunciación cordobesa de <span class="vowel red">Nene</span>. La primera <span class="vowel red">/e/</span> es más frontal y más abierta y un poco más enérgica y la segunda es más central, más neutra, más relajada y un poco más cerrada.</p>
<p>En inglés hay un pequeña ayuda para distinguir estas dos vocales, la <span class="vowel blue">/ɜ/</span> siempre es larga (en duración) y acompañada de la <span class="vowel blue">/r/</span>, como en <span class="vowel blue">bird</span>, <span class="vowel blue">girl</span>. Una forma de representarla en IPA es como <span class="vowel blue">/ɜ:r/</span>, los dos puntos significan sonido largo, ahora bien esa <span class="vowel blue">/r/</span> final en Inglés es una semivocal, luego quizás la forma más correcta de representarla en IPA es diptongarla con la <span class="vowel blue">/r/</span> semivocálica (utilizando el Schwa) y representarla como <span class="vowel blue">/ɛər/</span> (como hacen algunos diccionarios) de esa manera es siempre larga porque ¡Es un diptongo!</p>
<p>La <span class="vowel blue">/ɜ/</span> está muy cerca del Schwa <span class="vowel blue">/ə/</span>, de hecho esta es una vocal que cuando no está enfatizada se pronuncia como el Schwa. Es una vocal tan central que a veces parece <code>e-base</code> como en <span class="vowel blue">girl</span> o <span class="vowel blue">bird</span> y otra <code>o-base</code> como en <span class="vowel blue">word</span> o <span class="vowel blue">worth</span>, pero es exactamente el mismo sonido y es <code>e-base</code>.</p>
<p>Respecto a la la otra <span class="vowel blue">/ɛ/</span>, quizás el error más común al pronunciarla (como en <span class="vowel blue">bed</span>) es hacerlo como una <span class="vowel red">/e/</span> canónica. En Inglés existen los dos sonidos <span class="vowel blue">/ɛ/</span> y <span class="vowel blue">/e/</span> (que siempre va en diptongo) y son distintos, el truco para la <span class="vowel blue">/ɛ/</span> es hacerla más abierta (dejando caer la mandíbula), más frontal y estirar un poco la comisura de los labios hacia atrás, tiene que sonar más rotunda, más extrema.</p>
<p>Aquí no hay pares mínimos ya que una va siempre con la <span class="vowel blue">/r/</span> y la otra no (creo)</p>
<h2>o-base</h2>
<p><img class="left" src="http://nnombela.github.com/images/fonetica/base-o.png"></p>
<p>De nuevo hay dos vocales, aunque no está claro que la <span class="vowel blue">/o/</span> no sea en realidad un diptongo con la <span class="vowel blue">/ʊ/</span>, en mi opinión sí, y por eso la voy a representar mejor como <span class="vowel blue">/ow/</span> aunque en muchos sitios aparece como una vocal monoptonga. Yo no lo tengo claro.</p>
<p>La <span class="vowel blue">/ɔ/</span> es una vocal un poco más posterior que la <span class="vowel red">/o/</span> del Castellano, es más abierta y la comisura de los labios se cierra un poco pero no tanto como con la <span class="vowel red">/o/</span> del Castellano, los labios sólo se cierran levemente.</p>
<p>La <span class="vowel blue">/o/</span> u <span class="vowel blue">/ow/</span> (como me gusta más representarla) es básicamente la <span class="vowel red">/o/</span> castellana diptongada con la <span class="vowel blue">/ʊ/</span> en muchos sitios también aparece representado también como <span class="vowel blue">/oʊ/</span></p>
<p>El mejor ejemplo para entender y practicar la <span class="vowel blue">/ow/</span> es la palabra <span class="vowel blue">no</span>, en inglés tiene que sonar diptongada y claramente distinta de como lo pronunciamos en Castellano.</p>
<p>Algunos pares mínimos:</p>
<ul>
<li><span class="vowel blue">law - low</span></li>
<li><span class="vowel blue">walk - woke</span></li>
<li><span class="vowel blue">caught - coat</span></li>
<li><span class="vowel blue">call - coal</span></li>
<li><span class="vowel blue">nah - no</span></li>
</ul>
<h2>Schwa</h2>
<p>El Schwa <span class="vowel blue">/ə/</span> es la vocal presente en muchos idiomas pero no en Castellano, es una vocal especial ya que está justo en el centro, es el sonido vocálico más relajado y neutro que se puede pronunciar, hay que dejar la boca, la lengua, la mandíbula y la garganta totalmente relajadas, no puede haber tensión en ninguna parte y la mandibula en reposo, entonces sale un sonido neutro casi gutural.</p>
<p>En Inglés es una vocal comodín, muchas vocales, especialmente las centrales, cuando no van enfatizadas se reducen al Schwa, es el caso por ejemplo de <span class="vowel blue">were</span> en <span class="vowel blue">If I were you</span>. Eso hace que sea con diferencia la vocal más común del Inglés</p>
<p>Está enmedio de dos bases <code>e-base</code> y <code>o-base</code>, mi sensación es que aveces se mueve un pelín para una u otra base dependiendo de la palabra, por ejemplo en las palabras <span class="vowel blue">doct<strong>o</strong>r</span> y <span class="vowel blue">nat<strong>io</strong>n</span>, la última o es un Schwa pero suena un pelín <code>o-base</code>, mientras que en otra como <span class="vowel blue"><strong>a</strong>gain</span> y <span class="vowel blue">list<strong>e</strong>n</span>, suenan un poco más <code>e-base</code>, no sé…</p>
<h2>a-base</h2>
<p><img class="left" src="http://nnombela.github.com/images/fonetica/base-a.png"></p>
<p>Por fin hemos llegado a la última que también es la más difícil. Lo bueno es que si hemos entendido las anteriores estamos en buena disposición para entender ésta.</p>
<p>Aquí nos encontramos 3 vocales la <span class="vowel blue">/æ/</span>, la <span class="vowel blue">/ʌ/</span> y la <span class="vowel blue">/ɑ/</span>, (más una cuarta de la que hablaré más tarde) lo cual no es extraño ya que la base se expande por todo el eje-Y, hay una frontal, una central y una posterior (en realidad la posterior son dos con una pequeña diferencia)</p>
<p>Por desgracia ninguna de las tres es la <span class="vowel red">/a/</span> del Castellano, la <span class="vowel blue">/a/</span> canónica existe en Inglés pero siempre en diptongo, esto genera una enorme confusión.</p>
<p>Empezamos con la frontal, la <span class="vowel blue">/æ/</span>, es mi preferida, es una de las más comunes (después del Schwa) en Inglés y sin duda es la vocal más potente (muy abierta y muy adelantada) y característica del Inglés. Es una vocal que no existe en el Castellano y sólo en pocos idiomas ya que es trabajosa, hay que forzar bastante todo el sistema vocálico, y eso acaba siendo una ventaja ya que una vez que se entiende no interfiere con ninguna otra vocal, es como una vocal totalmente nueva. Una vez que se adquiere, y sólo por ello, tu nivel de Inglés da un salto cualitativo, hay un antes y un después, por eso merece muchísimo la pena adquirirla.</p>
<p>La <span class="vowel blue">/æ/</span> es una <code>a-base</code> muy frontal, el truco de nuevo es la comisura de los labios, si las llevamos hacia atrás al tiempo que abrimos la boca (y ésta es la parte trabajosa), los labios se estiran y se abren y la vocal de forma natural se mueve hacia adelante, tenemos que sentirla delante. Si en la <span class="vowel blue">/i/</span> la boca te queda como la de un buzón de correos en la <span class="vowel blue">/æ/</span> te queda abierta como la boca de las máscaras de los samurais japoneses… Si no llevas hacia atrás la comisura de los labios, la estás pronunciando mal.</p>
<p>La <span class="vowel blue">/ʌ/</span> central puede parecer la más fácil y ciertamente es la que un angloparlante percibe como la <span class="vowel red">/a/</span> del Castellano. Ahora bien la <span class="vowel blue">/a/</span> del Castellano está un pelín adelantada y es más abierta, por el contrario la <span class="vowel blue">/ʌ/</span> es totalmente central y no tan abierta, es esa la razón por la que puede llegar a percibirse como una <span class="vowel blue">/o/</span> como puede ocurrir con la palabra <span class="vowel blue">love</span> (pero cuidado es <code>a-base</code>)</p>
<p>La es <span class="vowel blue">/ʌ/</span> es un sonido abierto y muy relajado (en cierta manera es la hermana mayor del Schwa <span class="vowel blue">/ə/</span>, igual pero más abierta), al estar la cavidad vocal y la lengua tan relajadas, la vocal se siente y resuena más en el pecho que en la cavidad bucal (Nota: ver <span class="vowel blue">placement</span>). El truco para pronunciarla correctamente es sentir que no hay nada de tensión en la lengua ni en los labios.</p>
<p>Finalmente está la vocal <span class="vowel blue">/ɑ/</span>, que es posterior y es muy abierta, y esto es lo que la caracteriza, para producirla hay que tensionar un poco la lengua y hay que dejar caer la mandíbula para que se abra. La <span class="vowel blue">/ɑ/</span> es una vocal muy frecuente en Inglés Americano, pero no tanto en Inglés Británico donde es más común usar otra vocal que es la hermana gemela de ésta, es la <span class="vowel blue">/ɒ/</span> que es exactamente igual pero con los labios ligeramente cerrados, es decir la comisura de los labios se acercan levemente redondeando los labios, Es por ejemplo la diferencia entre de pronunciación en americano y en británico de las palabras <span class="vowel blue">hot</span>, <span class="vowel blue">lot</span>, <span class="vowel blue">god</span>, <span class="vowel blue">cop</span>, <span class="vowel blue">bought</span>, etc…</p>
<p>Nota: la <span class="vowel blue">/ɒ/</span> británica no es <code>o-base</code>, es muy <code>a-base</code> y es bastante abierta es un error frecuente de pronunciación hacerla <code>o-base</code></p>
<p>Nota 2: Finalmente hay también en Inglés Americano GenAm un proceso de sustitución de la <span class="vowel blue">/ɔ/</span> por la <span class="vowel blue">/ɑ/</span>, así que tanto la <span class="vowel blue">/ɔ/</span> como la <span class="vowel blue">/ɒ/</span> en GenAm acaban pronunciándose como la <span class="vowel blue">/ɑ/</span> y por eso es tan frecuente en este dialecto.</p>
<p>Mi mayor dificultad con las vocales ha sido y sigue siendo distinguir de oído la <span class="vowel blue">/ʌ/</span> de la <span class="vowel blue">/ɑ/</span>, creo que es el mayor reto, la clave es que la primera es más central, más relajada y la segunda es más abierta y se siente más atrás, para practicarlas una buena combinación es <span class="vowel blue">Come on!</span> estas dos palabras van enlazadas (se pronuncian como una sólo palabra sin pausa en medio) y la primera es una <span class="vowel blue">/ʌ/</span> y la segunda es una <span class="vowel blue">/ɑ/</span>, tienes que sentir que en la <span class="vowel blue">/ɑ/</span> la boca se abre un poco y la lengua se tensiona para retrasar la vocal, la diferencia es muy sutil</p>
<p>Algunos pares mínimos de <span class="vowel blue">/ʌ/</span> y <span class="vowel blue">/ɑ/</span> que te costarán son:</p>
<ul>
<li><span class="vowel blue">wonder - wander</span></li>
<li><span class="vowel blue">sucker - soccer</span></li>
<li><span class="vowel blue">come - calm</span></li>
<li><span class="vowel blue">cup - cop</span></li>
</ul>
<p>Algunos tripletes mínimos de las tres vocales serían:</p>
<ul>
<li><span class="vowel blue">cap - cup - cop</span></li>
<li><span class="vowel blue">bad - bud - bought</span></li>
<li><span class="vowel blue">cam - come - calm</span></li>
<li><span class="vowel blue">cat - cut - cought</span></li>
<li><span class="vowel blue">sang - sung - song</span></li>
</ul>
<h2>Por último</h2>
<p>La verdad es que me ha costado bastante hacer esta entrada, la he tenido varios meses en mi cabeza y tenía ganas de dejarla por escrito, a mi me ha servido de ayuda para organizar las ideas, pero no soy profesor de Inglés, ni lingüista y mi conocimiento de fonética es reducido, ni siquiera tengo un nivel de Inglés muy alto… pero por eso mismo creo que puedo aportar un punto de vista distinto en un área en la hay poca información y la mayoría excesivamente técnica y especializada. Espero que si un lingüista o experto en Fonética acaba leyendo esta entrada me perdone por las incorrecciones y omisiones que he cometido, que seguro han sido bastantes.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Agilescéptico]]></title>
<link href="http://nnombela.github.com/blog/2013/08/17/agilesceptico/"/>
<updated>2013-08-17T19:23:00+02:00</updated>
<id>http://nnombela.github.com/blog/2013/08/17/agilesceptico</id>
<content type="html"><![CDATA[<p>Lo confieso, me declaro “agilescéptico” y tengo que admitir que con el tiempo cada vez más, no <em>per se</em> sino más bien precavido y escéptico respecto a todo el circo que se ha montado alrededor de las metodologías ágiles.</p>
<p>Me explico, en mi opinión en desarrollo software sólo hay dos cosas importantes:</p>
<ul style="list-style-type: none;">
<li>1. Los <strong>Programadores</strong></li>
<li>2. El <strong>Código</strong></li>
</ul>
<p>Y en ese orden, y lo demás son florituras. Dicho de otra manera:</p>
<p>Con los programadores adecuados y dejándoles escribir el código que ellos consideren adecuado ya está casi todo hecho, la receta del éxito en desarrollo software ya estaría básicamente formulada. Y hablo del éxito técnico no comercial, esa es otra historia.</p>
<blockquote><p>La única “agilidad” que importa en desarrollo software es la que permite libremente a los <strong>programadores</strong> escribir, leer y cambiar <strong>código</strong> con rapidez (pero sin prisas).</p></blockquote>
<p>Ahora bien, lo primero que decidirán esos programadores (ellos y no otras personas) para poder escribir código de calidad serán las herramientas que van a utilizar, y de nuevo nos encontramos dos aspectos:</p>
<ul style="list-style-type: none;">
<li>3. Las <strong>Tecnologías</strong></li>
<li>4. La <strong>Metodología</strong></li>
</ul>
<p>Y en ese orden, porque el orden de nuevo importa.</p>
<!-- more -->
<p>Así que ya tenemos exactamente cuál es la importancia de la Metodología en Desarrollo Software: ocupa un <strong>modesto cuarto puesto</strong>, la metodología es importante pero ni siquiera está en el <em>podium</em> de lo más importante.</p>
<p>Y a las pruebas me remito, si buscas en los proyectos de software de más éxito encontrás básicamente grandes programadores (frecuentemente sus fundadores) y código de calidad, también algunas tecnologías usadas acertadamente pero apenas rastro de la metodología empleada, algo hay sí pero poco.</p>
<p>Y esto es lo que frecuentemente olvidan los predicadores, evangelistas y demás mundillo alrededor de las metodologías ágiles, muchas veces honestos entusiastas pero pocas veces con la legitimidad que les daría ser programadores competentes que no han dejado de programar.</p>
<p>…. y de ahí el origen de mi “agilescepticismo”.</p>
<p><strong>Nota:</strong> Conste que a mi me mola Scrum (incluso me divierte), lo de las tarjetas, los cerdos y las gallinas es genial (sin ironía); y aplaudo, valoro y envidio ”prácticas agiles” como ”Code Review”, “Pair Programming” y TDD, pero no se me olvida cuál es su importancia relativa respecto a lo que realmente importa.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Eventual Consistency, Parte II]]></title>
<link href="http://nnombela.github.com/blog/2012/05/15/eventual-consistency-parte-ii/"/>
<updated>2012-05-15T14:07:00+02:00</updated>
<id>http://nnombela.github.com/blog/2012/05/15/eventual-consistency-parte-ii</id>
<content type="html"><![CDATA[<p>En la primera parte sobre <a href="http://nnombela.com/blog/2012/02/17/eventual-consistency/">Consistencia Eventual (EC)</a>, un modelo de consistencia de datos para una arquitectura distribuida,
deje sin contar dos de los aspectos más importantes de la misma: <strong>la política de resolución de conflictos</strong>, y también, <strong>la política de propagación de los cambios</strong>.</p>
<p>Antes de empezar, para concretar y generar un poco más de interés pongamos ejemplos de sistemas distribuidos que utilizan alguna forma de EC:</p>
<ul>
<li>Los sistemas de control de versiones distribuidos y muy en concreto <a href="http://git-scm.com/">Git</a> que es un caso paradigmático.</li>
<li>Los sistemas de almacenamiento en la nube, por ejemplo <a href="http://www.dropbox.com">Dropbox</a>.</li>
<li>Los juegos multiusuario en tiempo real, casi todos ellos.</li>
<li>Los motores de búsqueda, cualquiera de ellos.</li>
<li>Algunas Aplicaciones Web como las redes sociales, pongamos <a href="http://facebook.com">Facebook</a> o <a href="http://twitter.com">Twitter</a></li>
</ul>
<!-- more -->
<p>En todos estos sistemas dos observadores del mismo pueden ver, en un momento dado, cosas distintas
pero eventualmente (en el tiempo) todos los observadores verán lo mismo (mejor dicho verán los mismos cambios).</p>
<p>En todos estos sistemas por tanto puede haber conflictos durante la propagación de los cambios,
y en todos existe una política de resolución de conflictos que resuelve mediante la aplicación de reglas establecidas dicho conflicto.</p>
<p>El modo de propagación de cambios se refiere a cómo los diferentes nodos sincronizan los datos entre si, en este punto hay mucha libertad,
la propagación puede ser de tipo push/pull a petición del usuario (como el que utiliza git), de tipo periódico (sincronización automática cada cierto intervalo de tiempo)
o puede ser dirigida por eventos como las de tipo pub/sub. Los nodos pueden tener una conexión permanente o establecer conexiones puntuales.
Las conexiones pueden ser bidireccionales o en un sólo sentido (típica arquitectura web), etc…</p>
<p>El modo de propagación de cambios no es importante en EC siempre y cuando se respete el principio de consistencia eventual:
<strong>La consistencia de datos se alcanza en algún intervalo de tiempo (eventualmente)</strong>, es decir tiene que existir propagación de cambios.</p>
<p>Lo que sí es importante para garantizar la consistencia de datos es <strong>la política de resolución de conflictos</strong>, porque la posibilidad de conflicto es el precio que hay que pagar en EC.
Un precio barato como ya comenté en la primera parte del <a href="http://nnombela.com/blog/2012/02/17/eventual-consistency/">post</a>, ya que es a cambio de un montón de cosas estupendas: escalabilidad, tolerancia a fallos, posibilidad de modo offline, etc…</p>
<p>En el caso concreto de los sistemas distribuidos de control de versiones, que probablemente todos hemos utilizado,
todos sabemos que es un conflicto y cómo se resuelve, se resuelve a <em>manini</em> y en origen por el usuario, mezclando los cambios, quizás con alguna herramienta de mezclado.</p>
<p>En el caso de los juegos multiusuario también puede haber conflictos, por ejemplo dos jugadores se disparan casi a la vez pero… <em>only one can win, my friend!</em>
En estos casos puede ocurrir que alguno de los jugadores vea por un momento a su oponente muerto y un instante después el que está mordiendo
el polvo sea el mismo y su oponente saliendo de rositas… <em>damn it!</em></p>
<p>En el caso de las redes sociales también puede haber conflictos, podemos ver cómo después de haber comentado una noticia y
creer que somos los primeros en hacerlo y de hecho verlo de esa manera, vemos posteriormente que no así y que alguien se nos ha adelantado con la misma ocurrencia…</p>
<p>En el caso de los motores de búsqueda, pues ya se sabe, más que conflictos lo que puede haber es diferentes resultados para la misma búsqueda dependiendo de dónde geográficamente se realice.</p>
<p>En realidad todos estos casos suelen ser casos extremos, casos que no son lo habitual, esa es una de las bazas de EC,
los conflictos son excepcionales y no interfieren en el normal funcionamiento del sistema.</p>
<p>Con riesgo de ser pesado, repito una vez más, la existencia de un conflicto durante la propagación de cambios no implica inconsistencia de datos
ya que existe una política que determina sin ambigüedad cómo se resuelve el conflicto y
cómo se propaga esta resolución (otra cosa es que esta política sea la más acertada para el sistema en concreto)</p>
<p>Para quien piense que no todos los sistemas pueden admitir EC y posibilidad de conflicto, sólo un dato,
no se me ocurre nada más sensible que el código de una aplicación (pensemos en una aplicación militar o de un banco como casos extremos) y
ya hace tiempo que la política de bloqueo de recursos en los sistemas de control de versiones cayó en desgracia…</p>
<p>Un sistema muy sensible a la inconsistencia de datos tendrá mecanismos de control, testeo unitario, de integración, etc..
En el caso de un banco, doble y triple contabilidad, etc.. Los tendrá no por que utilice EC si no por que incluso utilizando otros
modelos de consistencia “más garantistas” necesita, aún con todo, de estos mecanismos de control de la consistencia</p>
<p>Veamos entonces algunas posibles políticas de resolución de conflictos:</p>
<p>1) <strong>Mezclado automático, versionado y marcado como conflicto.</strong> Resolución en cliente.
Este es el más habitual en los sistemas de control de versiones y en la mayor parte de los sistemas de almacenamiento distribuido.
Los cambios se versionan y se intentan mezclar de forma automática y si no se consigue se marcan como <em>en conflicto</em>, se guardan ambas versiones.
Al nodo origen se le avisa de la situación y se espera que de forma activa la solucionen y propaguen el cambio.</p>
<p>2) <strong>Timestamp en origen.</strong> Este es el más habitual en los juegos multijugador y uno de los más sencillos.
Todos los cambios se propagan con un timestamp en origen (que tiene que estar sincronizado en todos los nodos),
cuando existe un conflicto prevalece el cambio con mayor o menor timestamp (al gusto), se resuelve en servidor y la resolución se propaga de vuelta a los nodos origen.</p>
<p>3) <strong>Prioridad en origen.</strong> a los nodos origen (donde se originan los cambios) se les da una prioridad distinta,
en caso de que exista conflicto durante la propagación prevalece el cambio del nodo con mayor prioridad, la resolución se propaga de vuelta.</p>
<p>Hay muchos otras y en realidad cada sistema distribuido que quiera utilizar alguna forma de EC deberá diseñar su propia política de resolución específica de la aplicación
y que mejor resultado pueda dar. Esta política es absolutamente clave para el éxito de este tipo de modelo de consistencia.</p>
<p>Una cosa importante es que los conflictos se pueden resolver en todos los nodos (que tengan estado): en origen, en nodos intermedios o en los nodos de datos finales
(la consistencia se alcanza en todos los nodos), y su resolución también se propaga como otro cambio. La política de resolución y propagación puede ser distinta
dependiendo del tipo de nodo pero su aplicación tiene que garantizar la consistencia, y aquí es donde hay que ser muy cuidadosos o podemos encontrarnos con una situación de tipo ping-pong.</p>
<p>Lo mejor es que sea bien el nodo origen (caso de los sistemas de control de versiones) o bien el nodo final (casos de los juegos multiusuarios) quien
resuelva el conflicto lo antes posible y en el menor tiempo posible y propague dicho cambio.</p>
<p>Bueno, con esta segunda parte cierro este tema de momento. Es un tema que da mucho de si especialmente en estos momentos en
los que este modelo de consistencia de datos está llegando a aplicaciones modestas y con bajo presupuesto pero que tienen vocación de crecer y hacerlo muy rápidamente.
Además se empiezan a ofrecerse servicios distribuidos en la nube (también económicamente elásticos) con arquitecturas que utilizan estos
principios de consistencia (muy en particular los que ofrece Amazon y Windows Azure, en esto Google y especialmente Apple van por detŕas)</p>
<p>Quizás en algún momento me anime hacer algún prototipo de aplicación web con este tipo de arquitectura y con todos los elementos clave:
nodo cliente (con estado), nodo servicio (sin estado) y nodo de datos (con estado distribuido) y política de resolución de conflictos en nodo cliente por el usuario (que es la que más me gusta).</p>
<p>Como adelanto, hoy por hoy y para un prototipo utilizaría: para el nodo cliente utilizaría <a href="http://documentcloud.github.com/backbone/">Backbone.js</a>, para el servicio sin estado <a href="http://nodejs.org/">Node.js</a>
(y algún módulo para servicios REST como <a href="http://mcavage.github.com/node-restify/">Restify</a>) y para la base de datos <a href="http://couchdb.apache.org/">CouchDB</a>
con alguna vista Map/Reduce chula y quizás sincronización
automática de datos con los nodos cliente (hasta donde sé CouchDB es el único que ofrece esto con cosas como <a href="https://github.com/mikeal/pouchdb">PouchDB</a> para el navegador y
<a href="https://github.com/couchbaselabs/TouchDB-iOS">TouchDB-iOS</a> y <a href="https://github.com/couchbaselabs/TouchDB-Android">TouchDB-Android</a> para dispositivos móviles).
En cualquier caso como veis todo estaría con JavaScript y JSON, y ojo al dato, serían todas tecnologías que aún no están maduras…
Esta tercera parte la dejo muy pendiente.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Asincronicidad en Node.js]]></title>
<link href="http://nnombela.github.com/blog/2012/03/21/asincronicidad-en-node-dot-js/"/>
<updated>2012-03-21T11:53:00+01:00</updated>
<id>http://nnombela.github.com/blog/2012/03/21/asincronicidad-en-node-dot-js</id>
<content type="html"><![CDATA[<p>El modelo de programación de Node.js es monohilo, asíncrono y dirigido por eventos. En esta primera parte del
post veremos algo de código que nos permita entender un poco mejor que significa programar en un modelo monohilo asíncrono,
en la segunda parte de post veremos un ejemplo de programación dirigida por eventos utilizando eventos propios.</p>
<p>Tener un sólo hilo de ejecución para todo el código tiene varias consecuencias en nuestro código de las que hay que estar alerta, estas
son:</p>
<!-- more -->
<ol>
<li><p>No puede haber código bloqueante o todo el servidor quedará bloqueado y esto incluye no responder a nuevas peticiones entrantes.
Cualquier tarea que pueda dar lugar a esperas activas o simplemente su tiempo de ejecución sea demasiado grande debe ser tratado
de manera asíncrona. Esto incluye muy especialmente
todas las tareas que impliquen algún tipo de comunicación I/O, salida a red, a base de datos o incluso al sistema de ficheros. Si tenemos
alguna tarea computacionalmente intensiva deberemos intentar trocearla en varios bloques o trocearla en el tiempo (time-slice) para
darle respiro al servidor y que pueda atender otros bloques de código, afortunadamente esto último no es nada habitual.</p></li>
<li><p>La asincronicidad implica que no sabemos cuándo ni en que orden se va a ejecutar el código, generalmente esto no es importante
pero en ocasiones sí lo es y habrá que tenerlo en cuenta. En cuanto al cuándo lo más habitual será tener que tener en cuenta
un posible evento de <code>timeout</code>, si estamos utilizando un modulo externo será tan simple como suscribirnos al evento, si es código
propio utilizaremos la función <code>setTimeout()</code>. En cuanto al orden de ejecución, algo también poco habitual, si tenemos que controlarlo
utilizaremos <code>callbacks</code> anidados o la función <code>process.nextTick()</code> para retrasar la ejecución dentro de la cola de eventos.
Luego veremos ejemplos de utilización de estas funciones.</p></li>
<li><p>En caso de error inesperado debemos capturarlo y controlar el posible estado en que haya podido quedar la ejecución
del código. Muy especialmente en caso de haya recursos que no hayan sido liberados, haya tareas
(bloques de código o <code>callbacks</code>) dependientes de la tarea que ha generado el error o tengamos una política de reintentos.
Aunque si nuestro código es realmente
asíncrono y dirigido por eventos la liberación de los recursos ocurrirá cuando salte el correspondiente evento de <code>timeout</code> asociado al
recurso o el <code>timeout</code> asociado a la tarea dependiente.</p></li>
</ol>
<p>Llegado a este punto uno puedo pensar que programar en un modelo mohilo asíncrono es mucho más difícil que programar en un modelo
multihilo sincrono más tradicional, pero no es así por que para programar BIEN en servidor en cualquier de los dos modelos un programador
tiene que tener siempre en la cabeza y tener en cuenta todos todos los aspectos anteriores, que se resumen en:</p>
<ol>
<li>Esperas y posibilidad de código bloqueante</li>
<li>Eventos de <code>timeouts</code> en la comunicación I/O</li>
<li>Capturas de errores inesperados, política de reintentos y liberación de recursos</li>
</ol>
<p>En la programación de servidor multihilo sincrona más tradicional todos estos aspectos quedan ocultos, no forman parte
del modelo de programación, en muchas muchísimas ocasiones no se tienen en cuenta, incluso por programadores expertos.
Erróneamente se puede llegar a pensar que la lógica que tiene que tener todo esto en cuenta no es necesaria en un primer
momento o es una forma de optimización prematura, además no resulta sencillo implementar la lógica de manera correcta.</p>
<blockquote><p>Es decir, en este tipo de modelo de programación es muy fácil o casi inevitable programar MAL código de servidor.</p></blockquote>
<p>En cambio en la programación de servidor monohilo asíncrono dirigida por eventos todos estos aspectos están presentes de serie
desde el princio, forman parte del modelo de programación, son mucho más evidentes y si no se tienen en cuenta el posible problema no pasa inadvertido y desde el principio
se manifiesta con resultados a veces catastróficos como dejar el servidor bloqueado. Ademas la programación asíncrona por eventos
resulta la manera más sencilla, correcta y desacoplada de tratar con todos los aspectos anteriores.</p>
<blockquote><p>Es decir, en este tipo de modelo de programación es difícil o fácilmente evitable programar MAL código de servidor.</p></blockquote>
<p>Ahora vamos a ver un ejemplo sencillo de código bloqueante, de esperas, de la cola de eventos y de timeouts. Veamos
primero un ejemplo de código bloqueante, un “Hello World” con un bloque de código bloqueante.</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">http</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"http"</span><span class="p">);</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">util</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"util"</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">writeResponse</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">response</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span><span class="s2">"Content-Type"</span><span class="o">:</span> <span class="s2">"text/plain"</span><span class="p">});</span>
</span><span class='line'> <span class="nx">response</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s2">"Hello World"</span><span class="p">);</span>
</span><span class='line'> <span class="nx">response</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
</span><span class='line'> <span class="nx">util</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"OnRequest ended"</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">sleepSynch</span><span class="p">(</span><span class="nx">seconds</span><span class="p">,</span> <span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">startTime</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">();</span>
</span><span class='line'> <span class="k">while</span> <span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">()</span> <span class="o"><</span> <span class="nx">startTime</span> <span class="o">+</span> <span class="mi">1000</span> <span class="o">*</span> <span class="nx">seconds</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="c1">// do nothing</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="nx">writeResponse</span><span class="p">(</span><span class="nx">response</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nx">http</span><span class="p">.</span><span class="nx">createServer</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">util</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"OnRequest started"</span><span class="p">);</span>
</span><span class='line'> <span class="nx">sleepSynch</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="nx">response</span><span class="p">);</span> <span class="c1">// bloque síncrono</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">// sleepAsynch(10, response) // bloque asíncrono</span>
</span><span class='line'> <span class="c1">// sleepAsynchWithNextTick(10, response); // bloque asíncrono con nextTick</span>
</span><span class='line'><span class="p">}).</span><span class="nx">listen</span><span class="p">(</span><span class="mi">8888</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Listening on port 8888"</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p><code>sleepSynch</code> es un bloque de código síncrono, espera activamente durante 10 segundos sin hacer nada, es un simple bucle
<code>while</code> que comprueba el tiempo transcurrido. Pudiera ser un bloque que realiza una tarea computacionalmente intesiva o una lectura
o escritura en disco de un fichero de gran tamaño o cualquier otra tarea bloqueante, lo importante del ejemplo es que si
lo ejecutamos veremos como nuestro servidor de “Hola Mundo después de 10 segundos” queda bloqueado y es más bien un servidor
de “Hola Mundo después de 10 segundos o mucho más”. Atiende las peticiones en serie una detrás de otra.</p>
<p>Vamos a ver ahora este mismo ejemplo pero utilizando código asíncrono no bloqueante, todo queda igual excepto el bloque de
código bloqueante que ahora sería asíncrono</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">sleepAsynch</span><span class="p">(</span><span class="nx">seconds</span><span class="p">,</span> <span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">doResponse</span><span class="p">(</span><span class="nx">response</span><span class="p">);</span>
</span><span class='line'> <span class="p">},</span> <span class="mi">1000</span> <span class="o">*</span> <span class="nx">seconds</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>La función <code>setTimeout()</code> es un función nativa asíncrona, muy frecuéntemente utilizada en Node.js para controlar
tiempos de ejecución de código. Lo importante es ver que ahora nuestro servidor de “Hola Mundo después de 10 segundos” queda
desbloqueado, ahora ya es capaz de responder a todas las peticiones de forma paralela (al menos de forma efectiva)</p>
<p>Por último vamos a ver otra forma de conseguir la asincronicidad de forma menos óptima utizando la función <code>process.nextTick()</code>. Esta
función acepta un bloque de código o <code>callback</code> que será ejecutado una vez vaciada la cola de eventos actual, mediante esta técnica
conseguimos que el servidor no quede bloqueado y que el resto de tareas tengan oportunidad de ejecutarse.</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">sleepAsynchWithNextTick</span><span class="p">(</span><span class="nx">seconds</span><span class="p">,</span> <span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">endTime</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1000</span> <span class="o">*</span> <span class="nx">seconds</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="p">(</span><span class="kd">function</span> <span class="nx">check</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">process</span><span class="p">.</span><span class="nx">nextTick</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">()</span> <span class="o"><</span> <span class="nx">endTime</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">check</span><span class="p">();</span>
</span><span class='line'> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">doResponse</span><span class="p">(</span><span class="nx">response</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">});</span>
</span><span class='line'> <span class="p">})()</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>La función <code>process.nextTick()</code> es un técnica sencilla de conseguir asincronicidad y evitar el bloqueo del servidor, otra forma
hubiese sido utilizar un <code>setTimeout(0, ..)</code> con tiempo 0, otra forma posible forma
hubiese sido emitir un evento propio y escuchar por ese evento, aunque no está nada claro el orden de ejecución de los eventos
dentro de la cola de eventos, no he encontrado documentación al respecto…</p>
<p>Espero que este ejemplo simple sirva para entender un poco mejor el modelo de programación de Node.js, en la segunda parte de este
post veremos un ejemplo de programación dirigida por eventos propios</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Sobre Node.js]]></title>
<link href="http://nnombela.github.com/blog/2012/03/16/sobre-node-dot-js/"/>
<updated>2012-03-16T12:12:00+01:00</updated>
<id>http://nnombela.github.com/blog/2012/03/16/sobre-node-dot-js</id>
<content type="html"><![CDATA[<p>En el <a href="http://nnombela.com/blog/2012/02/17/eventual-consistency/">post</a> anterior comenté que <a href="htt://nodejs.org">Node.js</a> era la tecnología
que más rápidamente he visto crecer en poco tiempo. Realmente
a poco que uno lo siga, el fenómeno es abrumador. El sistema de paquetes de Node <a href="http://npmjs.org/">npm</a> tiene cerca
de <a href="http://search.npmjs.org/">8000 paquetes</a>! A pesar del poco tiempo muchos de ellos ya están siendo utilizados en producción en proyectos
reales y por empresas muy serias como Amazon, Linkedlin y Microsoft. Actualmente es el tecnología que más actividad
y crecimiento tiene en GitHub.</p>
<p>Un ejemplo real que pone de manifiesto este fenómeno sería <a href="http://ldapjs.org/">ldapjs</a>, es un LDAP hecho con Node.js en 4 días
prácticamente desde cero! A 24 horas de su publicación en twitter ya había un proyecto utilizándolo y en una semana ya
estaba integrado en varios proyectos importantes. En comparación un proyecto similar hecho en
Java <a href="http://www.opends.org/">OpenDS</a> ha tardado 1 año en sacar la primera versión estable (y no es mucho tiempo) y apenas tiene
actividad. Estamos hablando de una ratio de 1 a 100 en tiempos de desarrollo, es una salvajada, desde luego es un caso
extremo y no creo que esa sea la norma, pero da una idea del dinamismo y de la velocidad a la que se está moviendo el
fenómeno Node.js que desde luego está atrapando a desarrolladores con mucho talento.</p>
<!-- more -->
<p>Resulta curioso que el fenómeno que protagoniza Node.js en el lado del servidor es en realidad una cara de un fenómeno
más amplio y que tiene como movimiento recíproco lo que está ocurriendo en el lado del cliente con JQuery y frameworks
MVC que tradicionalmente estaban en el servidor como Backbone.js. La capa cliente se hace cada vez más pesada
pareciéndose más a la capa servidor y por el otro lado la capa servidor se hace cada vez más ligera pareciéndose
más a la capa cliente. Curioso.</p>
<p>De hecho más que hablar de capas es más correcto hablar de nodos. Donde antes había dos lados (cliente y servidor)
completamente distintos en cuanto a lenguaje, lógica, modelo de programación y peso, ahora empieza a vislumbrarse
lo contrario, dos nodos, cliente y servidor muy parecidos (lenguaje, modelo de programación, tipo de lógica) y con
un peso también parecido (mayor peso en el lado cliente y menor en el lado servidor).</p>
<blockquote><p>Tanto es el parecido entre el nodo cliente y el nodo servidor que ya hay interesantes
iniciativas en <a href="http://npmjs.org/">npm</a> como <a href="http://nowjs.com/">nowjs</a> para que el acoplamiento y comunicación entre ambos nodos sea aún más directo,
transparente y sencillo.</p></blockquote>
<p>Vamos a repasar las características de Node.js para entender un poco mejor este nuevo
modelo de programación en servidor (nuevo en cuanto a popularidad). Empecemos con la característica más sorprendente:</p>
<ul>
<li><p><strong>Single Threaded</strong>. <em>Todo tu código (no todo el código pero sí el tuyo) corre en un único hilo de ejecución. No se vosotros
pero la primera vez que vi esto no encontré ningún aspecto positivo, después de conocerlo mejor tengo que decir que
estaba equivocado y que de hecho puede ser muy positivo en aspectos en los que la programación web más tradicional
falla continuamente, como es la complejidad de la programación multi-hilo o en la ejecución inadvertida de código
bloqueante, para entender cómo un defecto puede convertirse en virtud hay que explicar la siguiente característica.</em></p></li>
<li><p><strong>Asynchronous Event Driven</strong>. <em>Se utiliza un modelo de programación asíncrona dirigida por eventos.
Este es el modelo que permite que la ejecución en un único hilo sea posible. La asincronicidad es una característica
no ideal en cualquier modelo de programación, una perdida de información, se pierden dos cosas: el intervalo de
tiempo y el orden de ejecución del código. Es el precio que hay que pagar a cambio de ganar en otros aspectos</em></p></li>
</ul>
<p>Veamos cuáles son estos aspectos:</p>
<ol>
<li><p>El código asíncrono dirigido por eventos es, en principio, código no bloqueante, entendido bloqueante como aquel
en el que el código (la CPU) no esta haciendo nada constructivo excepto esperar por alguna condición externa, típicamente
algún tipo de comunicación I/O. En realidad el
código en Node.js puede ser igualmente bloqueante, pero resulta primero, más difícil hacerlo inadvertidamente, y
segundo, resulta más catastrófico (recuerda que sólo hay un único hilo de ejecución). El programador es mucho más
consciente del problema, su estilo de programación tiende a ser completamente asíncrono y cuando no lo es en seguida
advierte el problema, no queda oculto como ocurre en la programación multi-hilo.</p>
<p> He tenido la oportunidad de ver y incluso auditar bastantes aplicaciones web con problemas de rendimiento hechas en Java,
en el 100% de los casos Java como lenguaje no tenía nada que ver con el problema. El problema estaba en muchos casos
en código bloqueante: Acceso a otros Servicios Web, acceso a BBDD o acceso al sistema de ficheros, en ese orden.</p></li>
<li><p>El código asíncrono no sólo es idealmente no bloqueante sino que como consecuencia de ello es más
eficiente (no consume tiempo de esperas) y por lo tanto su rendimiento y su eficiencia son mayorres. Además como
todo tu código corre en un único hilo no existe el “overhead” asociado al cambio de hilo.</p></li>
<li><p>Como el código corre en un único hilo no existen, en principio, los problemas asociados al código multihilo, que
tan difíciles son de detectar y de solucionar (aunque de hecho puede haberlos igualmente). Hay menos código y es más sencillo y por lo tanto es más mantenible</p></li>
<li><p>La programación dirigida por eventos permite una programación mucho más modular, ya no es necesario diseñar
cuidadosamente las dependencias entre módulos. En la programación por eventos la comunicación se realiza emitiendo
eventos y registrando <code>listeners</code> de esos eventos, es un mecanismo totalmente desacoplado del diseño. El resultado es
código mucho más sencillo, más desacoplado, más modular y sobre todo con mucha más flexibilidad respecto a los
cambios de diseño, aunque también tiene sus aspecto negativos como la dificultad en la depuración.</p></li>
</ol>
<p>En cierta manera el modelo de programación asíncrono, mono-hilo y dirigido por eventos sería equivalente a un modelo
altamente multi-hilo, donde cada uno de los trozos de código asíncronos o <code>callbacks</code> es un hilo de ejecución por
software o <code>green thread</code> y los eventos son mensajes que se envían y reciben por los hilos siguiendo un patrón parecido
al <code>Actor Model</code> , carece de la sofisticación del modelo implementado en Erlang o Scala, pero el principio es básicamente
el mismo, en mi opinión, y al mismo tiempo es más simple de utilizar. Este tipo de modelos están demostrando tener grandes ventajas
en el lado del servidor.</p>
<p>La programación asíncrona mono-hilo y dirigida por eventos no es una gran desconocida para el programador web, al
menos no para aquel que no trabaja exclusivamente en código de servidor, ya que es el modelo que se utiliza en la
programación cliente con el código JavaScript que se ejecuta dentro del navegador. Y lo ha hecho con enorme éxito y
esa es una de las razones que ha hecho este mismo modelo se haya llevado al servidor en Node.js</p>
<p>En el post anterior <a href="http://nnombela.com/blog/2012/02/17/eventual-consistency/">Eventual Consistency</a> comentaba que el
modelo de programación de Node.js es uno de los que mejor
encajan con el modelo de datos con consistencia eventual, ahora ya podemos ver por qué es así, la consistencia eventual
implica asincronicidad y el modelo de programación asíncrono usado en Node.js es uno de los más sencillos.</p>
<p>Por último comentar un detalle importante sobre Node.js, utiliza JavaScript como lenguaje de programación (aunque hay
una tendencia cada vez más fuerte a utilizar CoffeScript). Existen frameworks similares en
Python <a href="http://twistedmatrix.com/trac/">Twisted</a> y Ruby <a href="http://rubyeventmachine.com/">Event Machine</a> y el
modelo de programación web
dirigido por eventos no es ni siquiera novedoso, pero una de las claves de la explosión de Node.js ha sido la decisión
muy acertada de su creador <a href="http://www.youtube.com/watch?v=jo_B4LTHi3I">Ryan Dahl</a> de usar JavasScript como lenguaje y el
motor V8 de Chrome.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Eventual Consistency]]></title>
<link href="http://nnombela.github.com/blog/2012/02/17/eventual-consistency/"/>
<updated>2012-02-17T12:11:00+01:00</updated>
<id>http://nnombela.github.com/blog/2012/02/17/eventual-consistency</id>
<content type="html"><![CDATA[<p>La Consistencia Eventual (EC) es un modelo de consistencia de datos. EC es un tema realmente interesante. Aunque bautizado
con este nombre en el ámbito de la replicación de datos de grandes BBDD distribuidas, la misma idea y técnicas similares
se han estado aplicando, desde que existen, a cualquier tipo de sistema distribuido con necesidades de baja latencia y alta disponibilidad.</p>
<p>La consistencia de datos es una propiedad importante en cualquier sistema, sin ella su estado puede no estar
correctamente definido y su comportamiento volverse impredecible. Idealmente sólo existiría un modelo de
consistencia: cuando hay un cambio en los datos del sistema todos los posibles observadores del sistema ven ese cambio
al mismo tiempo. Este modelo es el que se denomina Consistencia Inmediata.</p>
<!-- more -->
<p>La Consistencia Inmediata es el modelo habitual en la mayoría de los sistema y en particular en las aplicaciones web
de pequeño-mediano tamaño e incluso de gran tamaño.. pero no en las mega infraestructuras de las herramientas de los
grandes empresas de Internet, como Google, Amazon o en las de las grandes redes sociales como Twiter o Facebook. En estos
sistemas altamente distribuidos es necesario algún tipo de modelo de Consistencia Eventual.</p>
<p>En el modelo EC la consistencia de datos no se alcanza inmediatamente para todos los observadores del sistema al mismo tiempo,
sino en un intervalo de tiempo no determinado, es decir, eventualmente. Existe una propagación en el tiempo de los
cambios del sistema y una política de resolución de conflictos en caso de que los hubiese (situación que ocurre con
mucha menos frecuencia de lo que pudiera pensarse). En cualquier caso existe una garantía de consistencia eventual
en el tiempo de los datos, y esto es lo importante.</p>
<p>EC es un modelo que tiene gran importancia en los sistemas distribuidos y especialmente en aquellos que buscan baja
latencia, alta disponibilidad, alta escalabilidad y alta tolerancia a fallos, es decir, todos, ya que por definición
un sistema distribuido más tarde o más temprano se encontrará con alguno o todos estos problemas,
ver <a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">Fallacies of Distributed Computing</a></p>
<p>La consistencia eventual es un típico trade-off de ingeniería, es renunciar a algo que pensabas que era más importante
para el sistema de lo que realmente es, a cambio de tener otras cualidades que realmente sí son necesarias. ¿Cuál es
la renuncia? Se renuncia a tener una consistencia de datos inmediata en todo el sistema y en un mismo momento, jugando
con la variable tiempo conseguimos que nuestro sistema distribuido (en el espacio) sea mejor ahí donde más le duele:
latencia, disponibilidad, escalado y tolerancia a fallos ¡Valla chollo no! Vamos a ver con algunos ejemplos en qué
consiste y cómo conseguirlo.</p>
<p>Hay que tener en cuenta que desde el momento que una aplicación tiene un cliente y un servidor es un sistema
distribuido, el <code>nodo cliente</code> puede mantener unos datos (un estado) distinto de los que tiene el <code>nodo servidor</code> y
eventualmente sincronizar este estado con él. No es lo habitual en la mayor parte de las aplicaciones web clásicas
donde el estado de la aplicación está en servidor, pero sí es más habitual en un nuevo modelo de arquitectura web
que está surgiendo con fuerza de aplicación JavaScript corriendo en su totalidad en cliente (navegador) y sincronizando
datos eventualmente con el servidor (de forma asíncrona utilizando AJAX). Servidor que a su vez puede tener los datos
en un sistema externo tipo DHT (Distributed Hash Table) o similar que utilice replicación siguiendo un modelo de
consistencia eventual.</p>
<p>Este tipo de arquitecturas distribuidas destacan por tener:</p>
<ul>
<li><p><strong>Baja latencia</strong>, <em>el usuario ve los cambios inmediatamente, ya que ocurren primero en cliente y luego estos
cambios se van propagando por el sistema.</em></p></li>
<li><p><strong>Alta disponibilidad y tolerancia a fallos</strong>, <em>de nuevo la aplicación corre básicamente en cliente, pudiendo
funcionar, al menos en parte, en modo offline. Los servicios son stateless y los datos están replicados</em></p></li>
<li><p><strong> Alta capacidad de escalado</strong>, <em>la aplicación corre en local, los servicios externos son sin estado y los datos
están distribuidos en nodos que siguen modelo de consistencia eventual donde los cambios se van propagando por los nodos.</em></p></li>
</ul>
<p>¿Cuáles son las claves tecnológicas de estos sistemas distribuidos? Pero muy especialmente cuando se trata de aplicaciones
web (y aplicaciones multi-dispositivo).</p>
<ol>
<li><p><em>JavaScript en el <code>nodo cliente</code>: navegador, tablet, smartphone, TV… pero incluso en las aplicaciones desktop del próximo
Windows 8 (por cierto que aquí MS está teniendo mucho más clara las ideas que otros y en algunos aspectos va un paso por delante).</em></p></li>
<li><p><em>De nuevo JavaScript en medio, en la <code>nube de servicios</code> (que no capa…). ¿De nuevo JavaScript? Aquí probablemente habré
cogido con el pie cambiado a más de uno. Node.js es la tecnología con más “hype” y que más rápidamente estoy viendo crecer, y
ya he visto unas cuantas. Es una de las tecnologías que mejor encajan, hay varias razones: los servicios idealmente deben ser
sin estado, asíncronos, y mejor con REST y JSON, pero estas razones merecen un post aparte… como avance diré que también
tienen que ver mucho con 1) y con 3). (De nuevo aquí la plataforma Windows Azure sorpresivamente parece ir un paso por delante).</em></p></li>
<li><p><em>NoSQL en los <code>nodos de datos</code> y muy en particular aquellas que tienen como tecnología subyacente algún tipo
de DHT o similar (casi todas) y vistas Map/Reduce (vistas de datos), por supuesto ambas con un modelo de consistencia
de datos eventual (tanto en los datos como en las vistas), que es el tema que da título a este post. Lo ideal es utilizar
aquí también JSON, con lo que de nuevo es ideal utilizar también aquí JavaScript en las funciones Map y Reduce (de las
que hablaré en otro post), por aquello de que JS es un lenguaje funcional sencillo y también por homogeneidad con el resto de nodos.</em></p></li>
</ol>
<p>Es un cambio de paradigma donde en vez de tener un sistema de varias capas que desde fuera (para los observadores del sistema)
parece un único nodo, se tienen muchos nodos distribuidos, con un nodo cliente casi autónomo (con mayor o menor capacidad
de funcionar offline), que se comunica de forma eventual y asíncrona con multitud de pequeños nodos que proporcionan servicios
sin estado en la nube y finalmente un estado almacenado en nodos distribuidos DHT que utilizan un modelo de consistencia
eventual. JavaScript y JSON son el pegamento de esta arquitectura y no olvidemos que es el único lenguaje que corre de forma
nativa en la mayoría de los navegadores y múltiples dispositivos.</p>
<p>Actualmente estamos entrando en una etapa que algunos denominan Polyglot, con múltiples lenguajes y tecnologías en un mismo
sistema, que previsiblemente se mantendrá durante un tiempo, pero teniendo en cuanta la fuerza con la que vienen las nuevas
tecnologías JavaScript y su vocación multi-paradigma y multi-plataforma, pues no sé si va a ser una etapa transitoria
o qué va a pasar. Desde luego el futuro en este mundo de las tecnologías Internet ha demostrado ser cualquier cosa
menos predecible… Y si no ¿Quién iba a decirle al creador de JavaScript que su lenguaje iba a tener un segundo hype
tan fuerte como está teniendo más de 20 años después?</p>
<blockquote><p>Una nota, JavaScript es un lenguaje con muchas deficiencias, pero actualmente existen algunas iniciativas de hacerlo
avanzar (JS.next), como son ES Harmony, CoffeScript o Google Dart, todas ellas compatibles o que compilan a JS.</p></blockquote>
<p>Mi intención al inicio de este post era hablar exclusivamente de Consistencia Eventual, un modelo poco conocido,
al menos con este nombre, pero que considero muy interesante conocer y entender, especialmente para ser utilizado en aplicaciones
distribuidas, finalmente he acabado hablando un poco de muchas otras cosas y me he dejado cosas por contar, en concreto,
ver algunos ejemplos concretos de aplicaciones distribuidas y explicar una parte fundamental de EC que es la <strong>política de
resolución de conflictos</strong>, lo dejo para una segunda parte de este post.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Groovy closures explicados con Java]]></title>
<link href="http://nnombela.github.com/blog/2012/02/14/groovy-closures-explicados-con-java/"/>
<updated>2012-02-14T11:26:00+01:00</updated>
<id>http://nnombela.github.com/blog/2012/02/14/groovy-closures-explicados-con-java</id>
<content type="html"><![CDATA[<p>Llevando 3 años usando Grails casi de continuo, en mi trabajo es habitual que me pregunten cuánto tiempo le llevaría a un javero de toda la vida
ponerse las pilas y coger ritmo en un proyecto en Grails. Yo siempre respondo lo mismo, Grails es un framework para hacer aplicaciones
web, el javero, a veces muy a su pesar, está muy curtido en esto de probar y utilizar nuevos frameworks, de hecho encontrará Grails
especialmente sencillo y fácil de utilizar, y si es de los que ha bregado a fondo con frameworks del universo (por extenso) Spring incluso
te dirá que de sencillo que es no le parece un framework serio.</p>
<p>Pero el mayor obstáculo y la verdadera dificultad de trabajar con Grails está en el lenguaje que se utiliza: Groovy. Siendo un
lenguaje, Groovy te obliga a cambiar la forma de hacer las cosas y de pensar en ellas.
Afortunadamente la curva de entrada de Groovy para un javero es muy suave, no es una renuncia de Java, es casi una evolución,
al principio es habitual seguir programando igual que en Java y poco a poco ir incorparando la nueva sintáxis y la nueva forma de hacer las cosas.
El tiempo para una adaptación plena varia con la persona, pero típicamente lleva varias semanas o incluso meses, depende de las ganas que le ponga.</p>
<!-- more -->
<p>Y de todas las dificultades la mayor que se va a encontrar, y probablemente la última en superar, será entender y usar adecuadamente el concepto de
<code>Closure</code> en Groovy. Personalmente (es lo que a mi me ocurrió) creo que la mayor dificultad para entenderlo es que normalmente se explica
en lenguaje convencional o natural, en Inglés o en Castellano, y dicho así no se pilla.</p>
<p>Un ejercicio bastante didáctico, y que espero ayude a captar el concepto <code>Closure</code> más rápidamente a un javero, es intentar explicarlo en Java…</p>
<p>Vamos a ello, para modelar los closures vamos a utilizar dos aspectos del lenguaje Java poco usados que son: las clases anonimas y las clases internas.</p>
<p>De momento un <code>Closure</code> se puede modelar en Java como una interfaz, con un único método <code>execute()</code> que acepta un mapa de argumentos
y devuelve un resultado.</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="kd">interface</span> <span class="nc">Closure</span> <span class="o">{</span>
</span><span class='line'> <span class="n">Object</span> <span class="nf">execute</span><span class="o">(</span><span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">></span> <span class="n">args</span><span class="o">);</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Una implementación del método <code>forEach()</code> utilizando closures sería esta</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="kd">static</span> <span class="n">Object</span> <span class="nf">forEach</span><span class="o">(</span><span class="n">Collection</span> <span class="o"><</span><span class="n">Object</span><span class="o">></span> <span class="n">collection</span><span class="o">,</span> <span class="n">Closure</span> <span class="n">closure</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">Object</span><span class="o">[]</span> <span class="n">array</span> <span class="o">=</span> <span class="n">collection</span><span class="o">.</span><span class="na">toArray</span><span class="o">();</span>
</span><span class='line'> <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o"><</span><span class="n">array</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="o">++</span><span class="n">i</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">></span> <span class="n">args</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">>();</span>
</span><span class='line'> <span class="n">args</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"index"</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
</span><span class='line'> <span class="n">args</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"it"</span><span class="o">,</span> <span class="n">array</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
</span><span class='line'>
</span><span class='line'> <span class="n">closure</span><span class="o">.</span><span class="na">execute</span><span class="o">(</span><span class="n">args</span><span class="o">);</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="k">return</span> <span class="n">collection</span><span class="o">;</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Y un ejemplo de uso en Java del anterior código sería el siguiente</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'> <span class="c1">// First we build the a collection</span>
</span><span class='line'> <span class="n">Collection</span><span class="o"><</span><span class="n">Object</span><span class="o">></span> <span class="n">collection</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o"><</span><span class="n">Object</span><span class="o">>();</span>
</span><span class='line'> <span class="n">collection</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="s">"Hola"</span><span class="o">);</span>
</span><span class='line'> <span class="n">collection</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="s">"Adios"</span><span class="o">);</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">// Then we traverse the collection</span>
</span><span class='line'> <span class="n">forEach</span><span class="o">(</span><span class="n">collection</span><span class="o">,</span> <span class="k">new</span> <span class="nf">Closure</span><span class="o">()</span> <span class="o">{</span>
</span><span class='line'> <span class="kd">public</span> <span class="n">Object</span> <span class="nf">execute</span><span class="o">(</span><span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">></span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">args</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"index"</span><span class="o">)</span> <span class="o">+</span> <span class="s">": "</span> <span class="o">+</span> <span class="n">args</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"it"</span><span class="o">)</span> <span class="o">+</span> <span class="s">" Caracola"</span><span class="o">);</span>
</span><span class='line'> <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">});</span>
</span></code></pre></td></tr></table></div></figure>
<p>En java usamos clases anónimas para crear el closure, pero la sintaxis como puede observarse no es muy intuitiva.
En groovy el código anterior quedaría reducido a</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="o">[</span><span class="err">'</span><span class="n">Hola</span><span class="err">'</span><span class="o">,</span> <span class="err">'</span><span class="n">Adios</span><span class="err">'</span><span class="o">].</span><span class="na">eachWithIndex</span> <span class="o">{</span> <span class="n">it</span><span class="o">,</span> <span class="n">index</span> <span class="o">-></span>
</span><span class='line'> <span class="n">println</span> <span class="s">"$index : $it Caracola"</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<blockquote><p>Nota: El método <code>eachWithIndex()</code> debería de llamarse <code>each()</code> a secas, ver <a href="http://jira.codehaus.org/browse/GROOVY-1182">remove eachWithIndex</a></p></blockquote>
<p>Si esto fuese todo, los closures no serían complicados de entender pero la cosa se complica cuando tenemos en cuenta el
aspecto más interesante de los closures:
<strong>los closures tienen acceso a las variables del contexto donde fueron creados</strong>. Para modelar esto en Java es necesario
introducir una nueva entidad <code>Context</code>.
En java existe algo parecido a los closures en el aspecto de llevar consigo el contexto donde fueron creados, que son las inner clases, y de hecho se metieron en la especificación
final de Java con esta idea y con muchas dudas (que el tiempo a confirmado fundadas) sobre su utilidad.</p>
<p>Vamos a modelar el contexto con un clase <code>Context</code> (qué basicamente es un mapa de variables) y el closure con una clase interna (inner class)
que está vez no será una interfaz si no una clase abstracta. Los argumentos del método <code>execute()</code> serán en vez de un mapa un <code>Context</code>
y podemos crear los argumentos usando el método <code>createArgs()</code> del objeto <code>Closure</code>. El objeto <code>Context</code> puede tener a su vez un
contexto “padre”, pudiendo formar una cadena de contextos.</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="kd">class</span> <span class="nc">Context</span> <span class="o">{</span>
</span><span class='line'> <span class="n">Context</span> <span class="n">parent</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
</span><span class='line'> <span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">></span> <span class="n">variables</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">>();</span>
</span><span class='line'>
</span><span class='line'> <span class="kd">public</span> <span class="nf">Context</span><span class="o">(</span><span class="n">Context</span> <span class="n">parent</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="k">this</span><span class="o">.</span><span class="na">parent</span> <span class="o">=</span> <span class="n">parent</span><span class="o">;</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'>
</span><span class='line'> <span class="kd">public</span> <span class="n">Context</span> <span class="nf">add</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">Object</span> <span class="n">object</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">variables</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">name</span><span class="o">,</span> <span class="n">object</span><span class="o">);</span>
</span><span class='line'> <span class="k">return</span> <span class="k">this</span><span class="o">;</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">// Traverse context chain</span>
</span><span class='line'> <span class="kd">public</span> <span class="n">Object</span> <span class="nf">get</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">variables</span><span class="o">.</span><span class="na">containsKey</span><span class="o">(</span><span class="n">name</span><span class="o">)?</span> <span class="n">variables</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">name</span><span class="o">)</span> <span class="o">:</span>
</span><span class='line'> <span class="n">parent</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">?</span> <span class="n">parent</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">name</span><span class="o">)</span> <span class="o">:</span> <span class="kc">null</span><span class="o">;</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'>
</span><span class='line'> <span class="kd">public</span> <span class="kd">abstract</span> <span class="kd">class</span> <span class="nc">Closure</span> <span class="o">{</span>
</span><span class='line'> <span class="kd">public</span> <span class="kd">abstract</span> <span class="n">Object</span> <span class="nf">execute</span><span class="o">(</span><span class="n">Context</span> <span class="n">args</span><span class="o">);</span>
</span><span class='line'>
</span><span class='line'> <span class="kd">public</span> <span class="n">Context</span> <span class="nf">createArgs</span><span class="o">()</span> <span class="o">{</span>