Today was a really poor day for the user of our chessboard (no new feature!). BUT I’m quite satisfied with the progress made on the app structure and the development experience. Almost everything I mentioned yesterday has been implemented.
Redux and ducks
I started the day by setting up Redux. I decided to do this early because…
- it is much more convenient to hold the state of the application in one single store.
- it will be more convenient to handle user actions.
- it will allow time-travel between moves (something that chess.js doesn’t support).
- it allows me to conveniently test the app logic (by dispatching actions and comparing the expected state to the actual state.
To do so I installed the following libraries: redux, react-redux, immutable, redux-immutable, reselect, redux-devtools-extension. Then I refactored the currently very simple codebase to match the ‘ducks’ organisation, which I previously used on the ChineseMe project and found very convenient when scaling up.
Improved Game State
Instead of saving the full FEN string in the store, I decided to cut it into it’s six distinct parts. This will make it easier later to update the game situation based on user actions:
I use Reselect to recreate the full FEN string based on those six elements:
Testing the app logic
With this first ‘duck’ in place I can now develop the logic following a TDD approach. With Redux, the idea is quite simple: the only thing that can happen is user actions resulting in redux actions, which are handled by reducers, which update the state in the store. The UI then displays components by querying the store’s state via selectors.
This means that we can test that every part of the flow works as expected by creating tests that:
- Generate an action using an action creator
- Calculate the next state by passing the action to the reducer
- Get the next state via the appropriate selector
- Compare the next state to the expected state
With that in mind I wrote a failing test for a future ‘MOVE’ action:
As expected the test is currently failing since the position is not yet updated. I’ll handle the logic of the ‘MOVE’ action tomorrow:
Useful util functions
When handling user actions it will be more convenient to work at the square level. If we represent the board by an array of 64 strings, it’s easy to understand what ‘moving a piece’ means: moving elements within the array.
However as far of the app state is concern, it’s much more convenient to keep track of the position as a string. And it would be more convenient if a server was added to this project (a simple string is easier to save in a database than a JS array.
With that in mind I developed two useful util functions:
I followed a TDD approach to facilitate the development of those functions: