Setting class fields and then modifying them in in methods - java

I dont get to write java frequently and when i do its usually expanding others code so I apologize for the basic nature of this question. I have a class that is used to test another application. each method in this class is an individual test. there are hundreds of tests in this class. as this class evolved, each new method was cloned, so there wasn't a lot of foresight into the overall design. Im trying to refactor this class so to make it easier to maintain.
So for the question - Each method has a block of code that populates 2 string arrays. Array 1 is a list of things you want turned on. Array 2 is a list of things you want off. Those 2 arrays are passed into another method as parms. The problem is that if you create a new "thing you want on/off" you have to set it in each method. Id like to move array1 and array2 to properties. See the code example below
Public class MyClass{
String[] OnThings = {"Thing1", "Thing2"}
String[] OffThings = {"Thing3"}
}
protected void Test1{
/**Below method iterates both arrays and turns things on or off**/
turnThingsOnOrOff(OnThings, OffThings)
/**Do a bunch of testing here**/
}
protected void Test2{
/**This particular test I want to turn off Thing 1**/
OnThings.Remove{"Thing1"}
OffThings.Add{"Thing1"}
turnThingsOnOfOff(OnThings, OffThings)
/**Do a bunch of testing here**/
}
As the code currently exists, if you to add a new thing (Thing4) and test it in every test, you have to go into each of the 100's of methods and add it to the list of "OnThings"
With the proposed code, you just add Thing4 once to the class property and it will run in all the tests. If you want turn if off for a few tests, then you can go modify those methods using .Add and .Remove.
Currently , the array of strings do not seem to support Add or Remove

Make the onThings and offThings properties static so you will be able to use them outside the class without creating new object each time.
Also, if you want to add or remove data from the arrays, use ArrayList<String> instead of String[]. ArrayLists are dynamic in size and objects can be added or removed from them easily.
Here is the modified code :-
Public class MyClass{
public static ArrayList<String> OnThings = new ArrayList<String>(Arrays.asList("Thing1", "Thing2"));
public static ArrayList<String> OffThings = new ArrayList<String>(Arrays.asList("Thing3"));
}
protected void Test1{
/**Below method iterates both arrays and turns things on or off**/
turnThingsOnOrOff(MyClass.OnThings, MyClass.OffThings)
/**Do a bunch of testing here**/
}
protected void Test2{
/**This particular test I want to turn off Thing 1**/
OnThings.Remove{"Thing1"}
OffThings.Add{"Thing1"}
turnThingsOnOfOff(MyClass.OnThings, MyClass.OffThings)
/**Do a bunch of testing here**/
}
More about ArrayList can be found here.

Related

Side effects in Java methods

This might be a trivial question, but I need some clarification...
There is a book called Clean Code that says that our methods should be small, preferably up to 5-10 lines long. In order to achieve that we need to split our methods into smaller ones.
For instance, we may have someMethod() shown below. Let's say, modification of 'Example' takes 5 lines and I decide to move it into a separate method, modify 'Example' there and return it back to someMethod(). By doing this, someMethod() becomes smaller and easier to read. That's good, but there is a thing called "side effects" which says that we shouldn't pass an object to another method and modify it there. At least, I was told that it's a bad idea ) But I haven't seen anything prohibiting me from doing so in Clean Code.
public Example someMethod() {
// ... different lines here
Example example = new Example();
example = doSomethingHere(example, param1, param2, ...);
// ... different lines here
return example;
}
private Example doSomethingHere(Example example, 'some additional params here') {
// ... modify example's fields here ...
return example;
}
So, am I allowed to split the methods this way or such a side effect is prohibited and instead I should deal with a rather long-line method that definitely breaks Clean Code's rules talking about short methods?
UPDATED (more specific name for the sub-method)
public Example someMethod() {
// ... different lines here
Example example = new Example();
example = setExampleFields(example, param1, param2, ...);
// ... different lines here
return example;
}
private Example setExampleFields(Example example, 'some additional params here') {
// ... modify example's fields here ...
return example;
}
As JB Nizet commented, it's not actually a side effect if it's the only effect, so any blanket statement that "all side effects are bad" doesn't apply here.
Still, the main question stands: Is this (side) effect okay?
Talking about the principles first, side effects are, in general, dangerous for two reasons:
they make concurrency more difficult
they obscure/hide information
In your example, there is some information that is hidden. You could call this a potential side effect, and it can be exposed with a question: "Does this doSomethingHere method create a new object or modify the one I pass in?"
The answer is important, and even more so if it's a public method.
The answer should be trivial to find by reading the doSomethingHere method, especially if you're keeping your methods 'clean', but the information is nonetheless hidden/obscured.
In this specific case, I would make doSomethingHere return void. That way there's no potential for people to think that you've created a new object.
This is just a personal approach - I'm sure that plenty of developers say you should return the object you modify.
Alternatively, you can pick a 'good' method name. "modifyExampleInPlace" or "changeSomeFieldsInPlace" are pretty safe names for your specific example, imo.
we shouldn't pass an object to another method and modify it there.
Who says that? That is actually a good practice in order to split your function in a way that forms a "recipe" and have specific functions that know exactly how to populate your object properly.
What is not recommended (and probably the source where you got your recommendation misunderstood this rule) is defining a public API and modify the arguments. Users appreciate not having their arguments modified as it leads to less surprises. An example of that is passing arrays as arguments to methods.
When you define an object and pass it to an other method, method itself can modify the content of the object therein which may be unwanted in some cases. This is because you pass the reference(shallow copy) of the object to that method and method can modify that object.For example when you pass an Array, Arrays are objects, to a method, method can change the content of the Array which may not be what the caller method expects.
public static void main(String[] args){
int[] arr= {1,2,3,4};
y(arr);
//After the method arr is changed
}
public void y(int[] comingArray){
comingArray[0] = 10;
}
To make sure the values of Array cannot be changed, deep copy of the Array should be sent to method which is another story
However this is not the case when you use primite types(int, float etc.)
public static void main(String[] args){
int a= 1
y(a);
//After the method a is not changed
}
public void y(int comingInt){
comingInt = 5;
}
Due to the nature of the Objects, you should be carefulTo learn more about shallow copy and deep copy https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm

Difference in passing an object to an arraylist (initializing once and more than once)

This is my main class MainClass and it has an arraylist MyList. I created an object for ExtractClass [not shown] extract and added it to my MyList. There is also another class PressClass [not shown]
public class MainClass {
public static void main(String[] args) {
ArrayList<ExtractClass> MyList = new ArrayList<ExtractClass>();
ExtractClass Extract = new ExtractClass();
MyList.add(Extract);
MyList.add(Extract);
PressClass Press = new PressClass();
Press.pressMethod(MyList);
}
}
Here is another version of the above program. I have initialized an object Extract and then added to MyList and i repeated it once more.
public class trailclass {
public static void main(String[] args) {
ArrayList<ExtractClass> MyList = new ArrayList<ExtractClass>();
ExtractClass Extract;
Extract = new ExtractClass();
MyList.add(Extract);
Extract = new ExtractClass();
MyList.add(Extract);
PressClass Press = new PressClass();
Press.pressMethod(MyList);
}
}
I got the same output for both programs. What is the difference between both? Does any of the above two codes breaks the rules of java? As a developer, which piece of code does one prefer?
It depends on what you try to achieve...
In the first snippet you are adding the same ExtractClass instance twice to the list and in the second code snippet you are adding 2 different ExtractClass instances to the list. As I am not aware to the internals of your ExtractClass I can determine which of the codes is "right".
Simple answer is that you are creating two objects, one of which you don't need. The garbage collector wont destroy it however because it is in the ArrayList MyList so a reference to it is still reachable.
In the first example the same object is being added to an ArrayList twice. In the second example, an object is made and added to to the ArrayList. After that, a new object is created and it too is added tot he ArrayList. The objects may have the same values (However you made your constructor) but the references are different.
If you want more explanation please ask.
What is the difference between both?
Firt one creates one single object and add it twice to the list
In the second you create two different(1) objects and add each one once to the list, this is what actualy you will in most cases intend to do.
Does any of the above two codes breaks the rules of java?
Technically not. List allows the same object to appear more than one time in it. Semantically, it depends whether it is your intetion to have the same object more than one time in the list or not.
As a developer, which piece of code does one prefer?
In general you mean the have the second version.
(1) different depends on your implementation of hashCode and equals. The defaults from the base class Object just dows a reference check. So the different instances will not be equal and thus different. You can see the impact of this when you use the List#contains method. Depending on your implementation of the former methods and on which instance you pass to it you may get different results.
The presented 2 solutions are not the same. The first adds the same object twice to the list while the second adds 2 different instances to the list.
Btw initializing a local variable in the same line is more compact and you should prefer that if it is a simple object creation:
ExtractClass Extract = new ExtractClass();
Also note that if you don't use the local variable, you can simply leave that out and add directly to the list:
MyList.add(new ExtractClass());
Also by convention you should start your variable names with lowercased letters and start your types (e.g. class name) with uppercased letter.
As per your current Implementation Both programs would work because you are adding object new ExtractClass()
with default implemnentation in the list. First program adds same object twice while the second adds 2 different instances to the list.
If you have scenario where ExtarctClass constructor accepts some parameter lets say File destDir you will be left with second Option because you may have to provide different destDir for different objects
with said above your second program would look like below
public class trailclass {
public static void main(String[] args) {
ArrayList<ExtractClass> MyList = new ArrayList<ExtractClass>();
ExtractClass Extract;
Extract = new ExtractClass(new File("c:\temp"));
MyList.add(Extract);
Extract = new ExtractClass(new File("c:\temp"));
MyList.add(Extract);
PressClass Press = new PressClass();
Press.pressMethod(MyList);
}
}
This can further be written as below
public class trailclass {
public static void main(String[] args) {
ArrayList<ExtractClass> MyList = new ArrayList<ExtractClass>();
MyList.add(new ExtractClass(new File("c:\temp")));
MyList.add(new ExtractClass(new File("c:\temp")));
PressClass Press = new PressClass();
Press.pressMethod(MyList);
}
}

How do I unit test adding to a collection in Java?

I'm still coming to terms with unit testing certain things and I have a question about my JUnit test for a relatively simple class:
public class Kite {
private List<String> strings = new ArrayList<String>();
public void addString(String string) { //... }
public void removeString(String string) { //... }
public List<String> getStrings() { //... }
public int getNumStrings() { //... }
}
In this case I would like to test all four methods. However the tests, now that I've written them, are all very similar. They (excluding the remove) all follow the basic structure of add a String to a Kite and then checking the number of Strings in the Kite object.
Is there a better way to test these "CRUD" types of methods?
Do I need to test them?
It's better to be more specific in your testing. For addString(), you want to test that:
The string you added is present in the collection.
No other strings were added to the collection as a side effect.
If you pass null to addString(), an IllegalArgumentException (or whatever the behavior should be) is thrown
If you pass the same string in twice, the behavior is what you want (could be an IllegalArgumentException, could be a no-op)
get the idea? You want to add tests for edge cases, as well as the normal behavior (sometimes called the "happy path"). Think about your tests in terms of possible inputs, possible outputs, and code paths that can be taken.
I would think about writing one test that models a transaction:
Check the pre-condition.
Perform add operation.
Check post-condition.
Rollback add operation with remove.
Make sure that Kite is in original state.
All those methods will be tested that way.

jUnit test for addAll method

For my assignment, I have to develop several jUnit tests for the method:
addAll(int index, Collection c)
This method is part of the class ArrayList - built in to java.
I figured out how to create the tests and run them in Eclipse IDE, but I'm a little confused as to exactly how I'm supposed to develop the tests. Could I get an example that includes what I should have in a #before, #beforeClass, #after, #test method?
To make this clear, I understand the format of the methods...I just don't understand HOW to test this method.
http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html#addAll(java.util.Collection)
So, what you need to test is that the method inserts all the elements in the passed Collection and that it inserts them into the appropriate position in the ArrayList.
Think of all the possible senerios and test each one.
start with empty arraylist
pass empty collection
use index of 0
use index > 0
etc, etc...
After the add, verify / assert that the ArrayList now has all the elements that it should have in the correct order / locations.
Also test the error cases with #Test(expected=...).
index < 0
index > arrayList.size()
null collection
come up with other ideas
Also... assertThat in combination with Hamcrest's IsIterableContainingInOrder would be helpful for verification.
You will need to think of the behaviour you want to test, and then create a number of methods annotated with #Test to test aspects of that behaviour. Think about how should addAll behave. For example, if a collection passed to it, and an index of 0, then it should add all those elements in index 0 of ArrayList, followed by previously existing objects. So, in your test method, create an ArrayList, stick some objects in it, create a collection (c), stick some objects in it, call addAll on your arrayList with index 0 and collection (c), and assert that it has done what it was supposed to do...
(That's just an example, I am not sure what is the exact expected behaviour of addAll in your case)
Even better take a look at the wikipedia article Vakimshaar posted :)
Stick with #Test and #Before Methods, the rest is probably not what you need.
Methods annotated with #Before get called every time before a method annotated with #Test is executed. You can use it to initialized stuff to a clean state which might be shared among multiple tests.
A starting point could be the following code (for more cases to test take a look at John's answer) and implement them yourself.
public class ArrayListTest {
public ArrayList<String> list;
#Before
public void before() {
// This the place where everything should be done to ensure a clean and
// consistent state of things to test
list = new ArrayList<String>();
}
#Test
public void testInsertIntoEmptyList() {
// do an insert at index 0 an verify that the size of the list is 1
}
#Test
public void testInsertIntoListWithMultipleItems() {
list.addAll(Arrays.asList("first", "second"));
list.addAll(1, Arrays.asList("afterFirst", "beforeSecond"));
// Verify that the list now contains the following elements
// "first", "afterFirst", "beforeSecond", "second"
List<String> theCompleteList = // put the expected list here
// Use Assert.assertEquals to ensure that list and theCompleteList are indeed the same
}
}
Use annotation #Test to mark test method that should return void and should not accept arguments.
For most usages this is enough. But if you want to run specific code before or after each test use implement appropriate method and mark them with #Before and #After annotation.
If you need some code that runs before or after test case (the class where you implement several tests) annotate appropriate methods using #BeforeClass and #AfterClass method. Pay attention that these methods must be static, so "before" method is executed event before the default constructor of your test case. You can use this fact if you wish too.

Does Java have a const reference equivalent?

Here's a snippet of code:
//Game board is made up of Squares. A player can place GamePieces on a Square.
public class CheckersBoard
{
public boolean PlaceGamePiece(GamePiece gamePiece, int nRow, int nColumn) {
return m_theGameBoard[nRow][nColumn].PlaceGamePiece(gamePiece);
}
private Square[][] m_theGameBoard;
}
Let say I'm testing the PlaceGamePiece method (using junit) and I need to access the m_theGameBoard so I can look at it and verify the GamePiece was placed on the correct Square and has the correct data.
In C++ I'd either make the test class a friend so it can access the private member m_theGameBoard, or I'd have a function that returns a const GameBoard that cannot be modified (because it's const):
const GameBoard& GetGameBoard() const { return m_theGameBoard; }
Now I can do what ever checking I want to do on the game board, but I can't modify the game board because it's const.
Java doesn't support returning const references or friend classes. So my question is what is the standard Java way of doing this?? Do I have to just provide a bunch of get accessors that allow me check the data on the Square?
UPDATE:
I ended up writing a GetPiece method as Kaleb Brasee suggested.
public GamePiece GetGamePiece(Point pt) {
return new GamePiece(m_theGameBoard[pt.GetRow()][pt.GetColumn()]);
}
Notice I create a new GamePiece object and return that. I'm not returning the GameBoards internal reference, therefore no one can modify the gameboard because they only have a copy! Nice! Thanks for the help guys, some really good advice.
FYI: I keep changing the names of the objects when I post them on here, sorry if that confused anyone.
Define the variable as protected, so that if the unit test is in the same package, it can access it.
However, I would just add a public method getPiece(int row, int col) that returns the piece on that square (or null if there's no piece there). It's likely you'll need a method like that anyway, and you could use it in your tests.
The default access modifier for a method or property is "package-protected", which means "visible only within my package". Therefore, you can emulate the semantics of "friendship", while maintaining a separate code base for tests, by having two distinct source folders, but with the same package structure.
src
|--com
|
--cchampion
|
--MyClass.java
tests
|--com
|
--cchampion
|
--TestMyClass.java
Then, within MyClass.java
public class MyClass {
private int nonTestedThing;
int[][] testedThing; // this is visible to TestMyClass
// or
// protected int[][] testedThing;
// if you want it visible to kids
}
This is not ideal in any respect, but it's one way to go about it.
Yes. Your choices basically boil down to either having:
Square getSquareAtLocation(int row, int col) { ... };
or using one of the Java collections which you could then pass through Collections.unmodifiableList(...)
(note that if you used a multidimensional List, you'd have to be careful to wrap the inner Lists as well to make sure they're not modifiable either)
If this is only ever going to be used for testing, you could also create a function that returns a deep copy of the array.

Categories

Resources