SlideShare une entreprise Scribd logo
1  sur  159
Télécharger pour lire hors ligne
El camino hacia la
programación declarativa
WHO ARE WE?
WHO ARE WE?
Daniel Jiménez
Daniel Jiménez Roque
WHO ARE WE?
Daniel Jiménez
Daniel Jiménez Roque
Gerard Madorell
Gerard Madorell
@GMadorell
DECLARATIVE
PROGRAMMING
DECLARATIVE PROGRAMMING
+ WHAT
- HOW
DECLARATIVE PROGRAMMING
Imperative Declarative
WHAT ARE WE GONNA DO TODAY?
WHAT ARE WE GONNA DO TODAY?
WHAT ARE WE GONNA DO TODAY?
+ =OOP
WHAT ARE WE GONNA DO TODAY?
https://github.com/lambtors/poker-api
Imperative
WHAT ARE WE GONNA DO TODAY?
Imperative Functional
WHAT ARE WE GONNA DO TODAY?
Imperative Abstract typesFunctional
WHAT ARE WE GONNA DO TODAY?
Imperative DeclarativeAbstract typesFunctional
WHAT ARE WE GONNA DO TODAY?
PLACE YOUR BETS
PLACE YOUR BETS
IMPERATIVE
trait PlayerRepository {
def search(playerId: PlayerId): Future[Option[Player]]
def insert(player: Player): Future[Unit]
}
trait PlayerRepository {
def search(playerId: PlayerId): Future[Option[Player]]
def insert(player: Player): Future[Unit]
}
FUTURE
Main thread
FUTURE
Main thread
insert()
FUTURE
Main thread
Future thread
insert()
FUTURE
Main thread
Future thread
insert()
insert db
FUTURE
Main thread
Future thread
insert()
insert db
FUTURE
Main thread
Future thread
insert()
insert db
player
inserted
trait PlayerRepository {
def search(playerId: PlayerId): Future[Option[Player]]
def insert(player: Player): Future[Unit]
}
OPTION
OPTION
Option[Burger]
OPTION
Option[Burger]
OPTION
Option[Burger]
OPTION
Some[Burger] None
Option[Burger]
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
FLATMAP
Future[Sauce]
Future[Sauce]
flatmap()
Sauce
Future[Sauce]
flatmap()
Sauce
Future[Sauce]
Future[Fish]
flatmap()
Sauce
Future[Sauce]
Future[Fish]
flatmap()
flatmap()
Sauce
Sauce + Fish
Future[Sauce]
Future[Fish]
flatmap()
flatmap()
Sauce
Sauce + Fish
Future[Sauce]
Future[Fish]
Future[Rice]
flatmap()
flatmap()
Sauce
Sauce + Fish
Future[Sauce]
Future[Fish]
Future[Rice]
flatmap()
flatmap()
flatmap()
Sauce
Sauce + Fish
Future[Sauce]
Future[Fish]
Future[Rice]
flatmap()
flatmap()
flatmap()
Sauce + Fish + Rice
Sauce
Sauce + Fish
Future[Sauce]
Future[Fish]
Future[Rice]
flatmap()
flatmap()
Future[Paella]
flatmap()
Sauce + Fish + Rice
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
A LITTLE BIT MORE
FUNCTIONAL
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
final class PlayerCardsFinder(playerRepository: PlayerRepository){
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(Future.failed(PlayerNotFound(playerId)))(
player => Future.successful((player.firstCard, player.secondCard)))
)
}
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
final class PlayerCardsFinder(playerRepository: PlayerRepository){
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(Future.failed(PlayerNotFound(playerId)))(
player => Future.successful((player.firstCard, player.secondCard)))
)
}
final class PlayerCardsFinder(playerRepository: PlayerRepository) {
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository.search(playerId).flatMap { playerOption =>
if (playerOption.isDefined) {
Future.successful(
(playerOption.get.firstCard, playerOption.get.secondCard))
} else {
Future.failed(PlayerNotFound(playerId))
}
}
}
final class PlayerCardsFinder(playerRepository: PlayerRepository){
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(Future.failed(PlayerNotFound(playerId)))(
player => Future.successful((player.firstCard, player.secondCard)))
)
}
FUTURE
CONSIDERED
HARMFUL
“A monad is just a monoid
in the category of endofunctors”
Paulo Coelho
trait PlayerRepository {
def search(playerId: PlayerId): Future[Option[Player]]
def insert(player: Player): Future[Unit]
}
trait PlayerRepository {
def search(playerId: PlayerId): Future[Option[Player]]
def insert(player: Player): Future[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
trait PlayerRepository {
def search(playerId: PlayerId): Future[Option[Player]]
def insert(player: Player): Future[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
val playerRepositoryFuture = new PlayerRepository[Future]
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
val playerRepositoryFuture = new PlayerRepository[Future]
val playerRepositoryTask = new PlayerRepository[Task]
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
val playerRepositoryFuture = new PlayerRepository[Future]
val playerRepositoryTask = new PlayerRepository[Task]
val playerRepositoryId = new PlayerRepository[Id]
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
val playerRepositoryFuture = new PlayerRepository[Future]
val playerRepositoryTask = new PlayerRepository[Task]
val playerRepositoryId = new PlayerRepository[Id]
val playerRepositoryTry = new PlayerRepository[Try]
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
val playerRepositoryFuture = new PlayerRepository[Future]
val playerRepositoryTask = new PlayerRepository[Task]
val playerRepositoryId = new PlayerRepository[Id]
val playerRepositoryTry = new PlayerRepository[Try]
class FuturePlayerRepository
extends PlayerRepository[Future] {
def search(playerId: PlayerId): Future[Option[Player]]
def insert(player: Player): Future[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
val playerRepositoryFuture = new PlayerRepository[Future]
val playerRepositoryTask = new PlayerRepository[Task]
val playerRepositoryId = new PlayerRepository[Id]
val playerRepositoryTry = new PlayerRepository[Try]
class FuturePlayerRepository
extends PlayerRepository[Future] {
def search(playerId: PlayerId): Future[Option[Player]]
def insert(player: Player): Future[Unit]
}
final class PlayerCardsFinder(playerRepository: PlayerRepository){
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(Future.failed(PlayerNotFound(playerId)))(
player => Future.successful((player.firstCard, player.secondCard)))
)
}
final class PlayerCardsFinder(playerRepository: PlayerRepository){
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(Future.failed(PlayerNotFound(playerId)))(
player => Future.successful((player.firstCard, player.secondCard)))
)
}
final class PlayerCardsFinder[P[_]: Monad](
playerRepository: PlayerRepository[P]) {
def find(playerId: PlayerId): P[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(
MonadErrorThrowable[P].raiseError(PlayerNotFound(playerId)))(player =>
(player.firstCard, player.secondCard).pure[P]))
}
final class PlayerCardsFinder(playerRepository: PlayerRepository){
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(Future.failed(PlayerNotFound(playerId)))(
player => Future.successful((player.firstCard, player.secondCard)))
)
}
final class PlayerCardsFinder[P[_]: Monad](
playerRepository: PlayerRepository[P]) {
def find(playerId: PlayerId): P[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(
MonadErrorThrowable[P].raiseError(PlayerNotFound(playerId)))(player =>
(player.firstCard, player.secondCard).pure[P]))
}
final class PlayerCardsFinder(playerRepository: PlayerRepository){
def find(playerId: PlayerId): Future[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(Future.failed(PlayerNotFound(playerId)))(
player => Future.successful((player.firstCard, player.secondCard)))
)
}
final class PlayerCardsFinder[P[_]: Monad](
playerRepository: PlayerRepository[P]) {
def find(playerId: PlayerId): P[(Card, Card)] =
playerRepository
.search(playerId)
.flatMap(
_.fold(
MonadErrorThrowable[P].raiseError(PlayerNotFound(playerId)))(player =>
(player.firstCard, player.secondCard).pure[P]))
}
trait Monad[P[_]] {
def flatMap[A, B](pa: P[A])(function: A => P[B]): P[B]
def pure[A](a: A): P[A]
}
trait Monad[P[_]] {
def flatMap[A, B](pa: P[A])(function: A => P[B]): P[B]
def pure[A](a: A): P[A]
}
final class MonadFuture extends Monad[Future] {
def flatMap[A, B](pa: Future[A])(
function: (A) => Future[B]): Future[B] =
pa.flatMap(f)
def pure[A](a: A): Future[A] =
Future(a)
}
DECLARATIVE
HAPPINESS
P[_]
P[_]
Abstract, but denotes
implementation
P[_]
REAL LOGIC
Abstract, but denotes
implementation
TRANSFORMERS
OptionT
Operate directly on the option,
ignoring the higher kinded type.
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): OptionT[P, Player]
def insert(player: Player): P[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): P[Option[Player]]
def insert(player: Player): P[Unit]
}
trait PlayerRepository[P[_]] {
def search(playerId: PlayerId): OptionT[P, Player]
def insert(player: Player): P[Unit]
}
playerRepository
.search(playerId)
.flatMap(
_.fold(…)(…)
)
playerRepository
.search(playerId)
.flatMap(
_.fold(…)(…)
)
playerRepository
.search(playerId)
.fold(…)(…)
OTHER
TRANSFORMERS
Other transformers
EitherT[P[_], A, B] P[Either[A, B]]
Other transformers
Other transformers
Nested[F[_], G[_], A] F[G[A]]
Other transformers
Nested[F[_], G[_], A] F[G[A]]
Nested[List, Option, A] List[Option[A]]
Other transformers
Nested[F[_], G[_], A] F[G[A]]
Nested[List, Option, A] List[Option[A]]
Nested[Future, List, A] Future[List[A]]
THERE'S MORE...
val pokerGameRepository: PokerGameRepository[Future] =
mock[PokerGameRepository[Future]]
val pokerGameRepository: PokerGameRepository[Future] =
mock[PokerGameRepository[Future]]
def shouldInsertPokerGame(pokerGame: PokerGame) =
(pokerGameRepository.insert _)
.expects(pokerGame)
.once()
.returning(Future.successful(Unit))
“should create a poker game" in {
val command = CreatePokerGameCommandStub.random()
shouldNotFindPokerGame(…)
shouldInsertPokerGame(…)
(1 to command.amountOfPlayers).foreach {
shouldInsertPlayer(…)
}
commandHandler.handle(command) should beSuccessfulFuture
}
“should create a poker game" in {
val command = CreatePokerGameCommandStub.random()
shouldNotFindPokerGame(…)
shouldInsertPokerGame(…)
(1 to command.amountOfPlayers).foreach {
shouldInsertPlayer(…)
}
commandHandler.handle(command) should beSuccessfulFuture
}
“should create a poker game" in {
val command = CreatePokerGameCommandStub.random()
shouldNotFindPokerGame(…)
shouldInsertPokerGame(…)
(1 to command.amountOfPlayers).foreach {
shouldInsertPlayer(…)
}
commandHandler.handle(command) should beSuccessfulFuture
}
“should create a poker game" in {
val command = CreatePokerGameCommandStub.random()
shouldNotFindPokerGame(…)
shouldInsertPokerGame(…)
(1 to command.amountOfPlayers).foreach {
shouldInsertPlayer(…)
}
commandHandler.handle(command) should beSuccessfulFuture
}
StateT
StateT
PokerGameRepository PlayerRepository
insert
update
search
insert
update
search
mock
mock
mock
Application
State

PokerRepositoryState PlayerRepositoryState
StateT
ApplicationState
PlayerRepository.insert
ApplicationState’
StateT
case class PokerState(
pokerGameRepositoryState: Map[GameId, PokerGame],
playerRepositoryState: Map[GameId, Map[PlayerId, Player]]
)
case class PokerState(
pokerGameRepositoryState: Map[GameId, PokerGame],
playerRepositoryState: Map[GameId, Map[PlayerId, Player]]
)
type State[A] = StateT[Exception, PokerState, A]
case class PokerState(
pokerGameRepositoryState: Map[GameId, PokerGame],
playerRepositoryState: Map[GameId, Map[PlayerId, Player]]
)
val pokerGameRepository = new PokerGameRepository[State] {
override def insert(pokerGame: PokerGame): State[Unit] =
State[Unit].changeState(
state => (state.withGame(pokerGame), Unit)
)
}
type State[A] = StateT[Exception, PokerState, A]
"create a poker game" in {
val command = CreatePokerGameCommandStub.random()
var initialState = PokerState.empty
var finalState = PokerState.empty
finalState = finalState.withGame(…)
(1 to command.amountOfPlayers).foreach { _ =>
finalState = finalState.withPlayer(…)
}
commandHandler.handle(command) should
beValidWithState(initialState, finalState)
}
"create a poker game" in {
val command = CreatePokerGameCommandStub.random()
var initialState = PokerState.empty
var finalState = PokerState.empty
finalState = finalState.withGame(…)
(1 to command.amountOfPlayers).foreach { _ =>
finalState = finalState.withPlayer(…)
}
commandHandler.handle(command) should
beValidWithState(initialState, finalState)
}
"create a poker game" in {
val command = CreatePokerGameCommandStub.random()
var initialState = PokerState.empty
var finalState = PokerState.empty
finalState = finalState.withGame(…)
(1 to command.amountOfPlayers).foreach { _ =>
finalState = finalState.withPlayer(…)
}
commandHandler.handle(command) should
beValidWithState(initialState, finalState)
}
"create a poker game" in {
val command = CreatePokerGameCommandStub.random()
var initialState = PokerState.empty
var finalState = PokerState.empty
finalState = finalState.withGame(…)
(1 to command.amountOfPlayers).foreach { _ =>
finalState = finalState.withPlayer(…)
}
commandHandler.handle(command) should
beValidWithState(initialState, finalState)
}
"create a poker game" in {
val command = CreatePokerGameCommandStub.random()
var initialState = PokerState.empty
var finalState = PokerState.empty
finalState = finalState.withGame(…)
(1 to command.amountOfPlayers).foreach { _ =>
finalState = finalState.withPlayer(…)
}
commandHandler.handle(command) should
beValidWithState(initialState, finalState)
}
Benefits
Benefits
You test the changes of state of the application
Benefits
You test the changes of state of the application
You can check intermediate state between steps
Benefits
You test the changes of state of the application
You can check intermediate state between steps
And...
pokerGameRepository
.insert(…)
.map(_ =>
(1 to amountOfPlayers.amount).foreach(_ => createPlayer(…))
)
}
pokerGameRepository
.insert(…)
.map(_ =>
(1 to amountOfPlayers.amount).foreach(_ => createPlayer(…))
)
}
Futures are not lazy
Futures are not lazy
We are iterating over a list and then
inserting players
Futures are not lazy
We are iterating over a list and then
inserting players
But we’re not doing anything with those
futures!!!
Futures are not lazy
We are iterating over a list and then
inserting players
But we’re not doing anything with those
futures!!!
We lose control over when they will
execute. Race conditions!!!!
Mocks only return our expected result, 

they don't simulate the application behaviour
pokerGameRepository
.insert(…)
.flatMap(_ =>
(1 to amountOfPlayers.amount).foreach(_ => createPlayer(…))
)
}
pokerGameRepository
.insert(…)
.flatMap(_ =>
(1 to amountOfPlayers.amount).foreach(_ => createPlayer(…))
)
}
pokerGameRepository
.insert(…)
.flatMap(_ =>
(1 to amountOfPlayers.amount).traverse(_ => createPlayer(…))
)
}
pokerGameRepository
.insert(…)
.flatMap(_ =>
(1 to amountOfPlayers.amount).foreach(_ => createPlayer(…))
)
}
pokerGameRepository
.insert(…)
.flatMap(_ =>
(1 to amountOfPlayers.amount).traverse(_ => createPlayer(…))
)
}
map: List[Future[Unit]]
traverse:
map: List[Future[Unit]]
traverse:
Future[
map: List[Future[Unit]]
traverse: Future[
map: List[Future[Unit]]
traverse: Future[
List[
map: List[Future[Unit]]
traverse: Future[List[
map: List[Future[Unit]]
traverse: Future[List[
Unit]]
map: List[Future[Unit]]
traverse: Future[List[Unit]]
THE END OF THE ROAD
Difficultytounderstand
Imperative Functional AbstractTypes Declarative
Logic Impl
BE DECLARATIVE, MY FRIEND
BE DECLARATIVE, MY FRIEND
Domain logic is easier to understand
BE DECLARATIVE, MY FRIEND
Domain logic is easier to understand
Increased productivity
BE DECLARATIVE, MY FRIEND
Domain logic is easier to understand
Increased productivity
Flexibility
BE DECLARATIVE, MY FRIEND
Domain logic is easier to understand
Increased productivity
Flexibility
Simpler, but harder
BE DECLARATIVE, MY FRIEND
Domain logic is easier to understand
Increased productivity
Flexibility
Simpler, but harder
Better and unmocked tests
THE END?
Free
monads
Reader
Monad
Writer
Monad
Optics
Extensible
Effects
ANY QUESTIONS?
P[applause]
ANY QUESTIONS?
P[applause]

Contenu connexe

Tendances

Tips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query PitfallsTips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
Desenvolvimento web usando django
Desenvolvimento web usando djangoDesenvolvimento web usando django
Desenvolvimento web usando django
yurimalheiros
 
Gareth hayes. non alphanumeric javascript-php and shared fuzzing
Gareth hayes. non alphanumeric javascript-php and shared fuzzingGareth hayes. non alphanumeric javascript-php and shared fuzzing
Gareth hayes. non alphanumeric javascript-php and shared fuzzing
Yury Chemerkin
 
第二讲 预备-Python基礎
第二讲 预备-Python基礎第二讲 预备-Python基礎
第二讲 预备-Python基礎
anzhong70
 

Tendances (20)

PHP 1
PHP 1PHP 1
PHP 1
 
テストデータどうしてますか?
テストデータどうしてますか?テストデータどうしてますか?
テストデータどうしてますか?
 
Use cases in the code with AOP
Use cases in the code with AOPUse cases in the code with AOP
Use cases in the code with AOP
 
[1062BPY12001] Data analysis with R / week 4
[1062BPY12001] Data analysis with R / week 4[1062BPY12001] Data analysis with R / week 4
[1062BPY12001] Data analysis with R / week 4
 
An Elephant of a Different Colour: Hack
An Elephant of a Different Colour: HackAn Elephant of a Different Colour: Hack
An Elephant of a Different Colour: Hack
 
WordCamp Bristol 2019 - WordPress custom theme building
WordCamp Bristol 2019 - WordPress custom theme buildingWordCamp Bristol 2019 - WordPress custom theme building
WordCamp Bristol 2019 - WordPress custom theme building
 
Tips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query PitfallsTips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query Pitfalls
 
Programação Funcional
Programação FuncionalProgramação Funcional
Programação Funcional
 
Desenvolvimento web usando django
Desenvolvimento web usando djangoDesenvolvimento web usando django
Desenvolvimento web usando django
 
Gareth hayes. non alphanumeric javascript-php and shared fuzzing
Gareth hayes. non alphanumeric javascript-php and shared fuzzingGareth hayes. non alphanumeric javascript-php and shared fuzzing
Gareth hayes. non alphanumeric javascript-php and shared fuzzing
 
Python avanzado - parte 1
Python avanzado - parte 1Python avanzado - parte 1
Python avanzado - parte 1
 
PHP 5.4
PHP 5.4PHP 5.4
PHP 5.4
 
Presentation1
Presentation1Presentation1
Presentation1
 
Python. Строки
Python. СтрокиPython. Строки
Python. Строки
 
第二讲 预备-Python基礎
第二讲 预备-Python基礎第二讲 预备-Python基礎
第二讲 预备-Python基礎
 
第二讲 Python基礎
第二讲 Python基礎第二讲 Python基礎
第二讲 Python基礎
 
What's new in C# 6?
What's new in C# 6?What's new in C# 6?
What's new in C# 6?
 
The Future of JavaScript (SXSW '07)
The Future of JavaScript (SXSW '07)The Future of JavaScript (SXSW '07)
The Future of JavaScript (SXSW '07)
 
An (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to PythonAn (Inaccurate) Introduction to Python
An (Inaccurate) Introduction to Python
 
Pre-Bootcamp introduction to Elixir
Pre-Bootcamp introduction to ElixirPre-Bootcamp introduction to Elixir
Pre-Bootcamp introduction to Elixir
 

Similaire à SCBCN17 - El camino hacia la programación declarativa

Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdfIfgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
fazilfootsteps
 
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdfWrite a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
rozakashif85
 
Node meetup feb_20_12
Node meetup feb_20_12Node meetup feb_20_12
Node meetup feb_20_12
jafar104
 
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
MongoSF
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
stasimus
 

Similaire à SCBCN17 - El camino hacia la programación declarativa (20)

Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdfIfgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
 
asad.pptx
asad.pptxasad.pptx
asad.pptx
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
Django tips and_tricks (1)
Django tips and_tricks (1)Django tips and_tricks (1)
Django tips and_tricks (1)
 
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdfWrite a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
 
Node meetup feb_20_12
Node meetup feb_20_12Node meetup feb_20_12
Node meetup feb_20_12
 
afsdsdfs.pptx
afsdsdfs.pptxafsdsdfs.pptx
afsdsdfs.pptx
 
What's in Groovy for Functional Programming
What's in Groovy for Functional ProgrammingWhat's in Groovy for Functional Programming
What's in Groovy for Functional Programming
 
David Kopal - Write better React with ReasonML - Codemotion Milan 2018
David Kopal - Write better React with ReasonML - Codemotion Milan 2018David Kopal - Write better React with ReasonML - Codemotion Milan 2018
David Kopal - Write better React with ReasonML - Codemotion Milan 2018
 
Glancing essential features of Dart, before stepping into Flutter
Glancing essential features of Dart, before stepping into FlutterGlancing essential features of Dart, before stepping into Flutter
Glancing essential features of Dart, before stepping into Flutter
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
 
Inside PyMongo - MongoNYC
Inside PyMongo - MongoNYCInside PyMongo - MongoNYC
Inside PyMongo - MongoNYC
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
 
Profiling PL/pgSQL
Profiling PL/pgSQLProfiling PL/pgSQL
Profiling PL/pgSQL
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
 
groovy databases
groovy databasesgroovy databases
groovy databases
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heaven
 
Event Sourcing and Functional Programming
Event Sourcing and Functional ProgrammingEvent Sourcing and Functional Programming
Event Sourcing and Functional Programming
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 

Dernier

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 

Dernier (20)

%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 

SCBCN17 - El camino hacia la programación declarativa