Thanks to visit codestin.com
Credit goes to www.slideshare.net

Beyond null & more
Taming the monsters, the right way!
jayas@cisco.com
NullPointerException !!!
It must be some kind of race condition!!!
Functional and Reactive
Programming 101
for Java 7 Developers
What will you get?
● Get started with basic
Functional Programming
principles
● Reactive System Design
● Adopt in your day to day
work from now!
Functional Programming Intro
● Function
○ y = f(x)
● Functions as ‘First Class’ Citizens
○ Similar to values
○ Pass to / return from other functions
● Separate Data from Functions
○ Data is passed to functions
○ Data may be returned from functions
○ State Management outside of Functions
Programming with Functions
Functional Programming Facets
● Pure Functions
○ No Side Effects
○ Referential Transparency
● Immutable Data Structures
● Expressive Power
○ Ability to Reason - Equational Reasoning
○ Function Composition
■ f : b -> c , g : a -> b
■ f o g : a -> c
● f o g = f(g(x))
Pure Functions
● No side effects , including IO
○ For a set of inputs, always produce the same output
● Referential Transparency
○ Can ‘inline’ the function everywhere with no changes to the
behavior
○ Works with substitution model of computation
● Ensures Testability
Pure Functions
Is this a pure function?
func increment(int value ) {
return value + 1;
}
Pure Functions
How about this?
func increment(int value )
{
if(value < maxVal) {
return value + 1;
} else {
return maxVal;
}
}
func increment(int value, int maxVal )
{
if(value < maxVal) {
return value + 1;
} else {
return maxVal;
}
}
Pure Functions
..and this too?
func increment(int value ) {
int newValue = value +1;
localStorage.put(“curValue”,
newValue);
return newValue;
}
func increment(int value ) {
return {
“val” : value +1,
“task” : {
“task” : localStorage,
“key” : “curValue”,
“val” : value+1
}
};
}
Pure Functions
Ignore IO and let’s discuss this
func updatePwd(String pwd )
{
Node node = nodeFromExternal();
if(node.id == 2) {
invokeApi(node,pwd);
}
}
func updatePwd(String pwd , int id) {
Node node = nodeFromExternal();
if(id == node.id ) {
invokeApi(node,pwd);
}
}
Immutability
Reference to a data structure is *only* for reading from the data structure
Once you have a reference:
● Guarantees that no one will modify its contents
● Pass along to any number of threads without fear of ‘stepping on each
other’
○ Enables safe concurrency and parallelism
● Any updates to the data structure returns a new reference
Immutability : an Example
Defects (holds list of open defects)
val defectList = List(Defect(id="CSSid1234",age=48,engineer="jayas"),Defect(id="CSCid5678",age=12,engineer="otherone"))
defectList.foreach { defect =>
if (defect.age > 28) {
sendMsg(defect.engineer)
}
}
defectList.dropWhile { defect =>
defect.engineer == "jayas" }
Thread 1 Thread 2
val myDefectList =
Why Functional Programming
Pure Functions
● Guarantees Testability
● Easy Refactoring
● Reduce Defects
Immutable Data Structures
● Safe Concurrency and Parallelism
○ Eliminate concurrency / multi-threading defects
○ Enables lock free operations
● Ensures Testability
Why Functional Programming
Expressive Power
● Readability and Maintainability
● Adhering to mathematical laws and
principles
● Programming by whole values
○ Lesser Lines of Code , and thus
lesser the possibility of defects
More Info
● View “Why Functional Programming
Matters”
OOP
OO - in its Original Form
● State Encapsulation in Objects
● Message Passing for Communication
○ Objects to process messages sent to it
○ Respond by sending messages
● Not intended to use as Data
Containers/Holders
OO - as what we do for living
● Primarily a Data Holder
● No Message Passing - arbitrary retrieval and
update of data
● Imperative Programming to the core
○ Manipulating State
○ Instructing Computer on How to Do
● Hard to do Concurrency
Imperative Vs Functional
● Programming By Word Vs Whole Values
○ No word at a time processing
○ Work with entire value (data structures)
● How to Do Vs What To Do
○ Focus on business logic implementation
○ E.g: No instructions on how to traverse a list
● Less Code that Does more
○ Reduce Lines of Code
○ Reduce Possibility of Defects
for(int i=0; i< j; i++)
{
....
}
Whole Value Programming
map (A ->B) List<A> -> List<B>
● List of agents -> List of agent UserIds
flatMap (A -> List<B>) List<A> -> List<B>
● List of agents -> List of extension numbers
filter (A->Boolean) List<A> -> List<A>
● Get all supervisors from user list
foldl (acc x -> y) x List<x> -> y
● Total talk time from a list of call data records
Do a map, filter and fold it!
map a list of agents to list of strings (using Guava in Java 7)
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
Function<Agent, String> agentTransformer= new Function<Agent,String>() {
@Override
public String apply(Agent agent) {
return agent.getId();
}
};
List<String> agentIds = new ArrayList<String>(Collections2.transform(agents,agentTransformer));
Whole Value Programming
filter a list of agents to list of supervisors (using Guava in Java 7)
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
Predicate<Agent> supervisorFilter = new Predicate<Agent>() {
@Override
public boolean apply(Agent agent) {
return agent.role == Role.SUPERVISOR;
}
};
Collection<Agent> supervisors = Collections2.filter(agents, supervisorFilter);
List<String> supervisorIds = new ArrayList<String>(Collections2.transform(supervisors,agentTransformer));
Whole Value Programming
Strong Static Typing
● Type System and Compiler as First Line of defense
● Reduces dependency on Unit Tests
○ Most of the time, if it compiles, it will run
● Expressive Power By Type
○ e.g: Optional for indicating Value being present or not (vs returning null)
Strong Static Typing
Get rid of null, Now. (using Guava in Java 7)
import com.google.common.base.Optional;
class Agent {
Optional<String> agentAlias; // alias may not may not be set
public void setAlias(String alias) {
agentAlias = Optional.fromNullable(alias); // alias could be null, Java !!
}
public Optional<String> getAlias() {
return agentAlias; // returns Optional indicating that alias may or may not be there
}
}
Strong Static Typing
Indicate Error by Type, Later. ( in Scala)
def fetchDefectsFromDB() : Try[List[Defect]]= {
Try {
readFromDB// Get the list from DB
}
}
val defectList : Try[List[Defect]] = fetchDefectsFromDB()
defectList.map { defects => defects.foreach {defect => if (defect.age > 28) { sendMsg(defect.engineer)} } }
def fetchDefectsWhenDBDown() : Try[List[Defect]]= {
Failure(new Throwable(new IllegalStateException("DB Service is not in Running State)))
}
I am not sure.. What Can I do
Adopt these rules
● No nulls to indicate absence. Use Optional
○ Use it judiciously.
○ Do not use it purely to indicate an un-initialized internal state
○ Use it to indicate to other that data may or may not be present
● No loops . Use Collections2 utils
○ Simple for expression may be still efficient for simple iterations.
○ Use Guava if it avoids code duplication and does not cause performance overhead
● Make all method parameters final
○ Unfortunately there are no immutable collections in Java
I am not sure.. What Can I do
Adopt these rules
● No Explicit Multi threading / Concurrency
○ For state, in case concurrency is a need, ensure all messages to the object are processed in
sequence (yes, sequentially)
○ Use a single threaded executor to handle messages received by an object
● Question and Revisit Impure functions / methods
○ Strictly adhere to Single Responsibility Principle of OO
○ Write pure functions unless it’s unavoidable
○ It’s fine to have a class with all static methods, which are pure!
● Isolate State management and IO to one part of the system
○ Let 80 % of the implementation be pure and stateless
I am not sure.. What Can I do
Adopt these rules
● As Always, there are exceptions to all the rules , check with Architect.
● Performance , Maintainability and Readability are of most importance
○ Do not compromise on these
Learn Functional Programming
Haskell: https://github.com/data61/fp-course
Elm: https://www.elm-tutorial.org/en/
Stay Tuned for Elm training and other FP initiatives!
Architecture & Design
Reactive Programming
Corner cases are Corner Stones in Customer Experience
Design For Failure - Failures are Inevitable
Ensure testability at all levels - architecture, design, code
Reactive Systems Traits
Responsive
Message Driven
Resilient Elastic
Source: https://www.reactivemanifesto.org
Design & Architecture
Asynchronous Communication
● Message Passing across components
○ Asynchronous APIs another choice across systems
● Non Blocking IO, Lock Free Operations
○ Use Async Servlet (in Servlet 3.0) for web applications (Shindig is a perfect use case)
○ Use non blocking version of libraries, say http-client, jersey server and client
● Work on Futures and Future Compositions
○ Composition of Futures - not present by default in Java 7
○ Use ListenableFuture in Guava / CompletableFuture in Java 8
○ Evaluate and Use RxJava
Design & Architecture
Resiliency
● Build for failures
○ Failures are Inevitable
○ Architecture and Design should facilitate failure propagation and recovery
● Communicate Error & Recover from Failures
○ Let the user know
○ Provide error recovery option
● Retries for inter-component interactions / critical operations
● Location Transparency for distributed/ clustered systems
○ Distributed Cache usage does not rely on fetching cache entry from a particular node
Design & Architecture
Responsive
● Respond even when subsystems are down
○ Let the user know
● Provide degraded /lower set of functionalities than being totally unresponsive
● Have alternate option for dependent critical subsystems / external systems
Design & Architecture
Elastic
● Ability to scale up / down / out / in
○ Build services that caters to 400 users (CCX) , at the same time that can scale for 18000
users (CCE)
○ Utilize all the cores of CPU
○ Ability to add more machines to scale out
■ distributed data processing, location transparency for processing engines
Additional Learnings
Guava Wiki
RxJava
John Backus’s Turing Award Lecture
Learn Functional Programming in Haskell
Effects As Data - Talk
Thank You!

Functional Programming 101 for Java 7 Developers

  • 1.
    Beyond null &more Taming the monsters, the right way! [email protected]
  • 2.
  • 3.
    It must besome kind of race condition!!!
  • 6.
    Functional and Reactive Programming101 for Java 7 Developers
  • 7.
    What will youget? ● Get started with basic Functional Programming principles ● Reactive System Design ● Adopt in your day to day work from now!
  • 8.
    Functional Programming Intro ●Function ○ y = f(x) ● Functions as ‘First Class’ Citizens ○ Similar to values ○ Pass to / return from other functions ● Separate Data from Functions ○ Data is passed to functions ○ Data may be returned from functions ○ State Management outside of Functions Programming with Functions
  • 9.
    Functional Programming Facets ●Pure Functions ○ No Side Effects ○ Referential Transparency ● Immutable Data Structures ● Expressive Power ○ Ability to Reason - Equational Reasoning ○ Function Composition ■ f : b -> c , g : a -> b ■ f o g : a -> c ● f o g = f(g(x))
  • 10.
    Pure Functions ● Noside effects , including IO ○ For a set of inputs, always produce the same output ● Referential Transparency ○ Can ‘inline’ the function everywhere with no changes to the behavior ○ Works with substitution model of computation ● Ensures Testability
  • 11.
    Pure Functions Is thisa pure function? func increment(int value ) { return value + 1; }
  • 12.
    Pure Functions How aboutthis? func increment(int value ) { if(value < maxVal) { return value + 1; } else { return maxVal; } } func increment(int value, int maxVal ) { if(value < maxVal) { return value + 1; } else { return maxVal; } }
  • 13.
    Pure Functions ..and thistoo? func increment(int value ) { int newValue = value +1; localStorage.put(“curValue”, newValue); return newValue; } func increment(int value ) { return { “val” : value +1, “task” : { “task” : localStorage, “key” : “curValue”, “val” : value+1 } }; }
  • 14.
    Pure Functions Ignore IOand let’s discuss this func updatePwd(String pwd ) { Node node = nodeFromExternal(); if(node.id == 2) { invokeApi(node,pwd); } } func updatePwd(String pwd , int id) { Node node = nodeFromExternal(); if(id == node.id ) { invokeApi(node,pwd); } }
  • 15.
    Immutability Reference to adata structure is *only* for reading from the data structure Once you have a reference: ● Guarantees that no one will modify its contents ● Pass along to any number of threads without fear of ‘stepping on each other’ ○ Enables safe concurrency and parallelism ● Any updates to the data structure returns a new reference
  • 16.
    Immutability : anExample Defects (holds list of open defects) val defectList = List(Defect(id="CSSid1234",age=48,engineer="jayas"),Defect(id="CSCid5678",age=12,engineer="otherone")) defectList.foreach { defect => if (defect.age > 28) { sendMsg(defect.engineer) } } defectList.dropWhile { defect => defect.engineer == "jayas" } Thread 1 Thread 2 val myDefectList =
  • 17.
    Why Functional Programming PureFunctions ● Guarantees Testability ● Easy Refactoring ● Reduce Defects Immutable Data Structures ● Safe Concurrency and Parallelism ○ Eliminate concurrency / multi-threading defects ○ Enables lock free operations ● Ensures Testability
  • 18.
    Why Functional Programming ExpressivePower ● Readability and Maintainability ● Adhering to mathematical laws and principles ● Programming by whole values ○ Lesser Lines of Code , and thus lesser the possibility of defects More Info ● View “Why Functional Programming Matters”
  • 19.
  • 20.
    OO - inits Original Form ● State Encapsulation in Objects ● Message Passing for Communication ○ Objects to process messages sent to it ○ Respond by sending messages ● Not intended to use as Data Containers/Holders
  • 21.
    OO - aswhat we do for living ● Primarily a Data Holder ● No Message Passing - arbitrary retrieval and update of data ● Imperative Programming to the core ○ Manipulating State ○ Instructing Computer on How to Do ● Hard to do Concurrency
  • 22.
    Imperative Vs Functional ●Programming By Word Vs Whole Values ○ No word at a time processing ○ Work with entire value (data structures) ● How to Do Vs What To Do ○ Focus on business logic implementation ○ E.g: No instructions on how to traverse a list ● Less Code that Does more ○ Reduce Lines of Code ○ Reduce Possibility of Defects for(int i=0; i< j; i++) { .... }
  • 23.
    Whole Value Programming map(A ->B) List<A> -> List<B> ● List of agents -> List of agent UserIds flatMap (A -> List<B>) List<A> -> List<B> ● List of agents -> List of extension numbers filter (A->Boolean) List<A> -> List<A> ● Get all supervisors from user list foldl (acc x -> y) x List<x> -> y ● Total talk time from a list of call data records Do a map, filter and fold it!
  • 24.
    map a listof agents to list of strings (using Guava in Java 7) import com.google.common.base.Function; import com.google.common.collect.Collections2; Function<Agent, String> agentTransformer= new Function<Agent,String>() { @Override public String apply(Agent agent) { return agent.getId(); } }; List<String> agentIds = new ArrayList<String>(Collections2.transform(agents,agentTransformer)); Whole Value Programming
  • 25.
    filter a listof agents to list of supervisors (using Guava in Java 7) import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; Predicate<Agent> supervisorFilter = new Predicate<Agent>() { @Override public boolean apply(Agent agent) { return agent.role == Role.SUPERVISOR; } }; Collection<Agent> supervisors = Collections2.filter(agents, supervisorFilter); List<String> supervisorIds = new ArrayList<String>(Collections2.transform(supervisors,agentTransformer)); Whole Value Programming
  • 26.
    Strong Static Typing ●Type System and Compiler as First Line of defense ● Reduces dependency on Unit Tests ○ Most of the time, if it compiles, it will run ● Expressive Power By Type ○ e.g: Optional for indicating Value being present or not (vs returning null)
  • 27.
    Strong Static Typing Getrid of null, Now. (using Guava in Java 7) import com.google.common.base.Optional; class Agent { Optional<String> agentAlias; // alias may not may not be set public void setAlias(String alias) { agentAlias = Optional.fromNullable(alias); // alias could be null, Java !! } public Optional<String> getAlias() { return agentAlias; // returns Optional indicating that alias may or may not be there } }
  • 28.
    Strong Static Typing IndicateError by Type, Later. ( in Scala) def fetchDefectsFromDB() : Try[List[Defect]]= { Try { readFromDB// Get the list from DB } } val defectList : Try[List[Defect]] = fetchDefectsFromDB() defectList.map { defects => defects.foreach {defect => if (defect.age > 28) { sendMsg(defect.engineer)} } } def fetchDefectsWhenDBDown() : Try[List[Defect]]= { Failure(new Throwable(new IllegalStateException("DB Service is not in Running State))) }
  • 30.
    I am notsure.. What Can I do Adopt these rules ● No nulls to indicate absence. Use Optional ○ Use it judiciously. ○ Do not use it purely to indicate an un-initialized internal state ○ Use it to indicate to other that data may or may not be present ● No loops . Use Collections2 utils ○ Simple for expression may be still efficient for simple iterations. ○ Use Guava if it avoids code duplication and does not cause performance overhead ● Make all method parameters final ○ Unfortunately there are no immutable collections in Java
  • 31.
    I am notsure.. What Can I do Adopt these rules ● No Explicit Multi threading / Concurrency ○ For state, in case concurrency is a need, ensure all messages to the object are processed in sequence (yes, sequentially) ○ Use a single threaded executor to handle messages received by an object ● Question and Revisit Impure functions / methods ○ Strictly adhere to Single Responsibility Principle of OO ○ Write pure functions unless it’s unavoidable ○ It’s fine to have a class with all static methods, which are pure! ● Isolate State management and IO to one part of the system ○ Let 80 % of the implementation be pure and stateless
  • 32.
    I am notsure.. What Can I do Adopt these rules ● As Always, there are exceptions to all the rules , check with Architect. ● Performance , Maintainability and Readability are of most importance ○ Do not compromise on these
  • 33.
    Learn Functional Programming Haskell:https://github.com/data61/fp-course Elm: https://www.elm-tutorial.org/en/ Stay Tuned for Elm training and other FP initiatives!
  • 34.
  • 35.
    Corner cases areCorner Stones in Customer Experience
  • 36.
    Design For Failure- Failures are Inevitable
  • 37.
    Ensure testability atall levels - architecture, design, code
  • 38.
    Reactive Systems Traits Responsive MessageDriven Resilient Elastic Source: https://www.reactivemanifesto.org
  • 39.
    Design & Architecture AsynchronousCommunication ● Message Passing across components ○ Asynchronous APIs another choice across systems ● Non Blocking IO, Lock Free Operations ○ Use Async Servlet (in Servlet 3.0) for web applications (Shindig is a perfect use case) ○ Use non blocking version of libraries, say http-client, jersey server and client ● Work on Futures and Future Compositions ○ Composition of Futures - not present by default in Java 7 ○ Use ListenableFuture in Guava / CompletableFuture in Java 8 ○ Evaluate and Use RxJava
  • 40.
    Design & Architecture Resiliency ●Build for failures ○ Failures are Inevitable ○ Architecture and Design should facilitate failure propagation and recovery ● Communicate Error & Recover from Failures ○ Let the user know ○ Provide error recovery option ● Retries for inter-component interactions / critical operations ● Location Transparency for distributed/ clustered systems ○ Distributed Cache usage does not rely on fetching cache entry from a particular node
  • 41.
    Design & Architecture Responsive ●Respond even when subsystems are down ○ Let the user know ● Provide degraded /lower set of functionalities than being totally unresponsive ● Have alternate option for dependent critical subsystems / external systems
  • 42.
    Design & Architecture Elastic ●Ability to scale up / down / out / in ○ Build services that caters to 400 users (CCX) , at the same time that can scale for 18000 users (CCE) ○ Utilize all the cores of CPU ○ Ability to add more machines to scale out ■ distributed data processing, location transparency for processing engines
  • 44.
    Additional Learnings Guava Wiki RxJava JohnBackus’s Turing Award Lecture Learn Functional Programming in Haskell Effects As Data - Talk
  • 45.