It would be nice if KotlinX IO had something like ...
# io
j
It would be nice if KotlinX IO had something like this so I don't have to pass FileSystem and Path around together everywhere.
👍 1
k
This kind of conflates what's a services and what's data, which in my opinion makes Java's various IO libraries so painful to use.
Particularly the companion
temporary
function has a hidden static dependency on the system file system which is really difficult to use under test.
j
That's because at the moment, KXIO has
SystemTemporaryDirectory
which AFAIK only applies to the
SystemFileSystem
.
Also, I think Java's baseline
File
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.
I think, however, that just means that function isn't a good one in particular and should change. That doesn't mean the core idea of providing a combined class doesn't make sense.
m
Another way of dealing with this problem would be to do what UNIX systems do. You have one program wide global file system and you mount all other file systems in that. The global file system is a singleton then by definition and you don’t have to pass it along with every single path because the local file system is then encoded in the path already.
j
Another thing that could be done is removing the default from the constructor and encouraging the use of the below instead:
Copy code
val FileSystem.root: KFile get() = ...
SystemFileSystem.root.path("opt", "myprogram", "data.csv")
m
In my comment above I missed the fact that you explicitly asked for KotlinX IO. My comment refers to Okio which actually has various FileSystem implementations right now already and KotlinX IO doesn’t.
j
Eh, they're close enough the same thing. KotlinX IO is so clearly based on Okio. I actually was originally going to just go use Okio figuring they probably had something like this already, and made this instead when I found out the didn't. I look at KFile as similar to a
ZonedDateTime
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.
k
The author of Okio has a blog post that touches on this: Identifiers aren't Services. It even touches on the specific
java.io.File
and
java.nio.Path
examples.
j
There'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.
Subclassing
File
is another thing you could do, but shouldn’t:
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.
m