I'm puzzled, most of my adult life I believed that using absolute paths are one of the tell-tell signs of bad programmers.

Seeing things like open(C,"C:\perl5\modules\my-stuff\sth"); made me shrivel and run away...

But now, I've been reading excellent tutorial on thread-safety, and there, absolute paths are a must. You're supposed to convert your old, non-thread safe, relative-path-using modules, into new, shiny, absolute-path-using jewels of thread safety.

The reason is understandable - different threads share single CWD, thus, for them not to step on each other toe, you're supposed to use absolute paths. This reason is fine, and hard to argue with...

How can I make this change, I've accumulated lot's of examples and fine reasons for avoiding absolut paths througout my life, and avoiding them became a second nature.

UPDATE Think about this as a case for accessing hierarchical databases (and typical filesystem is an example of such).

By using absolute path (be it hardcoded, or constructed with File::Spec->catfile($prefix, $relative);) you're reducing it to a flat space.

The filename "/fs/sth/db/category/subcategory/file" instead of address, becomes just a long name...

THAT is the evil pattern here, and THAT is the thing I'm having a hard time adjusting to.

This leads to inefficencies (with pattern

chdir($workdir); foreach ($files) { workOnFile(); }
) you're going through filesystem hierarchy only once, with
workOnSomeFile($cwd,$file); ... workOnSomeOtherFile($cwd,$file);
you're going through it many times, which is costly.

Java programmers tend to write sth like this: chdir("/some/dir1/dir2");..workOnFile("/some/dir1/dir2/file") which I find highly unelegant and slightly disturbing.

Do you know of a way to overcome a mental barrier before I can start writing code like that without feeling guilty?

Replies are listed 'Best First'.
Re: Best practices - absolute paths?
by graff (Chancellor) on Aug 13, 2005 at 15:03 UTC
    At first, this comment of yours didn't make sense:
    ... different threads share single CWD, thus, for them not to step on each other toe, you're supposed to use absolute paths.

    The issue of threads not stepping on each other seems unrelated to how file paths are specified; e.g. if two threads try to write to the same output file without proper steps being taken to control their timing, you have a problem, regardless of whether the file path was relative or absolute.

    But then I found this little bit in perlthrtut:

    Note that while threads themselves are separate execution threads and Perl data is thread-private unless explicitly shared, the threads can affect process-scope state, affecting all the threads.

    The most common example of this is changing the current working directory using chdir(). One thread calls chdir(), and the working directory of all the threads changes.

    Even more drastic example of a process-scope change is chroot(): the root directory of all the threads changes, and no thread can undo it (as opposed to chdir()).

    Well, there are ways to get around that other than switching to all absolute paths all the time. Store your CWD path in a scalar variable (which, by default, is not shared across threads); use that variable together with file names when opening files; you won't ever need to do chdir(), but even if you do, using that path variable with file names will keep the thread behavior consistent with respect to files. If one thread needs a different CWD from others, it can change its own copy of that variable (or you can give it a different value when you start the thread) without affecting other threads. (And don't ever use chroot() with threads, not that anyone would...)

    But a more important point is that threads can step on each other in various ways besides improper use of chdir and file paths, and absolute vs. relative paths have nothing to do with those.

Re: Best practices - absolute paths?
by jonadab (Parson) on Aug 13, 2005 at 11:48 UTC
    I'm puzzled, most of my adult life I believed that using absolute paths are one of the tell-tell signs of bad programmers.

    It's hardcoded paths that are a sign of shoddy programming. If anything, hardcoded relative paths are probably worse than hardcoded absolute paths, merely because somebody's going to run the thing from a different directory at some point.

    With that said, I use hardcoded paths all the time in QAD one-off scripts that I don't intend to redistribute or deploy for production use, and I have occasionally caught myself using one in production. But it's much better to put the path in a configuration file, take it from the command line arguments, or grab the current directory at startup time.


    "In adjectives, with the addition of inflectional endings, a changeable long vowel (Qamets or Tsere) in an open, propretonic syllable will reduce to Vocal Shewa. This type of change occurs when the open, pretonic syllable of the masculine singular adjective becomes propretonic with the addition of inflectional endings."  — Pratico & Van Pelt, BBHG, p68
Re: Best practices - absolute paths?
by sparkyichi (Deacon) on Aug 12, 2005 at 19:03 UTC
    I find that it depends on what you are doing. You should use the right tool for the job at hand and do not dismiss any potential weapons you could use.

    Sparky
    FMTEYEWTK
Re: Best practices - absolute paths?
by jdhedden (Deacon) on Aug 12, 2005 at 21:07 UTC
    If your threads don't do any chdir()'ing, then there's no problem with continuing to use relative paths.

    My approach would be to start the application in a certain location and then use relative paths from there without doing any chdir()'ing. The startup location would either be configurable or be specified on the command line.


    Remember: There's always one more bug.
Re: Best practices - absolute paths?
by itub (Priest) on Aug 12, 2005 at 20:05 UTC
    Parhaps you can construct the absolute paths, relative what was the working directory before spawning the threads?

    I don't think absolute paths are that bad, as long as they are not hard-coded.

Re: Best practices - absolute paths?
by Joost (Canon) on Aug 12, 2005 at 20:52 UTC

      Agreed, but watch out for canonpath from File::Spec::Functions - it converts /'s to \'s. Bad for matching actual paths against a constant path!


      Perl is Huffman encoded by design.
      What is wrong/dangerous about chdir'ing?
Re: Best practices - absolute paths?
by nothingmuch (Priest) on Aug 16, 2005 at 18:21 UTC
    There is a conflict between the paths the programmer deals with, which should be relatives, and the paths given to the system calls, which for thread safety should be absolute (unless they're coming straight from the user, in which case the user probably knows best).

    This issue is resolved by keeping a prefix directory:

    File::Spec->catfile($prefix, $relative);
    Which looks annoying at first, but actually works very well (and you never ever ever have to worry about portability again).

    The rule of thumb I follow is - construct prefix paths as early as possible, construct relative paths as convenient, and construct absolute paths as late as possible, optimizing for the most data reuse, and using very verbose variable names.

    This remains pretty clean, very readable, and flexible enough for it not to stink like hard coded paths.

    -nuffin
    zz zZ Z Z #!perl
Re: Best practices - absolute paths?
by anonymized user 468275 (Curate) on Aug 16, 2005 at 15:38 UTC
    I think this demonstrates the problem with the truth-but-not-the-whole-truth. Absolute paths do need to be avoided in source code, to enable the users or their adminstrators to follow their own installation policies rather than have every application that comes along make its own sweet rules for where it is installed and what working directories it uses.

    In the well-ordered world of Unix and Linux, shared libraries, applications and even data to some extent, have conventional places to live, many absolute paths are indeed absolutely reliable - but I do say only 'many'.

    In particular, a system adminstrator desperately needs the freedom to categorise applications according to a number of considerations, including whether the application is meant to be invoked ad hoc, at user login, or during what level of system startup, which will influence his personal or required choices of installation and working paths.

    The standard solution to address all such considerations is to place absolute paths in configuration files which are then either loaded into environment variables, accessible via %ENV, or a perl subroutine may load them directly, early in the execution of an application.

    But really conscientious applications will also define all subdirectories in configuration files so that the code is not only 100% free of hard-coded absolute paths but of hard-coded relative paths as well! Even those relative paths will then be computed into absolute paths at run-time and may also be configured by the user without touching the code.

    One world, one people

Re: Best practices - absolute paths?
by graff (Chancellor) on Sep 13, 2005 at 04:51 UTC
    I think your update to the OP came sometime after my first reply. I think your concerns are mostly answered by nothingmuch above, but to elaborate a bit, instead of this as your "more efficient" method:
    chdir($workdir); foreach ($files) { workOnFile(); ## should have $_ as an arg, shouldn't it? }
    (where you might want each thread to have its own "$workdir"), you could do it like this:
    foreach ( $files ) { workOnFile( "$workdir/$_" ); }
    If you think that's less efficient, try benchmarking it and see how much of a hit you take. I haven't actually tested it, but I expect the hit won't amount to much, if it's noticeable at all.