"proper" way to handle "global" data

Discussion in 'Java' started by Aryeh M. Friedman, Dec 18, 2007.

  1. 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])
    Aryeh M. Friedman, Dec 18, 2007
    #1
    1. Advertising

  2. Aryeh M. Friedman

    Arne Vajhøj Guest

    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
    Arne Vajhøj, Dec 19, 2007
    #2
    1. Advertising

  3. Aryeh M. Friedman

    Daniel Pitts Guest

    Arne Vajhøj wrote:
    > 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 injection of the shared object.

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, Dec 19, 2007
    #3
  4. On Dec 18, 9:11 pm, Arne Vajhøj <> wrote:
    > 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


    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])
    Aryeh M. Friedman, Dec 19, 2007
    #4
  5. On Dec 18, 9:19 pm, Daniel Pitts
    <> wrote:
    > Arne Vajhøj wrote:
    > > 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"
    Aryeh M. Friedman, Dec 19, 2007
    #5
  6. Aryeh M. Friedman

    Arne Vajhøj Guest

    Aryeh M. Friedman wrote:
    > 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
    Arne Vajhøj, Dec 19, 2007
    #6
  7. Aryeh M. Friedman

    Arne Vajhøj Guest

    Aryeh M. Friedman wrote:
    > On Dec 18, 9:19 pm, Daniel Pitts
    > <> wrote:
    >> Arne Vajhøj wrote:
    >>> 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
    Arne Vajhøj, Dec 19, 2007
    #7
  8. On Dec 18, 10:42 pm, Arne Vajhøj <> wrote:
    > Aryeh M. Friedman wrote:
    > > 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");
    }
    Aryeh M. Friedman, Dec 19, 2007
    #8
  9. Aryeh M. Friedman

    Roedy Green Guest

    On Tue, 18 Dec 2007 03:24:05 -0800 (PST), "Aryeh M. Friedman"
    <> wrote, quoted or indirectly quoted someone
    who 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


    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

    --
    Roedy Green Canadian Mind Products
    The Java Glossary
    http://mindprod.com
    Roedy Green, Dec 19, 2007
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Garrick
    Replies:
    0
    Views:
    559
    Garrick
    Sep 27, 2005
  2. darrel
    Replies:
    4
    Views:
    552
    =?ISO-8859-1?Q?G=F6ran_Andersson?=
    May 5, 2006
  3. atv
    Replies:
    5
    Views:
    368
    Peter Shaggy Haywood
    Dec 1, 2003
  4. Replies:
    1
    Views:
    383
    Michael Ekstrand
    Aug 21, 2005
  5. Andrew Berg

    Proper way to handle errors in a module

    Andrew Berg, May 11, 2011, in forum: Python
    Replies:
    10
    Views:
    498
    Steven D'Aprano
    May 13, 2011
Loading...

Share This Page