1

I know that passing a an Object is not a good practise. But in this case it seems the best solution to me.

public void doSomething(final Object obj) {
    // some code
    ...
    if (obj instanceof InputStream) {
            document = PDDocument.load((InputStream) obj);
    } else if (obj instanceof File) {
        document = PDDocument.load((File) obj);
    } else {
        throw new IllegalArgumentException("Argument must be an instance of " + InputStream.class.getName() + " or " + " " + File.class.getName() + ".");
    // more code
    ...
    }
}

An alternative solution would have more duplicated code (all the line before and after PDDocument.load(obj);)

public void doSomething(final InputStream obj) {
    // some code
    ...
    document = PDDocument.load(obj);
    // more code
    ...
    }
}

public void doSomething(final File obj) {
    // some code
    ...
    document = PDDocument.load(obj);
    // more code
    ...
    }
}

Due to the duplicated code I prefer the first solution.

Do you know any better solution to solve this problem?

1
  • mix them up. have two separate methods that call a shared method with the duplicate code. Commented Sep 4, 2017 at 7:06

3 Answers 3

6

Pass in the result of

PDDocument.load(specificallyTypedVariable)

as a parameter to the method.


This assumes that // some code isn't doing some kind of setup for the load call. If that's the case, you could pass in a Function<? super T, PDDocument> along with the T you're going to load it from:

public <T> void doSomething(final T obj, Function<? super T, PDDocument> loader) {
  // some code
  PDDocument document = loader.apply(obj);
  // other code.
}

and invoke like:

doSomething(someFile, PDDocument::load);
doSomething(someInputStream, PDDocument::load);
Sign up to request clarification or add additional context in comments.

2 Comments

I would use this idea, 3 methods (the two with specific param that will instanciate the document and call the third private accepting the PDDocument document that will have the full logic), simple and correctly typed. I guess this is your idea behing this answer.
@AxelH the idea here is the Law of Demeter (principle of least knowledge). The method doesn't need to know if the document is loaded from a file, read from a stream etc: it just needs the document. It is notable how only passing the thing you need makes the code simpler (just 1 method required) and more flexible (you could doSomething to documents from a wider range of sources).
1

Since PDDocument can load from an InputStream and you can obtain an InputStream from a File anyway, I'd suggest:

public void doSomething(final InputStream in)
{
    // some code
    document = PDDocument.load(in);
    // more code
}

public void doSomething(final File file)
{
    try (
        final InputStream in = new FileInputStream(file);
    ) {
        doSomething(in);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

Of course, handle errors accordingly!


Also, I don't understand why you don't return the document and put that processing in a method returning void?

4 Comments

nit: "A variable declared in a resource specification is implicitly declared final (§4.12.4) if it is not explicitly declared final." Making it explicitly final is merely noise, IMO :)
Maybe add the "...some code..." parts to the InputStream overload to make it more clear as to how this reduces the code duplication.
A slight variation on this idea would be: don't provide an overload for File at all: just make it so you've got to pass in an InputStream; caller can decide how to do that.
@AndyTurner hmm... I didn't know that :) I'll remember that. I'm a little too much final-happy :)
0

Move

// some code
...
document = PDDocument.load(obj);
// more code

to a separate private method which can only be called by the two above methods

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.