scala, the startup way

31
Scala, the startup way Marcus Lönnberg Hongchao Liu

Upload: marcus-loennberg

Post on 12-Apr-2017

87 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Scala, the startup way

Scala, the startup way

Marcus Lönnberg Hongchao Liu

Page 3: Scala, the startup way

The Startup way● Limited resources● Limited time● Fast iterations● Least power principle● Make an effort to understand the trade offs● Consciously evaluate and justify the cost of moving

up/down the abstraction ladder

Page 4: Scala, the startup way

The spectrum of abstractions● Moving up

○ More powerful○ Less constraints

● Moving down○ More properties○ More constraints○ Closer to the problem

● Moving cost● Cognitive cost● Least power principle● Abstraction overfitting

Reference: https://www.youtube.com/watch?v=mVVNJKv9esE

Page 5: Scala, the startup way

Example: Vim v.s. Emacs

● Emacs is more powerful● Vim is more specific● Abstraction level● Usage pattern

Emacs

Vim

Browse MassagePlay music GTD Editing

Page 6: Scala, the startup way

Example: Static v.s.Dynamic typing

● Static typing○ More constraints○ Compile time checking○ Should alway use it! :)○ Unless it gets in our way

● Dynamic typing○ Less constraints○ More flexible / powerful

Dynamic typing

Static typing

Page 7: Scala, the startup way

Data types

● Built-in types● Algebraic data types

○ case class○ sealed trait

● Functions● Ad-hoc classes

○ Ubiquitous in Java

Ad-hoc classes

ADT Functions

Built-in types

Reference: http://www.lihaoyi.com/post/StrategicScalaStylePrincipleofLeastPower.html

Page 8: Scala, the startup way

Asynchronous Programming model● Data

○ Single element○ Stream of elements

● Topology○ Unidirectional edge○ Complex graph

● Location○ Local○ Distributed

● Type safety○ Typed○ Untyped

Page 9: Scala, the startup way

Asynchronous Programming model● Future

○ An object that acts like a proxy for an initially unknown result○ Typed○ Composable○ Bounded timeout○ Unidirectional○ Treating data as its entirety○ Local abstraction

Page 10: Scala, the startup way

Asynchronous Programming model● Akka Stream

○ Complex graph, typed

○ Composable○ Back pressure○ Treating data as stream of elements○ Local abstraction

final class Source[+Out, +Mat] extends Graph[SourceShape[Out], Mat]

final class Sink[-In, +Mat] extends Graph[SinkShape[In], Mat]

final class Flow[-In, +Out, +Mat] extends Graph[FlowShape[In, Out], Mat]

Page 11: Scala, the startup way

Asynchronous Programming model● Akka actors

○ Message passing with internal state, very expressive○ Location transparency, distribution○ Complex graph, untyped (experimental akka typed)

○ Not composable (because of the signature above)○ Treating data as stream of elements (messages) but hard to achieve

stable streaming (bounded mailbox)○ Opacity of the actors makes it hard to reason about complex programs

type Receive = PartialFunction[Any, Unit]

def tell(msg: Any, sender: ActorRef): Unit

Page 12: Scala, the startup way

Asynchronous Programming model● We use Future extensively

○ use scala-async if too much control flows

● Streams for things like websockets, bank synchronization● Haven’t come across the case of using Akka Actor yet

Page 13: Scala, the startup way

Dependency Injection

● Assemble components● Separate dependency

creation and behavior● Encourage modularityManual injection

Guice

Macwire

Spring

Page 14: Scala, the startup way

Dependency Injection● Manual DI

○ No magic, simple to understand○ Static type checking for dependency graph○ Flexible enough for expressing various injection strategies○ Might be tedious○ Roll your own if in need of “advanced” DI features

class Services {

val foo = new Foo()

val bar = new Bar()

val doo = new Doo(foo, bar)

}

Page 15: Scala, the startup way

Dependency Injection● Have to be lazy, sometimes

● Sometimes being lazy isn’t enough

class Services {

val foo = new Foo()

lazy val doo = new Doo(foo, bar)

lazy val bar = new Bar()

}

class Services {

lazy val foo = new Foo(bar)

lazy val bar = new Bar(foo)

}

Page 16: Scala, the startup way

Dependency Injection● Using implicits

○ Remove some of the tediousness○ Had to declare implicits as parameters, which could be confusing

● Thin cake○ Use Traits to separate concerns ○ Make it “feel” like less tedious○ Manage name conflicts

trait FooModule { val foo = new Foo() }

trait BarModule { val bar = new Bar() }

trait DooModule {

val doo = new Doo(foo, bar)

val foo: Foo

val bar: Bar

}

class Services {

val modules = new DooModule

extends FooModule

with BarModule

}

Page 17: Scala, the startup way

Dependency Injection● Guice

○ Address tediousness with annotations or bind○ Things are done at runtime

@implementedBy(classOf[FooImpl])

trait Foo { ??? }

@implementedBy(classOf[BarImpl])

trait Bar { ??? }

val injector = Guice.createInjector();

val doo = injector.getInstance(classOf[Doo]);

● Spring○ Address tediousness with annotations or applicationContext.xml○ Abstraction is so heavy that it is hard to know what it does○ Things are done at runtime

Page 18: Scala, the startup way

Dependency Injection● Macwire

○ Use macro to automatically remove tediousness of manual DI○ Static type checking of dependency graphs○ Features such as interceptors○ Doesn’t do much magic○ Big enough benefits to introduce it?

import com.softwaremill.macwire._

class Services {

val foo = wire[Foo]

val bar = wire[Bar]

val doo = wire[Doo]

}

Page 19: Scala, the startup way

Dependency Injection● Stick with manual DI since due to

○ Simplicity○ Easy to understand / debug○ Level of tediousness is tolerable○ Not in need of more advanced DI features

● Thin cake?● Macwire?

Page 20: Scala, the startup way

Storage model● Constantly evolving data model● Analyse data● Traceability● Handle sensitive data

Page 21: Scala, the startup way

Event Sourcing● Events

○ All updates that can be performed on a model is through events

● Views○ Projection of events○ Can have multiple

● Constrained by the events○ Append only

Page 22: Scala, the startup way

Event Sourcingsealed trait ProductEvent

case class ProductCreated(productId: ProductId, supplierId: SupplierId, price: Price, at: DateTime)

extends ProductEvent

case class ProductPriceChanged(productId: ProductId, price: Price, at: DateTime) extends ProductEvent

case class ProductDeleted(productId: ProductId, at: DateTime) extends ProductEvent

case class ProductView(id: ProductId, supplierId: SupplierId, price: Price, state: ProductState,

createdAt: DateTime)

Page 23: Scala, the startup way

ExampleProductCreated (productId, supplier, Price(10), DateTime("2017-02-28 12:00:00" ))

=> ProductView(productId, supplier, Price(10), Active, DateTime("2017-02-28 12:00:00" ))

Page 24: Scala, the startup way

ExampleProductCreated (productId, supplier, Price(10), DateTime("2017-02-28 12:00:00" ))

=> ProductView(productId, supplier, Price(10), Active, DateTime("2017-02-28 12:00:00" ))

ProductPriceChanged (productId, Price(15), DateTime("2017-02-28 13:30:00" ))

=> ProductView(productId, supplier, Price(15), Active, DateTime("2017-02-28 12:00:00" ))

Page 25: Scala, the startup way

ExampleProductCreated (productId, supplier, Price(10), DateTime("2017-02-28 12:00:00" ))

=> ProductView(productId, supplier, Price(10), Active, DateTime("2017-02-28 12:00:00" ))

ProductPriceChanged (productId, Price(15), DateTime("2017-02-28 13:30:00" ))

=> ProductView(productId, supplier, Price(15), Active, DateTime("2017-02-28 12:00:00" ))

ProductDeleted (productId, DateTime("2017-02-28 14:00:00" ))

=> ProductView(productId, supplier, Price(15), Deleted, DateTime("2017-02-28 12:00:00" ))

Page 26: Scala, the startup way

CRUD● Mutable changes

○ Update○ Delete

● Lower cost without traceability

○ Use when no benefits of event sourcing

● Event sourcing is more constrained

Event sourcing

CRUD

Page 27: Scala, the startup way

Deployment● Easy to deploy● Deploy often● Scaleable platform● Controlled releases

Docker containers

Docker compose

Kubernetes

Page 28: Scala, the startup way

Deployment

Deploying

InTo

Kubernetes

Health status

Showing logs

Page 29: Scala, the startup way

Deployment

Demo

Page 30: Scala, the startup way

Like Scala?Like scaling up systems?Love to create user value?

Page 31: Scala, the startup way

Scala, the startup way

Questions?

Marcus Lönnberg Hongchao Liu