Showing posts with label LetsLearnJava. Show all posts
Showing posts with label LetsLearnJava. Show all posts

Wednesday, September 14, 2016

JAVA 22 - Methods aren't always pass by value

Well - I thought we were done!  The funny thing about learning, you never really are done.

Today before leaving, I have a conversation with one of our new developers who's learning Java about passing values to methods.

We covered this back a way ago here, where we passed primitive data types, and could see if we changed the value in the method, it didn't affect the value passed, because primitives are passed by value.  You can find the exact code on Github here.

My developer, David, was looking at this item on StackOverflow (it's a great source of information and worked-through problems, which always comes up in any Google search).

That example given seemed to be saying that if you pass an object, rather than just a primitive data type (integer, String etc), then you are passing the object by reference.  This means that any changes you make the to item you've been passed get made to the original object itself - you are NOT creating a copy as with primitive variables.

Even our more experienced developer was sure this was wrong.  I managed to talk them into looking at it from my perspective, in the only way that really matters - let's build it and find out!

We have the following simple dogClass to keep methods,



And the following variations of methods,



For these methods,

  • changeNameByString changes the value of a String that is passed to it
  • changeNameUsingMethod calls a method within the class to change the name
  • changeNameUsingAttribute changes the attribute itself, which I've naughtily left public (hey, it's an educational test, it's allowed for curiosity)
  • getNewDog assigns a newly declared dogClass to the object passed
  • returnNewDog returns a newly declared dogClass


Here's my test ...



And here's the result ...


So basically, if you pass an object to a method, and manipulate it, the changes will happen to the original [changeNameUsingMethod  & changeNameUsingAttribute ]

If you use the method to create a new object [getNewDog], that object will be lost, unless you return it, and assign the new object to the old one [returnNewDog].

If you pass an attribute for the method, then change it, those changes are lost when you leave the method - basically a copy is made [changeNameByString].

This was a really fun piece of learning for all of us.  It also highlights my testing approach to development - which is "find a way to test and check what happens - come up with variations, and see what happens".  Don't be so sure that something can't possibly happen - find evidence to prove or disprove.

If you're shocked with the result, then you've found an area to learn more about.  Target some study there.

And most of all, have fun!



Find this example here in Github.

Saturday, September 10, 2016

JAVA 21 - Get coding!

So that's it!  We've gone through a lot of theory and examples together.

Next steps?  Well maybe Alan Richardson's book on Java For Testers is a good start  if you've not picked it up already.  But above all else, get coding, get practicing, get learning.

The following are a set of ideas for you to try out as revision for what we've covered so far.  Try not to go back to my code, but do use the internet to look up functions - most programmers do!

Revision exercises


  1. Create a HelloWorld program
  2. Create a HelloWorld program, where "Hello World"is declared as a string printMe, and passed to be printed.
  3. Create a HelloWorld program. Declare "Hello"as string Str1, and "World" as string Str2.  How do you put them together into string printMe to be published?
  4. Create a method printHelloWorld, which does just that.
  5. Use a loop to call printHelloWorld 10 times.
  6. Create a functon called printGutenTag, which prints "Guten Tag".  Create a loop which prints "Hello World" on odd numbers, and "Guten Tag" on even numbers, using if statements.
  7. Create a class called Card which has two attributes "suite" and "value".  Create a method for setting these values, and for getting the value of the card.
  8. Create a class called CardDeck, which contains 52 cards.  Create a method to draw a card at random.
  9. Look up Conways Game Of Life.  Create a class for a cell, and a series of JUnit tests for it.
  10. Look at our recent examples of Game Of Life, Character Creation or Account User.  Add some more JUnit tests which include assertions.


Building on character creation

The customer wants the following addition to our character creation code.


[REQ_1]  Add a combat system onto our Character Creation.  Characters must first hit with their weapon, then wound.
[REQ_2]  To hit - characters must roll equal or under their fighting attribute if doing hand-to-hand or shooting if done with a ranged attack.  This roll is done on a D20 (20 sided dice, with 20 always high).
[REQ_3]  If the character has the skill martial arts for hand-to-hand or archery for ranged attacks, they get to reroll a failed miss if it occurs (but the next result stands as is).
[REQ_4]  If they roll a 1 to hit, it's an automatic wound (skip the to wound roll)
[REQ_5]  To wound - if the character rolls equal or under their strength, they cause the loss of 1 health from their opponent.
[REQ_6]  If they roll a 1, then they cause the loss of D6 health in a critical hit.

Add code to support the above, including any JUnit tests needed.


Building on Account User

Revisit our account user code.

[REQ_7]  It's been decided, users will now user have their username created for them.  Use the method from unique username to create their username automatically on creation.
[REQ_8]  Sometimes there's just too many audits to read through.  Create a method to print out only audits which contain a certain action/phrase and test it.


Add code to support the above, including any JUnit tests needed.

JAVA 20 - Customer Account

Just a disclaimer, the code I've produced here forms a working model of a customer account class to work with.  This is not intended to be a demonstrator of good design for a customer account management system, just a working model we can play around with.

In this last worked out example, we're going to create code for a customer account management system.

Our requirements


[REQ_1]  Users can register their account by providing us their username, an initial password, and their date of birth.

[REQ_2]  Throughout their lifetime with us, customers or people with admin privileges can add or change the following details to a customer account,
  • Full name
  • Mailing address
  • Email
  • Phone number

[REQ_3]  Only the account owner is able to change their password.

[REQ_4]  The username and date of birth are fixed at account creation, and cannot be amended.  In the rare case where someone has forgotten their own birthday, we'll get the value changed in the database.

[REQ_5]  Both the account owner and admins are able to view account details.

[REQ_6]  The account will be fully audited, including every time change of data, every time it's viewed, every time access is denied.  

[REQ_7]  Details of passwords will not be displayed, either within account details or in account view.

[REQ_8]  The account view will also list all audit events.


The solution

I'm not going to go into the same level of detail I have with previous projects.  The code can be found here on Github.

Probably the key thing to look at here is the AuditEvent class.



We have a whole List of these audit objects within our customer CustomerAccountClass.



We add a new AuditEvent for everything we do.



I have a pretty obvious method to check permissions when needed - it's assumed that the method receives the username of the person trying to perform the change.


I mentioned this in the comment in the constructor, but I added a List of admin staff usernames, who have permission to make changes.  The way I did that was a bit of a hack, but hey, I don't want to build a whole system for my demo here.



So when you run, this is a taste of what you get - quite neat!



Extension material

Create admin class

The adminStaff List included within the customer account class is ugly.  Create a class which contains a list of admin staff, and returns whether someone is authorised to make changes or not.

This will separate out between customer data & methods and admin data & methods, and so be considerably tidier.

Don't forget to declare this admin staff within your @Test methods.

Date of birth

I currently handle date of birth as a String, which was just for quick convenience.  Replace it with a date format, you will have to Google to find what types you can find in Java.

Tuesday, September 6, 2016

JAVA 19 - RPG Character Class

The following example is a class which allows you to create a role playing (RPG) character.  Below are the rules ...

Character attributes and skills
Character are given a name on creation, they are also set the following attributes,
  • Fighting - how good they are at close combat
  • Shooting - how good they are at ranged combat
  • Strength - how hard they can hit/pull back a bow
  • Health - their maximum health

In addition, they can have a list of skills or advantages that they've gained.
Character Level And Experience
All characters start at level 1, and as they go through they gain experience (XP).
Characters can spend 1000 XP to "level up" where they can either,
  • Increase an attribute by 1, to a maximum of 18.
  • Add a skill/advantage

This will increase their level by 1.
Taking damage/recovery
Characters have a status called current health.  This can only ever be the maximum of their health attribute.  However if they take damage, it will decrease.
If it falls to 0, they die.  However characters with the "cheat death" skill can fake their death, they have a 50% chance of being only mostly dead, and merely pining for the ffordes.  In which case they retain their last health point.
Characters can regenerate, gaining 2 x D6 current health back.  But this costs 100XP.  So don't spent it all, keep some in reserve.

Not surprisingly, this is our most complex piece of code yet ...

Attributes


Constructor



Not surprisingly, the constructor sets much of the attributes.  After creation, fighting/shooting/strength/health can only be changed through experience.

Print character sheet

It's useful to be able to see all the attributes ...


Add experience

Pretty simple - this adds experience to the character's pool.


Level up

Probably our most complex method to date - first of all it makes sure you have the 1000 experience to do this.

Then, if you've selected "Fighting", "Shooting", "Strength" or "Health", and these values are below 18, then they're increased.  In the case of health, your current health is also increased.

If you provide something other than these keywords, it assumes you are adding a skill, so adds to the list of skills.

You then have 1000 experience deducted, and your level increased by 1.



Add skill method is defined here ...


Wounds/healing/regeneration

Finally we have taking a wound, healing and regeneration, which are all here.  By now you should be getting good at reading this ...












The Disney Avenger Initiative

The world of the Disney comics is under threat from a whole lot of extraterrestrial threat - yeah, worse than this guy ...


So, agent Cobra Bubbles is calling in his own Avengers Initiative, and recruiting people with extra-ordinary abilities to be Planet Earth's first line of defense!



I'm going to use @Test methods to simulate some familiar Disney heroes for this RPG.

Mulan


Thanks to her extensive training, she is a highly skilled warrior,

  • Her fighting skill increases twice
  • She is proficient at cross-dressing
  • She has the martial arts skill
  • She is resilient, not taking defeat easily
  • She is a natural leader



Merida


A deadly shot with a bow, to put Robin Hood to shame ...



Tinkerbell


One of the lowest characters in terms of health, however her high strength reflects the increased damage from her magic.

She also has access to a magic wand and can fly.  Don't make her think unhappy thoughts.




Pocahontas

Give the girl a break, she was involved with Mel Gibson at one point.

Pocahontas excels at tracking, running and understanding foreign languages.  She's a pretty mean fighter when she wants to be as well.



Snow White

Because, y'know, kissing a supposedly "dead girl" isn't at all creepy is it?  Seriously, didn't your parents bring you up better than this?

No possum on earth can fake death quite like Snow White, she's also able to make animals do her bidding.  What kind of superpower is that?  I guess you've never seen The Birds then ...



Princess Jasmine



Her strength and health might seem abnormal, but this reflects how her pet tiger Rajah is always by her side protecting her.  She's also borrowed Aladdin's flying carpet.



Princess Ariel


Not only can she breath under water, she's really good at swimming.  She can also talk to the animals ... well the marine ones anyway.  Don't be surprised if her dad's got his very own Kraken - best be on her good side.



Queen Elsa


She has superb powers to control the realm of the ice and snow.  From the midnight sun, where the hot springs flow.

As you're probably aware, the cold doesn't bother her anyway.




The code for this can be found here on Github.

Does this need more tests?

Well, you might have noticed, I've got so swept up in character creation, that there are a lot more @Test methods especially using assertTrue and assertFalse needed to check some of that behaviour.

You're right - it needs them.  And guess who's going to do it?

JAVA 18 - Conway's Game Of Life example

Conway's Game Of Life is an algorithm used to simulate complex patterns - you can read more here.

We're going to build a class to enable us to reproduce the following logic for a single cell,

The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, alive or dead. Every cell interacts with its eight neighbours, which are the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:

  • Any live cell with fewer than two live neighbours dies, as if caused by under-population.
  • Any live cell with two or three live neighbours lives on to the next generation.
  • Any live cell with more than three live neighbours dies, as if by over-population.
  • Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
Attributes

For just a cell (all we're modelling at this point) there are two obvious attributes
  • isAlive - whether the cell is alive or not
  • numLiveNeighbours - the number of live neighbours the cell has


Methods - basic

I decided not to bother with complicated constructors and just use the basic one.  However I decided to "getter and setter" my attributes (make get and set methods for each).  This would allow me to configure a cell as I needed it configured.



Conway's Rules Method

This applies the above Conway's rules to the cell, and change the status.



Test it

The following are 3 @Test methods for my class - it really needs a lot more ...



I set up my cell, then assert it's in the state I expect.

The code is available in Github here.



Extension material

Create some more @Tests for this class.

Monday, September 5, 2016

JAVA 17 - Unique username example

As promised last time, with our theory covered over, I'm going to take you through a couple of additional examples to help you learn.

Today I'm looking at a very useful recipe I use both in Selenium Webdriver and in Monkey Tamper.

In a lot of projects you need a unique username when registering an account.  Generally I have a very disposable attitude to accounts - I like to use them, set as I want, then throw them away.

But typically you need a unique username - I know friends who will use a random generator, but that always has potential to go bad.



The getUniqueName will return a unique username specified by the Unix time in milliseconds.

I use the method System.currentTimeMillis() to get the number of milliseconds since January 1st 1970.  Note I have to use a long integer type for this.

Obviously I've not covered that method, but like you might have to, I used Google to find out what kind of library/methods are available.  I don't think there's a single textbook out there, even one of these, which covers everything you'd need!



Google is great as is StackOverflow - it can show you how the command works, or you might be able to find an example.

I then define the character sequence,

CharSequence css = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";

This is essentially an array of characters.  I find the length of this array by using css.length() which is similar to the .size() method we've used for ArrayLists.

I repeatedly perform a modulus calculation on the Unix time, dividing by the length of my character sequence.  This gives me any remainder, which I look up in the sequence to give me a character.

I build up a string of these characters as I find the modulus, then actually divide my Unix time, until it's all done.  This turns the time into a handy character sequence ... so for instance ...




I typically append a "User_" in front of this string.  For my system, I get an email for every registered user, so I can backtrace to find any accounts I've created quite easily.

This really useful piece of code can be found here on Github.

JAVA 16 - Classes ... within classes.

So far we've defined a class and even extended a class.

Once defined, you can use a class pretty much as you'd use any variable data types - meaning you can have classes which use classes within them.  You can also have arrays (or better, list arrays) of your class.

In this final part on Java theory, we're going to do just that!

I hate them dices to pieces


So far we've made a great class which simulates the action of a single dice.  But as mentioned, sometimes we need more than just another dice.

I want to keep the dice class as it is, simulating the random-ness of dice.  But I want to have a layer outside of that which will allow me to create groupings of dice.  And within this class I'm going to put a bit more of the rules of the game, and managing my expectations around multiple dice.

This class I'm calling diceGroupClass.

Attributes


In terms of attributes, one of the most important things is to declare a List for my dice.  I know it's going to be important to keep track of how many dice I have, and I did wonder if I should have a integer numDice attribute, but I can use the .size() method that's built into List to keep track of my dice quite easily.

Constructors


I'm expecting a number to be passed on creation of an object for this class - this number will defined the number of dice to be rolled in the group.  If no number is supplied, I'm going to assume it to be 2 dice, and call the constructor with it.

The constructor calls new ArrayList<diceClass>() to set up an ArrayList for the private attribute (though it's declared as the interface type of List in the variables section - see here for why).

It also passes the number of required dice to a function, setNumDice.

setNumDice



I had to have a big think about this - whether I wanted it to be private or public.  I decided to make it public, because I wanted to be able to dynamically change the number of dice I'm using (you'll see why later).

This method is passed the number of dice required, and compares with diceList.size(), then it either,
  • Uses a while loop to use the .add() method to add elements to the ArrayList until it's large enough
  • Uses a different while loop to use the .remove() method to remove elements from the ArrayList until it's small enough.

Yup - I know I'd typically pick on the ISTQB if they had a definition for a method that says .add() adds and .remove() removes.  But folks, it really is what-you-see-is-what-you-get there.

rollAllDice


This uses the really neat loop we've talked about previously for ArrayLists,

for(diceClass thisDice:diceList)

Will loop through each dice in our ArrayList, assigning the element to the handle thisDice.  We then use the .rollDice() method of that class to roll the dice.

sumAllDice


This rolls all the dice using the above method.  Then similar to rollAllDice, loops through each dice element, and adds the dice value to a running total, to get the sum of all the numbers on the dice.

getDiceOverThreshold


This is very similar to sumAllDice, but instead of the total, it uses the .diceOnOrOver method to compare each dice to a rollable number, and return 1 if the dice equals or exceeds.

I've not made a group method like this for .diceOnOrUnder - if you like, have a go.






@Test Roll two dice


Here I just simply want to roll 2 dice, and sum the result


@Test Warhammer Space Marine shooting simulator


This is a more complex test based on the rules of a game called Warhammer 40,000.

Ten Space Marines are shooting at Orks,
  • Each Space Marine gets 1 shot, which allows a dice roll
  • Each shot hits on a dice roll of 3+
  • For each hit you get, you re-roll and cause a wound on a roll of 4+


Here you can see I use the constructor to pass that I originally want 10 dice to be used, then set numHit to the results of the method .getDiceOverThreshold(3).

I then use .setNumDice to resize my group of dice, and re-roll them, using .getDiceOverThreshold(4) to find how many have causes a wound on a 4+ roll.


As always, my code can be found on Github here.









Congratulations if you're reading this, because you've come to the end of our theory.  I've managed to cover what I consider to be the core basics of Java over the last few weeks.  Remember this series is not everything you need to know, but enough to give you a taste of Java and to get exploring.  But most importantly to get you trying out these exercises, if you haven't been trying out some of these programs and modifying yourself, you're missing the main education to be had!

There's a few more things to cover off before we're done - I'm going to go through a couple more examples, then conclude the series with a set of things for you to try out yourself.