2

I use helper classes in my code. They are for example, displayHelper ( to open screens ) , resourceHelper (to get text resources) etc. I would like to not instantiate an instance every time. For that I created a common object which every class will extend

public class CommonObject {
     protected PropertiesManager properties = new  PropertiesManager();
     protected DisplayHelper displayHelper = new DisplayHelper();
}

A class will do this

public class AbcController extends CommonObject 

and in that class I can just use

displayHelper.openScreen(new AbcScreen());

this seems to work although I dont think this is the best way to do it. More over, I can't use this common object for classes which extend other classes.

What is the best practice to share common code across classes?

PS: I dont like using static or singletons because of the issues created which hinders proper unit testing. Dont want to use singletons because it holds state.

the solution has to work for Java 1.3 as I code mainly for blackberry

rfsk2010
  • 8,571
  • 4
  • 32
  • 46
  • use singleton class and use throughout the application – Biraj Zalavadia Dec 06 '13 at 09:43
  • Why don't you want to instantiate your helper classes each time? If there's no data in them, there's no overhead in having multiple instances of them. – Dawood ibn Kareem Dec 06 '13 at 09:45
  • @DavidWallace I don't want to instantiate every time, because each class which instantiates it needs to implement other interfaces as well to use some resource constants. I dont want to do the same thing for every class . I would like to do it once which is now possible with the code i have but i feel this is not the best practice. – rfsk2010 Dec 06 '13 at 09:57
  • No, just instantiate each helper when you use it. You don't need a great big wrapper around all your helpers. – Dawood ibn Kareem Dec 06 '13 at 09:58
  • And implementing an interface to get constants is an anti-pattern. Just use static imports for constants. – Dawood ibn Kareem Dec 06 '13 at 09:59
  • @DavidWallace I think instantiating everytime i use it is code duplication. If i add a parameter to the constructor, i will have to change it at multiple places. There are ways to avoid it, but for me it seems like code duplication. also, I cant use static imports as it is Java 1.3 – rfsk2010 Dec 06 '13 at 10:37
  • Who said anything about adding a parameter to the constructor? I don't see why you'd do that for a helper class - if it has data associated with it, it's not a helper any more. And instantiating one class is hardly code duplication. After all, that's kind of what classes are for! – Dawood ibn Kareem Dec 06 '13 at 10:40
  • 1
    Just for the record, I think BlackBerry development can be done using Java 1.4, not Java 1.3. – Peter Strange Dec 06 '13 at 12:19
  • 1
    Peter, Java 1.4 supports 'assert' which java-me does not support - Java 1.3 is the highest Java version supported by java-me devices, like BlackBerry and Nokia S40. – Michael Donohue Dec 06 '13 at 18:51
  • I stand corrected.. You set the compliance level as 1.4, but the Java language support is 1.3. See here: http://stackoverflow.com/questions/6092759/java-version-that-rim-used – Peter Strange Dec 07 '13 at 12:31

5 Answers5

2

Use static-methods. Example:

class RandomHelper {
    public static void doSomethingUseful() {
        //Do something
    }
}

This way you can call RandomHelper.doSomethingUseful() from everywhere where the class is visible.

LionC
  • 3,106
  • 1
  • 22
  • 31
  • ... thus creating a testability nightmare. See http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/ . So this is not a best practice at all. – Dawood ibn Kareem Dec 06 '13 at 09:41
  • @DavidWallace Concerning a design perspective this is exactly what static methods are for. Dont get me wrong I absolutely see the problems with Unit-testing them (e.g. not unit testing), but I think this is a problem of the concept of unit testing. – LionC Dec 06 '13 at 09:43
  • It's not about unit testing the static methods themselves; it's about unit testing code that uses them. – Dawood ibn Kareem Dec 06 '13 at 09:44
  • @DavidWallace There was a "with" missing in my comment, we talk about the same thing. Its just that I value design over pretty much everything else except performance if needed, and that by design I think there is no discussion that utility/helper whatever classes should have static methods. Testability gets hurt by it, but that is a whole other problem that has to be solved without hurting the design IMO – LionC Dec 06 '13 at 09:48
  • 1
    A design that hampers testability is a poor design. If you don't have testability, you don't have maintainability, and that means your design is frozen. – Dawood ibn Kareem Dec 06 '13 at 09:49
  • @DavidWallace True, but that is a problem of the testing concept we try to achieve combined with the programming language we try to achieve it with - not a problem of the basic concept of static methods, which is exactly what we need to have clean code that is self-expressing (if thats a word, english is not my native language) – LionC Dec 06 '13 at 09:51
  • But there is no need at all for static methods. Best here just to instantiate the class that has the methods, and to allow an instance to be injected at test time. This is just as clean, and just as expressive. Static methods (with the possible exception of one called "main") should never have been included in Java. – Dawood ibn Kareem Dec 06 '13 at 09:53
  • 1
    @DavidWallace Id like to discuss this more, but I think were kinda spamming comments with a discussion that isn't on topic enough, OP has decided that static is bad for his project because of unit testing so I do not think it will change stuff concerning this question – LionC Dec 06 '13 at 09:58
2

I know I kind of said this in my comments already, but here goes.

You do not need singletons. You do not need static methods. You do not need a dependency injection framework.

There is no need to avoid instantiating a class several times, especially if it doesn't have any fields. The "best practice" that you're looking for is that every class that needs one of the helpers should have a field whose type is the appropriate helper.

Instantiate those fields, either in the constructor, or in static initialisation. Also provide a setter for each of them. In other words, you might have this.

public class someClass {
    private MyHelper myHelper = new MyHelper();

    void setMyHelper(MyHelper myHelper){
        this.myHelper = myHelper;
    }

    // ...
}

Then if you want to mock the helper, you can use the setter to inject a mock into the class when you test it.

There is no reason not to do this. I guess it's kind of a "roll your own" dependency injection. But if you don't want to have the overhead of using Spring, this can be useful.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
  • I think instantiating everytime i use it is code duplication. If i add a parameter to the constructor, i will have to change it at multiple places. There are ways to avoid it, but for me it seems like code duplication. also, I cant use static imports as it is Java 1.3 – rfsk2010 Dec 06 '13 at 10:38
  • OK, but even without static imports, you can keep your constants in a class. You just have to qualify their names when you refer to them. It's OK to use `static` for constants and other fields, as this doesn't really have a testability impact. Just avoid using `static` for methods. – Dawood ibn Kareem Dec 06 '13 at 10:50
  • There are some reasons not to do this. Don't give a method 1 parameter when 0 will do. No need to put a class (the Helper) in `someClass`'s public interface, when only referring to it in the implementation will do. No need to call a constructor for an object that will have no state. This is a question about mobile java. `new`ing up objects can matter in mobile, if it happens a lot. The article you link to above, trying to use `Math.abs()` as an example, is flawed. Trying to gin up unit test code that avoids running the real `Math.abs()` is unnecessary, and may actually cause problems. – Nate Dec 07 '13 at 01:55
  • @Nate I don't agree with all of your comments, but you did point out one error. There is no need to make the setter public, if it will only be used for testing. Package-private will do. I have edited my answer accordingly. – Dawood ibn Kareem Dec 07 '13 at 06:42
  • 1
    This is a classical example of using a sword where a needle is required. Probably what you say may be fine for a J2EE project or an API. However, most BlackBerry apps are way smaller and easier to test. Static methods that do not change the application state are no different from inline code. If you think all procedural code is bad, you should stop writing anything within a method block. – Adwiv Dec 12 '13 at 07:13
2

First of all, if you are developing for Blackberry then your unit-testing capabilities are already hindered.

Now to your question.

You clearly need to extract those instances from that class and put them elsewhere.

Don't like static vars? Ok.
Don't like singletons? Ok.

Then declare a regular instance variable and put it in a central place (like the main Application class or some context like that.

Mister Smith
  • 27,417
  • 21
  • 110
  • 193
0

Ever tried with static methods?

Something like:

public class DisplayHelper{
    public static void setUpDisplay(){
        ...
    }
}

The call for those methods is DisplayHelper.setUpDisplay()

Cemron
  • 1,443
  • 1
  • 12
  • 15
0

Singleton.

public class DisplayHelper
{
    private static volatile DisplayHelper instance = null;

    public static DisplayHelper getInstance()
    {
        if (instance == null)
        {
            synchronized (DisplayHelper.class)
            {
                if (instance == null)
                {
                    instance = new DisplayHelper();
                }
            }
        }
        return instance;
    }
}
Dimentar
  • 603
  • 7
  • 13
  • 1
    Dont want to use singleton due to the issues outlined here http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – rfsk2010 Dec 06 '13 at 09:54