joseph_ivie
08/14/2025, 11:01 PMkevin.cianfarini
08/14/2025, 11:07 PMkevin.cianfarini
08/14/2025, 11:07 PMtemporary
function has a hidden static dependency on the system file system which is really difficult to use under test.joseph_ivie
08/14/2025, 11:08 PMSystemTemporaryDirectory
which AFAIK only applies to the SystemFileSystem
.joseph_ivie
08/14/2025, 11:10 PMFile
was in many ways much better to use than the follow up Path
specifically because I can't meaningfully use a Path
without a file system attached anyways.
This combines the best of both worlds, making a nice syntax while enabling the use of multiple file systems.
The only thing I really don't like about it is atomicMove
, which can crash due to poor usage by the user.joseph_ivie
08/14/2025, 11:11 PMMichael Paus
08/15/2025, 7:02 AMjoseph_ivie
08/15/2025, 2:29 PMval FileSystem.root: KFile get() = ...
SystemFileSystem.root.path("opt", "myprogram", "data.csv")
Michael Paus
08/15/2025, 2:36 PMjoseph_ivie
08/15/2025, 2:40 PMZonedDateTime
wrapper I made for KotlinX Date. It's just a convenience wrapper for moving data that is clearly associated around and doing operations that require both.
I wouldn't ever suggest removing Path
and FileSystem
in favor of this. This is just supposed to be a convenience and readability improvement tool.kevin.cianfarini
08/15/2025, 2:43 PMjava.io.File
and java.nio.Path
examples.joseph_ivie
08/15/2025, 3:16 PMThere's an HTTP client hiding in the URL class. When I call openStream(), that client is prepared and put to work. I don’t like being cut out of that setup! Ican't dependency-inject my own configured instance for production or a fake in a test.It's not hiding in
KFile
. It's directly accessible and it can be controlled. If the argument is that there should be no default file system in the constructor, I can agree with that. In fact, I'll go change the definition in the snippet.
Creating a KFile
now looks like this: SystemFileSystem.root.path("path", "to", "my", "file")
I might write an Android app that sends its collection of cached images to the server as a List<File>. My server could call File.delete() to free up space on that Android device, but that's not what would happen!
KFile
isn't serializable, so no, you couldn't send it any more than you could send FileSystem
. In addition, with the removal of the default file system in the constructor, it's clear to the user that you can't just use a String
to represent this type.
Subclassingis another thing you could do, but shouldn’t:File
KFile
is a final, transparent tuple of a separate identifier and service.
In short, I don't think any of the arguments made in the blog apply, at least not with the change I just made.
In addition, I think keeping Path
and FileSystem
separate in common usage actually has a different set of dangers - namely, accidentally using a Path
with the wrong FileSystem
! When moving them around in code, they should remain bound together. If you don't, you either have to have the discipline to pass them around together every time and keep which one belongs to which straight or - more likely, if you have junior devs - you'll end up having a bunch of functions just use SystemFileSystem
hardcoded that need all of their headers changed.Mark
08/17/2025, 1:06 PM