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
IFileSystem
in a given context - Simplicity: we'd like to avoid having to pass around a
IFileSystem
everywhere or using AbsolutePath/IFilesystem pairs
Considered Options
- Pass a
IFileSystem
to 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
IFileSystem
for a single method - Some methods on
AbsolutePath
need aIFileSystem
to work, these methods then become infectious throughout the code - Not all methods that use a
AbsolutePath
are on a component (e.g. extension methods). These then need to be passed aIFileSystem
as well, which further infects the code withIFileSystem
references. - Some methods don't even make sense when using a IFileSystem attached to the component. For example
the
FileExtractor
should 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
AbsolutePath
have an attachedIFileSystem
- Paths and
IFileSystem
are now tightly coupled, which makes it harder to use them in isolation, but makes it harder to accidentally use the wrongIFileSystem
- Components that create
AbsolutePath
instances need to be passed aIFileSystem
to 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.