In any programming task, my preference is to write fail-fast code. That doesn't seem to be too controversial. However, I've also seen many developers say that constructors should do as little as possible. I'm finding that these two goals are often at odds, and conversations over fail-fast design vs. constructor simplicity sometimes devolve into statements of preference.
Consider a class that provides write access to a file. The class accepts a file path in its constructor which must be a path to an existing file. Some developers would say that a constructor shouldn't be accessing the file system, so I might just do a null check:
private readonly string file;
public FileAccessProvider(string file)
{
this.file = string.IsNullOrEmpty(file)
? throw new ArgumentException(nameof(file)) : file;
}
Now, if the provided file doesn't exist, we might not know about it until the class actually attempts to write data to the file. In this case, would it be acceptable to do a check for file existence in the constructor?
private readonly string file;
public FileAccessProvider(string file)
{
this.file = string.IsNullOrEmpty(file)
? throw new ArgumentException(nameof(file)) : file;
if (!File.Exists(file))
{
throw new ArgumentException("File does not exist.");
}
}
This complicates my constructor, but better adheres to fail-fast design. We could even take this a step further and add code to the constructor that checks if the user has write permissions to the file.
What about a class that has to access a database or network resources?
Is there an accepted side to err on in situations like this?