Outside-In Classicist TDD by Sandro Mancuso - Mars Rover
HTML-код
- Опубликовано: 8 сен 2024
- In this screencast Sandro Mancuso performs the Mars Rover kata using Classicist TDD but starting from outside, that means, the public interface of the main class (Rover). As in any good classicist approach to TDD, design decisions are done during the refactoring phase. This video shows that the outside-in approach to design is still relevant regardless which TDD style you prefer.
Sandro, loved the video. Do some more please :)
Waiting for more tdd katas :)
Amazing, I need to read the enum direction three times to fully understand what they do. 😆
Sandro, congrats for the video, just one question: in the Rover class, the move method wouldn’t violate the Command Query principle with a state change (this.direction) and a return in the method? Thanks in advance
Rule 7 says : wraps around if it reaches the end of the grid.
And in the test with 15 MM.. the output is 0:5:N. I imagined that it only moves forward in this scenario so maybe should be a switch in direction at every wrap. Otherwise the last 5 moves are in a moonwalking style and not mars roving one.
Really enjoy watching the video
So you interpreted it as the rover turning around when reaching the end of the grid, instead of wrapping the coordinate values?
Here's a different perspective:
While rover can take commands and commander can issue commands
Commander: issues command
Rover: moves
Here, the command string plays the role of the commander, while the grid plays the role of the rover.
The detailed logic can be implemented within the above methods.
I don't know if I misunderstood the specification, but I believed that we should report where the obstacle was, not the position and direction from where we found an obstacle while moving 1 step in this direction from this position.
If this was the case, the function could continue to return the next position following the given direction.
Then the grid could allow the client to check if there is an obstacle in a specific position or the obstacles could be orthogonal to the grid and the obstacle logic could be at the rover logic, not at the grid logic, I don't know.
We could have a grid and a grid with obstacles. SRP.
Really enjoyed this. My only "thing" is, the rover starts in the bottom left (0,0) and the grid goes to 10,10 (assuming top-right) so that would make the grid 11 x 11 as the first row and column are zero?
Wouldn't it be better to implement a State pattern?
Have an interface called MooveDirection with:
- x
- y
- MooveDirection moove()
- MooveDirection rotateLeft()
- MooveDirection rotateRight()
Then have MooveLeft : MooveDirection
...
I don't see any particular benefit of using a state pattern here, it seems to over-engineer things. The enum extracts the left and right functionality out. If in the future additional directions were added, you would then have to go to multiple other Directions to account for the new Direction. Seems to make much more sense to keep the directions in one place, it is just as easy, if not easier, to add more directions in the future using an enum.
I believe the spec suggests to stop executing the commands once you encounter an obstacle. In such case you could add one more use case to "stop_at_obstacle". Eg: "RMML", "O:1:0:E" - L should not be executed as there's an obstacle at the second "M"
Nope. Specs clear in it. "...rover moves up to the last possible point". So if your "move" reach obstacle, rover stops, but it not prevent rover from rotaiting and further moving.
Even if you follow that spec, this solution is still wrong... because if the rover is able to rotate and THEN does indeed manage a successful movement, the obstacleString would be overriden.
Thanks for your videos. Its always helpful to watch others code and express their thoughts.
I would suggest to also include mixed tests. For example in the end it would be interesting if you are ok with the behaviour of the rover when the way is curvy and there is an obstacle on the way. You rover will hit the obstacle for a while, than turn and drive away. That would be potentially fatal for a mars rover, as it would drive a completely different route than it was intended ;-)
May be command sequence generated by pathfinding algorithm. Or this rover built for maze solving problem on Mars ))) Launch and forget. It is nothing about it in requirements.
@@olegdvd Actually the specification says the rover should report the last possible position of the route. So it is a mistake to continue driving afterwards. ;-)
Not stopping the processing when an obstacle is encountered is a clear miss of the specs... :) The rover will happily turn on and eventually move on...
Specs clear in it. "...rover moves up to the last possible point". Verb Move != Stop
Yes, but the obstacleString would be overwritten if there is a successful move operation.