wk 6 Exercise 103: Birdwatchers database

230 views
Skip to first unread message

Drayton Kittel

unread,
Mar 24, 2016, 5:45:42 PM3/24/16
to mooc.fi
I was wondering about the notes from this exercise: 

Note1: Your program should use only one Scanner object, i.e., it is allowed to call new Scanner only once.


Note2: Do not save anything in static variables. The main method is executed by the tests multiple times so the use of static variables might cause problems.


Is this a requirement because we use TMC? When I test my code myself it works fine with multiple scanners. When I use TMC it fails due to too many scanners. Is this because TMC runs the program over and over and over to test it? Is having more than one scanner a bad practice? 

Jarmo Isotalo

unread,
Mar 25, 2016, 8:01:40 AM3/25/16
to Drayton Kittel, mooc.fi
1) It's basically a pitfall of every testing framework there is. However, we don't enforce it only because it breaks our tests, but because it's a terrible habit. 
Hope this won't be too confusing. I tried to keep it brief, and I failed...

Basically the first reason falls into design patterns, like dependency injection... What it basically means is that, maybe one day instead of using new Scanner(System.in) you maybe would like to get the input from a web application. 
Or from, say new Scanner(MyMagicalInputStream) or whatever. 

In ideal case, you are already programming to an interface and not to an implementation (like using Map<Foo,Bar> instead of HashMap<Foo,Bar> as the type of variables) it would only take a minor change to start using the alternative implementation. With the map example, you could just swap the new HashMap to new TreeMap.... (I won't now go the the differences of these two).

And with dependency injection, fancy term which basically is situations when you get e.g Scanner as constructor parameter. And the class whom constructor gets the scanner shouldn't really care what kind of a scanner is. It just knows that the scanner has these methods and that it can use it. What it doesn't know if it is  new Scanner(System.in) or new Scanner(MyMagicalInputStream)... 

Now, if your code inside various methods creates a new scanner when necessary, the dependency injection becomes closer to impossible. And now if you want to change the implementation of scanner (the new Scanner(...)) it requires changes in all of the places where you create a new Scanner. Anyways the class shouldn't care/know how to create the scanner...

Now saying that your object shouldn't care/know hot to create a scanner might be confusing. As somewhere in your code you probably still need to create the scanner? yes. But because of the single responsibility principle we could presume that in most of the cases the class using scanner, shouldn't know how to create it, but just have your main method (or whatever initiates all the classes) to also create a scanner and pass that around. 

However, often in these exercises, we have decided how the design should go, and sometimes we tell that use the scanner given as the constructor parameter or just let you create the scanner.

We could also compare reusing and passing the same scanner around vs. creating the new scanner frequently to this: It's like buying a new car for each part of your trip, when common sense tells you that it's perfectly ok to use the same car all the way.
(It's now a fancy quote, it's just something I came up with...)

2) I'll try to keep this more brief.

So this again presumes that you have something more complex than simple hello world app.
So let's assume scenario where we create multiple instances of a class. Now the static variables are shared among all the instances of the class (given the instances are inside the same JVM instance).


Now say we have private static List<Measurement> measurements = new ArrayList<Measurement>() in the class, and the first instance adds 10  measurements to the list. Now we create the second instance of the same class, what happens is that the second instance has already the 10 measurements created by the first instance.

MeasurementApp app = new MeasurementApp();
app.doStuff(); // generates 10 measurements
MeasurementApp myApp = new MeasurementApp();
myApp.getMeasurements(); // returns the measurements generated by the app.

So in most of the cases this kind of behaviour is unexpected and unwanted. 

-Jarmo


--
http://mooc.fi
---
You received this message because you are subscribed to the Google Groups "mooc.fi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to moocfi+un...@googlegroups.com.
To post to this group, send email to moo...@googlegroups.com.
Visit this group at https://groups.google.com/group/moocfi.
To view this discussion on the web visit https://groups.google.com/d/msgid/moocfi/f222a24f-0362-45ed-bb32-57baf018c6ca%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages