Tuesday 16 September 2014

State in Functional Programming and OO

Just some musing...

In OO the global state, present in the old procedural programming, is broken up and the shards are moved into small, independent moving parts of the system, the objects. The objects don't expose their state, instead they expose behaviour. So the state disappears and and intricate net of acting agents fill its place. I have, like OO-fans, always seen this as an advantage, fascinated by the elegance of the transformation itself. But the disadvantage became obvious when I started learning FP. Since the state is obfuscated behind the objects' APIs, for a developer it can be hard to determine in exactly what state the system is. When I call a method on an object to return something it might send a message to another object or write into the DB and I won't know about it. Debugging is hard. Again I'm not sure it's a bad thing and I suppose sometimes it's good, e.g. in the case of logging. FP goes against this information hiding paradigm and promotes side-effect-free programming. Of course a program should have side-effects, otherwise what's the point? But FP forces the programmer to be very explicit about side-effects (= state changes). In an ideal FP architecture the inside of the onion is composed of pure functions and all the "impure stuff", like DB-operations, user input reading, web-service calling, etc, are in the outer layer, very visible, very explicit. So paradoxically, FB, being a state-shunning paradigm, is much more about the state than OO, which is about behaviour.

When I have some time and feel the creativity to do it, I'll append some examples.

Tuesday 2 September 2014

Mars Rovers in Clojure - Rewriting an Akka project to a Core Async one

I've decided to to reimplement Kaloz's Mars Rover Scala (for brevity's sake SMR from now on) project in Clojure (CMR). SMR is based on Actors of the Akka framework. Actors are the manifestation of the original idea of object orientation, that is, independent entities hiding their internal state and communicating via message passing. Since the whole model is purely about side effects, it seemed a nice challenge to implement in a functional way.
I wanted to have a jar as an end product that can be substituted to the backend of the original Scala, using the original presentation layer. I'm not there yet, but a first version is available on Github, where mars rovers can run in the REPL, spitting out their positions simply to the console.
All in all the project is a nice round 600 LOC. The Scala version had 548, which is not surprising. Scala, much like Clojure, is a very concise language, but because of its syntax you can compress the code more and still retain readability.

The main differences between SMR and CMR are
  • Instead of complecting state, identity and behavioural logic, the Clojure version uses pure functions to capture the behaviour.
  • All the "actors" have a receive method that takes the state of the "actor" and the received message (plus some additional information sometimes) and returns the new state with possibly a list of messages and executable effects. 
  • Context changes in actors are implemented in a surprisingly elegant way via multimethods. Different version of receive is called based on the state of the "actor"
  • The actors are simple atoms. The state of the atom is the input of the receive and the state part of the output is swap!-ed into it
  • The Clojure version, for the time being, lacks the distributed nature of Akka, and also its error handling mechanism. 
  • It uses the core.async for asynchronous communication. Where in the Scala version actors hold references to other actors, here channels are passed around
  • The architecture, not surprisingly, is quite different

Application = 75% pure functions + 6% glue + 8% application-level + 11% other

During the reimplementation I dissected the code to form 4 distinct parts. LOC-wise the sizes of these parts are
  1. 75% is pure, framework-neutral functional code. I moved all those source files under marsrover.pure package. 
  2. 6% is the glue, a mini messaging-framework I built over core.async in marsrover.glue.clj. In this "framework" a component's state is preserved in an atom. The component has an in-channel, an atom, and a function defining its behaviour. When a message arrives on the channel the component's state (value of the atom) and the message are the inputs of the behaviour function, and the output is the new state, the messages it has to send out, and possibly some effects. It's all very high level, doesn't know anything about our particular domain. 
  3. 8% is the application layer, it's in marsrover.app.clj. This takes the pure part and injects it in the glue
  4. 11% is other stuff like reading the expedition config (number of rovers, size of the plateau, etc).

So there is a big bulk of pure functional blob and a very thin layer glueing it together to form a proper application. I find this really fascinating. In the original Scala/Akka implementation the Akka framework and the logic was undisentangibly intertwined. Now the glue uses core.async, but if I wanted to use an actor-framework instead or any other approach, I would only need to change that 35 lines confined in a single source file. I say it again, it's fascinating. With functional approach we can push the framework/technology -related code to the outmost layer of our application, making it seem almost insignificant. The pure functions won't change if we want to move from the asynchronous model to synchronous, or replace core.async with any other integration solution. Imagine you'd wanna rewrite Mars Rovers in Scala, but not using Actors.

Finally, you can run the app by running marsrover.mars_expedition.clj in the REPL.