IFileSystem on Absolute Paths
Context and Problem Statement
With the switch to a IFileSystem abstraction (see ADR 0004) we need to decide where
the
IFileSystem should be used, should they be only in components, with AbsolutePath remaining just a set of strings, or
should
AbsolutePath always be relative to a given IFileSystem?
Decision Drivers
- Ease of use, we want the API to feel natural
- Avoid foot-guns: make it hard to accidentally use the wrong
IFileSystemin a given context - Simplicity: we'd like to avoid having to pass around a
IFileSystemeverywhere or using AbsolutePath/IFilesystem pairs
Considered Options
- Pass a
IFileSystemto every component that needs it.- Has a disadvantage of users accidentally passing a path to a component initialized with the wrong
IFileSystem - Some components only need a
IFileSystemfor a single method - Some methods on
AbsolutePathneed aIFileSystemto work, these methods then become infectious throughout the code - Not all methods that use a
AbsolutePathare on a component (e.g. extension methods). These then need to be passed aIFileSystemas well, which further infects the code withIFileSystemreferences. - Some methods don't even make sense when using a IFileSystem attached to the component. For example
the
FileExtractorshould extract files from and to anywhere, the filesystems involved are irrelevant, the filesystem to be used in a given call to the extractor is completely reliant on the path passed in
- Has a disadvantage of users accidentally passing a path to a component initialized with the wrong
- Require that every
AbsolutePathhave an attachedIFileSystem- Paths and
IFileSystemare now tightly coupled, which makes it harder to use them in isolation, but makes it harder to accidentally use the wrongIFileSystem - Components that create
AbsolutePathinstances need to be passed aIFileSystemto use, but this makes sense as these are the "constructor" methods for the given paths
- Paths and
Decision Outcome
Since there are cases where attaching IFileSystem to a component cannot work semantically, the decision was made to
place the
IFileSystem on the AbsolutePath itself. This means that every AbsolutePath has an attached IFileSystem and that
only components that need to
create AbsolutePath instances ex nihilo need to be passed a IFileSystem. If the behavior of such a component needs
to be configured,
it can be done by configuring the IFileSystem used in the DI container.