|
Boost : |
From: Beman Dawes (bdawes_at_[hidden])
Date: 2003-08-10 14:29:37
At 08:06 PM 8/9/2003, David Abrahams wrote:
>As a user of the filesystem library, I am having the experience that
>obvious things are hard to find, and the docs are much harder to
>understand than they ought to be. The use of creative naming really
>gets in the way. For example, the term "complete" is never defined
>anywhere.
It is defined by the is_compler() returns clause.
> The closest we come is in the following naming rationale.
>
> is_complete
>
> bool is_complete() const;
>
> Returns: For single-root operating systems,
> has_root_directory(). For multi-root operating systems,
> has_root_directory() && has_root_name().
>
> Naming rationale: The alternate name, is_absolute(), causes
> confusion and controversy because on multi-root operating systems
> some people believe root_name() should participate in
> is_absolute(), and some don't.
>
>I'm sorry if this sounds harsh, but I think the cure for someone being
>confused about the term "absolute" on multi-root OSes is to pick the
>definition that allows the term to be meaningful (an absolute path
>identifies a specific location, and so must include the root) and *add
>a clarifying note or definition for the corner case*, not to pick some
>new term which nobody knows about and makes the library hard to
>approach.
The library isn't all that large that people can't just read about each
function.
There were lengthy discussions on the list of this and other naming issues
during development, during review, and during the resolution of review
issues. Many people had fairly strong views. IIRC, the idea that
is_absolute( "/foo" ) was false on some operating systems was impeded by
long-held beliefs. By giving the function an unfamiliar name, people are
forced to actually read the specs instead of just assuming what it does,
and that ends up being a good thing, IMO.
I suppose if we were to discuss the names all over again we would come up
with a different set of names. But unless the new names are markedly
superior to the old names, it would just be churn to change them, and might
be a real step backwards.
>--- aside ---
>Regarding complete paths, is there any guarantee that they are
>canonical? Is foo/bar/../baz reduced to foo/baz?
Yes. That is documented as a postcondition specifying canonical form for
all the functions that modify a path. I've just double checked, and it
doesn't look like any were missed, but let me know if you spot any way to
alter path state that doesn't supply that postcondition.
> See
>http://java.sun.com/j2se/1.3/docs/api/java/io/File.html#getCanonicalPath()
>for an example of the possible semantics. We could learn a lot about
>what's useful and broadly implementable by studying the libraries of
>Java and/or Python (yes, I realize that the portability of Java ain't
>quite what it's cracked up to be).
Yes, I often found other libraries helpful, although many of them offer
syntactic portability rather than semantic portability.
The legacy operating system API's interesting because they sometimes take
different approaches. Sometimes what we think of as a path is just a key
used to find the actual path via some external mapping mechanism.
>--- aside ---
>
>The formal description of some of the function semantics leaves
>something to be desired. For example, the docs for remove_all say:
>
> unsigned long remove_all( const path & ph );
>
> Precondition: !ph.empty()
> Postcondition: !exists( ph )
> Returns: The number of files and directories removed.
> Throws: if ph.empty(). See empty path rationale.
>
>So, what does this do? At first I thought it removed all the
>directories along the branch described by ph. I think I'm now
>inferring that if ph is a file, it is the same as remove( ph ) and
>otherwise it removes all of the files and subdirectories in ph and
>then removes ph. A plain English description would help a lot here.
>This applies to many other functions in the library also.
Yes, a general prose description for each library would help.
>I also have some doubts about the validity of the postcondition, since
>another process can come along and create ph again before remove_all
>returns. This applies to many other functions in the library also.
The docs really weren't clear enough about postcondition/race-condition
interactions. I've just added a paragraph to
boost-root/libs/filesystem/doc/index.htm#Common_Specifications to make it
clear that postcoditions don't hold if race-conditions exist.
Because of the race-condition problem, the original docs did not specify
postconditions. Someone pointed out how much clearer they because if
postconditions were used, and the docs got converted at that point.
>The difference between is_empty(ph) and ph.empty() is too slight, IMO,
>for their differing semantics. IMO it's not useful to have one
>function which reports both empty files and empty directories - the
>implications of the two are much too different.
Early versions of the library did provide the finer granularity of
is_empty_file(ph) and is_empty_directory(ph), but they didn't work out in
practice, and we changed to a simpler set of non-compound functions.
Remember that the library was in private use for quite a while before the
public review, and we got to see what worked and what didn't. Compound
conditional functions definitely fell in the "didn't" category.
--Beman
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk