Can a finite state machine work with persistence without breaking the FSM encapsulation? - oop

Say we have a (UK) Traffic Light simulation app and a class TrafficLight has an associated finite state machine defined as:-
* --> RED --> RED_AMBER --> GREEN --> AMBER --> RED --> ...
(repeat until the proverbial cows make an appearance )
On construction TrafficLight's state is RED
Some kind of time trigger causes a state change.
In the app there may be some code like ( removing any code that takes away from point ) ...
TrafficLight trafficLightsAtBigJunction = new TrafficLight(); // state = RED
trafficLightsAtBigJunction.setState( TrafficLightState.RED_AMBER );
trafficLightsAtBigJunction.setState( TrafficLightState.GREEN );
trafficLightsAtBigJunction.setState( TrafficLightState.AMBER );
trafficLightsAtBigJunction.setState( TrafficLightState.RED );
trafficLightsAtBigJunction.setState( TrafficLightState.RED_AMBER );
:
:
:
The crux is, using the state pattern to implement the state machine, if we do
TrafficLight trafficLightsAtBigJunction = new TrafficLight(); // state = RED
trafficLightsAtBigJunction.setState( TrafficLightState.GREEN ); // Exception!!!!!
an exception is thrown ( by our design ) because it's an illegal state move. That's what we want. Everything is good with the world.
However if we then persist the traffic light and it happens to be at state = AMBER say then there appears to be a problem. When our user comes back 3 days later to watch the awesome traffic light simulation it is restored from the current state in some ( who cares ) persistent store.
How do we get the traffic light instance to be in state AMBER without breaking the encapsulation that the state pattern provides here?
There appears to be 2 choices:-
(1) Create a new instance and run through the relevant states
(2) Provide a special method to set the state to whatever we want that, by convention, is only used after reading from some persistence store. e.g.
trafficLight.setStateAfterReadingFromPersistanceSource( AMBER );
Issue with (1) as I see it is that there may very well be side effects I don't want when running through the states, plus the logic could be quite complex depending on the state machine
Issue with (2) is obviously it only works by convention so could introduce a bug without knowing when incorrectly used. More importantly it pretty much breaks all your nice pattern encapsulating which is what you wanted in the first place.
The question is persistence technology agnostic - same issue with ORM, Files, serialisation etc
I'm assuming there is a solution here but I can't think of one myself and my googling skills have not been sufficient.
Any pointers would be great.

Implementing a state machine by representing states and transitions as objects is certainly possible, but those objects require initialization (which appears to be your problem) and take the precious RAM.
However, there is also a completely different way of implementing state machines as pure code. This has so many advantages that I would never go back to the "state machine as data" method.
For a specific example, the DDJ article "UML Statecharts at $10.99" at http://www.drdobbs.com/architecture-and-design/uml-statecharts-at-1099/188101799 shows exactly how to implement a Pedestrian LIght CONtrolled (PELICAN) crossing as a hierarchical state machine.
This example is coded in C for a low-end microcontroller. If you are interested in C++ implementation, you can take a look at the open source QP/C++ framework available from SourceForge.net at https://sourceforge.net/projects/qpc/files/QP_C%2B%2B/

The way I see it, you want two ways to manipulate the state:
1) Transition from this state to another state, performing all side effects of this transition, throwing exception if illegal, etc
2) Set the machine directly to a state/set of internal values. Do nothing else.
You should persist everything that describes the FSM's internal state and have two methods, one that does the former, one that does the latter.
The latter will be used when setting up or when unpersisting. It's also much simpler to code since it'll just be transferring values into variables without worrying about what else needs to happen.
The former will be used during simulation.

The simplest approach may just be to pass the initial state as a constructor parameter - it's only your convention that the system starts with all lights as red.
Another approach would be to make the function which pulls data from the store a friend or member ( depending whether you're using operator>> to read it or something else ). This gives you the option to either transition to a state as per your example, or read an initial state from a store. There isn't much ambiguity as to what is happening, and it's up to the FSM to pull its state and whatever else it needs to and from the store when persisting.

For the short answer I agree with Pete that, in this simplistic example, you can pass it as
a constructor arg.
But I honestly think the entire design is flawed. I would think this should be modeled using the standard State design pattern. Something like this:
class TrafficLight
{
private TrafficLightState _lightState;
TrafficLight(initialState)
{
// utilize lookup table or factory-method to assign _lightState with the correct TrafficLightState subclass
}
// UI can use this to identify/render the appropriate color
Color getColorCode()
{
return _lightState.getColorCode();
}
// UI uses this to know when to signal the next light change (each color can have different duration)
int getDuration()
{
return _lightState.getDuration();
}
// assuming the UI has a timer that is set based on the current light's duration
void changeLight()
{
TrafficLightState nextState = _lightState.onChangeLight();
_lightState = nextState;
}
}
abstract class TrafficLightState
{
abstract Color getColorCode()
abstract TrafficLightState onChangeLight()
abstract int getDuration()
}
class RedLight : TrafficLightState
{
Color getColorCode()
{
return Color.Red;
}
TrafficLightState onChangeLight()
{
return new RedAmberLight();
}
int getDuration()
{
return 30;
}
}
class RedAmberLight : TrafficLightState
{
Color getColorCode()
{
return Color.Orange;
}
TrafficLightState onChangeLight()
{
return new GreenLight();
}
int getDuration()
{
return 10;
}
}
class GreenLight: TrafficLightState
{
Color getColorCode()
{
return Color.Green;
}
TrafficLightState onChangeLight()
{
return new AmberLight();
}
int getDuration()
{
return 25;
}
}
class AmberLight: TrafficLightState
{
Color getColorCode()
{
return Color.Yellow;
}
TrafficLightState onChangeLight()
{
return new RedLight();
}
int getDuration()
{
return 10;
}
}
State machines should not have an explicitly-exposed "change state" method that is used to transition in normal operations. Instead, think of them as having stimuli that allow the state machine to transition its own state. In this example, the stimuli was very simple but normally you'd have a bank of possible inputs that can cause a state transition. But with proper encapsulation, the caller need not be overly aware of the details.

Related

How to nicely init state from database in Jetpack Compose?

I have a Jetpack Compose (desktop) app with a database, and I want to show some UI based on data from the db:
val data = remember { mutableStateListOf<Dto>() }
Column {
data.forEach { /* make UI */ }
}
My question is, at which point should I execute my database query to fill the list?
I could do
val data = remember { mutableStateListOf<Dto>() }
if (data.isEmpty()) data.addAll(database.queryDtos())
The isEmpty check is needed to prevent requerying on re-compose, so this is obviously not the way to go.
Another option would be
val data = remember {
val state = mutableStateListOf<Dto>()
state.addAll(database.queryDtos())
state
}
This way I can't reuse a database connection, since it's scoped inside the remember block. And queries should probably happen async, not inside this initializer
So, how to do this nicely?
In Android the cleanest way is using view model, and call such code in init.
In Desktop it depends on the operation. The main benefit of this platform is that there's no such thing as Android configuration change, so remember/LaunchedEffect are not gonna be re-created.
If the initialization code is not heavy, you can run it right inside remember.
val data = remember { database.queryDtos() }
In case you need to update the list later, add .toMutableStateList()
If it's something heavy, it's better to go for LaunchedEffect. It will have the same lifecycle as remember - run the containing code only the first time the view appears:
val data = remember { mutableStateListOf<Dto>() }
LaunchedEffect(Unit) {
data.addAll(database.queryDtos())
}

Bind listview to config sourced property

I'm attempting to follow the guide to try to persist multiple choices from two lists to config. (https://edvin.gitbooks.io/tornadofx-guide/part2/Config%20Settings%20and%20State.html). The guide only discusses SimpleStringProperty in this context. I can see that I should be using SimpleListProperty, but I don't see the right way to associate it with config.
My rough attempt so far:
data class Devices(val receivers: List<String>, val transmitters: List<String>)
// XXX I'd like to just persist Devices, but I'm exposing separate properties for the constituents of Devices
class DevicesModel: ItemViewModel<Devices>() {
// XXX type ends up as Property<ObservableList<JsonValue>>, which seems wrong
val receivers = bind { SimpleListProperty(this, "receivers", config.jsonArray("receivers")!!.toObservable()) }
val transmitters = bind { SimpleListProperty(this, "transmitters", config.jsonArray("transmitters")!!.toObservable()) }
}
class FooView: View() {
val devicesModel = DevicesModel()
// XXX this wants a ReadOnlyListProperty, rather than what it's getting
fun receivers() = listview<String>(devicesModel.receivers) {
selectionModel.selectionMode = SelectionMode.MULTIPLE
}
fun transmitters() = listview<String>(devicesModel.transmitters) {
selectionModel.selectionMode = SelectionMode.MULTIPLE
}
}
Obviously I haven't tackled commit etc, which I will. My question is about the binding/association specifically -- where have I gone wrong? My lack of JavaFX / UI programming background is probably hurting me here.
I have three questions marked with XXX in code, specifically:
I have a mismatch between the properties I'm exposing and the data class. I suppose this could be dealt with in the commit, but that seems messy.
The typing on the properties themselves (particularly JsonValue being exposed) seems wrong, but I don't see a way to expose what I'm looking for.
Why does listview() want a ReadOnlyListProperty? How do I make this accept an Observable?
I will post a PR to the guide with an example, and some clarifying explanation, once I get this working.

Communication between objects

If I have Game Class, which has Player object and Board object, Game asks Player what are the coordinates, Player responds, then game checks Board for the coordinates and the result either Hit or Miss.
How can Game forward the result back to Player? so that Player uses the result to set the new coordinates.
I have created code sample below to explain more what i want to do
and also a link to the project here: https://github.com/hythm7/Battleship/tree/master
#!/usr/bin/env perl6
enum Result < Miss Hit >;
class Player {
method fire ( ) {
(^10).pick, (^10).pick
}
}
class Board {
has #.cell = [ +Bool.pick xx ^10 ] xx ^10;
}
class Game {
has Board $.board = Board.new;
has Player $!player = Player.new;
method run ( ) {
loop {
my ($x, $y) = $!player.fire;
if $!board.cell[$y][$x] {
say Hit;
}
else {
say Miss;
}
# How to forward the above result (Hit or Miss) back to the Player object? so
# it can set $y, $x accordingly for the next call to $player.fire
sleep 1;
}
}
}
my $game = Game.new;
$game.run;
Let's see. The main question here is a design one, I think, so let's go for it from this angle. I want to note beforehand that I will describe just a single example of the approach: there are a lot of ways to do it, and I am writing out the simplest I can imagine that works. Also, for the sake of simplicity, code that deals with synchronization, graceful termination and so on is omitted.
Firstly, you have a player to be a separate thing, but in your code it reacts only when it is called from the outside. When it looks like a natural approach when implementing turn-based games, we still want to have some kind of communication. What if a player leaves? What if there is some error condition?
And as you noted the server wants to notify the player about outcome of the game. It seems like we want to have a bi-directional messaging between our Server and Player. Of course, if there is a One Server -> Many Players relation, it is another deal, but we will keep it simple.
Let's prepare some boilerplate code:
# We will get to this `Start` later
enum EventType <Start Hit Miss>;
# A handy class to hold a position, and likely some other data in the future
class Position {
has Int $.x;
has Int $.y;
}
# A board
class Board {
has #.cell = [ +Bool.pick xx ^10 ] xx ^10;
}
Now here is a server:
class Server {
has Board $!board = Board.new;
has Supply $.shots;
has Channel $.player;
method serve {
react {
# Whenever we get a shot coordinates, sent a Hit or Miss to the player
whenever $!shots -> Position $pos {
$!player.send($!board.cell[$pos.y][$pos.x] ?? Hit !! Miss);
# Don't forget to say "I am ready for new events" for the client
$!player.send(Start);
}
# Somebody should start first, and it will be a Server...
$!player.send(Start);
}
}
}
It has a board, and two other attributes - a Supply $.shots and a Channel $.player. If we want to tell something to our player, we are sending a message to the channel. At the same time, we want to know what player wants us to know, so we are listening on everything that comes from our $!shots async stream of values.
The serve method just does our logic - reacts to player's events.
Now to our Player:
class Player {
has Channel $.server;
has Supply $.events;
method play {
react {
whenever $!events {
when Start {
# Here can be user's input
# Simulate answer picking
sleep 1;
$!server.send: Position.new(x => (^10).pick, y => (^10).pick);
# Can be something like:
# my ($x, $y) = get.Int, get.Int;
# $!server.send: Position.new(:$x, :$y);
}
when Hit {
say "I hit that! +1 gold coin!";
}
when Miss {
say "No, that's a miss... -1 bullet!"
}
}
}
}
}
Player has a Channel and a Supply too, as we want a bi-directional relationship. $!server is used to send actions to the server and $!events provides us a stream of events back.
The play method is implemented this way: if the server says that it is ok with our action, we can made our move, if not - we are basically waiting, and when a Hit or Miss event appears, we react to it.
Now we want to tie those two together:
class Game {
has Server $!server;
has Player $!player;
method start {
my $server-to-player = Channel.new;
my $player-to-server = Channel.new;
$!server = Server.new(player => $server-to-player,
shots => $player-to-server.Supply);
$!player = Player.new(server => $player-to-server,
events => $server-to-player.Supply);
start $!server.serve;
sleep 1;
$!player.play;
}
}.new.start;
Firstly, we are creating two channels with self-contained names. Then we create both Server and Player with those channels reversed: player can send to the first one and listen to the second one, server can send to the second one and listen to the first one.
As react is a blocking construct, we cannot run both methods in the same thread, so we start a server in another thread. Then we sleep 1 second to make sure it serves us(that's a hack to avoid negotiation code in this already pretty long answer), and start the player (be it emulation or a real input, you can try both).
Modifying the handlers and the data types sent between Player and Server you can build more complex examples yourself.
One way to do it is to add a Board to the player. If you make it $.board then you get at least a public read accessor which you'll be able to use in the Game class and if you make it is rw you'll get a write accessor so you can just write it.
So, add the Board to Player:
class Player {
has Board $.board is rw = Board.new;
method fire ( ) {
(^10).pick, (^10).pick
}
(And for that to compile you'll need to move the Board class declaration above Player otherwise you'll get a Type 'Board' is not declared error.)
And now you can add a line like this somewhere in the Board class:
$!player.board.cell[$y][$x] = Hit; # or Miss
Also, you need to record one of three states in the cells of the player's board, not two -- Hit, Miss, or unknown. Maybe add Unknown to the enum and initialize the player's board with Unknowns.

Testing state machine transitions implemented as Map

I have a state machine with a relatively small set of states and inputs and I want to test the transitions exhaustively.
Transitions are coded using a Map<State, Map<Input, State>>, the code is something like this:
enum State {
S1,
// ...
}
enum Input {
I1,
// ...
}
class StateMachine {
State current;
Map<State, Map<Input, State>> transitions = {
S1: {
I1: S2,
// ...
},
// ...
};
State changeState(Input x) {
if (transitions[current] == null)
throw Error('Unknows state ${current}');
if (transitions[current][x] == null)
throw Error('Unknown transition from state ${current} with input ${x}');
current = transitions[current][x];
return current;
}
void execute() {
// ...
}
}
To test it I see 3 approaches:
1) Write lot of boilerplate code to check every single combination
2) Automate the tests creation: this seems a better approach to me, but this would end up using a structure that is identical to the Map used in the StateMachine. What should I do? Copy the Map in the test file or import it from the implementation file? The latter would make the test file depend on the implementation and doesn't seem a good idea.
3) Test Map for equality, same problem as before: equality with itself or with a copy? This approach is essentially what I do with the other 2 but doesn't seem like a canonical test
Maybe you want to have a look at this: https://www.itemis.com/en/yakindu/state-machine/documentation/user-guide/sctunit_test-driven_statechart_development_with_sctunit
It shows, how you can do a model based and test driven development of state machines including the option to generate unit test code and measuring the test coverage.

How would you avoid context/class explosion in this case with MSpec?

I love mspec. It is great for providing key examples in way that is easy to communicate with non technical people but sometimes I find it provides an unnecessary verbosity, specifically an explosion of classes.
Take the following example.
I want to model the movement of a knight piece in chess. Assuming the knight is not near any other piece or the boundaries of the board there are 8 possible moves that knight can have I want to cover each of these possibilities but to be frank I am too lazy to write 8 separate specifications (8 classes). I know that I can be clever with behaviours and inheritance but as I want to cover the 8 valid moves I cannot see how I can do it with out 8 becauses so therefore 8 separate classes.
What is the best way to cover these scenarios with mspec?
Some code.
public class Knight
{
public string Position {get; private set;}
public Knight(string startposition)
{
Position = startposition;
}
public void Move
{
// some logic in here that allows a valid move pattern and sets positions
}
}
What I might do.
[Subject(typeof(Knight),"Valid movement")]
public class when_moving_the_knight
{
Establish that = () => knight =new Knight("D4");
Because of = ()=> knight.Move("B3");
It should_update_position = ()=> knight.Position.ShouldEqual("B3");
It should_not_throw;
/// etc..
}
But not 8 times.
Honestly, I couldn't tell you the best way to do that in MSpec. But I've experienced a similar class explosion problem with MSpec when using it in similar circumstances. I don't know if you have ever tried RSpec. In RSpec contexts and specifications are built up within the confines of executable code. What that means is you can create a data structure, iterate on it, and create several contexts and specs using one block of code. This becomes especially handy when you are trying to specify how something based in mathematics behaves (prime factors,tic tac toe, chess, etc...). A single pattern of behavior can be specified across each member of a set of given and expected values.
This example is written in NSpec, a context/spec framework for C# modeled after RSpec. I purposefully left a failing spec. I just went down this kata far enough to find a place to use iteration. The failing spec forces you to resolve the shortcomings of the naive implementation.
Here's another example of prime factor kata: http://nspec.org/#dolambda
Output:
describe Knight
when moving 2 back and 1 left
when a knight at D4 is moved to B3
knight position should be B3
when a knight at C4 is moved to A3
knight position should be A3 - FAILED - String lengths are both 2. Strings differ at index 0., Expected: "A3", But was: "B3", -----------^
**** FAILURES ****
describe Knight. when moving 2 back and 1 left. when a knight at C4 is moved to A3. knight position should be A3.
String lengths are both 2. Strings differ at index 0., Expected: "A3", But was: "B3", -----------^
at ChessSpecs.describe_Knight.<>c__DisplayClass5.<when_moving_2_back_and_1_left>b__4() in c:\Users\matt\Documents\Visual Studio 2010\Projects\ChessSpecs\ChessSpecs\describe_Knight.cs:line 23
2 Examples, 1 Failed, 0 Pending
Code:
using System.Collections.Generic;
using NSpec;
class describe_Knight : nspec
{
void when_moving_2_back_and_1_left()
{
new Each<string,string> {
{"D4", "B3"},
{"C4", "A3"},
}.Do( (start, moveTo) =>
{
context["when a knight at {0} is moved to {1}".With(start,moveTo)] = () =>
{
before = () =>
{
knight = new Knight(start);
knight.Move(moveTo);
};
it["knight position should be {0}".With(moveTo)] = () => knight.Position.should_be(moveTo);
};
});
}
Knight knight;
}
class Knight
{
public Knight(string position)
{
Position = position;
}
public void Move(string position)
{
Position = "B3";
}
public string Position { get; set; }
}
Just use the Its the way you want to. It should be able to move from here to there, it should be able to move from here(2) to there(2), etc. Very common pattern in rspec but not so much in MSpec because it's generally overused so no one ever talks about it for fear of guiding the wrong way. This is a great spot to use this though. You're describing the behavior of the Knight's moving.
You can describe it even better by being more specific in your Its. It should be able to move up two and to the right one, it should be able to move up two and to the left one. It should not be able to move onto a friendly piece, etc.
Yes, you'll need to put more than one line of code in your It, but that's OK. At least in my opinion.
From what I see your design states that the Knight would throw an exception if moved in an invalid position. In this case I think that your method has two different responsibilities, one for checking a valid move and the other for doing the correct move or throwing. I would suggest to split your method into the two distinct responsibilities.
For this specific case I would extract a method for checking whether a move is valid or not, and then calling it from your move method. Something like that:
public class Knight
{
internal bool CanMove(string position)
{
// Positioning logic here which returns true or false
}
public void Move(string position)
{
if(CanMove(position))
// Actual code for move
else
// Throw an exception or whatever
}
}
this way you could test the logic inside CanMove for testing valid positions for a given Knight (which you can do with a single test class and different "It"s), then make just one test for the Move method to see if it fails when given an invalid position.