it's the end of design patterns as we know it (and i feel fine)
TRANSCRIPT
It’s the end of Design Patterns as we know it
(and I feel fine)Today:
Introducing Monads
Luiz Borba http://borba.blog.br
Part 1 Deconstructing Design Patterns
1994
COBOL (61)
FORTRAN (57)
CLIPPER (85)
C (72)
C++ (83)
SMALLTALK (72)
PASCAL (86)PERL (87)
LISP (58)
OBJECT PASCAL (95)
HASKELL (90)
JAVA (95) RUBY (95)
PYTHON (91)
ML (73)
ALGOL (58)
POWERBUILDER (92)
BASIC (64)
VISUAL BASIC (91)
MS BASIC (75)
SQLWINDOWS (88)
PHP (95)
COBOL (61)
FORTRAN (57)
CLIPPER (85)
C (72)
C++ (83)
SMALLTALK (72)
PASCAL (86)PERL (87)
LISP (58)
OBJECT PASCAL (95)
HASKELL (90)
JAVA (95) RUBY (95)
PYTHON (91)
ML (73)
ALGOL (58)
POWERBUILDER (92)
BASIC (64)
VISUAL BASIC (91)
MS BASIC (75)
SQLWINDOWS (88)
PHP (95)
COBOL (61)
FORTRAN (57)
CLIPPER (85)
C (72)
C++ (83)
SMALLTALK (72)
PASCAL (86)PERL (87)
LISP (58)
OBJECT PASCAL (95)
HASKELL (90)
JAVA (95) RUBY (95)
PYTHON (91)
ML (73)
ALGOL (58)
POWERBUILDER (92)
BASIC (64)
VISUAL BASIC (91)
MS BASIC (75)
SQLWINDOWS (88)
DESKTOP
PHP (95)
COBOL (61)
FORTRAN (57)
CLIPPER (85)
C (72)
C++ (83)
SMALLTALK (72)
PASCAL (86)PERL (87)
LISP (58)
OBJECT PASCAL (95)
HASKELL (90)
JAVA (95) RUBY (95)
PYTHON (91)
ML (73)
ALGOL (58)
POWERBUILDER (92)
BASIC (64)
VISUAL BASIC (91)
MS BASIC (75)
SQLWINDOWS (88)
WEB
PHP (95)
COBOL (61)
FORTRAN (57)
CLIPPER (85)
C (72)
C++ (83)
SMALLTALK (72)
PASCAL (86)PERL (87)
LISP (58)
OBJECT PASCAL (95)
HASKELL (90)
JAVA (95) RUBY (95)
PYTHON (91)
ML (73)
ALGOL (58)
POWERBUILDER (92)
BASIC (64)
VISUAL BASIC (91)
MS BASIC (75)
SQLWINDOWS (88)
PHP (95)
COBOL (61)
FORTRAN (57)
CLIPPER (85)
C (72)
C++ (83)
SMALLTALK (72)
PASCAL (86)PERL (87)
LISP (58)
OBJECT PASCAL (95)
HASKELL (90)
JAVA (95) RUBY (95)
PYTHON (91)
ML (73)
ALGOL (58)
POWERBUILDER (92)
BASIC (64)
VISUAL BASIC (91)
MS BASIC (75)
SQLWINDOWS (88)
PHP (95)
I always knew that one day
Smalltalkwould replace Java.I just didn’t knowit would be called
Ruby
"
"(Kent Beck)
COBOL (61)
FORTRAN (57)
CLIPPER (85)
C (72)
C++ (83)
SMALLTALK (72)
PASCAL (86)PERL (87)
LISP (58)
OBJECT PASCAL (95)
HASKELL (90)
JAVA (95) RUBY (95)
PYTHON (91)
ML (73)
ALGOL (58)
POWERBUILDER (92)
BASIC (64)
VISUAL BASIC (91)
MS BASIC (75)
SQLWINDOWS (88)
Mainstream,It’s the
stupid!
AlwaysControversial
Ralph Johnson and Singleton
AreDesign Patternsmissing languages features?
AreDesign Patternshow languages evolve?
(Jeff Atwood)
COBOL (61)
FORTRAN (57)
CLIPPER (85)
C (72)
C++ (83)
SMALLTALK (72)
PASCAL (86)PERL (87)
LISP (58)
OBJECT PASCAL (95)
HASKELL (90)
JAVA (95) RUBY (95)
PYTHON (91)
ML (73)
ALGOL (58)
POWERBUILDER (92)
BASIC (64)
VISUAL BASIC (91)
MS BASIC (75)
SQLWINDOWS (88)
2010
Java
imperative languages
C FortranC++
add abstractions
subtract abstractions
LispML
Haskell
functional languages
Java
imperative languages
C FortranC++
add abstractions
subtract abstractions
LispML
Haskell
functional languages
Java
imperative languages
C FortranC++
add abstractions
hybrid languages
ScalaJava 8
C#F#
[x | x <- xs, x < 10]Haskell:
[x | x <- xs, x < 10]
from x in xs where x < 10 select x;
Haskell:
C#:
[x | x <- xs, x < 10]
from x in xs where x < 10 select x;
Haskell:
C#:
Java 8:xs.stream().filter(x -> x < 10)
2014
Java 8
C#
Swift
C
PHP
Python
Ruby
Javascript
Dart
Scala
Go
Clojure
Rust
Groovy
Erlang
Elixir
Coffeescript
C++
Objective-C
Haskell
F#
Java 8
C#
Swift
C
PHP
Python
Ruby
Javascript
Dart
Scala
Go
Clojure
Rust
Groovy
Erlang
Elixir
Coffeescript
C++
Objective-C
Haskell
F#
We need to rewrite thedesign patterns book
Part 2 Introducing Monads
(Douglas Crockford)
Once you understandMonadsfor yourself
you lose the ability
to explain them to others
"
"
A Monad is justa monoid in thecategory ofendofunctors
WTF?
WARM UP
What’s aStack?
Value
Operations
Rules
+ = stack.push(value).top == value stack.isEmpty == truestack.push(value).isEmpty == false
We can implement them however we like
We can use them without knowing their implementation
and..
What’s aQueue?
What are
Queue?Stack &
ABSTRACT
TYPESDATA
JavascriptPromises
modern,(Anders Hejlsberg)
Asynchronousprogramming is becoming the norm in
connected applications"
"
var FS = require('fs'), request = require('request');
function getResults(pathToFile, callback) { FS.readFile(pathToFile, 'utf8', function(err, data) { if (err) return callback(err); var response1, response2;
request.post('http://service1.example.com?data=' + data), function(err, response, body) { if(err) return callback(err); response1 = response; next(); });
request.post('http://service2.example.com?data=' + data), function(err, response, body) { if(err) return callback(err); response2 = response; next(); });
function next(){ if(response1 && response2){ callback(null, [response1, response2]); } } }); }
asyncCall(function(err, data1){ if(err) return callback(err); anotherAsyncCall(function(err2, data2){ if(err2) return calllback(err2); oneMoreAsyncCall(function(err3, data3){ if(err3) return callback(err3); // are we done yet? }); }); });
asyncCall() .then(function(data1){ // do something... return anotherAsyncCall(); }) .then(function(data2){ // do something... return oneMoreAsyncCall(); }) .then(function(data3){ // the third and final async response }) .fail(function(err) { // handle any error resulting from any of the above calls }) .done();
var promise = new Promise(initialFunction) var anotherPromise = promise.then(functionB) var yetAnotherPromise = anotherPromise.then(functionC) ...
var promise = new Promise(initialFunction) var anotherPromise = promise.then(functionB) var yetAnotherPromise = anotherPromise.then(functionC) ...
var promise = new Promise(initialFunction) var anotherPromise = promise.then(functionB) var yetAnotherPromise = anotherPromise.then(functionC) ...
Java 8Optional
String version = computer .getSoundcard() .getUSB() .getVersion();
String version = "UNKNOWN"; if(computer != null){ Soundcard soundcard = computer.getSoundcard(); if(soundcard != null){ USB usb = soundcard.getUSB(); if(usb != null){ version = usb.getVersion(); } } }
String name = Optional.of(computer) .map(Computer::getSoundcard)
.map(Soundcard::getUSB) .map(USB::getVersion) .orElse("UNKNOWN");
String name = Optional.of(computer) .map(Computer::getSoundcard)
.map(Soundcard::getUSB) .map(USB::getVersion) .orElse("UNKNOWN");
String name = Optional.of(computer) .map(Computer::getSoundcard)
.map(Soundcard::getUSB) .map(USB::getVersion) .orElse("UNKNOWN");
Promises and Optional are Monads
A Monad is a structure that puts a value in a
computational context
Monad<A> unit(A a)
Monad<A> unit(A a)
Monad<A> unit(A a)
Monad<B> bind(M<A> ma, Function<A, M<B>> f)
Monad<B> bind(M<A> ma, Function<A, M<B>> f)
Monad<B> bind(M<A> ma, Function<A, M<B>> f)
unit(x) = Monad x unit(x).bind(f) = Monad f(x) unit(x).bind(f).bind(g) = Monad g(f(x))
Monad: Value, Operations and Rules
HaskellI/O
return :: Monad m => a -> m a (>>=) :: Monad m => m a -> (a -> m b) -> m b (>>) :: Monad m => m a -> m b -> m b
Unit & Bind in Haskell
main :: IO () main = putStrLn "What is your name?" >> getLine >>= \name -> putStrLn ("Hello, " ++ name)
I/O Example
main :: IO () main = do putStrLn "What is your name?" name <- getLine putStrLn ("Hello, " ++ name)
Sequence
main :: IO () main = do putStrLn "What is your name?" name <- getLine putStrLn ("Hello, " ++ name)
What is that?
Imperative codein functional style
PARADIGM MIX,stupid!
It’s the
One more thing…
BuilderResult<Group> groupBuilder = new Builder<Group>(Group.class) .daoContext(daoContext) .user(loginUser) .comments(body.getCreateComments()) .set(Field.name).with(name).validations(required(), unique()) .set(Field.owners).with(ownerIds).converting(convertToOwner()) .validations(required()) .set(Field.description).with(body.getDesc()).withoutValidation() .build();
Accidental Monad
"Six of one or half dozen of the other"
Set<PersistenceEventListener> result = new HashSet<>(); for (String channel: channels) { List<PersistenceEventListener> channelListeners = listenersPerChannel.get(channel); if (channelListeners != null) { result.addAll(channelListeners); } } return result;
return listenersPerChannel.entrySet().stream() .filter(e -> Arrays.asList(channels).contains(e.getKey())) .map(e -> e.getValue()) .flatMap(l -> l.stream()) .collect(Collectors.toSet());
X
Moral of the Story
Languages are evolving
Programmers must evolve along with the languages and
enjoy learning new things
Luiz Borba http://borba.blog.br
It’s the end of Design Patterns as we know it (and I feel fine)
Thank you!