µObject : Battleship
At Agile Open Northwest, I had the opportunity to explore µObjects through a battleship kata. I felt the environment and process doing it during the mobbing session were a bit more contrived than I normally work with. Fortunately the limited amount we got through did show some of the power along architecture that microObjects drive.
I'm curious how a full Battleship example in µObject will play out; as well as wanting to share it with others.
That's what we'll go through now. :)
I'm adding an extra twist for myself; I'm going to try to use ApprovalTests and that we used a bit at Agile Open mobbing sessions. I'm going to use it; probably not what I think is the proper way to use it; but to play with it. I also think that it'll be a good validation for battleship which is validation at a broad scale - the board scale.
First test I'm going to go for is a ship placed horizontally. Which I'm not going to do in a board. I'm just going to do the ship. This is where I'll probably deviate a bit from how Llewellyn describes the process and how he was demonstrating it. Maybe I'll hate it and which I hadn't done it like this. Gotta try stuff to figure out where it works and where it hurts.
The first tests is just a Aircraft Carrier horizontal. It passes by just returning AAAAA
.
Let's make a vertical version. At least force the use of the Orientation
value.
Currently the Aircraft is a hackjob
public class AircraftCarrier : IShip
{
private readonly IOrientation _orientation;
public AircraftCarrier(int horzCoord, int vertCoord, IOrientation orientation)
{
_orientation = orientation;
}
public override string ToString()
{
return _orientation.IsHorizontal() ? "AAAAA" : "A\nA\nA\nA\nA";
}
}
but it is passing.
I can see that starting from the board forces some of the broader constructs that just don't show until we're forced to interact with it differently.
In this case; we're not really looking to verify the WHOLE of the ship location; but from the board, it'll call a specific method to get the ships "value".
Let's update our tests to be this style instead. Working from the lower level does require a bit more churn to get all the API's into place. I think that working from the inside out delivers better structured code; so that's how I'm preferring to do it.
[TestMethod]
public void AircraftCarrierReturnsSpecifiedIndicatorForBeingAtPoint()
{
//Create an aircraft carrier at zero, zero horizontally
IShip subject = new AircraftCarrier(0, 0, Orientation.Horizontal);
IResult result = subject.At(0, 0);
Approvals.Verify(result);
}
The result is just a 'wrapper' around the "A"
. I could go with just a string... but that's boring; and not an interface. :)
This works; though I suspect I'm wholely abusing how Approvals should be used. I'm treating it like a Unit Test, not scenario test. Which... yep. I figured I'd be doing it like this; I've got my bias against outside-in testing.
Yep - Definitely using Approvals like I would FluentAssertions. I'm gonna roll off Approvals.
I think I'll use it for bigger scale; but I like inside out; and it's not the correct tool for this. Commit 0a684e49 is before Approvals removal.
Looking at the Aircraft class; I'm seeing a some relationships around the coords (surprise!), but also the size. These all are used together.
I want to introduce the vertical checking before doing the encapsulation; as it might tell me a better way.
I've shoved the "Hit Checking" into the Orientation. Not sure it fully belongs there; but I had it as
if(orientation.IsHorizontal()){
// do stuff
else{
// do other stuff
}
and that felt wrong. It still feels wrong in the orientation; but less so.
I renamed it to "ShipDetector". It makes more sense now.
I'm just kinda plugging along. This is the first time every doing Battleship; so I'm a little in the "solve the problem" phase.
Commit 4f7de85e has the final form of the Aircraft Carrier and ship so far.
At this point I feel I've got the ship pretty well set. There's a smell around the coordinates and the size - they have some kinda relationship; just not sure what yet.
I'm going to move onto the board and get that going. Maybe come back to the points later on; see if they make any more sense then.
There's a board at Commit 916ec15a now. It's using Approvals. That's a pretty clean way using what I have; though I'm a bit uncertain about how it's forcing some string-ification into the project.
I'm not super pleased with this result. It feels a bit cluttered. I'll need to do it again, maybe a couple times to get a better feel for it.
The coordinates stand out as an issue...
This will be sufficient for now. It's not HORRIBLE... but it's not as well done as I think it can/should be.
I'll do another soon; as I think it's a kata that has a little more intelligence capability which will put different pressure on the µObject concept.
I don't want to churn on this code and clutter it. It is a go at it. Not the best result; but a result. I'm seeing a lot of opportunity with Battleship to stress some of the "rules" for µObjects. Which I'm happy to have such a simple example that will allow that kinda investigation.
Code is available in my microBattleshipFirst repo.