In the last couple of weeks I spent a fair amount of time partially rewriting the Mars Rovers (source is here). I added a Swing UI so the rovers can be visually tracked.
Run it from command line
You can run it from the command line with
$ lein run
You can also overwrite the default number of rovers and the number of actions each can take before "freezing".
$ lein run ":rover-number 1000 :action-number 9999999"
It's a bit inelegant to use quotes, but I haven't had time yet to implement a proper command line interface.
UI
As you can see, the rovers seem to move in discrete steps instead of a continuous flow. This is partly due to the fact that the Swing panel is to refresh every time a Rover sends a position changed message to the Plateau, which triggers a message sent to the displaying component. We are talking about ~10,000 messages per second, so I had to introduce some sampling. You can read about it in one of the previous posts.
Performance
The number of moves taken by the Rovers is printed out to the console at every 10,000th move. With the default 100 Rovers on my MacBook Pro (16 GB 1600 MHz DDR3, 2.3 GHz Intel Core i7) this number is 740,000 in 20 seconds, so 37,000 moves per second. This many messages are running through the core.async channels. I don't know how the Scala actors perform, but seems to be pretty impressive. Once I tried with 10,000 Rovers, but all the cores jumped up to 100% and the cooling system started up so vigorously that I saw it better to kill the process. The max it seems to be able to take is 1,000 Rovers, but the number of moves per second is much lower in that case then the one with a 100.
Tests
Painfully lacking...
Next steps...
will be some better documentation, marking dead Rovers with different colours, tests, etc...
Tuesday, 28 October 2014
Thursday, 16 October 2014
Closures are the poor man's objects
I've heard this a lot without giving too much thought about it. But the Circuit Breaker made me contemplate the idea a bit. So....creating a stateful object in Clojure is actually pretty easy. The simplest I can think of is a unique id generator. This would look something like this in java
In Clojure
Of course it's a boring example so I've come up with another, slightly more interesting one, a simplified vending machine.
An epitome of applied Single Responsibility Principle. Does only one thing and hides its internals completely. Of course I could leverage dynamic typing to overload the function and perform any kind of other logic - getting information of the content, changing the state, whatever. I could make a mess, but I would have to awkwardly work against the language to do it.
In Clojure
Of course it's a boring example so I've come up with another, slightly more interesting one, a simplified vending machine.
An epitome of applied Single Responsibility Principle. Does only one thing and hides its internals completely. Of course I could leverage dynamic typing to overload the function and perform any kind of other logic - getting information of the content, changing the state, whatever. I could make a mess, but I would have to awkwardly work against the language to do it.
Wednesday, 15 October 2014
Immutable datastructures vs information hiding
One generally accepted OO-concept Rich Hickey challenges with Clojure is the wisdom of information hiding. In rich object models (one proposals of DDD for example) aggregates are encouraged to eschew exposing their internal structure.
As a simple example we can imagine we are to write a card game with multiple players. Any card game actually, the point is that the players have hole cards which they don't share with others. Not even with the rest of the code. This project implements a simplified Blackjack game what perfectly serves the purpose of this post. This is the class for the participating players.
The player doesn't expose her cards, which is fine for us. Now imagine we want to spice up our game with some fantasy elements. Some player can cast Spying Spells to peek into their opponents' hands. This is orthogonal to the existing functionality, so the code change preferably shouldn't touch the existing code. But it does, because we have to modify Player some way.
Thus the Player class now serves two independent features of the game.
In Clojure classes are not used, instead functions operate on associative information models (@Copyright Rich Hickey), namely maps, lists, vectors, sets. There is no information hiding, the player is represented something like this
The logic is decoupled from the data, thus we can avoid awkward things like creating a new View object, but because Clojure uses immutable data structure there is no harm exposing their details either. We can easily add new functionality too without touching existing code.
As a simple example we can imagine we are to write a card game with multiple players. Any card game actually, the point is that the players have hole cards which they don't share with others. Not even with the rest of the code. This project implements a simplified Blackjack game what perfectly serves the purpose of this post. This is the class for the participating players.
The player doesn't expose her cards, which is fine for us. Now imagine we want to spice up our game with some fantasy elements. Some player can cast Spying Spells to peek into their opponents' hands. This is orthogonal to the existing functionality, so the code change preferably shouldn't touch the existing code. But it does, because we have to modify Player some way.
Thus the Player class now serves two independent features of the game.
In Clojure classes are not used, instead functions operate on associative information models (@Copyright Rich Hickey), namely maps, lists, vectors, sets. There is no information hiding, the player is represented something like this
The logic is decoupled from the data, thus we can avoid awkward things like creating a new View object, but because Clojure uses immutable data structure there is no harm exposing their details either. We can easily add new functionality too without touching existing code.
Tuesday, 14 October 2014
Dynamic typing - Sampler filter
This post is superficially related to the basic concept of the previous, but shows a very similar pattern to Circuit Breaker. I call it Sampler filter, but I'm pretty sure there is an established name in the field of electrical engineering.
By implementing a Swing UI of my Mars Rover project (source code is here) I recently faced the problem that if I run hundreds of rovers, then refreshing the panel after every rover position change is impossible. Each position change puts an event - containing the positions for all rovers - on the channel the displayer logic listens to, and the messages just kept piling up. It's a typical IO bottleneck. So I decided it's enough to display every 100th or 1000th of them. They would change faster than my eyes can process them anyway. So I took the original function performing the display - repaint! - and wrapped it in a sampler. Here is the code
By implementing a Swing UI of my Mars Rover project (source code is here) I recently faced the problem that if I run hundreds of rovers, then refreshing the panel after every rover position change is impossible. Each position change puts an event - containing the positions for all rovers - on the channel the displayer logic listens to, and the messages just kept piling up. It's a typical IO bottleneck. So I decided it's enough to display every 100th or 1000th of them. They would change faster than my eyes can process them anyway. So I took the original function performing the display - repaint! - and wrapped it in a sampler. Here is the code
Labels:
Clojure
,
Dynamic typing
Thursday, 2 October 2014
Dynamic typing - Circuit breaker
Despite my fascination for Clojure I'm yet to be sold on dynamic typing. Frankly the most frustrating thing about Clojure for me is the constant struggle with the lack of static type check. What went wrong and where? There are no types to guide me nor auto-completion, and I feel I have to hold too much in my head instead of letting the IDE help me out so I can concentrate on the problem. I read quite often arguments like "dynamic typing gives you a much greater flexibility" and "the static type system is often in your way", but honestly I don't understand them. Probably because I never have done anything serious in a dynamically typed language. So I've embarked on a journey of deliberately looking for situations when dynamic typing clearly gives an advantage. Here I'd like to show the first (and so far the only) one I found. Before looking at the more complex task of writing a circuit breaker, I'd like to start with a simple one.
Now this logger is able to transform any function with the (Int, Int) => Int signature to a logging one. Which is cool, but not cool enough. For every signature it has to be reimplemented. In a dynamically typed language you can use the same logger function for all. But this logger is a quite boring example, so I'd like to show something that is really useful and practical, the...
...Circuit Breaker
Imagine you application has to call a lot of web services, but the systems on the other end are quite unreliable. Sometimes they respond, but they have the habit of being unavailable for short time windows. You wouldn't like to waste time and thread calling them the n-th time if they haven't been responsive for a while. Better to wait a bit, then try again later. This is where the Circuit Breaker can help.
The Clojure version is
An easy way to try it out is to find a function that is simple to call with arguments that will break it, and wrap it in the circuit-breaker. The arithmetic divison is the perfect candidate.
Circuit Breaker is a fascinating pattern for many reasons. First it shows a clean analog to physical engineering solutions, making software engineering look like real engineering, and also making it easy to understand. Second, from an ezoteric FP point of view, Circuit Breaker is like magical entity that swallows a "stupid" function and spits out its doppelganger, same in signature and behaviour, but with an extra "intelligence".
The reason why dynamic typing fits so well to circuit breaker, I think, is that the extra functionality it adds has nothing to do with what the function does, nor with its signature.
Logger wrapper
Imagine you'd like to log the call of some functions. In Scala or Clojure it's an easy thing to do with higher-order functions.
Now this logger is able to transform any function with the (Int, Int) => Int signature to a logging one. Which is cool, but not cool enough. For every signature it has to be reimplemented. In a dynamically typed language you can use the same logger function for all. But this logger is a quite boring example, so I'd like to show something that is really useful and practical, the...
...Circuit Breaker
Imagine you application has to call a lot of web services, but the systems on the other end are quite unreliable. Sometimes they respond, but they have the habit of being unavailable for short time windows. You wouldn't like to waste time and thread calling them the n-th time if they haven't been responsive for a while. Better to wait a bit, then try again later. This is where the Circuit Breaker can help.
The Clojure version is
An easy way to try it out is to find a function that is simple to call with arguments that will break it, and wrap it in the circuit-breaker. The arithmetic divison is the perfect candidate.
The reason why dynamic typing fits so well to circuit breaker, I think, is that the extra functionality it adds has nothing to do with what the function does, nor with its signature.
Labels:
Clojure
,
Dynamic typing
Subscribe to:
Posts
(
Atom
)