0

(note: I used Java to make it easer to explain my question, but the actual language is irrelevant for this dilemma)

TL; DR: I have a wrapper around some underlying class. At which point should I instantiate the underlying class (in the constructor, in a separate method, on first use) and why?


Lets say, for example, that I want to create a simple class to read from a file (it can actually be anything where the main functionality of a class depends on one or more underlying classes, but file reading seemed simplest to explain). This class will wrap around/simplify another class called File. In the past, I'd implement my file reader class this way:

class MyFileReader {
    private File file;

    public MyFileReader(String filename) {
        this.file = new File(filename);
    }

    public String read() {
        this.file.read(...);
    }
}

Thus, the creation of my object immediately opens the file (if there's a possibility that the file doesn't exist, I'd throw an exception in the constructor).

Nowadays, I'd usually implement that class like this:

class MyFileReader {
    private File file;
    private boolean isOpen = false;

    public void open(String filename) {
        if (this.isOpen) close();
        this.file = new File(filename);
        this.isOpen = true;
    }

    public void close() {
        if (this.isOpen) {
            this.file.close();
            this.isOpen = false;
        }
    }

    public String read() {
        if (this.isOpen) {
            this.file.read(...);
        }
    }
}

In other words, object creation is separate from actually opening the file (if there's a possibility that the file doesn't exist, I'd make the open method return a boolean indicating whether the class managed to open the file successfully) and it's possible for the object to exist without any file currently open.

Finally, another approach which I rarely used is to open the file "lazily", when it's first needed, like this:

class MyFileReader {
    private File file;
    private String filename;
    private boolean isOpen = false;

    public MyFileReader(String filename) {
        this.filename = filename;
    }

    public String read() {
        if (!this.isOpen) {
            this.file = new File(filename);
            this.isOpen = true;
        }

        this.file.read(...);
    }
}

Now the question is - which one of these approaches is the best? And, since the answer is probably "it depends", what does it depend on and in which scenario(s) is each of these methods best applied?

  • 1
    I'd add gently, for the sake of completeness, that you still want a close() method even when you open it in the constructor. – Yam Marcovic Sep 26 '14 at 20:41
  • 1
    And, as a general direction, that the constructor approach is only useful so long as you have access to the concrete class. As soon as you start getting into interfaces (or dependency injection), that sort of interface can pose some problems. – Yam Marcovic Sep 26 '14 at 20:42
  • Wouldn't having a close() method in the first example (one with the constructor) allow the possibility of the object existing in an invalid state (as explained by @busy_wait in his answer)? – fstanis Sep 26 '14 at 21:25
  • 1
    Indeed - but in a language without destructors, that's part of the contract when handling unmanaged resources, such as files. Otherwise, you might never close them as long as your process is alive, and most likely never in the time you want to. – Yam Marcovic Sep 27 '14 at 14:38
3

In my experience, as a general rule, you should instantiate the underlying object as soon as you have enough information to create it, and destroy it when the scope or object that owns it terminates. In other words, as soon as you know you don't need the information contained in it and can afford the runtime cost of destruction.

Considerations include:

  • Valid state of objects - does the wrapper object have any right to exist without the core? Objects should always exist in a valid state. If your wrapper needs the core object to make sense, you should instantiate the core as soon as you instantiate the wrapper.
  • Nullability - does it make sense for the wrapper to contain a null value? If so, it should contain a nullable reference. Does it make sense to swap out objects within the wrapper? If so, you should create the core objects when you know which object needs to be wrapped.
  • Ease of use - Does your interface make it easy for the client to use the functionality your object provides?
  • Ease of misuse - Does your interface make it easy to use your object wrong?
  • Ownership - who owns the underlying resource? They should decide when it gets destroyed.

If your file reader example, the second option make it easy to use the object wrong, because I can easily call read() before specifying which file to read. I'd use either the first or last option, or maybe provide both by combining a variant of the last option with a factory function called get_open_file(filename).

  • Thank you, that cleared some thing up. Do you have a good example of an object which makes sense to exist without the core object? – fstanis Sep 27 '14 at 6:55
0

I think the real answer is a little bit subjective, but there are 3 scenarios coming to my mind(and there are more, for sure):

  1. Decorator -> you pass the underlying object in the constructor
  2. Proxy -> if the underlying object is expensive to create, delay its creation until you actually need it.
  3. Singleton -> same as proxy, create the instance on demand if expensive

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.