SlideShare ist ein Scribd-Unternehmen logo
1 von 89
Functional Systems
Or: Functional Functional Programming

Marius Eriksen • Twitter Inc.

@marius • QCon San Francisco ‘14
InfoQ.com: News & Community Site
• 750,000 unique visitors/month
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• News 15-20 / week
• Articles 3-4 / week
• Presentations (videos) 12-15 / week
• Interviews 2-3 / week
• Books 1 / month
Watch the video with slide
synchronization on InfoQ.com!
http://www.infoq.com/presentations
/twitter-scala
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Presented at QCon San Francisco
www.qconsf.com
Caveat emptor
Where am I coming from?

• 1k+ engineers working on

• a large scale Internet service

• I build systems — I’m not a PL person

I’m not attempting to be unbiased — this is part
experience report.
Systems
Systems design is largely about managing
complexity.

Need to reduce incidental complexity as much as
possible.

We’ll explore the extent languages help here.
The language isn’t the whole story
Three pieces
Three specific ways in which we’ve used functional
programming for great profit in our systems work:

1. Your server as a function

2. Your state machine as a formula

3. Your software stack as a value
1.
Your server as a function
Modern server software
Highly concurrent

Part of larger distributed systems

Complicated operating environment

• Asynchronous networks

• Partial failures

• Unreliable machines

Need to support many protocols
Futures
Pending Successful Failed
Futures are containers for value
Futures
val a: Future[Int]
a
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
a
b
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
a
b
c
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
a
b
c
d
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16 b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16 b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16
528
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16
528
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16
528
4
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16
528
4
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16
528
4
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16
528
4
(528,
4)
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16
528
4
(528,
4)
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
16
528
4
(528,
4)
532b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
0 b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
0
512
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
0
512
Ex
b
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
0
512
Ex
Exb
c
d e
Futures
val a: Future[Int]
val b = a map { x => x + 512 }
val c = a map { x => 64 / x }
val d = Future.join(b,c)
val e = d map { case (x, y) => x + y }
a
0
512
Ex
Ex Exb
c
d e
Dependent composition
Futures may also be defined as a function of other
futures. We call this dependent composition.

Future[T].flatMap[U](

f: T => Future[U]): Future[U]
Given a Future[T], produce a new Future[U].
The returned Future[U] behaves as f applied to t.

The returned Future[U] fails if the outer
Future[T] fails.
Flatmap
def auth(id: Int, pw: String): Future[User]

def get(u: User): Future[UserData]



def getAndAuth(id: Int, pw: String)

: Future[UserData]

= auth(id, pw) flatMap { u => get(u) }
Composing errors
Futures recover from errors by another form of
dependent composition.

Future[T].rescue(

PartialFunction[Throwable,Future[T]])
Like flatMap, but operates over exceptional futures.
Rescue
val f = auth(id, pw) rescue {

case Timeout => auth(id, pw)

}
(This amounts to a single retry.)
Multiple dependent composition
Future.collect[T](fs: Seq[Future[T]])

: Future[Seq[T]]
Waits for all futures to succeed, returning the
sequence of returned values.

The returned future fails should any constituent future
fail.
Segmented search
def querySegment(id: Int, query: String)

: Future[Result]



def search(query: String)

: Future[Set[Result]] = {



val queries: Seq[Future[Result]] = 

for (id <- 0 until NumSegments) yield {

querySegment(id, query)

}



Future.collect(queries) flatMap {

results: Seq[Set[Result]] =>

Future.value(results.flatten.toSet)

}

}
Segmented search
def querySegment(id: Int, query: String)

: Future[Result]



def search(query: String)

: Future[Set[Result]] = {

val queries: Seq[Future[Result]] = 

for (id <- 0 until NumSegments) yield {

querySegment(id, query)

}



Future.collect(queries) flatMap {

results: Seq[Set[Result]] =>

Future.value(results.flatten.toSet)

}

}
search
querySegment
rpc
querySegment
rpc
querySegment
rpc
querySegment
…
rpc…
Services
A service is a kind of asynchronous function.

trait Service[Req, Rep]

extends (Req => Future[Rep])
val http: Service[HttpReq, HttpRep]

val redis: Service[RedisCmd, RedisRep]

val thrift: Service[TFrame, TFrame]
Services are symmetric
// Client:

val http = Http.newService(..)



// Server:

Http.serve(..,

new Service[HttpReq, HttpRep] {

def apply(..) = ..

}

)
// A proxy:

Http.serve(.., Http.newService(..))
Filters
Services represent logical endpoints; filters embody
service agnostic behavior such as:

• Timeouts

• Retries

• Statistics

• Authentication

• Logging
trait Filter[ReqIn, ReqOut, RepIn, RepOut]

extends 

((ReqIn, Service[ReqOut, RepIn]) => Future[RepOut])
ReqIn ReqOut RepIn RepOut
Filter[ReqIn, RepOut, ReqOut, RepIn]
Service[ReqOut, RepIn]
Example: timeout
class TimeoutFilter[Req, Rep](to: Duration)

extends Filter[Req, Rep, Req, Rep] {



def apply(req: Req, svc: Service[Req, Rep]) = 

svc(req).within(to)

}
Example: authentication
class AuthFilter extends

Filter[HttpReq, AuthHttpReq, HttpReq, HttpRep]

{

def apply(

req: HttpReq, 

svc: Service[AuthHttpReq, HttpRep]) =

auth(req) match {

case Ok(authreq) => svc(authreq)

case Failed(exc) => Future.exception(exc)

}

}
Combining filters and services
val timeout = new TimeoutFilter(1.second)

val auth = new AuthFilter
val authAndTimeout = auth andThen timeout
val service: Service[..] = ..
val authAndTimeoutService =

authAndTimeout andThen service
Real world filters
recordHandletime andThen

traceRequest andThen

collectJvmStats andThen

parseRequest andThen

logRequest andThen

recordClientStats andThen

sanitize andThen

respondToHealthCheck andThen

applyTrafficControl andThen

virtualHostServer
Futures, services, & filters
In combination, these form a sort of orthogonal basis
on which we build our server software.

The style of programming encourages good
modularity, separation of concerns.

Most of our systems are phrased as big future
transformers.
Issues
There are some practical shortcomings in treating
futures as persistent values:

1. Decoupling producer from consumer is not
always desirable: we often want to cancel
ongoing work.

2. It’s useful for computations to carry a context
so that implicit computation state needn’t be
passed through everywhere.
Interrupts
val p = new Promise[Int]

p.setInterruptHandler {

case Cancelled =>

if (p.updateIfEmpty(Throw(..)))

cancelUnderlyingOp()

}



val f = p flatMap …



f.raise(Cancelled)
Locals
// Locals are equivalent to 

// thread-locals, but with arbitrary

// delimitation.



val f, g: Future[Int]

val l = new Local[Int]

l() = 123

f flatMap { i =>

l() += i

g map { j =>

l() + j

}

}
monkey.org/~marius/funsrv.pdf
2.
Your state machine as a formula
Service discovery
Backed by ZooKeeper

Maintain convergent view of the cluster of machines

ZooKeeper is notoriously difficult to deal with
correctly

Difficult to reason about the state of your view

In addition, we have to do resource management
com.twitter.util.Var
trait Var[+T] {

def flatMap[U](f: T => Var[U])

: Var[U]

def changes: Event[T]

…

}



trait Event[+T] {

def register(s: Witness[T]): Closable

…

}
A simple example
val x = Var[Int](2)

val y = Var[Int](1)



val z: Var[Int] = for {

x0 <- x

y0 <- y

} yield x0 + y0

// z() == 3

x() = 100 // z() == 101 

y() = 100 // z() == 200
com.twitter.util.Activity
sealed trait State[+T]

case class Ok[T](t: T) extends State[T]

object Pending extends State[Nothing]

case class Failed(exc: Throwable)

extends State[Nothing]


case class Activity[+T](

run: Var[Activity.State[T]]) {

def flatMap[U](f: T => Activity[U])

: Activity[U] = …

…

}
Future : val :: Activity : var
A simple wrapper
// Turn ZooKeeper operations into 

// activities.

case class Zk(underlying: ZooKeeper) {

def globOf(pat: String)

: Activity[Seq[String]] = …



def immutableDataOf(path: String)

: Activity[Option[Buf]] = …



def collectImmutableDataOf(paths: Seq[String])

: Activity[Seq[(String, Option[Buf])]] = {

def get(path: String)

: Activity[(String, Option[Buf])] =

immutableDataOf(path).map(path -> _)

Activity.collect(paths map get)

}

}
Implementing serversets
case class Serverset(zk: Zk) {

def dataOf(pat: String)

: Activity[Seq[(String, Option[Buf])]] =

zk.globOf(pat).flatMap(

zk.collectImmutableDataOf)



def parse(Seq[(String, Option[Buf])])

: Set[SocketAddress] = ..



def entriesOf(pat: String)

: Activity[Set[SocketAddress]] =

dataOf(pat).map(parse)

}
Broken ZK clients
class VarServerSet(v: Var[ServerSet]) {

def entriesOf(path: String)

: Activity[Set[Entry]] = Activity(

v.flatMap(ss =>

ss.entriesOf(path.run))

}
Retrying ZK instance
object Zk {

// Constructor for dynamic ZK

// instance.

def retrying(backoff: Duration)

: Var[Zk]

…

}
Gluing it together
val serverset = VarServerSet(

Zk.retrying(10.seconds).map(zk =>

new ServerSet(zk)))



val set =

serverset.entriesOf(“/foo/bar”)



set.changes.observe({ addrs =>

updateLoadBalancer(addrs)

})
Resource management
trait Event[+T] {

def register(s: Witness[T]): Closable

…

}



trait Closable {

def close(deadline: Time)

: Future[Unit]

…

}
Composable closable
object Closable {

def all(closables: Closable*)

: Closable



def sequence(closables: Closable*)

: Closable



val nop: Closable



def closeOnCollect(

closable: Closable, obj: Object)



…

}
Resource management
Lifetime of observation is entirely determined by
consumer. Everything else composes on top.

Anything in the middle (Var.flatMap) does not
need to be concerned with resource management.

If updates aren’t needed, Vars are closed.
3.
Your software stack as a value
Software configuration
Finagle comprises many modules (filters, services)
which compose together to give the emergent
behavior we want.

They need to be parameterized:

• systems parameters — e.g. pool sizes,
concurrency limits;

• module injection — e.g. stats, logging, tracing.

Prior art: “cake pattern,” dependency injection
frameworks (e.g. Guice)
Ours is a more regular world
We can take advantage of the fact that our software
is highly compositional: e.g. the entire Finagle stack is
expressed in terms of Service composition.

Idea: make it a first class persistent data structure
which can be inspected and transformed.

• injecting a parameter is ‘mapping’ over this data
structure;

• inserting a module is a transformation
com.twitter.finagle.Stack
trait Stack[T] {

def transform(

fn: Stack[T] => Stack[T]): Stack[T]



def ++(right: Stack[T]): Stack[T]

def +:(stk: Stackable[T]): Stack[T]



def make(params: Params): T

}
Nodes
case class Node[T](

mk: (Params, Stack[T]) => Stack[T],

next: Stack[T]

) extends Stack[T] {

def make(params: Params) = 

mk(params, next).make(params)

}



case class Leaf[T](t: T)

extends Stack[T] {

def make(params: Params) = t

}
Parameters
// A typeclass for parameter types

trait Param[P] {

def default: P

}



trait Params {

def apply[P: Param]: P

def contains[P: Param]: Boolean

def +[P: Param](p: P): Params

}
Parameter definition
case class Poolsize(min: Int, max: Int)



implicit object Poolsize

extends Stack.Param[Poolsize] {

val default =

Poolsize(0, 100)

}
Parameter use
val params: Params



val Poolsize(min, max) = params[Poolsize]

…

new Pool(min, max)
Modules
object FailFast {

def module[Req, Rep] =

new Stack.Module2[Stats, Timer, ServiceFactory[Req, Rep]] {

def make(

stats: Stats, 

timer: Timer, 

next: ServiceFactory[Req, Rep]) =

new FailFastFactory(

next, stats.scope("failfast"), timer)

}
Building
val stk = new StackBuilder[ServiceFactory[Req, Rep]]

(nilStack[Req, Rep])



stk.push(ExpiringService.module)

stk.push(FailFastFactory.module)

stk.push(DefaultPool.module)

stk.push(TimeoutFilter.module)

stk.push(FailureAccrualFactory.module)

stk.push(StatsServiceFactory.module)

stk.push(StatsFilter.module)

stk.push(ClientDestTracingFilter.module)

stk.push(MonitorFilter.module)

stk.push(ExceptionSourceFilter.module)



val stack: Stack[ServiceFactory[Req, Rep]] =

stk.result
Using
val params = Params.empty + 

Stats(statsReceiver) +

Poolsize(10, 50) +

…



val factory: ServiceFactory[..] =

stack.make(params)
Modifying
val muxStack = stdStack

.replace(Pool, ReusingPool.module)

.replace(PrepConn, Leaser.module)
Inspection
scala> println(StackClient.newStack[Int, Int])

Node(role = prepfactory, description = PrepFactory)

Node(role = tracer, 

description = Handle span lifecycle events to report tracing from protocols)

Node(role = servicecreationstats, 

description = Track statistics on service creation failures and .. latency)

Node(role = servicetimeout, 

description = Time out service acquisition after a given period)

Node(role = requestdraining, description = RequestDraining)

Node(role = loadbalancer, description = Balance requests across multiple
endpoints)

Node(role = exceptionsource, description = Source exceptions to the service name)

Node(role = monitoring, description = Act as last-resort exception handler)

Node(role = endpointtracing, description = Record remote address of server)

Node(role = requeststats, description = Report request statistics)

Node(role = factorystats, description = Report connection statistics)

Node(role = failureaccrual, 

description = Backoff from hosts that we cannot successfully make requests to)

Node(role = requesttimeout, description = Apply a timeout to requests)

Node(role = pool, description = Control client connection pool)

Node(role = failfast, 

description = Backoff exponentially on connection failure)

Node(role = expiration, 

description = Expire a service after a certain amount of idle time)

Node(role = prepconn, description = PrepConn)

Leaf(role = endpoint, description = endpoint)
Dynamic inspection
What have we learned?
On abstraction
Abstraction has gotten a bad name because of
AbstractBeanFactoryImpls.

Rule of thumb: introduce abstraction when it
increases precision, when it serves to clarify.

Often, we can use abstraction to make things more
explicit.

Avoid needless indirection.
Compose
Composability is one of our greatest assets
— combine simple parts into a whole with emergent
behavior.

• Easy to reason about, test, constituent parts

• Easy to combine in multiple ways

• Enforces modularity

Find your “orthogonal bases.”

• Find abstractions which combine in non
overlapping ways
Decouple, separate concerns
Separate semantics from mechanism; handle
problems separately (and reusably)

• Leads to cleaner, simpler systems

• Simpler user code — pure application logic

• Flexibility in implementation

Leads to a “software tools” approach to systems
engineering.
Keep it simple
Scala, and FP languages generally, are very powerful.
Use the simple features that get you a lot of mileage.

When your platonic ideal API doesn’t quite fit, it’s
okay to dirty it up a little, but be careful.

Be mindful of the tradeoffs of static guarantees with
simplicity and understandability — always remember
the reader!

Software engineering is in part the art of knowing
when to make things worse.
Functional programming
Many tools for complexity management: Immutability,
rich structures, modularity, strong typing.

It’s easier to reason about correctness, but harder to
reason about performance.

Bridging the platonic world of functional
programming to the more practical one requires us to
get dirty.
And have fun! Thanks.
@marius
https://finagle.github.io/
Watch the video with slide synchronization on
InfoQ.com!
http://www.infoq.com/presentations/twitter-
scala

Weitere ähnliche Inhalte

Was ist angesagt?

Computer graphics programs in c++
Computer graphics programs in c++Computer graphics programs in c++
Computer graphics programs in c++Ankit Kumar
 
DAA Lab File C Programs
DAA Lab File C ProgramsDAA Lab File C Programs
DAA Lab File C ProgramsKandarp Tiwari
 
The Ring programming language version 1.9 book - Part 38 of 210
The Ring programming language version 1.9 book - Part 38 of 210The Ring programming language version 1.9 book - Part 38 of 210
The Ring programming language version 1.9 book - Part 38 of 210Mahmoud Samir Fayed
 
cocos2d 事例編 HungryMasterの実装から
cocos2d 事例編 HungryMasterの実装からcocos2d 事例編 HungryMasterの実装から
cocos2d 事例編 HungryMasterの実装からYuichi Higuchi
 
imager package in R and examples..
imager package in R and examples..imager package in R and examples..
imager package in R and examples..Dr. Volkan OBAN
 
Swift, via "swift-2048"
Swift, via "swift-2048"Swift, via "swift-2048"
Swift, via "swift-2048"Austin Zheng
 
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Dimitrios Platis
 
Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.UA Mobile
 
Solutionsfor co2 C Programs for data structures
Solutionsfor co2 C Programs for data structuresSolutionsfor co2 C Programs for data structures
Solutionsfor co2 C Programs for data structuresLakshmi Sarvani Videla
 
CUDA First Programs: Computer Architecture CSE448 : UAA Alaska : Notes
CUDA First Programs: Computer Architecture CSE448 : UAA Alaska : NotesCUDA First Programs: Computer Architecture CSE448 : UAA Alaska : Notes
CUDA First Programs: Computer Architecture CSE448 : UAA Alaska : NotesSubhajit Sahu
 
Cbse question paper class_xii_paper_2000
Cbse question paper class_xii_paper_2000Cbse question paper class_xii_paper_2000
Cbse question paper class_xii_paper_2000Deepak Singh
 
10 - Scala. Co-product type (sum type)
10 - Scala. Co-product type (sum type)10 - Scala. Co-product type (sum type)
10 - Scala. Co-product type (sum type)Roman Brovko
 
Advanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part IIAdvanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part IIDr. Volkan OBAN
 

Was ist angesagt? (20)

Computer graphics programs in c++
Computer graphics programs in c++Computer graphics programs in c++
Computer graphics programs in c++
 
DAA Lab File C Programs
DAA Lab File C ProgramsDAA Lab File C Programs
DAA Lab File C Programs
 
The Ring programming language version 1.9 book - Part 38 of 210
The Ring programming language version 1.9 book - Part 38 of 210The Ring programming language version 1.9 book - Part 38 of 210
The Ring programming language version 1.9 book - Part 38 of 210
 
cocos2d 事例編 HungryMasterの実装から
cocos2d 事例編 HungryMasterの実装からcocos2d 事例編 HungryMasterの実装から
cocos2d 事例編 HungryMasterの実装から
 
imager package in R and examples..
imager package in R and examples..imager package in R and examples..
imager package in R and examples..
 
Lambda expressions in C++
Lambda expressions in C++Lambda expressions in C++
Lambda expressions in C++
 
Swift, via "swift-2048"
Swift, via "swift-2048"Swift, via "swift-2048"
Swift, via "swift-2048"
 
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
 
C++ TUTORIAL 6
C++ TUTORIAL 6C++ TUTORIAL 6
C++ TUTORIAL 6
 
Mosaic plot in R.
Mosaic plot in R.Mosaic plot in R.
Mosaic plot in R.
 
C++ TUTORIAL 10
C++ TUTORIAL 10C++ TUTORIAL 10
C++ TUTORIAL 10
 
Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.
 
C programs
C programsC programs
C programs
 
C++ TUTORIAL 9
C++ TUTORIAL 9C++ TUTORIAL 9
C++ TUTORIAL 9
 
Solutionsfor co2 C Programs for data structures
Solutionsfor co2 C Programs for data structuresSolutionsfor co2 C Programs for data structures
Solutionsfor co2 C Programs for data structures
 
CUDA First Programs: Computer Architecture CSE448 : UAA Alaska : Notes
CUDA First Programs: Computer Architecture CSE448 : UAA Alaska : NotesCUDA First Programs: Computer Architecture CSE448 : UAA Alaska : Notes
CUDA First Programs: Computer Architecture CSE448 : UAA Alaska : Notes
 
Cbse question paper class_xii_paper_2000
Cbse question paper class_xii_paper_2000Cbse question paper class_xii_paper_2000
Cbse question paper class_xii_paper_2000
 
C++ TUTORIAL 7
C++ TUTORIAL 7C++ TUTORIAL 7
C++ TUTORIAL 7
 
10 - Scala. Co-product type (sum type)
10 - Scala. Co-product type (sum type)10 - Scala. Co-product type (sum type)
10 - Scala. Co-product type (sum type)
 
Advanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part IIAdvanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part II
 

Andere mochten auch

20151108 Day2 環團opendata流程說明
20151108 Day2 環團opendata流程說明20151108 Day2 環團opendata流程說明
20151108 Day2 環團opendata流程說明Chia Hua Lu
 
3 image based_breast_analysis_john_winder
3 image based_breast_analysis_john_winder3 image based_breast_analysis_john_winder
3 image based_breast_analysis_john_winderIñaki Meis Morante
 
Digital Advertising: Rethinking Practices for Recruitmment
Digital Advertising: Rethinking Practices for RecruitmmentDigital Advertising: Rethinking Practices for Recruitmment
Digital Advertising: Rethinking Practices for RecruitmmentConverge Consulting
 
審議民主 x 導入校園 陳俊宏
審議民主 x 導入校園 陳俊宏審議民主 x 導入校園 陳俊宏
審議民主 x 導入校園 陳俊宏Chia Hua Lu
 
ICLEI組織介紹及首爾參訪成果影片分享
ICLEI組織介紹及首爾參訪成果影片分享ICLEI組織介紹及首爾參訪成果影片分享
ICLEI組織介紹及首爾參訪成果影片分享Chia Hua Lu
 
Asociate/ Pricing Strategist (APAC/ EMEA)
Asociate/ Pricing Strategist (APAC/ EMEA)Asociate/ Pricing Strategist (APAC/ EMEA)
Asociate/ Pricing Strategist (APAC/ EMEA)Sabrina Teo
 
DevDay 2016: Thomas Haase - Sicherheit der Dinge, Hacking im Internet of Things
DevDay 2016: Thomas Haase - Sicherheit der Dinge, Hacking im Internet of ThingsDevDay 2016: Thomas Haase - Sicherheit der Dinge, Hacking im Internet of Things
DevDay 2016: Thomas Haase - Sicherheit der Dinge, Hacking im Internet of ThingsDevDay Dresden
 
DevDay 2016: Sascha Askani - Cloud-Umgebungen mit Terraform verwalten
DevDay 2016: Sascha Askani - Cloud-Umgebungen mit Terraform verwaltenDevDay 2016: Sascha Askani - Cloud-Umgebungen mit Terraform verwalten
DevDay 2016: Sascha Askani - Cloud-Umgebungen mit Terraform verwaltenDevDay Dresden
 
Unbundled Pricing - A Reference Price Solution
Unbundled Pricing - A Reference Price SolutionUnbundled Pricing - A Reference Price Solution
Unbundled Pricing - A Reference Price SolutionIterative Path
 
Power BI reports and dashboards for Microsoft Project Server
Power BI reports and  dashboards for Microsoft Project ServerPower BI reports and  dashboards for Microsoft Project Server
Power BI reports and dashboards for Microsoft Project ServerAdvaiya Solutions, Inc.
 
Cooperative societies and joint stock companies
Cooperative societies and joint stock companiesCooperative societies and joint stock companies
Cooperative societies and joint stock companiesindianeducation
 
Формування правильної звуковимови та навичок фонематичного аналізу за допомог...
Формування правильної звуковимови та навичок фонематичного аналізу за допомог...Формування правильної звуковимови та навичок фонематичного аналізу за допомог...
Формування правильної звуковимови та навичок фонематичного аналізу за допомог...Alyona Bilyk
 
Проблемне питання педагога-організатора
Проблемне питання педагога-організатораПроблемне питання педагога-організатора
Проблемне питання педагога-організатораAlla Kolosai
 
Windows 10 vs Windows 7
Windows 10 vs Windows 7Windows 10 vs Windows 7
Windows 10 vs Windows 7Jonathan Min
 

Andere mochten auch (17)

Глух С.П., ДОУ №1
Глух С.П., ДОУ №1 Глух С.П., ДОУ №1
Глух С.П., ДОУ №1
 
20151108 Day2 環團opendata流程說明
20151108 Day2 環團opendata流程說明20151108 Day2 環團opendata流程說明
20151108 Day2 環團opendata流程說明
 
відчуй
відчуйвідчуй
відчуй
 
3 image based_breast_analysis_john_winder
3 image based_breast_analysis_john_winder3 image based_breast_analysis_john_winder
3 image based_breast_analysis_john_winder
 
Digital Advertising: Rethinking Practices for Recruitmment
Digital Advertising: Rethinking Practices for RecruitmmentDigital Advertising: Rethinking Practices for Recruitmment
Digital Advertising: Rethinking Practices for Recruitmment
 
審議民主 x 導入校園 陳俊宏
審議民主 x 導入校園 陳俊宏審議民主 x 導入校園 陳俊宏
審議民主 x 導入校園 陳俊宏
 
ICLEI組織介紹及首爾參訪成果影片分享
ICLEI組織介紹及首爾參訪成果影片分享ICLEI組織介紹及首爾參訪成果影片分享
ICLEI組織介紹及首爾參訪成果影片分享
 
Asociate/ Pricing Strategist (APAC/ EMEA)
Asociate/ Pricing Strategist (APAC/ EMEA)Asociate/ Pricing Strategist (APAC/ EMEA)
Asociate/ Pricing Strategist (APAC/ EMEA)
 
DevDay 2016: Thomas Haase - Sicherheit der Dinge, Hacking im Internet of Things
DevDay 2016: Thomas Haase - Sicherheit der Dinge, Hacking im Internet of ThingsDevDay 2016: Thomas Haase - Sicherheit der Dinge, Hacking im Internet of Things
DevDay 2016: Thomas Haase - Sicherheit der Dinge, Hacking im Internet of Things
 
DevDay 2016: Sascha Askani - Cloud-Umgebungen mit Terraform verwalten
DevDay 2016: Sascha Askani - Cloud-Umgebungen mit Terraform verwaltenDevDay 2016: Sascha Askani - Cloud-Umgebungen mit Terraform verwalten
DevDay 2016: Sascha Askani - Cloud-Umgebungen mit Terraform verwalten
 
Unbundled Pricing - A Reference Price Solution
Unbundled Pricing - A Reference Price SolutionUnbundled Pricing - A Reference Price Solution
Unbundled Pricing - A Reference Price Solution
 
Power BI reports and dashboards for Microsoft Project Server
Power BI reports and  dashboards for Microsoft Project ServerPower BI reports and  dashboards for Microsoft Project Server
Power BI reports and dashboards for Microsoft Project Server
 
Cooperative societies and joint stock companies
Cooperative societies and joint stock companiesCooperative societies and joint stock companies
Cooperative societies and joint stock companies
 
Формування правильної звуковимови та навичок фонематичного аналізу за допомог...
Формування правильної звуковимови та навичок фонематичного аналізу за допомог...Формування правильної звуковимови та навичок фонематичного аналізу за допомог...
Формування правильної звуковимови та навичок фонематичного аналізу за допомог...
 
Проблемне питання педагога-організатора
Проблемне питання педагога-організатораПроблемне питання педагога-організатора
Проблемне питання педагога-організатора
 
Windows 10 vs Windows 7
Windows 10 vs Windows 7Windows 10 vs Windows 7
Windows 10 vs Windows 7
 
Опыт работы ДОУ
Опыт работы ДОУОпыт работы ДОУ
Опыт работы ДОУ
 

Ähnlich wie Functional Systems @ Twitter

Fighting history of CGFloat in Swift
Fighting history of CGFloat in SwiftFighting history of CGFloat in Swift
Fighting history of CGFloat in SwiftHirohito Kato
 
Create a java project that - Draw a circle with three random init.pdf
Create a java project that - Draw a circle with three random init.pdfCreate a java project that - Draw a circle with three random init.pdf
Create a java project that - Draw a circle with three random init.pdfarihantmobileselepun
 
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...GeeksLab Odessa
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksSeniorDevOnly
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJSKyung Yeol Kim
 
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Ruslan Shevchenko
 
Finagle By Twitter Engineer @ Knoldus
Finagle By Twitter Engineer @ KnoldusFinagle By Twitter Engineer @ Knoldus
Finagle By Twitter Engineer @ KnoldusKnoldus Inc.
 
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Igalia
 
Async Microservices with Twitter's Finagle
Async Microservices with Twitter's FinagleAsync Microservices with Twitter's Finagle
Async Microservices with Twitter's FinagleVladimir Kostyukov
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concernssaintiss
 
CS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and CullingCS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and CullingMark Kilgard
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenPawel Szulc
 
Event Sourcing and Functional Programming
Event Sourcing and Functional ProgrammingEvent Sourcing and Functional Programming
Event Sourcing and Functional ProgrammingGlobalLogic Ukraine
 
How to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ CodeHow to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ CodeMicrosoft Tech Community
 
How to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ CodeHow to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ CodeMicrosoft Tech Community
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiInfluxData
 

Ähnlich wie Functional Systems @ Twitter (20)

Fighting history of CGFloat in Swift
Fighting history of CGFloat in SwiftFighting history of CGFloat in Swift
Fighting history of CGFloat in Swift
 
Create a java project that - Draw a circle with three random init.pdf
Create a java project that - Draw a circle with three random init.pdfCreate a java project that - Draw a circle with three random init.pdf
Create a java project that - Draw a circle with three random init.pdf
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risks
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
 
Finagle By Twitter Engineer @ Knoldus
Finagle By Twitter Engineer @ KnoldusFinagle By Twitter Engineer @ Knoldus
Finagle By Twitter Engineer @ Knoldus
 
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
 
Go a crash course
Go   a crash courseGo   a crash course
Go a crash course
 
Async Microservices with Twitter's Finagle
Async Microservices with Twitter's FinagleAsync Microservices with Twitter's Finagle
Async Microservices with Twitter's Finagle
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concerns
 
CS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and CullingCS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and Culling
 
C++ Inheritance
C++ InheritanceC++ Inheritance
C++ Inheritance
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heaven
 
Event Sourcing and Functional Programming
Event Sourcing and Functional ProgrammingEvent Sourcing and Functional Programming
Event Sourcing and Functional Programming
 
How to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ CodeHow to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ Code
 
How to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ CodeHow to Adopt Modern C++17 into Your C++ Code
How to Adopt Modern C++17 into Your C++ Code
 
C++ programs
C++ programsC++ programs
C++ programs
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
 

Mehr von C4Media

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoC4Media
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileC4Media
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020C4Media
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsC4Media
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No KeeperC4Media
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like OwnersC4Media
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaC4Media
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideC4Media
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDC4Media
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine LearningC4Media
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at SpeedC4Media
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsC4Media
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsC4Media
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerC4Media
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleC4Media
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeC4Media
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereC4Media
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing ForC4Media
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data EngineeringC4Media
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreC4Media
 

Mehr von C4Media (20)

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live Video
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy Mobile
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java Applications
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No Keeper
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like Owners
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate Guide
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CD
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine Learning
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at Speed
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep Systems
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.js
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly Compiler
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix Scale
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's Edge
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home Everywhere
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing For
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data Engineering
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
 

Kürzlich hochgeladen

A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 

Kürzlich hochgeladen (20)

A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 

Functional Systems @ Twitter

  • 1. Functional Systems Or: Functional Functional Programming Marius Eriksen • Twitter Inc. @marius • QCon San Francisco ‘14
  • 2. InfoQ.com: News & Community Site • 750,000 unique visitors/month • Published in 4 languages (English, Chinese, Japanese and Brazilian Portuguese) • Post content from our QCon conferences • News 15-20 / week • Articles 3-4 / week • Presentations (videos) 12-15 / week • Interviews 2-3 / week • Books 1 / month Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations /twitter-scala
  • 3. Purpose of QCon - to empower software development by facilitating the spread of knowledge and innovation Strategy - practitioner-driven conference designed for YOU: influencers of change and innovation in your teams - speakers and topics driving the evolution and innovation - connecting and catalyzing the influencers and innovators Highlights - attended by more than 12,000 delegates since 2007 - held in 9 cities worldwide Presented at QCon San Francisco www.qconsf.com
  • 4. Caveat emptor Where am I coming from? • 1k+ engineers working on • a large scale Internet service • I build systems — I’m not a PL person I’m not attempting to be unbiased — this is part experience report.
  • 5. Systems Systems design is largely about managing complexity. Need to reduce incidental complexity as much as possible. We’ll explore the extent languages help here.
  • 6. The language isn’t the whole story
  • 7. Three pieces Three specific ways in which we’ve used functional programming for great profit in our systems work: 1. Your server as a function 2. Your state machine as a formula 3. Your software stack as a value
  • 8. 1. Your server as a function
  • 9. Modern server software Highly concurrent Part of larger distributed systems Complicated operating environment • Asynchronous networks • Partial failures • Unreliable machines Need to support many protocols
  • 10. Futures Pending Successful Failed Futures are containers for value
  • 12. Futures val a: Future[Int] val b = a map { x => x + 512 } a b
  • 13. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } a b c
  • 14. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) a b c d
  • 15. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a b c d e
  • 16. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 b c d e
  • 17. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 b c d e
  • 18. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 528 b c d e
  • 19. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 528 b c d e
  • 20. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 528 4 b c d e
  • 21. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 528 4 b c d e
  • 22. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 528 4 b c d e
  • 23. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 528 4 (528, 4) b c d e
  • 24. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 528 4 (528, 4) b c d e
  • 25. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 16 528 4 (528, 4) 532b c d e
  • 26. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 0 b c d e
  • 27. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 0 512 b c d e
  • 28. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 0 512 Ex b c d e
  • 29. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 0 512 Ex Exb c d e
  • 30. Futures val a: Future[Int] val b = a map { x => x + 512 } val c = a map { x => 64 / x } val d = Future.join(b,c) val e = d map { case (x, y) => x + y } a 0 512 Ex Ex Exb c d e
  • 31. Dependent composition Futures may also be defined as a function of other futures. We call this dependent composition. Future[T].flatMap[U](
 f: T => Future[U]): Future[U] Given a Future[T], produce a new Future[U]. The returned Future[U] behaves as f applied to t. The returned Future[U] fails if the outer Future[T] fails.
  • 32. Flatmap def auth(id: Int, pw: String): Future[User]
 def get(u: User): Future[UserData]
 
 def getAndAuth(id: Int, pw: String)
 : Future[UserData]
 = auth(id, pw) flatMap { u => get(u) }
  • 33. Composing errors Futures recover from errors by another form of dependent composition. Future[T].rescue(
 PartialFunction[Throwable,Future[T]]) Like flatMap, but operates over exceptional futures.
  • 34. Rescue val f = auth(id, pw) rescue {
 case Timeout => auth(id, pw)
 } (This amounts to a single retry.)
  • 35. Multiple dependent composition Future.collect[T](fs: Seq[Future[T]])
 : Future[Seq[T]] Waits for all futures to succeed, returning the sequence of returned values. The returned future fails should any constituent future fail.
  • 36. Segmented search def querySegment(id: Int, query: String)
 : Future[Result]
 
 def search(query: String)
 : Future[Set[Result]] = {
 
 val queries: Seq[Future[Result]] = 
 for (id <- 0 until NumSegments) yield {
 querySegment(id, query)
 }
 
 Future.collect(queries) flatMap {
 results: Seq[Set[Result]] =>
 Future.value(results.flatten.toSet)
 }
 }
  • 37. Segmented search def querySegment(id: Int, query: String)
 : Future[Result]
 
 def search(query: String)
 : Future[Set[Result]] = {
 val queries: Seq[Future[Result]] = 
 for (id <- 0 until NumSegments) yield {
 querySegment(id, query)
 }
 
 Future.collect(queries) flatMap {
 results: Seq[Set[Result]] =>
 Future.value(results.flatten.toSet)
 }
 } search querySegment rpc querySegment rpc querySegment rpc querySegment … rpc…
  • 38. Services A service is a kind of asynchronous function. trait Service[Req, Rep]
 extends (Req => Future[Rep]) val http: Service[HttpReq, HttpRep]
 val redis: Service[RedisCmd, RedisRep]
 val thrift: Service[TFrame, TFrame]
  • 39. Services are symmetric // Client:
 val http = Http.newService(..)
 
 // Server:
 Http.serve(..,
 new Service[HttpReq, HttpRep] {
 def apply(..) = ..
 }
 ) // A proxy:
 Http.serve(.., Http.newService(..))
  • 40. Filters Services represent logical endpoints; filters embody service agnostic behavior such as: • Timeouts • Retries • Statistics • Authentication • Logging
  • 41. trait Filter[ReqIn, ReqOut, RepIn, RepOut]
 extends 
 ((ReqIn, Service[ReqOut, RepIn]) => Future[RepOut]) ReqIn ReqOut RepIn RepOut Filter[ReqIn, RepOut, ReqOut, RepIn] Service[ReqOut, RepIn]
  • 42. Example: timeout class TimeoutFilter[Req, Rep](to: Duration)
 extends Filter[Req, Rep, Req, Rep] {
 
 def apply(req: Req, svc: Service[Req, Rep]) = 
 svc(req).within(to)
 }
  • 43. Example: authentication class AuthFilter extends
 Filter[HttpReq, AuthHttpReq, HttpReq, HttpRep]
 {
 def apply(
 req: HttpReq, 
 svc: Service[AuthHttpReq, HttpRep]) =
 auth(req) match {
 case Ok(authreq) => svc(authreq)
 case Failed(exc) => Future.exception(exc)
 }
 }
  • 44. Combining filters and services val timeout = new TimeoutFilter(1.second)
 val auth = new AuthFilter val authAndTimeout = auth andThen timeout val service: Service[..] = .. val authAndTimeoutService =
 authAndTimeout andThen service
  • 45. Real world filters recordHandletime andThen
 traceRequest andThen
 collectJvmStats andThen
 parseRequest andThen
 logRequest andThen
 recordClientStats andThen
 sanitize andThen
 respondToHealthCheck andThen
 applyTrafficControl andThen
 virtualHostServer
  • 46.
  • 47.
  • 48. Futures, services, & filters In combination, these form a sort of orthogonal basis on which we build our server software. The style of programming encourages good modularity, separation of concerns. Most of our systems are phrased as big future transformers.
  • 49. Issues There are some practical shortcomings in treating futures as persistent values: 1. Decoupling producer from consumer is not always desirable: we often want to cancel ongoing work. 2. It’s useful for computations to carry a context so that implicit computation state needn’t be passed through everywhere.
  • 50. Interrupts val p = new Promise[Int]
 p.setInterruptHandler {
 case Cancelled =>
 if (p.updateIfEmpty(Throw(..)))
 cancelUnderlyingOp()
 }
 
 val f = p flatMap …
 
 f.raise(Cancelled)
  • 51. Locals // Locals are equivalent to 
 // thread-locals, but with arbitrary
 // delimitation.
 
 val f, g: Future[Int]
 val l = new Local[Int]
 l() = 123
 f flatMap { i =>
 l() += i
 g map { j =>
 l() + j
 }
 }
  • 53. 2. Your state machine as a formula
  • 54. Service discovery Backed by ZooKeeper Maintain convergent view of the cluster of machines ZooKeeper is notoriously difficult to deal with correctly Difficult to reason about the state of your view In addition, we have to do resource management
  • 55.
  • 56. com.twitter.util.Var trait Var[+T] {
 def flatMap[U](f: T => Var[U])
 : Var[U]
 def changes: Event[T]
 …
 }
 
 trait Event[+T] {
 def register(s: Witness[T]): Closable
 …
 }
  • 57. A simple example val x = Var[Int](2)
 val y = Var[Int](1)
 
 val z: Var[Int] = for {
 x0 <- x
 y0 <- y
 } yield x0 + y0
 // z() == 3
 x() = 100 // z() == 101 
 y() = 100 // z() == 200
  • 58. com.twitter.util.Activity sealed trait State[+T]
 case class Ok[T](t: T) extends State[T]
 object Pending extends State[Nothing]
 case class Failed(exc: Throwable)
 extends State[Nothing] 
 case class Activity[+T](
 run: Var[Activity.State[T]]) {
 def flatMap[U](f: T => Activity[U])
 : Activity[U] = …
 …
 }
  • 59. Future : val :: Activity : var
  • 60. A simple wrapper // Turn ZooKeeper operations into 
 // activities.
 case class Zk(underlying: ZooKeeper) {
 def globOf(pat: String)
 : Activity[Seq[String]] = …
 
 def immutableDataOf(path: String)
 : Activity[Option[Buf]] = …
 
 def collectImmutableDataOf(paths: Seq[String])
 : Activity[Seq[(String, Option[Buf])]] = {
 def get(path: String)
 : Activity[(String, Option[Buf])] =
 immutableDataOf(path).map(path -> _)
 Activity.collect(paths map get)
 }
 }
  • 61. Implementing serversets case class Serverset(zk: Zk) {
 def dataOf(pat: String)
 : Activity[Seq[(String, Option[Buf])]] =
 zk.globOf(pat).flatMap(
 zk.collectImmutableDataOf)
 
 def parse(Seq[(String, Option[Buf])])
 : Set[SocketAddress] = ..
 
 def entriesOf(pat: String)
 : Activity[Set[SocketAddress]] =
 dataOf(pat).map(parse)
 }
  • 62. Broken ZK clients class VarServerSet(v: Var[ServerSet]) {
 def entriesOf(path: String)
 : Activity[Set[Entry]] = Activity(
 v.flatMap(ss =>
 ss.entriesOf(path.run))
 }
  • 63. Retrying ZK instance object Zk {
 // Constructor for dynamic ZK
 // instance.
 def retrying(backoff: Duration)
 : Var[Zk]
 …
 }
  • 64. Gluing it together val serverset = VarServerSet(
 Zk.retrying(10.seconds).map(zk =>
 new ServerSet(zk)))
 
 val set =
 serverset.entriesOf(“/foo/bar”)
 
 set.changes.observe({ addrs =>
 updateLoadBalancer(addrs)
 })
  • 65. Resource management trait Event[+T] {
 def register(s: Witness[T]): Closable
 …
 }
 
 trait Closable {
 def close(deadline: Time)
 : Future[Unit]
 …
 }
  • 66. Composable closable object Closable {
 def all(closables: Closable*)
 : Closable
 
 def sequence(closables: Closable*)
 : Closable
 
 val nop: Closable
 
 def closeOnCollect(
 closable: Closable, obj: Object)
 
 …
 }
  • 67. Resource management Lifetime of observation is entirely determined by consumer. Everything else composes on top. Anything in the middle (Var.flatMap) does not need to be concerned with resource management. If updates aren’t needed, Vars are closed.
  • 69. Software configuration Finagle comprises many modules (filters, services) which compose together to give the emergent behavior we want. They need to be parameterized: • systems parameters — e.g. pool sizes, concurrency limits; • module injection — e.g. stats, logging, tracing. Prior art: “cake pattern,” dependency injection frameworks (e.g. Guice)
  • 70. Ours is a more regular world We can take advantage of the fact that our software is highly compositional: e.g. the entire Finagle stack is expressed in terms of Service composition. Idea: make it a first class persistent data structure which can be inspected and transformed. • injecting a parameter is ‘mapping’ over this data structure; • inserting a module is a transformation
  • 71. com.twitter.finagle.Stack trait Stack[T] {
 def transform(
 fn: Stack[T] => Stack[T]): Stack[T]
 
 def ++(right: Stack[T]): Stack[T]
 def +:(stk: Stackable[T]): Stack[T]
 
 def make(params: Params): T
 }
  • 72. Nodes case class Node[T](
 mk: (Params, Stack[T]) => Stack[T],
 next: Stack[T]
 ) extends Stack[T] {
 def make(params: Params) = 
 mk(params, next).make(params)
 }
 
 case class Leaf[T](t: T)
 extends Stack[T] {
 def make(params: Params) = t
 }
  • 73. Parameters // A typeclass for parameter types
 trait Param[P] {
 def default: P
 }
 
 trait Params {
 def apply[P: Param]: P
 def contains[P: Param]: Boolean
 def +[P: Param](p: P): Params
 }
  • 74. Parameter definition case class Poolsize(min: Int, max: Int)
 
 implicit object Poolsize
 extends Stack.Param[Poolsize] {
 val default =
 Poolsize(0, 100)
 }
  • 75. Parameter use val params: Params
 
 val Poolsize(min, max) = params[Poolsize]
 …
 new Pool(min, max)
  • 76. Modules object FailFast {
 def module[Req, Rep] =
 new Stack.Module2[Stats, Timer, ServiceFactory[Req, Rep]] {
 def make(
 stats: Stats, 
 timer: Timer, 
 next: ServiceFactory[Req, Rep]) =
 new FailFastFactory(
 next, stats.scope("failfast"), timer)
 }
  • 77. Building val stk = new StackBuilder[ServiceFactory[Req, Rep]]
 (nilStack[Req, Rep])
 
 stk.push(ExpiringService.module)
 stk.push(FailFastFactory.module)
 stk.push(DefaultPool.module)
 stk.push(TimeoutFilter.module)
 stk.push(FailureAccrualFactory.module)
 stk.push(StatsServiceFactory.module)
 stk.push(StatsFilter.module)
 stk.push(ClientDestTracingFilter.module)
 stk.push(MonitorFilter.module)
 stk.push(ExceptionSourceFilter.module)
 
 val stack: Stack[ServiceFactory[Req, Rep]] =
 stk.result
  • 78. Using val params = Params.empty + 
 Stats(statsReceiver) +
 Poolsize(10, 50) +
 …
 
 val factory: ServiceFactory[..] =
 stack.make(params)
  • 79. Modifying val muxStack = stdStack
 .replace(Pool, ReusingPool.module)
 .replace(PrepConn, Leaser.module)
  • 80. Inspection scala> println(StackClient.newStack[Int, Int])
 Node(role = prepfactory, description = PrepFactory)
 Node(role = tracer, 
 description = Handle span lifecycle events to report tracing from protocols)
 Node(role = servicecreationstats, 
 description = Track statistics on service creation failures and .. latency)
 Node(role = servicetimeout, 
 description = Time out service acquisition after a given period)
 Node(role = requestdraining, description = RequestDraining)
 Node(role = loadbalancer, description = Balance requests across multiple endpoints)
 Node(role = exceptionsource, description = Source exceptions to the service name)
 Node(role = monitoring, description = Act as last-resort exception handler)
 Node(role = endpointtracing, description = Record remote address of server)
 Node(role = requeststats, description = Report request statistics)
 Node(role = factorystats, description = Report connection statistics)
 Node(role = failureaccrual, 
 description = Backoff from hosts that we cannot successfully make requests to)
 Node(role = requesttimeout, description = Apply a timeout to requests)
 Node(role = pool, description = Control client connection pool)
 Node(role = failfast, 
 description = Backoff exponentially on connection failure)
 Node(role = expiration, 
 description = Expire a service after a certain amount of idle time)
 Node(role = prepconn, description = PrepConn)
 Leaf(role = endpoint, description = endpoint)
  • 82. What have we learned?
  • 83. On abstraction Abstraction has gotten a bad name because of AbstractBeanFactoryImpls. Rule of thumb: introduce abstraction when it increases precision, when it serves to clarify. Often, we can use abstraction to make things more explicit. Avoid needless indirection.
  • 84. Compose Composability is one of our greatest assets — combine simple parts into a whole with emergent behavior. • Easy to reason about, test, constituent parts • Easy to combine in multiple ways • Enforces modularity Find your “orthogonal bases.” • Find abstractions which combine in non overlapping ways
  • 85. Decouple, separate concerns Separate semantics from mechanism; handle problems separately (and reusably) • Leads to cleaner, simpler systems • Simpler user code — pure application logic • Flexibility in implementation Leads to a “software tools” approach to systems engineering.
  • 86. Keep it simple Scala, and FP languages generally, are very powerful. Use the simple features that get you a lot of mileage. When your platonic ideal API doesn’t quite fit, it’s okay to dirty it up a little, but be careful. Be mindful of the tradeoffs of static guarantees with simplicity and understandability — always remember the reader! Software engineering is in part the art of knowing when to make things worse.
  • 87. Functional programming Many tools for complexity management: Immutability, rich structures, modularity, strong typing. It’s easier to reason about correctness, but harder to reason about performance. Bridging the platonic world of functional programming to the more practical one requires us to get dirty.
  • 88. And have fun! Thanks. @marius https://finagle.github.io/
  • 89. Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations/twitter- scala