On Github timoteoponce / presentation_functional_programming_java
Por Timoteo Ponce
Swissbytes Ltda.
2008 Suiza, Dinamarca, Australia, Bolivia ATM, BRMS, Web Applications
Programming Pearls Magazine, 1986
"Leer un archivo de texto, determinar la cantidad de palabras mas usadas, e imprimir una lista ordenada de estas palabras junto con sus frecuencias." Jon Bentley, Programming Pearls, 1986
- Donald Knuth - Doug McIlroy
$> tr -cs A-Za-z '\n' | tr A-Z a-z | sort | uniq -c | sort -rn | sed ${1}q
Programación procedimental
Orientada a objetos
Orientada a aspectos
Funcional
Lógica
Los programas complejos tienen mas bugs
Los programas complejos son mas difíciles de cambiar
Los programas complejos son menos legibles
Los programas complejos son menos flexibles
Nosotros escribimos programas que toman decisiones
Las decisiones se basan en valores o datos
Los datos son percibidos o calculados
Los datos calculados son estables
Nuestros programas deben ser estables
String readAsString(InputStream stream) throw IOException{ val reader = new InputStreamReader(stream); return CharStreams.toString(reader); } List<String> readAsLines(InputStream stream) throw IOException{ return IOUtils.readLines(stream); } void main(){ val input = new FileInputStream("myfile.txt"); println("content: " + readAsString(input)); println("lines: " + readAsLines(input)); }
String readAsString(InputStream stream) throw IOException{ val reader = new InputStreamReader(cloneOf(stream)); return Streams.toString(reader); } List<String> readAsLines(InputStream stream) throw IOException{ return IOUtils.readLines(cloneOf(stream)); } InputStream cloneOf(InputStream input){ val cloned .... return cloned; }
No tocar el estado global
No modificar datos de entrada
No interrumpir el flujo de ejecución
Alcance local
Determinístico
Baja complejidad
No interrumpe el flujo de ejecución
Valores < - > Tiempo
Git / Mercurial / Fossil
Request req = new Request("http://juanbandafanpage.com"); req.method(Request.POST); request.body("fanId=chichico"); request.fetch(); Request req = new Request("http://juanbandafanpage.com"); // req.method(Request.POST); request.body("fanId=chichico"); request.fetch(); //NPE!!!
Request req = new Request("http://juanbandafanpage.com"); req = req.body("fanId=chichico"); req = req.post(); req.fetch(); Request req = new Request("http://juanbandafanpage.com"); req.body("fanId=chichico").post().fetch();
Todo valor es inmutable por defecto
Todo valor modificado, genera un nuevo valor
Los estados mutables son privados/locales
Los valores no cambian, generan nuevos valores
Los valores no necesitan thread-safety
No existen efectos secundarios
Identidad!!!
int countBugs(String filePath){ Path path = Paths.get(filePath); int count = 0; try(FileReader reader = new FileReader( Files.newInputStream(path)) ){ String line = null; while( (line = reader.readLine()) != null ) if(line.contains(“BUG”)) count++; }catch(IOException e){ printErr(e); } }
int countBugs(String filePath){ return Files.readAllLines(Paths.get(filePath)) .stream() .filter(line -> line.contains(“BUG”)) .count(); }
List<Deposit> deposits= …; // give me the big transfers long allBigTransfers = deposits.stream() .filter(d -> d.amount > 10000L) .mapToLong(d -> t.amount) .sum(); // give me the smallest transfer Optional<> minTransfer = deposits.stream() .min((d1, d2) -> d1 > d2);
Enfocarse en el qué, no en el cómo
Abstraer infraestructura
Generar expresiones, y no órdenes
Código expresivo/legible
Enfoque en el fondo, no la forma
Simplicidad inherente
Evaluación optimizable
getAsyncContext,getAttribute, getAttributeNames, getCharacterEncoding,getLength,getContentLength, getType,getContentType,getDispatcherType,getLocalName, getLocalAddr,getLocale,getLocales,getLocalName, getLocalPort,getParameterNames,getParameterValues, getProtocol,getReader,getRealPath,getRemoteAddr, getRemoteHost,getRemotePort,getRequestDispatcher, getScheme,getServerName,getServerPort,isSecure, removeAttribute,setAttribute,setCharacterEncoding, startAsync,getHeader,getHeaderNames,getIntHeader, getResponseStream, ...
[ "remote-addr": "127.0.0.1", "scheme": "http", "form-params": [], "query-string": "fanId=chichico", "request-method": "GET", "content-type": "text/csv", "server-name": "localhost", "params": ["key": "value"], "server-port": 8080, "headers": [ "accept-encoding" : "gzip, deflate", "connection": "close", "content-length": 0, ... ] ]
class CustomerId{ private int id; private String value; //..... } class InValue{ private int id; private String value; private int type; //... } class OutValue{ //... } class InValueContainer{ //... } class OutValueContainer{ //... }
Inconsistencia
Duplicidad
Acoplamiento
Primitives
Lists
Sets
Dictionary
Usar primitivos hasta donde se pueda
Usar estructuras hasta donde se pueda
Evitar los objetos anémicos
Evitar estructuras hereditarias
Datos expresivos y claros
Uniformidad y simplicidad de código
Re-utilización
JSON...