in reply to A DWIM too far?

Given that we've been over the rename(2) behaviour-copying and so on, I thought I'd hijack part of this thread for a more abstract discussion:

What's better, familiar behaviour or intuitive behaviour?

I first came across this argument in Maguire's Writing Solid Code book. His example (and mine) was a wrapper for C's malloc(3) and friends, for instance, to detect memory leaks. You can call stdlib realloc with a NULL pointer, in which case it acts like malloc, or with a zero size, in which case it acts like free. Maguire argues that in almost every case, NULL-pointer or zero-size calls to realloc are errors rather than clever tricks. Accordingly, he removed this behaviour from his realloc wrapper. I did the same when I wrote a realloc wrapper, for the same reasons.

In general, I tend to think that duplicating broken behaviour in the interests of familiarity is a bad idea. The question, then, becomes: "Is rename's behaviour broken, or just unexpected?"

--
F o x t r o t U n i f o r m
Found a typo in this node? /msg me
% man 3 strfry

Replies are listed 'Best First'.
Re^2: A DWIM too far?
by BrowserUk (Patriarch) on Jun 18, 2004 at 00:10 UTC

    I'm not sure which I find the most bizarre

    1. That the silently destructive behaviour was ever adopted in the first place.
    2. That such a (IMO) flawed behaviour should have been perpectuated.
    3. Or the outpouring of support for it.

    As is, the behaviour makes it impossible to safely rename a file.

    You can test existance before issuing the rename, but in any multi-tasking environment there is always the possibility that the target file will be created between the test for existance and the rename. This renders the the often hard won (and IMO, sacrosanct) atomicity of the OS rename API useless.

    This rates up there with non-exlusive-opens-by-default and cooperative locking as remnant bahaviours of a bygone era that should have been superceded long ago.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
      As is, the behaviour makes it impossible to safely rename a file.

      That depends on your definition of "safely". The other possible default (not renaming if the target file exists), also prevents "safely" renaming a file. Because that will prevent the to-be-renamed file to be renamed. So that's also "unsafe".

      You should also consider what should happen in the following situation:

      $ touch file $ ln -s target link $ rename file link
      Rename or not?

      Note that if you want to do a "safe" rename, you can do so, although it involves a copy:

      my ($f1, $f2); if (sysopen $f1, "new", O_WRONLY | O_CREAT | O_EXCL) { open $f2 => "old" or die; print $f1 <$fh2>; close $f1 or die; unlink "old" or die; }
      You can test existance before issuing the rename, but in any multi-tasking environment there is always the possibility that the target file will be created between the test for existance and the rename.
      Frankly, I don't get your point. What are you trying to say here? That the rename is making you lose data? That I disagree with. Suppose you are multi-tasking, one threads wants to create a file "new", and another thread wants to move "old" to "new", but you want to end up with both the data that is in "old", and with the data that would be placed in "new" by the other thread. Suppose you would have a 'rename' that doesn't rename if there is already a "new" file. Does that win you anything? Not if the renaming process thread goes first. Then "old" will be renamed to "new", and then wiped out by the other thread that's creating "new". Rename is not to blame in this scenario - the programmer is to blame by not syncronizing two threads that modify the same resource.
      This rates up there with non-exlusive-opens-by-default and cooperative locking as remnant bahaviours of a bygone era that should have been superceded long ago.
      Well, you can always change your system calls. Oh, wait, you can't.

      Abigail

        Note that if you want to do a "safe" rename, you can do so, although it involves a copy

        I may have missed something, but I think it can be done much more easily like this:

        sub rename_i { my($src, $dest) = @_; link($src, $dest) or die "Can't link $src to $dest: $!"; unlink($src) or die "Can't unlink $src: $!"; }

        Hugo

        Well, you can always change your system calls. Oh, wait, you can't.

        Of course I could--but I don't need to :)


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
      As is, the behaviour makes it impossible to safely rename a file.
      It makes it harder, at least:
      sub myrename { my $rename = ( $^O eq 'MSWin32' ) ? 'move -y' : 'mv -i'; `$rename @_[0,1]`; return $!; } myrename('abc','def') or die $!;
      I can't recall how to do this to the CORE, perhaps someone will remind me?

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

        It seems you answered the wrong question. The problem is that you can't be sure to not overwrite a file by renaming it. Your rename subroutine does quite the opposite. Or have I completely misunderstood your reply?
        *GLOBAL::CORE::rename = \&myrename;

        Update: The above is wrong! It should be

        *CORE::GLOBAL::rename = \&myrename;

        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon

      Here's something else you might find bizarre. There's a programming language many people greatly enjoy using that has very little stricture by default, lots of similar but slightly different ways to do the same thing, an object system that lets you use whatever type of datastructure you damn well please, and generally encourages a culture of "stay out of my living room because I ask, not because I have a shotgun." Perhaps you find it bizarre, but I find it downright refreshing.

      I feel the same way about cooperative locking, non-exclusive opens, and -- to a far lesser extent -- the overwriting rename(). Do I wish there was a reasonable way to rename without clobbering-by-default? Yes, I do. That doesn't make me like the current behavior any less. Personally, I like a platform that lets me do what I want, even if what I want might be shooting myself in the foot. If this mentality is so strange to you, I wonder how exactly you've managed to stick with Perl as long as you have.

        There is a difference.

        Most of those permissive behaviours that you describe,and which I mostly relish, are controlled entirely within the auspices of my program!

        The destructive behaviour of rename means that I may well be destroying someone else's data, or someone else accidentally or deliberatly destroying mine.

        I consider that a fundemental distinction.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
Re^2: A DWIM too far?
by chromatic (Archbishop) on Jun 18, 2004 at 07:01 UTC
    What's better, familiar behaviour or intuitive behaviour?

    Which is bluer, blue or blue?