Patrones de Programación Funcional
Sebastián Estrella
Acerca de mí
¿Qué es Programación Funcional?
¿Qué es Programación Declarativa?
Inmutabilidad
Inmutabilidad
- Código predecible
- Facilita la concurrencia
- Reduce el riesgo de condiciones de carrera
Referencia Transparencial
- Resultados determinísticos
- Facilita el razonamiento del comportamiento de un programa
Composición
- Dividir un problema en pequeñas partes
- Hacer una cosa y hacerla bien (Linux)
- Código facíl de probar
- Mayor reusabilidad
¿Cuál es el problema con la Programación Orientada a Objetos?
Mutabilidad
- Problemas de concurrencia
- Díficil de debuggear
- El número mágico siete, más o menos dos (Miller)
Mutabilidad
Efectos secundarios
- Operaciones de I/O
- Modificación de variables
- Cambios de estado en general
- Pruebas fragiles
Mantenibilidad
- Mayor nivel de indirección
- Demasiado detalles de implementación (wholemeal)
0
Advanced issues found▲
1
Hablar es fácil, muéstrame el código
- Linus Torvalds
Partamos de un escenario real...
...los Vengadores nos necesitan!
public class User {
...
public User(String firstName, String lastName, boolean admin, boolean enabled) {
this.firstName = firstName;
this.lastName = lastName;
this.admin = admin;
this.enabled = enabled;
}
...
}
List<User> users = Arrays.asList(
// admins
new User("Bruce", "Banner", true, true),
new User("Clinton", "Barton", true, false),
new User("Natasha", "Romanoff", true, true),
new User("Steve", "Rogers", true, true),
new User("Thor", "Odisen", true, true),
new User("Tony", "Stark", true, true),
// members
new User("Peter", "Parker", false, false),
new User("Stephen", "Strange", false, true)
);
Table table = new Table();
for (User user : users) {
if (user.isEnabled()) {
Row row = new Row();
row.addColumn(new Column(user.getFirstName() + " " + user.getLastName()));
String role = "";
if (user.isAdmin()) {
role = "ADMIN";
} else {
role = "MEMBER";
}
row.addColumn(new Column(role));
table.addRow(row);
}
}
table.render();
| Bruce Banner | ADMIN |
| Natasha Romanoff | ADMIN |
| Steve Rogers | ADMIN |
| Thor Odisen | ADMIN |
| Tony Stark | ADMIN |
| Stephen Strange | MEMBER |
Inmutabilidad
Table table = new Table();
for (User user : users) {
if (user.isEnabled()) {
Row row = new Row();
row.addColumn(new Column(user.getFirstName() + " " + user.getLastName()));
String role = user.isAdmin() ? "ADMIN" : "MEMBER";
row.addColumn(new Column(role));
table.addRow(row);
}
}
table.render();
Principio de responsabilidad única
List<User> enabledUsers = new ArrayList<User>();
for (User user : users) {
if (user.isEnabled()) {
enabledUsers.add(user);
}
}
List<Row> rows = new ArrayList<Row>();
for (User user : enabledUsers) {
Row row = new Row();
row.addColumn(new Column(user.getFirstName() + " " + user.getLastName()));
String role = user.isAdmin() ? "ADMIN" : "MEMBER";
row.addColumn(new Column(role));
rows.add(row);
}
Table table = new Table();
table.addRows(rows);
table.render();
List<User> enabledUsers = new ArrayList<User>();
for (User user : users) {
if (user.isEnabled()) {
enabledUsers.add(user);
}
}
List<Row> rows = new ArrayList<Row>();
for (User user : enabledUsers) {
Row row = new Row();
row.addColumn(new Column(user.getFirstName() + " " + user.getLastName()));
String role = user.isAdmin() ? "ADMIN" : "MEMBER";
row.addColumn(new Column(role));
rows.add(row);
}
Table table = new Table();
table.addRows(rows);
table.render();
1) Seleccionar los usuarios habilitados
2) Crear una fila por cada usuario
3) Presentar el contenido de la tabla
Patrones Funcionales
List<User> enabledUsers = new ArrayList<User>();
for (User user : users) {
if (user.isEnabled()) {
enabledUsers.add(user);
}
}
List<Row> rows = new ArrayList<Row>();
for (User user : enabledUsers) {
Row row = new Row();
row.addColumn(new Column(user.getFirstName() + " " + user.getLastName()));
String role = user.isAdmin() ? "ADMIN" : "MEMBER";
row.addColumn(new Column(role));
rows.add(row);
}
Table table = new Table();
table.addRows(rows);
table.render();
Funciones de Orden Superior
List<User> enabledUsers = users.stream()
.filter(user -> user.isEnabled())
.collect(Collectors.toList());
List<Row> rows = new ArrayList<Row>();
for (User user : enabledUsers) {
Row row = new Row();
row.addColumn(new Column(user.getFirstName() + " " + user.getLastName()));
String role = user.isAdmin() ? "ADMIN" : "MEMBER";
row.addColumn(new Column(role));
rows.add(row);
}
Table table = new Table();
table.addRows(rows);
table.render();
List<User> enabledUsers = users.stream()
.filter(user -> user.isEnabled())
.collect(Collectors.toList());
List<Row> rows = enabledUsers.stream()
.map(user -> {
Row row = new Row();
row.addColumn(new Column(user.getFirstName() + " " + user.getLastName()));
String role = user.isAdmin() ? "ADMIN" : "MEMBER";
row.addColumn(new Column(role));
return row;
})
.collect(Collectors.toList());
Table table = new Table();
table.addRows(rows);
table.render();
Composición
List<Row> rows = users.stream()
.filter(user -> user.isEnabled())
.map(user -> {
Row row = new Row();
row.addColumn(new Column(user.getFirstName() + " " + user.getLastName()));
String role = user.isAdmin() ? "ADMIN" : "MEMBER";
row.addColumn(new Column(role));
return row;
})
.collect(Collectors.toList());
Table table = new Table();
table.addRows(rows);
table.render();
Un nuevo Vengador se ha unido al equipo
List<User> users = Arrays.asList(
// admins
new User("Bruce", "Banner", true, true),
new User("Clinton", "Barton", true, false),
new User("Natasha", "Romanoff", true, true),
new User("Steve", "Rogers", true, true),
new User("Thor", "Odisen", true, true),
new User("Tony", "Stark", true, true),
// members
new User("Peter", "Parker", false, false),
new User("Stephen", "Strange", false, true),
new User(null, "Pointer", true, true)
);
Integer number = null;
String text = null;
Object object = null;
Dr. Null Pointer: Superpoderes
1) Camuflaje
2) Inmunidad al compilador
3) Paranoia
Integer a = null + 1;
Assert.notNull(x);
Assert.notNull(y);
return x + y;
| Bruce Banner | ADMIN |
| Natasha Romanoff | ADMIN |
| Steve Rogers | ADMIN |
| Thor Odisen | ADMIN |
| Tony Stark | ADMIN |
| Stephen Strange | MEMBER |
| null Pointer | ADMIN |
List<Row> rows = users.stream()
.filter(user -> user.isEnabled())
.map(user -> {
Row row = new Row();
String fullName = Optional.ofNullable(user.getFirstName())
.map(firstName -> {
return Optional.ofNullable(user.getLastName())
.map(lastName -> firstName + " " + lastName)
.get();
})
.orElse("<unknown>");
row.addColumn(new Column(fullName));
String role = user.isAdmin() ? "ADMIN" : "MEMBER";
row.addColumn(new Column(role));
return row;
})
.collect(Collectors.toList());
Table table = new Table();
table.addRows(rows);
table.render();
| Bruce Banner | ADMIN |
| Natasha Romanoff | ADMIN |
| Steve Rogers | ADMIN |
| Thor Odisen | ADMIN |
| Tony Stark | ADMIN |
| Stephen Strange | MEMBER |
| <unknown> | ADMIN |
References
Repositorio
Repositorio
Sebastián Estrella
Stack Builders
Sitio: https://www.stackbuilders.com
Quito Lambda: https://www.meetup.com/Quito-Lambda-Meetup/
Gracias
Patrones de Programación Funcional
By Sebastián Estrella
Patrones de Programación Funcional
- 109