0

Say I have a class that is used to monitor the size of a directory. Currently it can only monitor the size of a single directory:

public class DirectoryMonitor {

    private final File absolutePathToDirectory;

    public DirectoryMonitor(final File absolutePathToDirectory) {
        this.absolutePathToDirectory = checkNotNull(absolutePathToDirectory);
    }

    public BigInteger getSizeOfDirectoryInBytes() {
        return FileUtils.sizeOfDirectoryAsBigInteger(absolutePathToDirectory);
    }
}

Would it be better to have it able to monitor the size of any directory?

public class DirectoryMonitor {
    public BigInteger getSizeOfDirectoryInBytes(final File absolutePathToDirectory) {
        return FileUtils.sizeOfDirectoryAsBigInteger(absolutePathToDirectory);
    }
}

I prefer the first example since it's immutable: an instance of DirectoryMonitor can only ever operate on one directory throughout the instance's lifetime.

4
  • 7
    Your second example is also effectively immutable, since you're not holding any state in the class. Jul 18, 2019 at 23:58
  • 2
    Doesn't really answer your question (the answer to which totally depends on context) but in its current state I'd probably argue this class shouldn't exist at all - it's doesn't really provide anything over the underlying API.
    – Ant P
    Jul 19, 2019 at 13:44
  • @RobertHarvey Good point, thank you!
    – broAhmed
    Jul 19, 2019 at 19:24
  • @AntP Possibly overkill, but may want to use a different library to measure the size of the directory in the future. For example, the above implementation uses Apache Commons' FileUtils::sizeOfDirectoryAsBigInteger which can be buggy when called on a directory that's actively being written to.
    – broAhmed
    Jul 19, 2019 at 19:24

2 Answers 2

5

Without further context this cannot be answered. It depends on your usage scenario.

The difference here is not so much immutability (both your examples are immutable) as it is statefulness. If you care for the class remembering what directory it is monitoring and you want it to stick to that, go with the first. If you have multiple threads using the same instance you may want it to be stateless and go with the second (after applying a lock). In the latter case the method might as well be static.

1
  • 1
    Note that I edited the title from "Should this class operate on a single directory or multiple directories," but the outcome is the same. The second class still operates on a single directory at at time. Jul 19, 2019 at 0:06
0

Is FileUtils.sizeOfDirectoryAsBigInteger(absolutePathToDirectory) a real method, or is that something you're using as an illustration to simplify the examples? It looks like there is such a method in Apache Commons, so I'll assume you're using that. Since that method is actually doing the work, it may be worthwhile to examine their design decision to make it a stateless static method. Let's see why they might make that decision:

Stateless static method

  • No need to pass an instance of the class around to where it's used
  • No chance of a consumer incorrectly sharing an instance
  • More like a pure function, since the output depends only upon the input and not upon state (however, since it's effectively reading external state, you wouldn't really call it a pure function anyway).

Now, what would be the advantages of having a class wrapping this method as in your first example?

Class with state and instance method

  • Only need to know the directory path at construction time, not at evaluation time

Considering the advantages of each design, I would say that the stateless static method makes more sense in most cases, especially as a general-purpose utility in a library. That's probably why the Apache Commons method is designed that way. However, if your particular use-case is such that the configuration data for the directories to monitor is only available in one place but you need to check the directory size from many other places downstream, I would consider using the stateful class. That said, there's not too much difference between passing the instantiated class along to the consumers and just passing the configuration with the directory path, so it's not a big advantage anyway.

2
  • It might be worth it just for testability. It's entirely possible that the OP wants to abstract the filesystem away, in which case using the static method isn't possible. Jul 19, 2019 at 13:31
  • 1
    @VincentSavard If the intent was testability, the answer would be an interface which exposes a method taking the directory path and returning the size. The testability thing is really more about whether the method is virtual or not, not having a class keep the method parameters as state. Jul 19, 2019 at 13:53

Your Answer

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

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