SlideShare a Scribd company logo
1 of 77
Download to read offline
OOP vs and FP
by Mario Fusco
Red Hat – Principal Software Engineer
@mariofusco
A bad (and mostly wrong) joke
... and I did
the same
A world of false dichotomies
A world of false dichotomies
A world of false dichotomies
A world of false dichotomies
False dichotimies in software engineering
False dichotimies in software engineering
False dichotimies in software engineering
False dichotimies in software engineering
OOP as we
know it
Actually I made up the term "object-oriented",
and I can tell you I did not have C++ in mind.
Alan Kay
The way OOP is
implemented in most
common imperative
languages is
probably the biggest
misunderstanding
in the millenarian
history of engineering
This is Class Oriented Programming
A Smalltalk object can do exactly three things:
OOP == Message Passing
✔ Hold state (references to
other objects).
✔ Receive a message from
itself or another object.
✔ In the course of processing a
message, send messages to
itself or another object.
A Smalltalk object can do exactly three things:
OOP == Message Passing
✔ Hold state (references to
other objects).
✔ Receive a message from
itself or another object.
✔ In the course of processing a
message, send messages to
itself or another object.
That’s the Actor Model !!!
Functional Programming Myths
✔ FP is new: it is older than computer, origining from 1930s
lambda calculus. Haskell is 5 years older than Java
Functional Programming Myths
✔ FP is new: it is older than computer, origining from 1930s
lambda calculus. Haskell is 5 years older than Java
✔ FP is well-defined: are lambdas enough? Should it follow
the mathemathical definition? Something in the middle?
Functional Programming Myths
✔ FP is new: it is older than computer, origining from 1930s
lambda calculus. Haskell is 5 years older than Java
✔ FP is well-defined: are lambdas enough? Should it follow
the mathemathical definition? Something in the middle?
✔ FP is the opposite of OOP: they are orthogonal and can
be effectively mixed in any program
Functional Programming Myths
✔ FP is new: it is older than computer, origining from 1930s
lambda calculus. Haskell is 5 years older than Java
✔ FP is well-defined: are lambdas enough? Should it follow
the mathemathical definition? Something in the middle?
✔ FP is the opposite of OOP: they are orthogonal and can
be effectively mixed in any program
✔ FP is hard: OOP is not easier, just more familiar
Functional Programming Myths
✔ FP is less efficient: it’s the compiler job to produce efficient code
✔ FP is new: it is older than computer, origining from 1930s
lambda calculus. Haskell is 5 years older than Java
✔ FP is well-defined: are lambdas enough? Should it follow
the mathemathical definition? Something in the middle?
✔ FP is the opposite of OOP: they are orthogonal and can
be effectively mixed in any program
✔ FP is hard: OOP is not easier, just more familiar
Functional Programming Myths
✔ FP is less efficient: it’s the compiler job to produce efficient code
✔ FP is good only for math-like stuff: it is good for any task
including GUIs, think to functional reactive programming
✔ FP is new: it is older than computer, origining from 1930s
lambda calculus. Haskell is 5 years older than Java
✔ FP is well-defined: are lambdas enough? Should it follow
the mathemathical definition? Something in the middle?
✔ FP is the opposite of OOP: they are orthogonal and can
be effectively mixed in any program
✔ FP is hard: OOP is not easier, just more familiar
Functional Programming Myths
✔ FP is less efficient: it’s the compiler job to produce efficient code
✔ FP is good only for math-like stuff: it is good for any task
including GUIs, think to functional reactive programming
✔ FP is an all or nothing game: you can choose the amount of FP
that is right for you according to your task, skills and tastes
✔ FP is new: it is older than computer, origining from 1930s
lambda calculus. Haskell is 5 years older than Java
✔ FP is well-defined: are lambdas enough? Should it follow
the mathemathical definition? Something in the middle?
✔ FP is the opposite of OOP: they are orthogonal and can
be effectively mixed in any program
✔ FP is hard: OOP is not easier, just more familiar
Functional Programming Myths
✔ FP is less efficient: it’s the compiler job to produce efficient code
✔ FP is good only for math-like stuff: it is good for any task
including GUIs, think to functional reactive programming
✔ FP is an all or nothing game: you can choose the amount of FP
that is right for you according to your task, skills and tastes
✔ FP solves all problems: oh yes, you can write horrible code also
doing pure functional programming
✔ FP is new: it is older than computer, origining from 1930s
lambda calculus. Haskell is 5 years older than Java
✔ FP is well-defined: are lambdas enough? Should it follow
the mathemathical definition? Something in the middle?
✔ FP is the opposite of OOP: they are orthogonal and can
be effectively mixed in any program
✔ FP is hard: OOP is not easier, just more familiar
Object Oriented Programming
Object-oriented programming (OOP) represents the concept
of objects that have data fields (attributes that describe the
object) and associated procedures known as methods.
Definitions
Functional Programming
Functional programming (FP) treats computation as
the evaluation and composition of mathematical
functions and avoids changing-state and mutable data.
What’s the difference?
All programs are functions operating on data
OOP and FP seems to differ in the manner in
which they bind functions and data together
FP: f(o)OOP: o.f()
What’s the difference?
(f o)
All programs are functions operating on data
OOP and FP seems to differ in the manner in
which they bind functions and data together
FP: f(o)OOP: o.f() But does it really matter?
In reality it is just
Functions ARE data, do you remember map/reduce?
But does it really matter?
What’s the difference?
(f o)
All programs are functions operating on data
polymorphism
OOP and FP seems to differ in the manner in
which they bind functions and data together
FP: f(o)OOP: o.f() But does it really matter?
In reality it is just
Functions ARE data, do you remember map/reduce?
But does it really matter?
Biggest OOP advantage: Polymorphism
Polymorphism is THE thing that truly
differentiates OO programs from non-OO ones
It is true that it can be achieved in FP
with long if/else chains, or better with
pattern matching
Polymorphism does NOT create a
source code dependency from the
caller to the callee
BUT in OOP
OOP vs FP Decomposition
eval toString hasZero ...
Int
Addition
Negation
...
OOP vs FP Decomposition
In OOP, break programs down
into classes that give
behaviour to some kind of data
eval toString hasZero ...
Int
Addition
Negation
...
fill the grid with
one class per row
OOP vs FP Decomposition
In FP, break programs down into
functions that perform some
operations over its arguments
In OOP, break programs down
into classes that give
behaviour to some kind of data
eval toString hasZero ...
Int
Addition
Negation
...
fill the grid with
one function per column
fill the grid with
one class per row
OOP Decomposition
public interface Expression {
int eval();
boolean hasZero();
String toString();
}
public class Int implements Expression {
private final int i;
public Int( int i ) { this.i = i; }
@Override
public int eval() { return i; }
@Override
public boolean hasZero() { return i == 0; }
@Override
public String toString() { return "" + i; }
}
public class Addition implements Expression {
private final Expression e1;
private final Expression e2;
public Addition( Expression e1, Expression e2 ) {
this.e1 = e1;
this.e2 = e2;
}
@Override
public int eval() {
return e1.eval() + e2.eval();
}
@Override
public boolean hasZero() {
return e1.hasZero() || e2.hasZero();
}
@Override
public String toString() {
return e1.toString() + " + " + e1.toString();
}
}
public class Negation implements Expression {
private final Expression e;
public Negation( Expression e ) { this.e = e; }
@Override
public int eval() { return - e.eval(); }
@Override
public boolean hasZero() { return e.hasZero(); }
@Override
public String toString() { return "-" + e.toString(); }
}
FP Decomposition
public interface Expression { }
public class Int implements Expression {
final int i;
public Int( int i ) {
this.i = i;
}
}
public class Negation implements Expression {
final Expression e;
public Negation( Expression e ) {
this.e = e;
}
}
public class Addition implements Expression {
final Expression e1;
final Expression e2;
public Addition( Expression e1,
Expression e2 ) {
this.e1 = e1;
this.e2 = e2;
}
}
static int eval(Expression expr) {
if (expr instanceof Int)
return (( Int ) expr).i;
if (expr instanceof Negation)
return - eval((( Negation ) expr).e);
if (expr instanceof Addition)
return eval((( Addition ) expr).e1) + eval((( Addition ) expr).e2);
throw new UnsupportedOperationException( "Unknown type: " + expr.getClass());
}
static boolean hasZero(Expression expr) {
if (expr instanceof Int)
return (( Int ) expr).i == 0;
if (expr instanceof Negation)
return hasZero((( Negation ) expr).e);
if (expr instanceof Addition)
return hasZero((( Addition ) expr).e1) || hasZero((( Addition ) expr).e2);
throw new UnsupportedOperationException( "Unknown type: " + expr.getClass());
}
static String toString(Expression expr) {
if (expr instanceof Int)
return "" + (( Int ) expr).i;
if (expr instanceof Negation)
return "-" + toString((( Negation ) expr).e);
if (expr instanceof Addition)
return toString((( Addition ) expr).e1) + " + " +
toString((( Addition ) expr).e2);
throw new UnsupportedOperationException( "Unknown type: " + expr.getClass());
}
Which one is better?
To write an interpreter FP
decomposition is more
natural: I’m evaluating an
expression and I have
separate cases for the
different expression’s kinds
Which one is better?
To write an interpreter FP
decomposition is more
natural: I’m evaluating an
expression and I have
separate cases for the
different expression’s kinds
In a GUI there are lots of different things on
the screen with different behaviours and
response to user’s actions: better to keep
these behaviours together with the
graphical objects using OO decomposition
Which one is better?
It’s mainly a matter of
personal tastes and using
the tool that fits better
the problem at hand
To write an interpreter FP
decomposition is more
natural: I’m evaluating an
expression and I have
separate cases for the
different expression’s kinds
In a GUI there are lots of different things on
the screen with different behaviours and
response to user’s actions: better to keep
these behaviours together with the
graphical objects using OO decomposition
Composition(?)
Functional composition
Composition(?)
OOP implements composition using 2 mechanisms:
1. Inheritance (IS-A)
Functional composition
Composition(?)
OOP implements composition using 2 mechanisms:
1. Inheritance (IS-A)
2. Association (HAS-A)
Functional composition
Composition(?)
OOP implements composition using 2 mechanisms:
1. Inheritance (IS-A)
2. Association (HAS-A), often implemented with
dependency injection
Functional composition
Biggest FP advantage: Immutability
✔ Thread-safety: immutable objects are inherently thread-
safe since race conditions are impossible
✔ Parallelizability: no race conditions implies also no need
for any synchronization
✔ Caching: the hardest problem in using a cache is
invalidation, but with immutable objects it is not necessary
✔ Correctness: immutability makes it easier to write, read
and reason about the code
✔ Consistency: once you are given an immutable object
and verify its state, you know it will always remain safe
✔ Better encapsulation: objects can always be passed by
reference and there is no need to have to worry about
solutions like defensive copying
OOP makes code understandable
by encapsulating moving parts
FP makes code understandable
by minimizing moving parts
- Michael Feathers
(im)mutability – OOP vs FP
... but this is only for historical reasons
nothing mandates that OOP implies mutability
An expression e is referentially transparent if for all programs p,
all occurrences of e in p can be replaced by the result of evaluating e,
without affecting the observable behavior of p
A function f is pure if the expression f(x) is referentially transparent
for all referentially transparent x
Referential transparency
RT
String x = "purple";
String r1 = x.replace('p', 't');
String r2 = x.replace('p', 't');
String r1 = "purple".replace('p', 't');
r1: "turtle"
String r2 = "purple".replace('p', 't');
r2: "turtle"
StringBuilder x = new StringBuilder("Hi");
StringBuilder y = x.append(", mom");
String r1 = y.toString();
String r2 = y.toString();
String r1 = x.append(", mom").toString();
r1: "Hi, mom"
String r2 = x.append(", mom").toString();
r1: "Hi, mom, mom"
Non-RT
vs.
Under a developer point of view:
Easier to reason about since effects of evaluation are purely local
Use of the substitution model: it's possible to replace a term with an equivalent one
Under a performance point of view:
The JVM is free to optimize the code by safely reordering the instructions
No need to synchronize access to shared data
Possible to cache the result of time consuming functions (memoization), e.g. with
Map.computeIfAbsent(K key,
Function<? super K,? extends V> mappingFunction)
Referential transparency
means no side-effects
OOP vs FP Error Management
public static int parseInt(String s) throws NumberFormatException
What’s wrong with this signature?
OOP vs FP Error Management
public static int parseInt(String s) throws NumberFormatException
What’s wrong with this signature?
1. There isn’t anything exceptional in a String that cannot be parsed into a number
2. Breaking referential transparency prevents use of memoization
public static OptionalInt parseInt(String s)
Map<String, OptionalInt> cache = new HashMap<>();
public OptionalInt memoizedParse(String s) {
return cache.computeIfAbsent(s, Integer::parseInt);
}
would allow memoization
✔
Often abused, especially for flow control
✔
Checked Exceptions harm API
extensibility/modificability
✔
They plays very badly with lambdas syntax
✔
Not composable: in presence of multiple
errors only the first one is reported
✔
In the end just a GLORIFIED
MULTILEVEL GOTO
Use Exception only Exceptionally
Exceptions should be used only
for non-recoverable errors
OOP : FP = Imperative : Declarative
List<String> errors = new ArrayList<>();
int errorCount = 0;
BufferedReader file = new BufferedReader(new FileReader(fileName));
String line = file.readLine();
while (errorCount < 40 && line != null) {
if (line.startsWith("ERROR")) {
errors.add(line);
errorCount++;
}
line = file.readLine();
}
List<String> errors =
Files.lines(Paths.get(fileName))
.filter(l -> l.startsWith("ERROR"))
.limit(40)
.collect(toList());
What a
beautiful
code!
Let’s
change
it a bit
Let’s
change
it a bit
We are now asked
to create a report
with the first 40 error
lines AND the line
before each of them
OOP version
List<String[]> errors = new ArrayList<>();
int errorCount = 0;
BufferedReader file = new BufferedReader(new FileReader(fileName));
String previous = null;
String current = file.readLine();
while (errorCount < 40 && current != null) {
if (current.startsWith("ERROR")) {
errors.add(new String[] { previous, current });
errorCount++;
}
previous = current;
current = file.readLine();
}
FP version 1
List<String[]> errors =
Files.lines(Paths.get(fileName))
.reduce(new LinkedList<String[]>(),
(list, line) -> {
if (!list.isEmpty()) list.getLast()[1] = line;
list.offer(new String[]{line, null});
return list;
},
(l1, l2) -> {
l1.getLast()[1] = l2.getFirst()[0];
l1.addAll(l2);
return l1;
})
.stream()
.filter(ss -> ss[1] != null && ss[1].startsWith("ERROR"))
.limit(40)
.collect( Collectors.toList());
FP version 1
List<String[]> errors =
Files.lines(Paths.get(fileName))
.reduce(new LinkedList<String[]>(),
(list, line) -> {
if (!list.isEmpty()) list.getLast()[1] = line;
list.offer(new String[]{line, null});
return list;
},
(l1, l2) -> {
l1.getLast()[1] = l2.getFirst()[0];
l1.addAll(l2);
return l1;
})
.stream()
.filter(ss -> ss[1] != null && ss[1].startsWith("ERROR"))
.limit(40)
.collect( Collectors.toList());
mutability
must read
the whole file
in memory
FP version 2
List<String[]> errors =
zip( Stream.concat(Stream.of(null), Files.lines(Paths.get(fileName))),
Stream.concat(Files.lines(Paths.get(fileName)), Stream.of(null)),
(s1, s2) -> new String[] { s1, s2 })
.filter(ss -> ss[1] != null && ss[1].startsWith("ERROR"))
.limit(40)
.collect( Collectors.toList() );
static <A,B,C> Stream<C> zip( Stream<? extends A> as,
Stream<? extends B> bs,
BiFunction<? super A, ? super B, ? extends C> zipper) {
Iterator<? extends B> itr = bs.iterator();
return as.filter( x -> itr.hasNext() ).map( x -> zipper.apply( x, itr.next() ) );
}
OOP – FP (false?) dichotomies
Polymorphism – Functional decomposition
Mutable – Immutable
Exceptions – Optional / Validation
Imperative – Declarative
OOP – FP (false?) dichotomies
Polymorphism – Functional decomposition
Mutable – Immutable
Exceptions – Optional / Validation
Imperative – Declarative
Stateful – Stateless
Threads – Futures
Statements – Expressions
Iteration – Recursion
Threads vs (Completable)Future
public double loadConversionRate(String currency1,
String currency2) {
return Double.NaN; // TODO – some long computation
}
public double loadUSDPrice(String productCode) {
return Double.NaN; // TODO – some long computation
}
public double getPrice(String productCode, String currency) {
return loadUSDPrice( productCode ) *
loadConversionRate( "USD", currency );
}
Threads vs (Completable)Future
public double loadConversionRate(String currency1,
String currency2) {
return Double.NaN; // TODO – some long computation
}
public double loadUSDPrice(String productCode) {
return Double.NaN; // TODO – some long computation
}
public double getPrice(String productCode, String currency) {
return loadUSDPrice( productCode ) *
loadConversionRate( "USD", currency );
}
private double result = 1.0;
public synchronized void processResult(double value) {
result *= value;
}
public double getPriceUsingThreads(String productCode,
String currency)
throws InterruptedException {
Thread t1 = new Thread( new Runnable() {
@Override
public void run() {
processResult( loadConversionRate( "USD", currency ) );
}
} );
Thread t2 = new Thread( new Runnable() {
@Override
public void run() {
processResult( loadUSDPrice( productCode ) );
}
} );
t1.start();
t2.start();
t1.join();
t2.join();
return result;
}
Threads vs (Completable)Future
public double loadConversionRate(String currency1,
String currency2) {
return Double.NaN; // TODO – some long computation
}
public double loadUSDPrice(String productCode) {
return Double.NaN; // TODO – some long computation
}
public double getPrice(String productCode, String currency) {
return loadUSDPrice( productCode ) *
loadConversionRate( "USD", currency );
}
private double result = 1.0;
public synchronized void processResult(double value) {
result *= value;
}
public double getPriceUsingThreads(String productCode,
String currency)
throws InterruptedException {
Thread t1 = new Thread( new Runnable() {
@Override
public void run() {
processResult( loadConversionRate( "USD", currency ) );
}
} );
Thread t2 = new Thread( new Runnable() {
@Override
public void run() {
processResult( loadUSDPrice( productCode ) );
}
} );
t1.start();
t2.start();
t1.join();
t2.join();
return result;
}
Threads vs (Completable)Future
The problem with object-oriented
languages is they’ve got all this implicit
environment that they carry around
with them. You wanted a banana but
what you got was a gorilla holding the
banana and the entire jungle.
- Joe Armstrong
public double loadConversionRate(String currency1,
String currency2) {
return Double.NaN; // TODO – some long computation
}
public double loadUSDPrice(String productCode) {
return Double.NaN; // TODO – some long computation
}
public double getPrice(String productCode, String currency) {
return loadUSDPrice( productCode ) *
loadConversionRate( "USD", currency );
}
private double result = 1.0;
public synchronized void processResult(double value) {
result *= value;
}
public double getPriceUsingThreads(String productCode,
String currency)
throws InterruptedException {
Thread t1 = new Thread( new Runnable() {
@Override
public void run() {
processResult( loadConversionRate( "USD", currency ) );
}
} );
Thread t2 = new Thread( new Runnable() {
@Override
public void run() {
processResult( loadUSDPrice( productCode ) );
}
} );
t1.start();
t2.start();
t1.join();
t2.join();
return result;
}
Threads vs (Completable)Future
public double loadConversionRate(String currency1,
String currency2) {
return Double.NaN; // TODO – some long computation
}
public double loadUSDPrice(String productCode) {
return Double.NaN; // TODO – some long computation
}
public double getPrice(String productCode, String currency) {
return loadUSDPrice( productCode ) *
loadConversionRate( "USD", currency );
}
Threads vs (Completable)Future
public double loadConversionRate(String currency1,
String currency2) {
return Double.NaN; // TODO – some long computation
}
public double loadUSDPrice(String productCode) {
return Double.NaN; // TODO – some long computation
}
public double getPrice(String productCode, String currency) {
return loadUSDPrice( productCode ) *
loadConversionRate( "USD", currency );
}
public double getPriceUsingFutures(String productCode, String currency) throws ExecutionException, InterruptedException {
return CompletableFuture.supplyAsync( () -> loadUSDPrice( productCode ) )
.thenCombine( CompletableFuture.supplyAsync( () -> loadConversionRate( "USD", currency ) ),
(price, rate) -> price * rate ).get();
}
Threads vs (Completable)Future
public double loadConversionRate(String currency1,
String currency2) {
return Double.NaN; // TODO – some long computation
}
public double loadUSDPrice(String productCode) {
return Double.NaN; // TODO – some long computation
}
public double getPrice(String productCode, String currency) {
return loadUSDPrice( productCode ) *
loadConversionRate( "USD", currency );
}
public double getPriceUsingFutures(String productCode, String currency) throws ExecutionException, InterruptedException {
return CompletableFuture.supplyAsync( () -> loadUSDPrice( productCode ) )
.thenCombine( CompletableFuture.supplyAsync( () -> loadConversionRate( "USD", currency ) ),
(price, rate) -> price * rate ).get();
}
Expressions vs Statements
Object result = condition ? doSomething() : doSomethingElse();
Object result;
if (condition) {
result = doSomething();
} else {
result = doSomethingElse();
}
Favor expressions when
possible, but in most cases this is
not a choice and it is determined
by the language’s syntax
Iteration vs Recursion
int sumAll(int n) {
int result = 0;
for (int i = 0; i <= n; i++) {
result += i;
}
return result;
}
int sumAll(int n) {
return IntStream.rangeClosed(0, n).sum();
}
Iteration vs Recursion
int sumAll(int n) {
int result = 0;
for (int i = 0; i <= n; i++) {
result += i;
}
return result;
}
int sumAll(int n) {
return IntStream.rangeClosed(0, n).sum();
}
int sumAll(int n) {
return n == 0 ? 0 : n + sumAll(n - 1);
}
FP in the small, OOP in the large ...
FP for calculation parts
OOP for stateful and architectural parts
FP in the small, OOP in the large ...
FP for calculation parts
OOP for stateful and architectural parts
FP to orchestrate and
combine small components
(objects) in a functional way
... or viceversa?
85% functional language purity
My real position is this: 100% pure
functional programing doesn’t work. Even
98% pure functional programming doesn’t
work. But if the slider between functional
purity and 1980s BASIC-style imperative
messiness is kicked down a few notches —
say to 85% — then it really does work. You
get all the advantages of functional
programming, but without the extreme mental
effort and unmaintainability that increases as
you get closer and closer to perfectly pure.
- James Hague
85% functional language purity
My real position is this: 100% pure
functional programing doesn’t work. Even
98% pure functional programming doesn’t
work. But if the slider between functional
purity and 1980s BASIC-style imperative
messiness is kicked down a few notches —
say to 85% — then it really does work. You
get all the advantages of functional
programming, but without the extreme mental
effort and unmaintainability that increases as
you get closer and closer to perfectly pure.
- James Hague Perfect is the enemy of good
­ Voltaire
To recap
OOP + FP
does not
have to look
like this
● OOP approach models the data (noun-based) while FP
processes them (action/verb-based)
● Good software is written in both styles, because it has
more than one need to satisfy
● Programming languages are becoming evolved enough so
that any attempt of categorization is fuzzy and unpractical
● Clearly delineate which part of your code are purely
functional (e.g. because they need to run in parallel) and
which are not (for efficiency or readability)
● Poly-paradigm programming is more generic, powerful
and effective than polyglot programming
● From object-oriented to functional programming
to functions-first programming
● If you come from an OOP, study FP.
If you come from an FP, study OOP.
Key Takeaways
BE PRAGMATIC
Mario Fusco
Red Hat – Principal Software Engineer
mario.fusco@gmail.com
twitter: @mariofusco
Q A
Thanks ... Questions?

More Related Content

What's hot

Programming Paradigms
Programming ParadigmsProgramming Paradigms
Programming ParadigmsDirecti Group
 
C#.NET
C#.NETC#.NET
C#.NETgurchet
 
Java 10 New Features
Java 10 New FeaturesJava 10 New Features
Java 10 New FeaturesAli BAKAN
 
Exceptions in Java
Exceptions in JavaExceptions in Java
Exceptions in JavaVadym Lotar
 
Kotlin for Android Development
Kotlin for Android DevelopmentKotlin for Android Development
Kotlin for Android DevelopmentSpeck&Tech
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesGanesh Samarthyam
 
Functional Programming.pptx
Functional Programming.pptxFunctional Programming.pptx
Functional Programming.pptxKarthickT28
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldJorge VĂĄsquez
 
Abstract Class Presentation
Abstract Class PresentationAbstract Class Presentation
Abstract Class Presentationtigerwarn
 
oops concept in java | object oriented programming in java
oops concept in java | object oriented programming in javaoops concept in java | object oriented programming in java
oops concept in java | object oriented programming in javaCPD INDIA
 
Python Programming Language
Python Programming LanguagePython Programming Language
Python Programming LanguageLaxman Puri
 
OOP Unit 1 - Foundation of Object- Oriented Programming
OOP Unit 1 - Foundation of Object- Oriented ProgrammingOOP Unit 1 - Foundation of Object- Oriented Programming
OOP Unit 1 - Foundation of Object- Oriented Programmingdkpawar
 
Introduction to Object Oriented Programming
Introduction to Object Oriented ProgrammingIntroduction to Object Oriented Programming
Introduction to Object Oriented ProgrammingMoutaz Haddara
 
Python Generators
Python GeneratorsPython Generators
Python GeneratorsAkshar Raaj
 
Object-oriented concepts
Object-oriented conceptsObject-oriented concepts
Object-oriented conceptsBG Java EE Course
 
Kotlin presentation
Kotlin presentation Kotlin presentation
Kotlin presentation MobileAcademy
 
Basics of JAVA programming
Basics of JAVA programmingBasics of JAVA programming
Basics of JAVA programmingElizabeth Thomas
 
Iterarators and generators in python
Iterarators and generators in pythonIterarators and generators in python
Iterarators and generators in pythonSarfaraz Ghanta
 

What's hot (20)

Programming Paradigms
Programming ParadigmsProgramming Paradigms
Programming Paradigms
 
C#.NET
C#.NETC#.NET
C#.NET
 
Java 10 New Features
Java 10 New FeaturesJava 10 New Features
Java 10 New Features
 
Exceptions in Java
Exceptions in JavaExceptions in Java
Exceptions in Java
 
Kotlin for Android Development
Kotlin for Android DevelopmentKotlin for Android Development
Kotlin for Android Development
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
 
Functional Programming.pptx
Functional Programming.pptxFunctional Programming.pptx
Functional Programming.pptx
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
 
Abstract Class Presentation
Abstract Class PresentationAbstract Class Presentation
Abstract Class Presentation
 
oops concept in java | object oriented programming in java
oops concept in java | object oriented programming in javaoops concept in java | object oriented programming in java
oops concept in java | object oriented programming in java
 
Java tutorial PPT
Java tutorial PPTJava tutorial PPT
Java tutorial PPT
 
Python Programming Language
Python Programming LanguagePython Programming Language
Python Programming Language
 
OOP Unit 1 - Foundation of Object- Oriented Programming
OOP Unit 1 - Foundation of Object- Oriented ProgrammingOOP Unit 1 - Foundation of Object- Oriented Programming
OOP Unit 1 - Foundation of Object- Oriented Programming
 
C function
C functionC function
C function
 
Introduction to Object Oriented Programming
Introduction to Object Oriented ProgrammingIntroduction to Object Oriented Programming
Introduction to Object Oriented Programming
 
Python Generators
Python GeneratorsPython Generators
Python Generators
 
Object-oriented concepts
Object-oriented conceptsObject-oriented concepts
Object-oriented concepts
 
Kotlin presentation
Kotlin presentation Kotlin presentation
Kotlin presentation
 
Basics of JAVA programming
Basics of JAVA programmingBasics of JAVA programming
Basics of JAVA programming
 
Iterarators and generators in python
Iterarators and generators in pythonIterarators and generators in python
Iterarators and generators in python
 

Similar to OOP and FP

Functional programming
Functional programmingFunctional programming
Functional programmingOpenAgile Romania
 
Mastering Python lesson3b_for_loops
Mastering Python lesson3b_for_loopsMastering Python lesson3b_for_loops
Mastering Python lesson3b_for_loopsRuth Marvin
 
F# and functional programming
F# and functional programmingF# and functional programming
F# and functional programmingramikarjalainen
 
Functional Programming in C# and F#
Functional Programming in C# and F#Functional Programming in C# and F#
Functional Programming in C# and F#Alfonso Garcia-Caro
 
Intro to Functional Programming
Intro to Functional ProgrammingIntro to Functional Programming
Intro to Functional ProgrammingJordan Parmer
 
Gentle Introduction To Funcitonal Programming - Detroit.Code
Gentle Introduction To Funcitonal Programming - Detroit.CodeGentle Introduction To Funcitonal Programming - Detroit.Code
Gentle Introduction To Funcitonal Programming - Detroit.CodeOnorioCatenacci
 
Inheritance Versus Roles - The In-Depth Version
Inheritance Versus Roles - The In-Depth VersionInheritance Versus Roles - The In-Depth Version
Inheritance Versus Roles - The In-Depth VersionCurtis Poe
 
Fp for the oo programmer
Fp for the oo programmerFp for the oo programmer
Fp for the oo programmerShawn Button
 
What the math geeks don't want you to know about F#
What the math geeks don't want you to know about F#What the math geeks don't want you to know about F#
What the math geeks don't want you to know about F#Kevin Hazzard
 
9781111530532 ppt ch05
9781111530532 ppt ch059781111530532 ppt ch05
9781111530532 ppt ch05Terry Yoast
 
9781111530532 ppt ch05
9781111530532 ppt ch059781111530532 ppt ch05
9781111530532 ppt ch05Terry Yoast
 
PARADIGM IT.pptx
PARADIGM IT.pptxPARADIGM IT.pptx
PARADIGM IT.pptxjamesmarken1
 
pythontraining-201jn026043638.pptx
pythontraining-201jn026043638.pptxpythontraining-201jn026043638.pptx
pythontraining-201jn026043638.pptxRohitKumar639388
 
Was kĂśnnen wir von Rebol lernen?
Was kĂśnnen wir von Rebol lernen?Was kĂśnnen wir von Rebol lernen?
Was kĂśnnen wir von Rebol lernen?lichtkind
 
Functional programming is the most extreme programming
Functional programming is the most extreme programmingFunctional programming is the most extreme programming
Functional programming is the most extreme programmingsamthemonad
 

Similar to OOP and FP (20)

Functional programming
Functional programmingFunctional programming
Functional programming
 
Mastering Python lesson3b_for_loops
Mastering Python lesson3b_for_loopsMastering Python lesson3b_for_loops
Mastering Python lesson3b_for_loops
 
F# and functional programming
F# and functional programmingF# and functional programming
F# and functional programming
 
Functional Programming in C# and F#
Functional Programming in C# and F#Functional Programming in C# and F#
Functional Programming in C# and F#
 
Intro to Functional Programming
Intro to Functional ProgrammingIntro to Functional Programming
Intro to Functional Programming
 
Presentation
PresentationPresentation
Presentation
 
Gentle Introduction To Funcitonal Programming - Detroit.Code
Gentle Introduction To Funcitonal Programming - Detroit.CodeGentle Introduction To Funcitonal Programming - Detroit.Code
Gentle Introduction To Funcitonal Programming - Detroit.Code
 
Inheritance Versus Roles - The In-Depth Version
Inheritance Versus Roles - The In-Depth VersionInheritance Versus Roles - The In-Depth Version
Inheritance Versus Roles - The In-Depth Version
 
ForLoops.pptx
ForLoops.pptxForLoops.pptx
ForLoops.pptx
 
Fp for the oo programmer
Fp for the oo programmerFp for the oo programmer
Fp for the oo programmer
 
What the math geeks don't want you to know about F#
What the math geeks don't want you to know about F#What the math geeks don't want you to know about F#
What the math geeks don't want you to know about F#
 
Python training
Python trainingPython training
Python training
 
9781111530532 ppt ch05
9781111530532 ppt ch059781111530532 ppt ch05
9781111530532 ppt ch05
 
9781111530532 ppt ch05
9781111530532 ppt ch059781111530532 ppt ch05
9781111530532 ppt ch05
 
PARADIGM IT.pptx
PARADIGM IT.pptxPARADIGM IT.pptx
PARADIGM IT.pptx
 
pythontraining-201jn026043638.pptx
pythontraining-201jn026043638.pptxpythontraining-201jn026043638.pptx
pythontraining-201jn026043638.pptx
 
Láş­p trĂŹnh C
Láş­p trĂŹnh CLáş­p trĂŹnh C
Láş­p trĂŹnh C
 
Was kĂśnnen wir von Rebol lernen?
Was kĂśnnen wir von Rebol lernen?Was kĂśnnen wir von Rebol lernen?
Was kĂśnnen wir von Rebol lernen?
 
Monad Fact #6
Monad Fact #6Monad Fact #6
Monad Fact #6
 
Functional programming is the most extreme programming
Functional programming is the most extreme programmingFunctional programming is the most extreme programming
Functional programming is the most extreme programming
 

More from Mario Fusco

Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automationMario Fusco
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APIMario Fusco
 
How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...Mario Fusco
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modelingMario Fusco
 
Drools 6 deep dive
Drools 6 deep diveDrools 6 deep dive
Drools 6 deep diveMario Fusco
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerMario Fusco
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Mario Fusco
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVMMario Fusco
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 WorkshopMario Fusco
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 
Monadic Java
Monadic JavaMonadic Java
Monadic JavaMario Fusco
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongMario Fusco
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondMario Fusco
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingMario Fusco
 
Real world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same languageReal world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same languageMario Fusco
 
Introducing Drools
Introducing DroolsIntroducing Drools
Introducing DroolsMario Fusco
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardMario Fusco
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife SpringMario Fusco
 

More from Mario Fusco (20)

Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automation
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java API
 
How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...
 
Lazy java
Lazy javaLazy java
Lazy java
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Drools 6 deep dive
Drools 6 deep diveDrools 6 deep dive
Drools 6 deep dive
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better Programmer
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVM
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
Monadic Java
Monadic JavaMonadic Java
Monadic Java
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional Programming
 
Real world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same languageReal world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same language
 
Introducing Drools
Introducing DroolsIntroducing Drools
Introducing Drools
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
 
Hammurabi
HammurabiHammurabi
Hammurabi
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife Spring
 

Recently uploaded

Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy LĂłpez
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessEnvertis Software Solutions
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
2.pdf Ejercicios de programaciĂłn competitiva
2.pdf Ejercicios de programaciĂłn competitiva2.pdf Ejercicios de programaciĂłn competitiva
2.pdf Ejercicios de programaciĂłn competitivaDiego IvĂĄn Oliveros Acosta
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 

Recently uploaded (20)

Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
2.pdf Ejercicios de programaciĂłn competitiva
2.pdf Ejercicios de programaciĂłn competitiva2.pdf Ejercicios de programaciĂłn competitiva
2.pdf Ejercicios de programaciĂłn competitiva
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 

OOP and FP

  • 1. OOP vs and FP by Mario Fusco Red Hat – Principal Software Engineer @mariofusco
  • 2. A bad (and mostly wrong) joke
  • 3. ... and I did the same
  • 4. A world of false dichotomies
  • 5. A world of false dichotomies
  • 6. A world of false dichotomies
  • 7. A world of false dichotomies
  • 8. False dichotimies in software engineering
  • 9. False dichotimies in software engineering
  • 10. False dichotimies in software engineering
  • 11. False dichotimies in software engineering
  • 13.
  • 14. Actually I made up the term "object-oriented", and I can tell you I did not have C++ in mind. Alan Kay
  • 15. The way OOP is implemented in most common imperative languages is probably the biggest misunderstanding in the millenarian history of engineering This is Class Oriented Programming
  • 16. A Smalltalk object can do exactly three things: OOP == Message Passing ✔ Hold state (references to other objects). ✔ Receive a message from itself or another object. ✔ In the course of processing a message, send messages to itself or another object.
  • 17. A Smalltalk object can do exactly three things: OOP == Message Passing ✔ Hold state (references to other objects). ✔ Receive a message from itself or another object. ✔ In the course of processing a message, send messages to itself or another object. That’s the Actor Model !!!
  • 18. Functional Programming Myths ✔ FP is new: it is older than computer, origining from 1930s lambda calculus. Haskell is 5 years older than Java
  • 19. Functional Programming Myths ✔ FP is new: it is older than computer, origining from 1930s lambda calculus. Haskell is 5 years older than Java ✔ FP is well-defined: are lambdas enough? Should it follow the mathemathical definition? Something in the middle?
  • 20. Functional Programming Myths ✔ FP is new: it is older than computer, origining from 1930s lambda calculus. Haskell is 5 years older than Java ✔ FP is well-defined: are lambdas enough? Should it follow the mathemathical definition? Something in the middle? ✔ FP is the opposite of OOP: they are orthogonal and can be effectively mixed in any program
  • 21. Functional Programming Myths ✔ FP is new: it is older than computer, origining from 1930s lambda calculus. Haskell is 5 years older than Java ✔ FP is well-defined: are lambdas enough? Should it follow the mathemathical definition? Something in the middle? ✔ FP is the opposite of OOP: they are orthogonal and can be effectively mixed in any program ✔ FP is hard: OOP is not easier, just more familiar
  • 22. Functional Programming Myths ✔ FP is less efficient: it’s the compiler job to produce efficient code ✔ FP is new: it is older than computer, origining from 1930s lambda calculus. Haskell is 5 years older than Java ✔ FP is well-defined: are lambdas enough? Should it follow the mathemathical definition? Something in the middle? ✔ FP is the opposite of OOP: they are orthogonal and can be effectively mixed in any program ✔ FP is hard: OOP is not easier, just more familiar
  • 23. Functional Programming Myths ✔ FP is less efficient: it’s the compiler job to produce efficient code ✔ FP is good only for math-like stuff: it is good for any task including GUIs, think to functional reactive programming ✔ FP is new: it is older than computer, origining from 1930s lambda calculus. Haskell is 5 years older than Java ✔ FP is well-defined: are lambdas enough? Should it follow the mathemathical definition? Something in the middle? ✔ FP is the opposite of OOP: they are orthogonal and can be effectively mixed in any program ✔ FP is hard: OOP is not easier, just more familiar
  • 24. Functional Programming Myths ✔ FP is less efficient: it’s the compiler job to produce efficient code ✔ FP is good only for math-like stuff: it is good for any task including GUIs, think to functional reactive programming ✔ FP is an all or nothing game: you can choose the amount of FP that is right for you according to your task, skills and tastes ✔ FP is new: it is older than computer, origining from 1930s lambda calculus. Haskell is 5 years older than Java ✔ FP is well-defined: are lambdas enough? Should it follow the mathemathical definition? Something in the middle? ✔ FP is the opposite of OOP: they are orthogonal and can be effectively mixed in any program ✔ FP is hard: OOP is not easier, just more familiar
  • 25. Functional Programming Myths ✔ FP is less efficient: it’s the compiler job to produce efficient code ✔ FP is good only for math-like stuff: it is good for any task including GUIs, think to functional reactive programming ✔ FP is an all or nothing game: you can choose the amount of FP that is right for you according to your task, skills and tastes ✔ FP solves all problems: oh yes, you can write horrible code also doing pure functional programming ✔ FP is new: it is older than computer, origining from 1930s lambda calculus. Haskell is 5 years older than Java ✔ FP is well-defined: are lambdas enough? Should it follow the mathemathical definition? Something in the middle? ✔ FP is the opposite of OOP: they are orthogonal and can be effectively mixed in any program ✔ FP is hard: OOP is not easier, just more familiar
  • 26. Object Oriented Programming Object-oriented programming (OOP) represents the concept of objects that have data fields (attributes that describe the object) and associated procedures known as methods. Definitions Functional Programming Functional programming (FP) treats computation as the evaluation and composition of mathematical functions and avoids changing-state and mutable data.
  • 27. What’s the difference? All programs are functions operating on data OOP and FP seems to differ in the manner in which they bind functions and data together FP: f(o)OOP: o.f()
  • 28. What’s the difference? (f o) All programs are functions operating on data OOP and FP seems to differ in the manner in which they bind functions and data together FP: f(o)OOP: o.f() But does it really matter? In reality it is just Functions ARE data, do you remember map/reduce? But does it really matter?
  • 29. What’s the difference? (f o) All programs are functions operating on data polymorphism OOP and FP seems to differ in the manner in which they bind functions and data together FP: f(o)OOP: o.f() But does it really matter? In reality it is just Functions ARE data, do you remember map/reduce? But does it really matter?
  • 30. Biggest OOP advantage: Polymorphism Polymorphism is THE thing that truly differentiates OO programs from non-OO ones It is true that it can be achieved in FP with long if/else chains, or better with pattern matching Polymorphism does NOT create a source code dependency from the caller to the callee BUT in OOP
  • 31. OOP vs FP Decomposition eval toString hasZero ... Int Addition Negation ...
  • 32. OOP vs FP Decomposition In OOP, break programs down into classes that give behaviour to some kind of data eval toString hasZero ... Int Addition Negation ... fill the grid with one class per row
  • 33. OOP vs FP Decomposition In FP, break programs down into functions that perform some operations over its arguments In OOP, break programs down into classes that give behaviour to some kind of data eval toString hasZero ... Int Addition Negation ... fill the grid with one function per column fill the grid with one class per row
  • 34. OOP Decomposition public interface Expression { int eval(); boolean hasZero(); String toString(); } public class Int implements Expression { private final int i; public Int( int i ) { this.i = i; } @Override public int eval() { return i; } @Override public boolean hasZero() { return i == 0; } @Override public String toString() { return "" + i; } } public class Addition implements Expression { private final Expression e1; private final Expression e2; public Addition( Expression e1, Expression e2 ) { this.e1 = e1; this.e2 = e2; } @Override public int eval() { return e1.eval() + e2.eval(); } @Override public boolean hasZero() { return e1.hasZero() || e2.hasZero(); } @Override public String toString() { return e1.toString() + " + " + e1.toString(); } } public class Negation implements Expression { private final Expression e; public Negation( Expression e ) { this.e = e; } @Override public int eval() { return - e.eval(); } @Override public boolean hasZero() { return e.hasZero(); } @Override public String toString() { return "-" + e.toString(); } }
  • 35. FP Decomposition public interface Expression { } public class Int implements Expression { final int i; public Int( int i ) { this.i = i; } } public class Negation implements Expression { final Expression e; public Negation( Expression e ) { this.e = e; } } public class Addition implements Expression { final Expression e1; final Expression e2; public Addition( Expression e1, Expression e2 ) { this.e1 = e1; this.e2 = e2; } } static int eval(Expression expr) { if (expr instanceof Int) return (( Int ) expr).i; if (expr instanceof Negation) return - eval((( Negation ) expr).e); if (expr instanceof Addition) return eval((( Addition ) expr).e1) + eval((( Addition ) expr).e2); throw new UnsupportedOperationException( "Unknown type: " + expr.getClass()); } static boolean hasZero(Expression expr) { if (expr instanceof Int) return (( Int ) expr).i == 0; if (expr instanceof Negation) return hasZero((( Negation ) expr).e); if (expr instanceof Addition) return hasZero((( Addition ) expr).e1) || hasZero((( Addition ) expr).e2); throw new UnsupportedOperationException( "Unknown type: " + expr.getClass()); } static String toString(Expression expr) { if (expr instanceof Int) return "" + (( Int ) expr).i; if (expr instanceof Negation) return "-" + toString((( Negation ) expr).e); if (expr instanceof Addition) return toString((( Addition ) expr).e1) + " + " + toString((( Addition ) expr).e2); throw new UnsupportedOperationException( "Unknown type: " + expr.getClass()); }
  • 36. Which one is better? To write an interpreter FP decomposition is more natural: I’m evaluating an expression and I have separate cases for the different expression’s kinds
  • 37. Which one is better? To write an interpreter FP decomposition is more natural: I’m evaluating an expression and I have separate cases for the different expression’s kinds In a GUI there are lots of different things on the screen with different behaviours and response to user’s actions: better to keep these behaviours together with the graphical objects using OO decomposition
  • 38. Which one is better? It’s mainly a matter of personal tastes and using the tool that fits better the problem at hand To write an interpreter FP decomposition is more natural: I’m evaluating an expression and I have separate cases for the different expression’s kinds In a GUI there are lots of different things on the screen with different behaviours and response to user’s actions: better to keep these behaviours together with the graphical objects using OO decomposition
  • 40. Composition(?) OOP implements composition using 2 mechanisms: 1. Inheritance (IS-A) Functional composition
  • 41. Composition(?) OOP implements composition using 2 mechanisms: 1. Inheritance (IS-A) 2. Association (HAS-A) Functional composition
  • 42. Composition(?) OOP implements composition using 2 mechanisms: 1. Inheritance (IS-A) 2. Association (HAS-A), often implemented with dependency injection Functional composition
  • 43. Biggest FP advantage: Immutability ✔ Thread-safety: immutable objects are inherently thread- safe since race conditions are impossible ✔ Parallelizability: no race conditions implies also no need for any synchronization ✔ Caching: the hardest problem in using a cache is invalidation, but with immutable objects it is not necessary ✔ Correctness: immutability makes it easier to write, read and reason about the code ✔ Consistency: once you are given an immutable object and verify its state, you know it will always remain safe ✔ Better encapsulation: objects can always be passed by reference and there is no need to have to worry about solutions like defensive copying
  • 44. OOP makes code understandable by encapsulating moving parts FP makes code understandable by minimizing moving parts - Michael Feathers (im)mutability – OOP vs FP ... but this is only for historical reasons nothing mandates that OOP implies mutability
  • 45. An expression e is referentially transparent if for all programs p, all occurrences of e in p can be replaced by the result of evaluating e, without affecting the observable behavior of p A function f is pure if the expression f(x) is referentially transparent for all referentially transparent x Referential transparency
  • 46. RT String x = "purple"; String r1 = x.replace('p', 't'); String r2 = x.replace('p', 't'); String r1 = "purple".replace('p', 't'); r1: "turtle" String r2 = "purple".replace('p', 't'); r2: "turtle" StringBuilder x = new StringBuilder("Hi"); StringBuilder y = x.append(", mom"); String r1 = y.toString(); String r2 = y.toString(); String r1 = x.append(", mom").toString(); r1: "Hi, mom" String r2 = x.append(", mom").toString(); r1: "Hi, mom, mom" Non-RT vs.
  • 47. Under a developer point of view: Easier to reason about since effects of evaluation are purely local Use of the substitution model: it's possible to replace a term with an equivalent one Under a performance point of view: The JVM is free to optimize the code by safely reordering the instructions No need to synchronize access to shared data Possible to cache the result of time consuming functions (memoization), e.g. with Map.computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) Referential transparency means no side-effects
  • 48. OOP vs FP Error Management public static int parseInt(String s) throws NumberFormatException What’s wrong with this signature?
  • 49. OOP vs FP Error Management public static int parseInt(String s) throws NumberFormatException What’s wrong with this signature? 1. There isn’t anything exceptional in a String that cannot be parsed into a number 2. Breaking referential transparency prevents use of memoization public static OptionalInt parseInt(String s) Map<String, OptionalInt> cache = new HashMap<>(); public OptionalInt memoizedParse(String s) { return cache.computeIfAbsent(s, Integer::parseInt); } would allow memoization
  • 50. ✔ Often abused, especially for flow control ✔ Checked Exceptions harm API extensibility/modificability ✔ They plays very badly with lambdas syntax ✔ Not composable: in presence of multiple errors only the first one is reported ✔ In the end just a GLORIFIED MULTILEVEL GOTO Use Exception only Exceptionally Exceptions should be used only for non-recoverable errors
  • 51. OOP : FP = Imperative : Declarative List<String> errors = new ArrayList<>(); int errorCount = 0; BufferedReader file = new BufferedReader(new FileReader(fileName)); String line = file.readLine(); while (errorCount < 40 && line != null) { if (line.startsWith("ERROR")) { errors.add(line); errorCount++; } line = file.readLine(); } List<String> errors = Files.lines(Paths.get(fileName)) .filter(l -> l.startsWith("ERROR")) .limit(40) .collect(toList());
  • 54. Let’s change it a bit We are now asked to create a report with the first 40 error lines AND the line before each of them
  • 55. OOP version List<String[]> errors = new ArrayList<>(); int errorCount = 0; BufferedReader file = new BufferedReader(new FileReader(fileName)); String previous = null; String current = file.readLine(); while (errorCount < 40 && current != null) { if (current.startsWith("ERROR")) { errors.add(new String[] { previous, current }); errorCount++; } previous = current; current = file.readLine(); }
  • 56. FP version 1 List<String[]> errors = Files.lines(Paths.get(fileName)) .reduce(new LinkedList<String[]>(), (list, line) -> { if (!list.isEmpty()) list.getLast()[1] = line; list.offer(new String[]{line, null}); return list; }, (l1, l2) -> { l1.getLast()[1] = l2.getFirst()[0]; l1.addAll(l2); return l1; }) .stream() .filter(ss -> ss[1] != null && ss[1].startsWith("ERROR")) .limit(40) .collect( Collectors.toList());
  • 57. FP version 1 List<String[]> errors = Files.lines(Paths.get(fileName)) .reduce(new LinkedList<String[]>(), (list, line) -> { if (!list.isEmpty()) list.getLast()[1] = line; list.offer(new String[]{line, null}); return list; }, (l1, l2) -> { l1.getLast()[1] = l2.getFirst()[0]; l1.addAll(l2); return l1; }) .stream() .filter(ss -> ss[1] != null && ss[1].startsWith("ERROR")) .limit(40) .collect( Collectors.toList()); mutability must read the whole file in memory
  • 58. FP version 2 List<String[]> errors = zip( Stream.concat(Stream.of(null), Files.lines(Paths.get(fileName))), Stream.concat(Files.lines(Paths.get(fileName)), Stream.of(null)), (s1, s2) -> new String[] { s1, s2 }) .filter(ss -> ss[1] != null && ss[1].startsWith("ERROR")) .limit(40) .collect( Collectors.toList() ); static <A,B,C> Stream<C> zip( Stream<? extends A> as, Stream<? extends B> bs, BiFunction<? super A, ? super B, ? extends C> zipper) { Iterator<? extends B> itr = bs.iterator(); return as.filter( x -> itr.hasNext() ).map( x -> zipper.apply( x, itr.next() ) ); }
  • 59. OOP – FP (false?) dichotomies Polymorphism – Functional decomposition Mutable – Immutable Exceptions – Optional / Validation Imperative – Declarative
  • 60. OOP – FP (false?) dichotomies Polymorphism – Functional decomposition Mutable – Immutable Exceptions – Optional / Validation Imperative – Declarative Stateful – Stateless Threads – Futures Statements – Expressions Iteration – Recursion
  • 61. Threads vs (Completable)Future public double loadConversionRate(String currency1, String currency2) { return Double.NaN; // TODO – some long computation } public double loadUSDPrice(String productCode) { return Double.NaN; // TODO – some long computation } public double getPrice(String productCode, String currency) { return loadUSDPrice( productCode ) * loadConversionRate( "USD", currency ); }
  • 62. Threads vs (Completable)Future public double loadConversionRate(String currency1, String currency2) { return Double.NaN; // TODO – some long computation } public double loadUSDPrice(String productCode) { return Double.NaN; // TODO – some long computation } public double getPrice(String productCode, String currency) { return loadUSDPrice( productCode ) * loadConversionRate( "USD", currency ); } private double result = 1.0; public synchronized void processResult(double value) { result *= value; } public double getPriceUsingThreads(String productCode, String currency) throws InterruptedException { Thread t1 = new Thread( new Runnable() { @Override public void run() { processResult( loadConversionRate( "USD", currency ) ); } } ); Thread t2 = new Thread( new Runnable() { @Override public void run() { processResult( loadUSDPrice( productCode ) ); } } ); t1.start(); t2.start(); t1.join(); t2.join(); return result; }
  • 63. Threads vs (Completable)Future public double loadConversionRate(String currency1, String currency2) { return Double.NaN; // TODO – some long computation } public double loadUSDPrice(String productCode) { return Double.NaN; // TODO – some long computation } public double getPrice(String productCode, String currency) { return loadUSDPrice( productCode ) * loadConversionRate( "USD", currency ); } private double result = 1.0; public synchronized void processResult(double value) { result *= value; } public double getPriceUsingThreads(String productCode, String currency) throws InterruptedException { Thread t1 = new Thread( new Runnable() { @Override public void run() { processResult( loadConversionRate( "USD", currency ) ); } } ); Thread t2 = new Thread( new Runnable() { @Override public void run() { processResult( loadUSDPrice( productCode ) ); } } ); t1.start(); t2.start(); t1.join(); t2.join(); return result; }
  • 64. Threads vs (Completable)Future The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle. - Joe Armstrong public double loadConversionRate(String currency1, String currency2) { return Double.NaN; // TODO – some long computation } public double loadUSDPrice(String productCode) { return Double.NaN; // TODO – some long computation } public double getPrice(String productCode, String currency) { return loadUSDPrice( productCode ) * loadConversionRate( "USD", currency ); } private double result = 1.0; public synchronized void processResult(double value) { result *= value; } public double getPriceUsingThreads(String productCode, String currency) throws InterruptedException { Thread t1 = new Thread( new Runnable() { @Override public void run() { processResult( loadConversionRate( "USD", currency ) ); } } ); Thread t2 = new Thread( new Runnable() { @Override public void run() { processResult( loadUSDPrice( productCode ) ); } } ); t1.start(); t2.start(); t1.join(); t2.join(); return result; }
  • 65. Threads vs (Completable)Future public double loadConversionRate(String currency1, String currency2) { return Double.NaN; // TODO – some long computation } public double loadUSDPrice(String productCode) { return Double.NaN; // TODO – some long computation } public double getPrice(String productCode, String currency) { return loadUSDPrice( productCode ) * loadConversionRate( "USD", currency ); }
  • 66. Threads vs (Completable)Future public double loadConversionRate(String currency1, String currency2) { return Double.NaN; // TODO – some long computation } public double loadUSDPrice(String productCode) { return Double.NaN; // TODO – some long computation } public double getPrice(String productCode, String currency) { return loadUSDPrice( productCode ) * loadConversionRate( "USD", currency ); } public double getPriceUsingFutures(String productCode, String currency) throws ExecutionException, InterruptedException { return CompletableFuture.supplyAsync( () -> loadUSDPrice( productCode ) ) .thenCombine( CompletableFuture.supplyAsync( () -> loadConversionRate( "USD", currency ) ), (price, rate) -> price * rate ).get(); }
  • 67. Threads vs (Completable)Future public double loadConversionRate(String currency1, String currency2) { return Double.NaN; // TODO – some long computation } public double loadUSDPrice(String productCode) { return Double.NaN; // TODO – some long computation } public double getPrice(String productCode, String currency) { return loadUSDPrice( productCode ) * loadConversionRate( "USD", currency ); } public double getPriceUsingFutures(String productCode, String currency) throws ExecutionException, InterruptedException { return CompletableFuture.supplyAsync( () -> loadUSDPrice( productCode ) ) .thenCombine( CompletableFuture.supplyAsync( () -> loadConversionRate( "USD", currency ) ), (price, rate) -> price * rate ).get(); }
  • 68. Expressions vs Statements Object result = condition ? doSomething() : doSomethingElse(); Object result; if (condition) { result = doSomething(); } else { result = doSomethingElse(); } Favor expressions when possible, but in most cases this is not a choice and it is determined by the language’s syntax
  • 69. Iteration vs Recursion int sumAll(int n) { int result = 0; for (int i = 0; i <= n; i++) { result += i; } return result; } int sumAll(int n) { return IntStream.rangeClosed(0, n).sum(); }
  • 70. Iteration vs Recursion int sumAll(int n) { int result = 0; for (int i = 0; i <= n; i++) { result += i; } return result; } int sumAll(int n) { return IntStream.rangeClosed(0, n).sum(); } int sumAll(int n) { return n == 0 ? 0 : n + sumAll(n - 1); }
  • 71. FP in the small, OOP in the large ... FP for calculation parts OOP for stateful and architectural parts
  • 72. FP in the small, OOP in the large ... FP for calculation parts OOP for stateful and architectural parts FP to orchestrate and combine small components (objects) in a functional way ... or viceversa?
  • 73. 85% functional language purity My real position is this: 100% pure functional programing doesn’t work. Even 98% pure functional programming doesn’t work. But if the slider between functional purity and 1980s BASIC-style imperative messiness is kicked down a few notches — say to 85% — then it really does work. You get all the advantages of functional programming, but without the extreme mental effort and unmaintainability that increases as you get closer and closer to perfectly pure. - James Hague
  • 74. 85% functional language purity My real position is this: 100% pure functional programing doesn’t work. Even 98% pure functional programming doesn’t work. But if the slider between functional purity and 1980s BASIC-style imperative messiness is kicked down a few notches — say to 85% — then it really does work. You get all the advantages of functional programming, but without the extreme mental effort and unmaintainability that increases as you get closer and closer to perfectly pure. - James Hague Perfect is the enemy of good ­ Voltaire
  • 75. To recap OOP + FP does not have to look like this
  • 76. ● OOP approach models the data (noun-based) while FP processes them (action/verb-based) ● Good software is written in both styles, because it has more than one need to satisfy ● Programming languages are becoming evolved enough so that any attempt of categorization is fuzzy and unpractical ● Clearly delineate which part of your code are purely functional (e.g. because they need to run in parallel) and which are not (for efficiency or readability) ● Poly-paradigm programming is more generic, powerful and effective than polyglot programming ● From object-oriented to functional programming to functions-first programming ● If you come from an OOP, study FP. If you come from an FP, study OOP. Key Takeaways BE PRAGMATIC
  • 77. Mario Fusco Red Hat – Principal Software Engineer mario.fusco@gmail.com twitter: @mariofusco Q A Thanks ... Questions?