Saturday, September 21, 2019

Creating the Deck class

Last section we created tests for building our deck class. Now we are ready to create a deck class. Initially we will create the code within the testDeck.html file but once it is functional move the code into the Deck.js file so it can be used by our various card projects. While it is certainly possible to create the code entirely within the Deck.js file and import that file, for prototyping it is often faster to write the code within the test file and iterate over the code before moving it to the appropriate class as during prototyping the structure of the code may change multiple times so keeping it outside of the main code-base until it is stable can make maintaining the project easier.

This class needs to hold 52 cards in a deck, deal out those cards, and shuffle those cards. First, we are going to need to create the constructor function for this class. This will just create an array for itself to hold the deck and fill that array with in-order values. We also set the index for where we are going to grab cards to the top of the deck.

spelchan.Deck = function()
{
this.cardArray = [];//new Array(52);
for (var cntr = 0; cntr < 52; ++cntr)
this.cardArray[cntr] = cntr + 1;
this.nextCardIndex = 0;
}

This means that we now have a deck of cards but running the test will still fail. While the card ids are in the deck, the deal method is not dealing them out! Dealing out a card is simply the matter of returning the card at the nextCardIndex while increasing the index.

spelchan.Deck.prototype.draw = function()
{
var rv = this.cardArray[this.nextCardIndex];
++this.nextCardIndex;
return rv;
}

Running the tests now show us that we are getting there but the shuffling is not sufficiently random enough to pass our test. This is because we are not shuffling the deck yet. We are going to need a way of shuffling the deck. Think about the different ways to shuffle a deck. There are many ways of shuffling, but most of them are inefficient as far as the computer is concerned. What our goal is, simply stated, is to make the cards in the deck appear in a random order. I realized that taking each card and swapping it at random with another card would be a very good way of shuffling as the computer can do this blindingly fast with really good results. While I came up with this algorithm on my own, my Algorithms teacher did tell me that I was not the first person to think of this and that this is like the technique that shuffling machines use.

spelchan.Deck.prototype.shuffle = function()
{
var cntr, temp, rnd;

for (cntr = 0; cntr < 52; ++cntr)
{
rnd = Math.floor(Math.random() * 52);
temp = this.cardArray[cntr];
this.cardArray[cntr] = this.cardArray[rnd];
this.cardArray[rnd] = temp;
}
this.nextCardIndex = 0;
}

Now when we run the test we see that all the tests have passed. We are now ready to start planning the tests we will be needing for a video poker game. There are other things that we could probably add to this class, but I have discovered over my years that it is easy to refactor and to add things later, especially if you have a testing framework to verify your changes don’t break anything. One tenant of Extreme Programming is to only write the code that you need. We have all that we need for video poker, so next chapter we will start working on a video poker game!

Saturday, September 7, 2019

Test Driven Deck

While having a plan for testing your code is important, Test Driven Development (TDD) takes this to another level. The idea here is that you write automated tests before you start writing the code. When it is practical to do this, it is an incredibly good way of creating code. Planning tests gets you thinking about the code you are going to write – hopefully with an idea of the fringe cases that you are going to encounter. Writing the tests give you something to check the code against. All tests should initially fail, with a successful test likely indicating either an error with the test or an error with the test plan.

You then write the code and run it against the tests trying to pass one test at a time. Once you have passed all the tests and no missing tests have been discovered, you are finished the code and can start planning the tests for the next piece of code that you need to write. Having automated tests also means that it is easy to have the tests running frequently while you do other things and if something breaks then you know right away and as it is likely what you (or someone on your team) is currently working on, it will be trivial to fix the bug! Remember that in general the quicker you can find a bug, the less it will cost to fix it. This cost is in time, but can also be in money if the bug is in a production version and you have marketing and patching costs in addition to the cost of finding and fixing a bug.

We have a card class that can display any card, so what we need next is a deck of cards. This deck needs to be able to be shuffled and we need to be able to deal cards from the deck. So, how would we test such a beast?

In a sorted deck, the cards should be from 1 to 52 so simply drawing cards from a sorted deck and making sure they are in sequence would solve this problem. A shuffled deck, however, has two issues that we need to check for. First, we want to make sure that all the cards are in the shuffle (that we haven’t duplicated cards losing some cards or other similar problem). Next we want tom make sure the cards are not in order. Simply checking to see the card is different from its position in the deck will not work as we would expect that at least some of the time a randomly shuffled card would end up in the proper deck position. A good shuffle would have at least half the cards in a different position so simply counting how many cards don’t match would suffice most of the time.

As the deck class can be written without the card class, as it uses card IDs and not instances of cards, it is possible to write the deck class in its own html file which I called deckTest. This starts off with your typical html5 boilerplate followed by a simple version of the Deck class with none of the necessary methods implemented.



Deck JavaScript Test


test results go here





Now some of you may have noticed that there is a lot of test code here. This is the downside to test driven development. You will often end up with test code that is the same size as the code that you are testing, and sometimes even larger. The plus side is that you know your code works within the testing parameters and if you refactor or change code you will be able to check to make sure that nothing you have done is broken. Manual testing could have been done with a lot less code. As always there is a trade-off that must be made. In a solo environment, and possibly a small team, manual testing may be adequate and may be productive enough. As you start to get to larger teams, people inadvertently mucking up other people’s code happens a lot more often than you would expect.