Este documento presenta conceptos sobre programación funcional y orientada a objetos, incluyendo paradigmas de programación, objetos inmutables, lambdas, traits, mixins, comunicación entre procesos asíncrona y síncrona, y el patrón promesa. También describe técnicas de programación funcional como traits, mixins y lambdas en varios lenguajes de programación como Java, C#, C/C++.
analisis tecnologico( diagnostico tecnologico, herramienta de toma de deciones)
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
1. PARADIGMAS FP Y OOP
USANDO TÉCNICAS AVANZADAS
DE PROGRAMACIÓN ASÍNCRONA
Cátedra Capgemini 2016/17 - Universitat de València a la innovación en el desarrollo de Software
2. Me presento ...
Víctor M. Bolinches
Software Architect en Capgemini.
Founder Programmer en PlayGram Games.
Ninja Developer en Indie VideoGames Development.
Github Linkedin Twitter
vicboma1 victorbolinches @vicboma1
2
4. Paradigmas de Programación
▹ OOP
▸ Estructura de datos llamados objetos
▸ Aglutinan propiedades y métodos
▸ Manipula datos de entrada para generar datos de salida específicos
▹ FP
▸ Estructura mediante expresiones
▸ Variables sin estado e inmutables
▸ Recursión y Funciones de primer orden
▸ Definición de cómputos y cálculo de lambdas
4
6. Objeto inmutable
▹ Objeto cuyo estado no puede ser modificado
▹ Seguridad de trabajo en proceso Multihilos
▹ Java/C#: String, Integer, Long, Short…
▹ Scala : val (keyword)
▹ C++ : “const”
6
7. Lambdas
▹ Bloque de código abstracto
▹ Procesamiento inline
▸ Árboles de decisión
▸ Delegados
▹ Parámetros de entrada y salida
▹ Inferencia de tipos
7
8. Lambdas
class A {
public void foo() {
Arrays.asList(1,2,3,4,5,6).forEach( s -> { System.out.println(s); } );
}
}
...eq
class A {
public void foo() {
Arrays.asList(1,2,3,4,5,6).forEach( [lambda for lambda$1 as Block] );
}
static void lambda$1(String s) {
System.out.println(s);
return;
}
8
10. Traits - Mejores prácticas por composición
public class BaseClass {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
@Override public Integer foo() { logger().info("foo…!!!!"); }
}
...
public interface Loggable {
default Logger getLogger(){
return LoggerFactory.getLogger(this.getClass());
}
public class BaseClass implements Loggable , Comparable … {
@Override public Integer foo() { getLogger().info("foo…!!!!"); }
}
10
11. Mixins
▹ Clase abstractas
▹ Modelo conceptual simple
▹ Puede guardar el estado de un objeto
▹ Clase base no tiene control sobre la composición del mixin
11
12. Mixins
public class abstract AbstractClass {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
@Override public Integer foo() { logger().info("foo…!!!!"); }
}
...
public interface Loggable {
default Logger getLogger(){ return LoggerFactory.getLogger(this.getClass()); }
}
public class abstract AbstractClass implements Loggable {
protected Integer LoggerInfoFoo() { getLogger().info("foo…!!!!"); }
}
public class BaseClass extends AbstractClass {
...
12
13. Comunicación entre procesos
▹ Síncrono
▸ Intercambio de información en tiempo real
▹ Concurrente
▸ Ejecución simultánea de tareas en tiempo real
▹ Paralelo
▸ Sistema multi-procesado (subdominio concurrente)
▹ Asíncrono
▸ Intercambio de información en tiempo diferido
13
15. Patrón Promesa
▹ Redirige flujos uniformes
▸ (A)sincronos
▹ Ordenada y estructura bloques
▸ then(myFunctionResolved(), myFunctionRejected())
▹ Flexibiliza nuestro código
▸ CallBacks
▹ Hacer p(), y luego q(), r() y s() - [ p ⇒ q ⇒ r ⇒ s ]
▸ Promise(p).then(q).then(r).then(s);
15
16. Test-driven Development ( TDD )
▹ Iteraciones
▸ Desarrollo mediante pruebas (Fallo - Acierto)
▸ Refactorizaciones
▹ Implementaciones mínimas necesarias
▹ Minimización del número de errores en producción
▹ Software modular, reutilizable y tolerable a cambios
16
20. Java 8 - Emulador GameBoy DMG 01 / Homebrew
▹ Metodología SOLID + TDD
▹ Desarrollo de un Framework (Winter)
▹ CPU Z80 emulada con un Pool Asíncrono
▹ SRAM emulada para el Display LCD
▹ Backlights customizadas por colores
▹ Tooling
▸ Consola asíncrona para debug
▸ Decompilador de instrucciones Z80
▸ Rom Hacking
20
24. Java 8 - Mejores Prácticas con Streams { Ejemplos }
▹ Clase que soporta operaciones con estilo funcional
▹ Lambdas
▹ Interfaces funcionales
▹ Métodos y constructores por referencias
▹ Definición de métodos predeterminados y estáticos a
interfaces (Traits ?)
▹ Acceso mediante patrón “Builder” - Pipelines
24
25. Java 8 - Streams { allMatch }25
/**
* Returns whether all elements of this stream match the provided predicate
* @throws Exception
*/
@Test
public void allMatch() throws Exception {
final boolean result = IntStream.of(0, 1, 2, 3, 4, 5, 6)
.allMatch(value -> value % 1 == 0);
Assert.assertTrue(result);
}
26. Java 8 - Streams { reduce }26
/** Performs a reduction on the elements of this stream, using an associative accumulation
* function, and returns an Optional describing the reduced value, if any.
* @throws Exception
*/
@Test
public void reduce() throws Exception {
final int expected = 789;
final int result = Arrays.asList(18, 19, 29, 23, 43, 266, 789)
.stream()
.reduce((p1, p2) -> p1 > p2 ? p1 : p2)
.get();
Assert.assertTrue(expected == result);
}
28. Java 8 - Creando nuestra programación funcional 128
/**
* Expresión Lambda que suma un incremento de +1
* @throws Exception
*/
Function<Integer,Integer> add1 = x -> x + 1;
@Test
public void addTest() throws Exception {
final int expected = 2;
final int result = add1.apply(1);
Assert.assertTrue(expected == result);
}
29. Java 8 - Migrando OOP a FP29
/**
* Clase que suma un incremento de +2
* @throws Exception
*/
public class Utils { public static Integer add2(Integer x) { return x + 2; } }
Function<Integer,Integer> add2 = Utils::add2;
@Test
public void addTest() throws Exception {
final int expected = 4;
final int result = add2.apply(2);
Assert.assertTrue(expected == result);
}
30. Java 8 - Ejemplo de uso - Scanlines Horizontal w/576i Emu GameBoy30
31. Java 8 - Ejemplo de uso - Scanlines Horizontal w/576i Emu GameBoy31
32. Java 8 - Ejemplo de uso - Scanlines Horizontal w/576i Emu GameBoy
▹ Proceso Concurrente
▹ Productor y Consumidor de Imágenes
▹ Recorrido, filtrado y reducciones con Streams
▹ Uso de variables ‘volatiles’ en contexto Threading
32
39. C# - Ejemplo de uso
▹ Cube Line Match 3
Focus Node Selected**
Auto Remove Link Match
Line / Left outer join**
** Copia de SleepyWings
39
40. C# - Ejemplo de uso ‘Cube Line Match 3’
▹ Arquitectura MVC + Adaptador
▹ Procesamiento Asíncrono con ‘Tasks’
▹ Pool Threading Task Async
▹ Uso de Linq
▹ ‘Left Outer Join’ sobre LinkedList
▹ Resolución de Matchs por Recursión
40
41. Unitor - Micro Framework para Unity 2D/3D
▹ Metodología SOLID + TDD
▹ Arquitectura basada en los mejores Frameworks
▸ Contexto
▸ Injector
▸ Dispatcher Asíncrono
▸ CommandMappers Asíncrono
▸ Pre-Configuración de recursos Asíncronos
▸ Promesas
▸ ...
41
43. C# - Lambda Expression
public static void Main(string[] args ) {
var first = Array.Find({ new Point(250, 375),new Point(275, 395), new Point(295, 450) },
point => point.X * point.Y > 100000 );
Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
}
public static void Main(string[] args) {
var dividir = (x,y) => Console.WriteLine(string.Format("Division: {0}", x/y));
dividir(10,5);
}
public static void Main(string[] args) {
var multiplicar = (x, y) => (x * y);
Console.WriteLine(string.Format("Multiplicar: {0}", multiplicar(10,5));
}
43
44. C# - Linq Query - TakeWhile
public void TakeWhile_Indexer() {
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);
Console.WriteLine("First numbers less than 6:");
foreach (var n in firstNumbersLessThan6)
{
Console.WriteLine(n);
}
}
-eq
public static void TakeWhile_Indexer(string[] args ) {
Console.WriteLine("First numbers less than 6:");
new[]{ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }.TakeWhile(n => n < 6)
.ToList()
.ForEach(x => Console.WriteLine(x));
}
44
45. C# - Programación Asíncrona
▹ CLR v1: APM – Modelo de Programación Asíncrona
▹ CLR v2: EAP – Patrón Asíncrono basado en Eventos
▹ CLR v4: TAP – Patrón Asíncrono basado en Tareas
▸ V4.5 async/await
▸ V4.6 Métodos estáticos con async/await & bloques
catch/finally
▹ C# v7 : Out vars, Pattern Matching, Arbitrary async returns
45
46. C# - Task & Patrón Asíncronos basado en Eventos (EAP)
// Método que permite descargar de manera asíncrona
// una url
//
public static Task<string> DownloadStringAsync(Uri url)
{
var tcs = new TaskCompletionSource<string>(); EventHandler es ineficiente… Debemos
var wc = new WebClient(); usar Action<T> / Func<T,H> ...
wc.DownloadStringCompleted += (s,e) =>
{
if (e.Error != null) tcs.TrySetException(e.Error);
else if (e.Cancelled) tcs.TrySetCanceled();
else tcs.TrySetResult(e.Result);
};
wc.DownloadStringAsync(url);
return tcs.Task;
}
46
47. ”47
▹ Async es un modificador que permite establecer o modificar la firma
de un método formal, una expresión lambda, o un método anónimo
para que sea tratado como un método asíncrono.
▹ await es un keyword que aplica a una tarea de un método asíncrono
para suspender la ejecución del mismo hasta que la tarea en espera
se resuelva.
Nota: Declarar un método como async es requisito indispensable para poder usar await.
48. C# - Mejores Prácticas con Task.Run<T>
// Método que permite obtener de manera asíncrona
// el tamaño en bytes de la página solicitada
//
private async Task<byte[]> SumPageSizesAsync()
{
HttpClient client = new HttpClient();
Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
return getContentsTask;
}
var result = await SumPageSizesAsync();
..eq
byte[] result = await SumPageSizesAsync();
48
50. +
C/C++ - Space Invader Nintendo DS
▹ Compilador "devkitPro 1.5.0 ARM" no oficial
▹ Librería Libnds para la gestión del proyecto
▹ Librería Libfat-nds para el manejo de ficheros
▹ Librería MaxMod para el sonido
50
53. C/C++ - Estructura Lambdas
[closures] (params) -> ret{body}
▹ Closures entre corchetes []
▹ Parámetros (si los hay) entre paréntesis ()
▹ El tipo de retorno precedido por ->
▹ El cuerpo de la función entre corchetes {}
53
54. C/C++ - Closures Lambdas
▹ [] Tipo void, no encapsula nada
▹ [&] Variables capturadas por referencia
▹ [=] Variables capturadas por valor
▹ [this] Acceso a los miembros de un objeto
▹ [x=y] Captura con renombrado (C++14)
54
55. C/C++ - Lambdas
#include <iostream>
using namespace std;
class Foo {
public :
Foo () : _x( 12345 ) {}
void apply_x(const vector<int>& v)const { for_each(v.begin(),v.end(),[this](int n){cout<< n*_x <<endl;}); }
void func () { [this] () { cout << _x; } (); }
private :
int _x;
};
int main() {
auto print = [] () { cout << "Hello world"; };
auto print2 = [] () { return 1; } //Infiere la salida el compilador
auto print3 = [] () -> int { return 1; } // Imponemos el tipo de salida
print();
print2();
print3();
Foo f;
f.func();
}
55
57. C/C++ - Programación concurrente con ppltask.h
▹ Concurrency::task
▸ Encadena múltiples operaciones sincrónicas y asincrónicas
▸ Administra excepciones
▸ Realizar cancelaciones
▸ Garantizar que las tareas individuales se ejecuten en el contexto o
contenedor de subproceso apropiado
57
58. C/C++ - Encadenamiento de Op Async con Tareas
#include <ppltasks.h>
using namespace concurrency;
using namespace Windows::Storage;
void App::DeleteWithTasks(String^ fileName)
{
StorageFolder^ localFolder = ApplicationData::Current::LocalFolder;
auto getFileTask = create_task(localFolder->GetFileAsync(fileName));
getFileTask
.then([](StorageFile^ storageFileSample) ->IAsyncAction^ {
return storageFileSample->DeleteAsync();
})
.then([](void) {
OutputDebugString(L"File deleted.");
});
}
58
76. F#
▹ Declaración Imperativa
▹ Lazy Evaluation a través de keyword (lazy)
▹ Pattern Matching
▹ Quoted Expression
▹ Funciones de primer orden
▹ Interoperabilidad con .Net
▹ Recursividad (Tail)
76
78. F# - AutoResetEvent
open System
let userTimerWithCallback =
let event = new System.Threading.AutoResetEvent(false)
let timer = new System.Timers.Timer(2000.0)
timer.Elapsed.Add (fun _ -> event.Set() | > ignore )
printfn "Esperando : %O" DateTime.Now.TimeOfDay
timer.Start()
printfn "Haciendo cosas mientras esperamos al evento"
event.WaitOne() | > ignore
printfn "Timer ticked %O" DateTime.Now.TimeOfDay
78
79. F# - IAsync Result / Async.RunSynchronously
let fileWriteWithAsync =
use stream = new System.IO.FileStream("test.txt", System.IO.FileMode.Create)
printfn "Empezando escritura asincrona"
let asyncResult = stream.BeginWrite(Array.empty,0,0,null,null)
let async = Async.AwaitIAsyncResult(asyncResult) |> Async.Ignore
printfn "Haciendo cosas mientras esperamos al evento"
Async.RunSynchronously async
printfn "Escritura asíncrona completada"
…
let sleepWorkflow = async{
printfn "Empezamos a dormir el workflow %O" DateTime.Now.TimeOfDay
do! Async.Sleep 2000
printfn "workflow finalizado %O" DateTime.Now.TimeOfDay
}
Async.RunSynchronously sleepWorkflow
79
80. F# - Async.Parallel
let sleepWorkflowMs ms = async {
printfn "%i ms workflow started" ms
do! Async.Sleep ms
printfn "%i ms workflow finished" ms
}
let sleep1 = sleepWorkflowMs 1000
let sleep2 = sleepWorkflowMs 2000
#time
[sleep1; sleep2]
|> Async.Parallel
|> Async.RunSynchronously
#time
80
82. Beneficios aportados por la programación asíncrona
▹ Explotamos rendimiento de procesador/es
▹ Evitamos cuellos de botella, bloqueos...
▹ Procesamiento de tareas en paralelo
▹ Trabajamos con subprocesos en interfaces de usuario
▹ Soporte a sistemas de alta escabilidad
▹ Robustez en las aplicaciones/juegos desarrollados
82
83. Desventajas de la programación asíncrona
▹ Código desarrollado
▸ Entendimiento
▸ Acoplamiento
▸ Mantenibilidad
▸ Dificultad de debuggear
83
84. Beneficios de la programación funcional
▹ Minimización del código
▹ Basado en expresiones
▹ Cálculos lambda
▹ Recursión
▹ Eficiencia
84