Slide 1

Slide 1 text

Functional Mocking Lars Hupel February 26th, 2015

Slide 2

Slide 2 text

What even is “Mocking”? “ In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways. Wikipedia: Mock object ” 2

Slide 3

Slide 3 text

What even is “Mocking”? “ In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways. Wikipedia: Mock object ” 2

Slide 4

Slide 4 text

Mocking in Scala Example: ScalaMock def testTurtle { val m = mock[Turtle] (m.setPosition _).expects(10.0, 10.0) (m.forward _).expects(5.0) (m.getPosition _).expects().returning(15.0, 10.0) drawLine(m, (10.0, 10.0), (15.0, 10.0)) } 3

Slide 5

Slide 5 text

Mocking: Why Not? “ When you write a mockist test, you are testing the outbound calls of the SUT to ensure it talks properly to its suppliers ... Mockist tests are thus more coupled to the implementation of a method. Changing the nature of calls to collaborators usually cause a mockist test to break. Martin Fowler ” 4

Slide 6

Slide 6 text

Mocking: Why Not? “ When you write a mockist test, you are testing the outbound calls of the SUT to ensure it talks properly to its suppliers ... Mockist tests are thus more coupled to the implementation of a method. Changing the nature of calls to collaborators usually cause a mockist test to break. Martin Fowler ” 4

Slide 7

Slide 7 text

It is pitch black. You are likely to be eaten by a grue.

Slide 8

Slide 8 text

Functional Mocking ... there’s no such thing. 6

Slide 9

Slide 9 text

Functional Mocking ... there’s no such thing. various techniques avoid the need for mocking altogether 6

Slide 10

Slide 10 text

Functional Programming ▶ separation of data and operations ▶ parametric polymorphism ▶ higher-order functions ▶ lightweight interpreters 7

Slide 11

Slide 11 text

A Simple Calculator data Expr = Literal Int | Var String | Sum Expr Expr evaluate :: Map String Int -> Expr -> Maybe Int 8

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

A Simple Calculator data Expr = Literal Int | Var String | Sum Expr Expr evaluate :: (String -> Maybe Int) -> Expr -> Maybe Int 10

Slide 14

Slide 14 text

A Simple Calculator data Expr a = Literal a | Var String | Sum (Expr a) (Expr a) evaluate :: Num a => (String -> Maybe a) -> Expr a -> Maybe a 10

Slide 15

Slide 15 text

A (Not So) Simple Calculator data Expr a t = Literal a | Var t | Sum (Expr a t) (Expr a t) evaluate :: Num a => (t -> Maybe a) -> Expr a t -> Maybe a 10

Slide 16

Slide 16 text

A (Not So) Simple Calculator data Expr a t = Literal a | Var t | Sum (Expr a t) (Expr a t) evaluateM :: (Num a, Monad m) => (t -> m a) -> Expr a t -> m a 10

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

Why This Complexity? “ Always implement things when you actually need them, never when you just foresee that you need them. Ron Jeffries about YAGNI ” 12

Slide 19

Slide 19 text

What Have We Gained? Abstraction over Num ▶ no messing around with the values ▶ caller knows that only the Num influences the behaviour Abstraction over Monad ▶ uniform data access ▶ Map ▶ database lookup ▶ reading from standard input 13

Slide 20

Slide 20 text

Even More Abstraction -- get all variables vars :: Expr a t -> [t] vars = error ”some traversal” -- check definedness of all variables check :: Expr a (Maybe t) -> Maybe (Expr a t) check = error ”traversing again?!” -- substitute variables subst :: (t -> Expr a t) -> Expr a t -> Expr a t subst = error ”seriously?” 14

Slide 21

Slide 21 text

Even More Abstraction -- get all variables vars :: Expr a t -> [t] vars = Data.Foldable.toList -- check definedness of all variables check :: Expr a (Maybe t) -> Maybe (Expr a t) check = Data.Traversable.sequenceA -- substitute variables subst :: (t -> Expr a t) -> Expr a t -> Expr a t subst = (=<<) 14

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Aspect-Oriented Programming What if we want to log the variable access in evaluateM? 16

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

YAGNI Revisited ▶ without early abstraction, many concepts stay hidden ▶ YAGNI limits thinking ▶ especially important when building libraries 18

Slide 26

Slide 26 text

Interlude: Immutable Data Structures class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } 19

Slide 27

Slide 27 text

Setter and Getter in Java company.getITDepartment() .getHead() .setName(”Grace Hopper”); 20

Slide 28

Slide 28 text

Immutable Data in Haskell data Company = data Department = Company { Department { it :: Department boss :: Person , hr :: Department , budget :: Currency } } data Person = Person { name :: String } 21

Slide 29

Slide 29 text

Updating Immutable Data company { it = (it company) { boss = (boss (it company)) { name = ”Grace Hopper” } } } 22

Slide 30

Slide 30 text

Updating Immutable Data company { it = (it company) { boss = (boss (it company)) { name = ”Grace Hopper” } } } 22

Slide 31

Slide 31 text

Costate Comonad Coalgebra ...? 23

Slide 32

Slide 32 text

Lenses To The Rescue! The Naive Formulation data Lens a b = Lens { get :: a -> b set :: a -> b -> a } 24

Slide 33

Slide 33 text

Lenses To The Rescue! The Naive Formulation data Lens a b = Lens { get :: a -> b set :: a -> b -> a } The Advanced Formulation type Lens a b = forall f. Functor f => (a -> f a) -> (b -> f b) 24

Slide 34

Slide 34 text

What Have We Gained? ▶ Composition for free! set (it . boss . name) ”Grace Hopper” company ▶ Mocking for free! lenses are ordinary functions, so can be swapped out 25

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

Calculator Revisited data Expr a t = Literal a | Var t | Sum (Expr a t) (Expr a t) 27

Slide 37

Slide 37 text

Calculator Revisited data Expr a t = Literal a | Var t | Sum (Expr a t) (Expr a t) > :t Sum Sum :: Expr a t -> Expr a t -> Expr a t 27

Slide 38

Slide 38 text

Calculator Revisited data Expr a t where Literal :: a -> Expr a t Var :: t -> Expr a t Sum :: Expr a t -> Expr a t -> Expr a t 27

Slide 39

Slide 39 text

Calculator Revisited data Expr a t where Literal :: a -> Expr a t Var :: t -> Expr a t Sum :: Expr a t -> Expr a t -> Expr a t ▶ So far: Expr a t contains only a literals ▶ type a is constant in the whole expression ▶ What if we want heterogeneous operations? > :t even even :: Integral a => a -> Bool 27

Slide 40

Slide 40 text

Calculator Revisited data Expr a where Literal :: a -> Expr a Sum :: Expr a -> Expr a -> Expr a 27

Slide 41

Slide 41 text

Calculator Revisited data Expr a where Literal :: a -> Expr a Sum :: Num a => Expr a -> Expr a -> Expr a Even :: Integral a => Expr a -> Expr Bool 27

Slide 42

Slide 42 text

Calculator Revisited data Expr a where Literal :: a -> Expr a Sum :: Num a => Expr a -> Expr a -> Expr a Even :: Integral a => Expr a -> Expr Bool 27

Slide 43

Slide 43 text

Calculator Revisited data Expr a where Literal :: a -> Expr a Sum :: Num a => Expr a -> Expr a -> Expr a Even :: Integral a => Expr a -> Expr Bool 27

Slide 44

Slide 44 text

Calculator Revisited data Expr a where Literal :: a -> Expr a Sum :: Num a => Expr a -> Expr a -> Expr a Even :: Integral a => Expr a -> Expr Bool Cast :: (a -> b) -> Expr a -> Expr b 27

Slide 45

Slide 45 text

A Fancy Calculator ▶ we now have a datatype which represents (some) arithmetic operations ▶ Apart from evaluating, what can we do with it? 28

Slide 46

Slide 46 text

A Fancy Calculator ▶ we now have a datatype which represents (some) arithmetic operations ▶ Apart from evaluating, what can we do with it? ▶ print ▶ count operations ▶ optimize 28

Slide 47

Slide 47 text

A Fancy Calculator ▶ we now have a datatype which represents (some) arithmetic operations ▶ Apart from evaluating, what can we do with it? ▶ print ▶ count operations ▶ optimize 28

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

30

Slide 50

Slide 50 text

The Essence of IO ▶ a representation of a computation ▶ ... which interacts with the world 31

Slide 51

Slide 51 text

The Essence of IO ▶ a representation of a computation ▶ ... which interacts with the world 31

Slide 52

Slide 52 text

The Essence of IO ▶ a representation of a computation ▶ ... which interacts with the world ▶ in Haskell: may contain all sorts of effects ▶ in GHC: opaque, non-inspectable 31

Slide 53

Slide 53 text

The Essence of IO ▶ a representation of a computation ▶ ... which interacts with the world ▶ in Haskell: may contain all sorts of effects ▶ in GHC: opaque, non-inspectable ▶ but: a better world is possible 31

Slide 54

Slide 54 text

IO as a DSL ▶ calculator: datatype with one constructor per operation ▶ terminal application: datatype with one constructor per operation? ▶ read from standard input ▶ write to standard output 32

Slide 55

Slide 55 text

IO as a DSL ▶ calculator: datatype with one constructor per operation ▶ terminal application: datatype with one constructor per operation? ▶ read from standard input ▶ write to standard output ▶ open file ▶ read from file ▶ ... 32

Slide 56

Slide 56 text

IO as a DSL ▶ calculator: datatype with one constructor per operation ▶ terminal application: datatype with one constructor per operation? ▶ read from standard input ▶ write to standard output ▶ open file ▶ read from file ▶ ... 32

Slide 57

Slide 57 text

A Datatype for Terminal IO data Terminal a where ReadLine :: Terminal String WriteLine :: String -> Terminal () 33

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

Simulating IO type IO a = PauseT (State RealWorld) a data RealWorld = RealWorld { workDir :: FilePath , files :: Map File Text , isPermitted :: FilePath -> IOMode -> Bool , handles :: Map Handle HandleData , nextHandle :: Integer , user :: User , mvars :: Map Integer MValue , nextMVar :: Integer , writeHooks :: [Handle -> Text -> IO ()] } 35

Slide 60

Slide 60 text

Conclusion ▶ FP provides a set of techniques for abstraction over evaluation ▶ Use them! 36

Slide 61

Slide 61 text

Conclusion ▶ FP provides a set of techniques for abstraction over evaluation ▶ Use them! “ Premature evaluation is the root of all evil. ” 36

Slide 62

Slide 62 text

Q & A  larsr h  larsrh

Slide 63

Slide 63 text

Image Credits ▶ Manu Cornet, http://www.bonkersworld.net/building-software/ ▶ Randall Munroe, https://xkcd.com/1312/ ▶ Thomas Kluyver, Kyle Kelley, Brian E. Granger, https://github.com/ipython/xkcd-font 38