Izbassar Tolegen
Izbassar Tolegen

Reputation: 2152

Immutable object with side effect

Let consider immutable object File which encapsulates fileName which points to file on the disk. That object has method rename which is obviously assign new name to the file on the disk.

public final class File {

   private final String fileName;

   public File(String fileName fileName) {
       this.fileName = fileName;
   }

   public File rename(String newName) {
        // Rename the actual file on the disk (code is omitted)
        // and that is the side effect!
        return new File(newName);
   }
}

So the questions are:

Assume that File is only an example.

Upvotes: 2

Views: 662

Answers (2)

Alexey Rykhalskiy
Alexey Rykhalskiy

Reputation: 418

I think, you should read the next article: http://www.yegor256.com/2016/09/07/gradients-of-immutability.html because Immutability is nor black or white

Upvotes: 2

skapral
skapral

Reputation: 1217

How to approach side effects with immutable objects? Our File object once created should be working always with the same encapsulated state. And return new object with modified state. This is perfectly done in java.lang.String class. But the old object (which is still point to wrong fileName) is not good. We can't use it as state is broken.

Your example has one issue, which is not possible to overcome. Your side effect, this part of code, is not in your control:

    // Rename the actual file on the disk (code is omitted)
    // and that is the side effect!

In case of String, you have every byte of the string under your control, so you can guarantee the purity for the methods on the String. In case of your File example, there is also an environment involved - operating system, where this file exists or not. Even if it exists, it may be not accessible to your process. There may be plenty of reasons why you cannot actually rename the file.

IMO it is not possible to overcome this. World around you is not pure - your code executes on system with lots of side effects and mutability. Your disk is stateful, your RAM is not constant. Even in Haskell the function renameFile :: FilePath -> FilePath -> IO () from https://hackage.haskell.org/package/directory-1.3.1.1/docs/System-Directory.html is not ideally pure - it can cause errors in some cases.

But it is not the reason to think that the object is invalid. As it was already said in comments, you encapsulated the file name, not the file descriptor. So, your File represents valid file name. Probably the question is more about validity of the renaming method?

Does it means that object is not truly immutable? And what if we want to work only with true immutable objects with consistent state? We shouldn't rename file on the disk? But how to get the job done when we actually need file to be renamed?

It is immutable. The call rename on this object is not pure, that's all. Immutability and Purity are different terms. Your object may be immutable and still have side effects, like in your example.

Upvotes: 4

Related Questions