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:
So, the calling script looks like this:
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.
So, this morning, I decided to write a function and comment it "properly". Here's the result:
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.
function makeFileName(Orig, New, Append) {
/*
Returns derived filename using:
Orig
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
String
New name for file, including extension
Append (Optional; default: true)
Boolean
true: append to existing name
false: replace existing name
*/
if (arguments.length < 2) {
throw "First two arguments are required."
}
if (Orig.constructor.name != "String") {
// Should be file or folder; get path
try {
Orig = Orig.path;
Orig.length;
} catch (e) {
throw "First argument must be a string or file/folder reference."
}
}
if (New.constructor.name != "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);
}
So, the calling script looks like this:
var myPath = getScriptPath();where getScriptPath() is a function that does this:
var PrefsFileName = makeFileName (myPath, "prefs.txt", true);
function getScriptPath() {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:
// This function returns the path to the active script, even when running ESTK
try {
return app.activeScript;
} catch(e) {
return e.fileName;
}
}
var myPath = getScriptPath();but that try construction clutters up the script making it hard to follow.
try {
var PrefsFileName = makeFileName (myPath, "prefs.txt", true);
} catch (e) {
errorExit("makeFileName reports: " + e)
}
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.