Sunday, December 18, 2005


Really Commenting Code

Most times, when I'm writing scripts, I tend to pay little more than lip-service to commenting the code, but I'm slowly learning to regret that. Each time I have to explore a function I create more than a few days ago, I end up investing an amount of time simply trying to fathom exactly what it does. For trivial functions, this might be OK, but for those that do more, this is proving to not be OK.

So, this morning, I decided to write a function and comment it "properly". Here's the result:

function makeFileName(Orig, New, Append) {
    Returns derived filename using:
      FileRef or String.
        If FileRef, full name of file used as basis;
        If string, can be path or just name; whichever, that's what's returned
        New name for file, including extension
    Append (Optional; default: true)
        true: append to existing name
        false: replace existing name
  if (arguments.length < 2) {  
    throw "First two arguments are required."
  if ( != "String") {
    // Should be file or folder; get path
    try {
      Orig = Orig.path;
    } catch (e) {
      throw "First argument must be a string or file/folder reference."
  if ( != "String") {
    throw "Second argument must be a string."
  if (arguments.length == 2) {
    Append = true;
  // Preliminaries complete; arguments are good.
  // Get platform independent version of Orig string
  var myString = File.decode(Orig);
  // If last part of name includes period, strip from last period on
  var lastDot = myString.lastIndexOf(".");
  var lastSlash = myString.lastIndexOf("/");
  if (lastDot > lastSlash) {
    myString = myString.slice(0, lastDot);
  // If we're not appending, get rid of last part of name
  if (!Append) {
    if (lastSlash == -1) {
      myString = ""; // there only is a last part
    } else {
      myString = myString.slice(0, lastSlash);
  // Append New, encode and return
  return File.encode(myString + New);
I think this makes the function a whole lot easier to understand, whether I'm coming back to it to use it as-is or if I'm trying to revise it for some extra functionality. For example, I wrote this to help me with a larger script where I'm trying to create a preferences file in the same folder as the running script. So, the initial purpose is to create a filepath that derives from the script's filepath.

So, the calling script looks like this:
var myPath = getScriptPath();
var PrefsFileName = makeFileName (myPath, "prefs.txt", true);
where getScriptPath() is a function that does this:
function getScriptPath() {
  // This function returns the path to the active script, even when running ESTK
  try {
    return app.activeScript;
  } catch(e) {
    return e.fileName;
I'm a little torn about what to do about those errors that makeFileName() throws. If I leave the call as it is above, I'll just get a run-time error should an error be detected by the script, which would be all right if I were writing this script for myself alone (and who knows, perhaps I am). This is a better version:
var myPath = getScriptPath();
try {
  var PrefsFileName = makeFileName (myPath, "prefs.txt", true);
} catch (e) {
  errorExit("makeFileName reports: " + e)
but that try construction clutters up the script making it hard to follow.

An alternative approach that I rejected for now would replace those "throw" statements with direct calls to errorExit(). I chose not to do this because one day I might write a script that makes use of those thrown errors to take some action other than just reporting the problem and quitting.

I'm not sure there are any rights or wrongs here so much as philosophical decisions. If I were writing solely for myself, I'd just let the run-time errors happen and not blink, but this particular script I'm working on has potential value for a larger community, so I'm leaving things the way they are even though the main script gets a bit more cluttered.

Comments: Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?