I wrote:The result will be either a tie when the computer and I make the same move, or I will win, or the computer will win.
Michael Bruce Allen wrote:I do not understand how you are not typing the name of the Enum before constants such as SCISSORS and methods such as beats. Unless somehow you made it static (if I know what I am talking about.) How did you do that?
Michael Bruce Allen wrote:Here is what I got so far. I am now thinking I should have a enum for game status such as WIN, LOSE, or TIE
Junilu Lacar wrote:Now, be honest, did you make sure to see your test fail before you made them pass? This is an important habit to form if you're going to do TDD. You should need to see your tests fail first. If you get comfortable seeing that green bar before you see a red bar, that's asking for trouble somewhere down the road.
Michael Bruce Allen wrote:
I wrote:
Your approach of first making beats() return true was correct. That made the test pass. The next step would be to add another test or assertion to show that ROCK.beats(SCISSORS) was not handled properly by the program code. This is the first aspect of variability that you tackle. When you run the test, you'd see a red bar. Then you'd add the if (this == ROCK && gesture == SCISSORS) "vice" to lock down that aspect of behavior. Run the test again and see it pass, green bar. Then you add another test or assertion for PAPER.beats(ROCK). You get a red bar again because your program code doesn't have that "vice". You put in the vice and get a green bar. Then add the final test or assertion for SCISSORS.beats(PAPER), see the red bar, add the correct check in the program code to get a green bar.
I wrote:
Michael Bruce Allen wrote:For your question above:
Do you understand why you would write ... instead of a full implementation of the algorithm?
I believe it is because in TDD, you want to write small incremental tests so that you do not jump ahead. So doing this caused me to make another test and it failed, causing me to question the next path to take and perhaps I might see something now that I wouldnt have if I had jumped the gun.
Junilu Lacar wrote:Another thing to note (I hope you don't get overwhelmed by all these points I'm making. Like I said, there's a lot more to think about when doing TDD than just the tests): there is a certain symmetry in the test names and the assertions being made. You should strive for symmetric code and names because it adds to the consistency of your program. The more consistent and symmetrical your program is, the easier it is to find inconsistencies and asymmetries which can harbor possible bugs or add to the cognitive load imposed on readers of the code.
Michael Bruce Allen wrote:
Now I am at a point where I am not liking the beats() method. I feel that asks for a boolean value and I do not think that is good enough. I would rather have a different name such as attacks (of course this may be a lame name) and I came up with that because you are essentially trying to win and there are 3 possibilities: You can either WIN, LOSE, or TIE. So I was thinking make a new enum for the result of the 'attack'. But am I thinking alright, even a little bit? This would mean that this test would call for writing a new enum and also writing a new method, and perhaps that is too much. So what should I do here? I have this idea. I want to refactor, I am not sure how to go about this. Even if this idea is bad, can you just go with me here because want to feel what it is like to go with a idea and do it properly with TDD. I am going to branch off at this point and experience and ill go back to the current branch when I get a good idea on how to go about this. Thank for everything.
Junilu Lacar wrote:On the other hand, if you feel strongly about an alternative idea or you have doubts about your current implementation, by all means go ahead and experiment. It's great that you're using source control and creating branches on which to experiment with alternative solutions. That's the mark of a smart engineer and it's a good habit to develop. The only caveat I would offer is that you should be able to recognize where the cost in your time and effort in investigating the alternative starts to outweigh the potential benefits you gain from it. Don't spend too much time chasing down a better solution if there is no substantial gain from doing so.
One way to keep your enthusiasm and creativity in check is to timebox your effort. Give yourself 30 minutes or an hour to explore the alternative. If you don't arrive at a significantly better solution in that time, go back to what was good enough before.
Again, here you should be using tests as the driving force. Write tests that show how the alternative would be better than the current solution. When those tests fail, implement your alternative solution to make them pass.
Michael Bruce Allen wrote:I have this idea. I want to refactor, I am not sure how to go about this. Even if this idea is bad, can you just go with me here because want to feel what it is like to go with a idea and do it properly with TDD
Michael Bruce Allen wrote:The problem is I have the logic code inside of the enum and it returns a boolean value of true or false. This is why I liked the idea of a enum to create three states of possible scoring. I would want the Gesture enum to return something other than a boolean.
Right now, I feel the code is not good the way I did it. The logic inside of the enum Gesture is returning a boolean which is only two values and of course I am not going to return null for a tie lol.
Michael Bruce Allen wrote:And again, where was the logic you are mentioning located?
Junilu Lacar wrote:
Michael Bruce Allen wrote:And again, where was the logic you are mentioning located?
In a class that uses Gesture, in a method that encapsulates the logic for one round of the game played.
Read that code and see if you can make out a story. Is that story clear and concise? Is it well-organized? Is it broken down into logic pieces and chunks?
Edit: refactored method tied to declareTie to make it more symmetrical with declareWinner
Junilu Lacar wrote:One refactoring I might perform to get to a better SLAP (Single Level of Abstraction Principle) is to extract method:
This makes the code in the oneTwoThreeShoot() method have a single level of abstraction and hides the details of the "judging" process in the declareResult() method.
Michael Bruce Allen wrote:
Are these ok test? None of them failed at all. But in TDD you write failing tests right?
Michael Bruce Allen wrote:Also, the next test I would want to do is a random pick for the computer test. How do I test something that has 3 possibilities?
Junilu Lacar wrote:
Michael Bruce Allen wrote:Also, the next test I would want to do is a random pick for the computer test. How do I test something that has 3 possibilities?
That's an interesting question. The math for this is probably governed by the Birthday Paradox so the number of tries you need to get to 100% certainty every time you run the test would probably be reasonably low given that you only have 3 possible values. Without doing the math, I'd guess that 500 tries would be enough to consistently get all three possible values through a pseudo-random generator. I'd probably do something like this:
To see the test fail, I'd start with a low number like 1 or 2 instead of 500 and slowly work my way up. I just ran this test about 20 times with 100 as the upper limit and got all green bars. I'm thinking that at least 500 times will make this test pass almost 100% of the time.
Edit: To make the test name be more consistent with the test assertion, I might refactor this to:
Using a Set rather than a List simplifies the code, too.
Yet another edit: One more refactoring to simplify (eliminate temporary variable).
There, that should be good enough.
Michael Bruce Allen wrote:For now, is HashSet used mostly with Enums?
Catch Ernie! Catch the egg! And catch this tiny ad too:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
|