Learning From Mistakes: Leaky Abstractions

On the project I’m working on I’ve had a requirement to store and read files from the file system. Alse the files had to be accessible from the web.

Having a gut feeling that the infrastructure may change as the business will grow, I decided to hide operations on the file system behind an interface:

public interface IFilesStorage {
    string StoreFile(Stream stream, string fileName);
    Stream GetFile(string virtualPath);
    string GetFileUrl(string virtualPath);
    string GetFilePath(string virtualPath);
}

As it looks, if someday I’ll need to switch from the file system to another storage mechanism, I’ll be able to do get the job done by writing another implementation of the interface. Right? Wrong! The requirement did come in - I’ve had to store the files in S3. And only then I realised that IFilesStorage is a leaky abstraction.

[Read More]