"proper" way to handle "global" data

A

Aryeh M. Friedman

If I have some piece of data that is used at arbitary times by an
arbitary method in the call stack and what ever it's value is is the
value globally (may change during the life of the executable)... for
example if I have a testing framework that sets some defaults (like
what type of test to run) at start up (the value comes from the
command line or has a hard coded value if not given on the command
line)... what is the "right" way of doing this... I also need to set
this to behavioral values like (make a dry run over a tree of tests
without actually running the test [used to count the size of the
tree... which is generated at runtime based on the call order])
 
A

Arne Vajhøj

Aryeh said:
If I have some piece of data that is used at arbitary times by an
arbitary method in the call stack and what ever it's value is is the
value globally (may change during the life of the executable)... for
example if I have a testing framework that sets some defaults (like
what type of test to run) at start up (the value comes from the
command line or has a hard coded value if not given on the command
line)... what is the "right" way of doing this... I also need to set
this to behavioral values like (make a dry run over a tree of tests
without actually running the test [used to count the size of the
tree... which is generated at runtime based on the call order])

To me it sounds as a good candidate for a singleton.

Arne
 
D

Daniel Pitts

Arne said:
Aryeh said:
If I have some piece of data that is used at arbitary times by an
arbitary method in the call stack and what ever it's value is is the
value globally (may change during the life of the executable)... for
example if I have a testing framework that sets some defaults (like
what type of test to run) at start up (the value comes from the
command line or has a hard coded value if not given on the command
line)... what is the "right" way of doing this... I also need to set
this to behavioral values like (make a dry run over a tree of tests
without actually running the test [used to count the size of the
tree... which is generated at runtime based on the call order])

To me it sounds as a good candidate for a singleton.

Arne
Or for dependency injection of the shared object.
 
A

Aryeh M. Friedman

Aryeh said:
If I have some piece of data that is used at arbitary times by an
arbitary method in the call stack and what ever it's value is is the
value globally (may change during the life of the executable)... for
example if I have a testing framework that sets some defaults (like
what type of test to run) at start up (the value comes from the
command line or has a hard coded value if not given on the command
line)... what is the "right" way of doing this... I also need to set
this to behavioral values like (make a dry run over a tree of tests
without actually running the test [used to count the size of the
tree... which is generated at runtime based on the call order])

To me it sounds as a good candidate for a singleton.

Arne

That is kind of how I was doing it currently:

public class Settings
{
public void addSetting(String key,Object val)
{
map.put(key,val);
}

public Object getSetting(String key)
{
return map.get(key);
}

private static Map<String,Object> map=new
HashMap<String,Object>();
}

even though this works I am starting to have bugs due to the fact the
data global.... for example when I go to count the number of tests in
a test set (so I can create a progress bar that actually shows
progress) the results get totally scrambled because each test has a
local copy of it's own the results and some other things (just in
typing this I realized that run() should not also construct the test
list [it will do it twice if you pre-count])
 
A

Aryeh M. Friedman

Arne said:
Aryeh said:
If I have some piece of data that is used at arbitary times by an
arbitary method in the call stack and what ever it's value is is the
value globally (may change during the life of the executable)... for
example if I have a testing framework that sets some defaults (like
what type of test to run) at start up (the value comes from the
command line or has a hard coded value if not given on the command
line)... what is the "right" way of doing this... I also need to set
this to behavioral values like (make a dry run over a tree of tests
without actually running the test [used to count the size of the
tree... which is generated at runtime based on the call order])
To me it sounds as a good candidate for a singleton.

Or for dependency injectiodependency injectionn of the shared object.

I just relized I sent the last two replies to you privately when I
meant to do so publically... so here it is again:

What is a "dependency injectiodependency"
 
A

Arne Vajhøj

Aryeh said:
public class Settings
{
public void addSetting(String key,Object val)
{
map.put(key,val);
}

public Object getSetting(String key)
{
return map.get(key);
}

private static Map<String,Object> map=new
HashMap<String,Object>();
}

even though this works I am starting to have bugs due to the fact the
data global.... for example when I go to count the number of tests in
a test set (so I can create a progress bar that actually shows
progress) the results get totally scrambled because each test has a
local copy of it's own the results and some other things (just in
typing this I realized that run() should not also construct the test
list [it will do it twice if you pre-count])

I am not sure that I understand your problem description.

But the non-static methods updating a static map look very
funky to me.

Arne
 
A

Arne Vajhøj

Aryeh said:
Arne said:
Aryeh M. Friedman wrote:
If I have some piece of data that is used at arbitary times by an
arbitary method in the call stack and what ever it's value is is the
value globally (may change during the life of the executable)... for
example if I have a testing framework that sets some defaults (like
what type of test to run) at start up (the value comes from the
command line or has a hard coded value if not given on the command
line)... what is the "right" way of doing this... I also need to set
this to behavioral values like (make a dry run over a tree of tests
without actually running the test [used to count the size of the
tree... which is generated at runtime based on the call order])
To me it sounds as a good candidate for a singleton.
Arne
Or for dependency injectiodependency injectionn of the shared object.

I just relized I sent the last two replies to you privately when I
meant to do so publically... so here it is again:

What is a "dependency injectiodependency"

My guess is that you can abbreviate it "Spring".

:)

Arne
 
A

Aryeh M. Friedman

Aryeh said:
public class Settings
{
public void addSetting(String key,Object val)
{
map.put(key,val);
}
public Object getSetting(String key)
{
return map.get(key);
}
private static Map<String,Object> map=new
HashMap<String,Object>();
}
even though this works I am starting to have bugs due to the fact the
data global.... for example when I go to count the number of tests in
a test set (so I can create a progress bar that actually shows
progress) the results get totally scrambled because each test has a
local copy of it's own the results and some other things (just in
typing this I realized that run() should not also construct the test
list [it will do it twice if you pre-count])

I am not sure that I understand your problem description.

But the non-static methods updating a static map look very
funky to me.


Since I am on a different machine then I wrote the example code from
memory the methods are static also. The problem was that if you write
something assuming no statics at all sometimes it get garbled when you
convert to a static is very a decent way to keep this from happening
(in this case like I said move the initialization to the ctor and
since that is only called once it solves the problem of double adding
some thins). Since I have since switched machines here is the cut and
pasted compile time version:

package dev.thistest.core;

import java.util.HashMap;
import java.util.Map;

public class Settings
{
public static void addSetting(String key,Object val)
{
init();
map.put(key,val);
}

public static Object getSetting(String key)
{
init();
return map.get(key);
}

public static Map<String,Object> getSettings()
{
init();
return map;
}

private static void init()
{
if(map!=null)
return;

map=new HashMap<String,Object>();
addSetting("RunTest",new Boolean(true));
}

private static Map<String,Object> map;
}

and here is a snippet of a working global in action (RunTest is buggy
right now):

in main():

if(args.length<1)
usage();

Class klass=Loader.load(args[0]);
Object inst=klass.newInstance();

Settings.addSetting("TestType",TestType.All);
Settings.addSetting("EventListener",this);

long start=System.nanoTime();
((Test) inst).run();
System.out.println();
System.out.println("Total running time (seconds): "+
((System.nanoTime()-start)/100000000.0));

printResults(((Test) inst).getResult());

How TestType is used in the actual test code:

private void runType(TestType type)
{
TestType defType=(TestType) Settings.getSetting("TestType");

for(Method m:this.getClass().getDeclaredMethods()) {
if(!canRun(m,type,defType))
continue;

try {
m.invoke(this);

if(type!=TestType.Setup)
getResult().addPass();
} catch(TestException e) {
getResult().addFail(e);
} catch(Throwable e) {
getResult().addNoResult(e);
}
}
}

private boolean canRun(Method m,TestType type,TestType defType)
{
TestCase ann=m.getAnnotation(TestCase.class);

if(ann==null||!Modifier.isPublic(m.getModifiers()))
return false;

if(!ann.value().equals(type))
return false;

if(defType!=TestType.All&&defType!=ann.value()&&ann.value()!
=TestType.Setup)
return false;

if(!(Boolean) Settings.getSetting("RunTest"))
return false;

return true;
}

and EventListener:

private void doTest(Event e)
{
if(report)
listener.testPerformed(e);
}

public Result(boolean report)
{
reset();
this.report=report;
}

public void reset()
{
pass=0;
fail=new ArrayList<TestException>();
noResult=new ArrayList<Throwable>();
listener=(EventListener) Settings.getSetting("EventListener");
}
 
R

Roedy Green

If I have some piece of data that is used at arbitary times by an
arbitary method in the call stack and what ever it's value is is the
value globally

Java likes to pretend it has no global variables, however it has
static variables. They need to belong to some class, perhaps a
universally accessible class with a name like Config.

see http://mindprod.com/jgloss/static.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top