Chess TDD 56: Threatened Pieces
It’s been a while since my last post in this series, and for that I kind of apologize. Normally, I’m apologizing because I’ve had too much to do and it renders the reasoning a little disjoint. But this time, I took a break for the holidays and left off at a natural stopping point, so the disjoint-ness is kind of moot. I apologize only that it’s been a while, but I don’t feel culpable. Anyway, in this episode, I start to tackle the concept of check by tackling the slightly more abstract concept of “threatened pieces.”
What I accomplish in this clip:
- Moved on to working on the concept of check.
- Laid the foundation for a general evaluation of whether a square on the board is threatened.
Here are some lessons to take away:
- One of the best ways to keep things moving efficiently when coding is to find ways to slice off bits of new functionality in new classes. Getting back to TDD around a new class makes it very easy to implement functionality. The trick is in figuring out logical seams to do this, and that comes with time and practice.
- Classes without mutable state are a lot easier to reason about, to test, and to work with.
- Passing booleans into methods is a smell, because usually it means that you’re passing in a control flow concern to tell the method how to behave. In this episode, I have a boolean argument that is actually a conceptual piece of data, so it’s not problematic vis a vis the single responsibility principle, but it is, nevertheless, a smell to keep an eye on and to, perhaps, move away from later.
- During TDD, it is fine (and even expected) to do obtuse things to get the early tests to pass, but only if each thing that you’re doing advances you toward the eventual solution and is sequentially less obtuse. That part is critical.
- A good trailing indicator that you can use for whether or not you’re biting off too much implementation with each test is what happens when you finish your changes to the production code. Do all tests immediately go green, or do you have unexpected failures that cause you to need to tweak and tinker with the code that you’ve written. Immediate green is a sign you’re in the Goldilocks zone while tinkering is a sign that you’re biting off more than you can chew.
More big blasts of state checks.
I had a similar implementation but I have the methods directly on the models.
Square is responsible for taking the board and searching for any pieces that could target it.
https://github.com/colin-higgins/ChessSharp/blob/master/Chess.Data/Entities/Square.cs
https://github.com/colin-higgins/ChessSharp/blob/master/Chess.Data/Entities/ChessPiece.cs
Yours is nice and clean so far. I could definitely clean mine up, but I think I prefer having the nested loop for rows and squares. I thought that it was valuable context and did not violate single responsibility (Find threats).
Looking forward to see how this develops.
I like the Square abstraction — that’s a concept that hadn’t really occurred to me, at least not in the sense that it would be board-aware. What I can foresee developing for my own implementation here is a decoupling of move evaluation from Board. So, Board would have simple things like Add/Remove/Move for pieces. But then, there’d be some other entity that would examine the Board, maybe BoardEvaluator, and that is what would compute the moves. Board evaluator would then make use of “CastlingChecker” and “ThreatEvaluator” (or whatever I called those things). Off the cuff, this might get rid of… Read more »