Even batch programs have user interfaces.  They start with actual or implied inputs (run control parameters in Peoplesoft).  They end with actual or implied outputs (reports, log files, Process Monitor messages).  We shouldn’t take these elements of program design for granted, even in the simplest programs.

Implied Inputs

Sometimes, what our users don’t say is more important than what they do say.  Every program is based on assumptions, sometimes specified, sometimes unrecognized, sometimes reliable, sometimes myopic.

Some programs are intended to execute at a specific time: the third day of each month, the day before each payroll confirmation, every other Tuesday, etc.  Those functional specifications suggest that the program can use the system date to determine which data to process, and the user need not supply that information.  If we can eliminate the run control parameters entirely, we can schedule the program to run automatically.

Another way to decide what to do without user input is to keep track of what has been done before.  If the program always flags or logs or deletes the data it processes, future instances can select only the unflagged or unlogged or still existing data.

Users are often interested in a predictable subset of the data.  Department analysts might only need data for the department to which they belong.  Sometimes we can create a table that identifies different users’ responsibilities; John needs the sales results in the eastern U.S., Mary needs them in the West.

It’s good for our programs to calculate whatever they can and spare us the trouble of informing them.  However, making the routine operations slightly easier can make the exceptional cases much more difficult.

There will be times when the regular schedule for the program is inappropriate.  If it is run manually, there will be times when the user forgets, or misses a day of work, or encounters a system outage.  Suppose the program uses the system clock to automatically process all the transaction in the prior week, and we need to run it in a test environment that was copied from production a month ago?  An export program that flags or deletes the data it processes will be helpless if we lose the export file and need to reprocess the latest data.  And how will Mary cover for John when he’s on vacation?

Peoplesoft’s run control architecture offers several solutions.  Each user can create any number of run control rows for each program.  Those rows can save the parameters from one instance of the program to the next.  (It might be worthwhile to write a utility to copy one user’s run control rows to another user to support job succession.)  Other options are to write Peoplecode to delete run control parameters or to calculate new default values with every new run.

Choosing Parameters Among Synonyms

There are usually several ways for users to communicate their preferences.  A snapshot report needs an as-of-date.  If we know the as-of-date is always the run date, the user doesn’t need to enter it.  (But is it really, really always?)  If we know the as-of-date is always the first day of a month, we have several input options.

  • The program can calculate the first day of the month that contains the run date.
  • The program can calculate the first day of a month that’s closest to the run date.
  • The program can set a cut-off date and “round down” before it and “round up” on or after it, e.g. October 24 maps to October 1, October 25 maps to November 1.
  • The user can input the name (October) or number (10) of the month and the program can calculate the first day of that month.
  • The user can enter the first of the month as a date, the run control record can validate that it is a date and it is the first of the month, and the program can use it.

There are various factors to guide us to the best choice among these options.

  • The most important question is whether our assumptions about the as-of-date are as unchangeable as the specification insists.  Are there ever any circumstances that could make it a different day?  It’s inefficient to use the programmer and the compiler for data entry.
  • The second key factor is consistency.  If every other program uses the name of the month, we don’t want to write the first program that uses an abbreviation.
  • The third aspect of good design is to make the program robust.  I used to think I was being helpful by “reading their minds” and figuring that anybody running the program on October 25th wanted to prepare a report for November, while anybody running the program on October 24th wanted to prepare a report for October.  After enough times of people asking me to temporarily change the program to reverse that behavior, I stopped offering that kind of “help.”

For programs related to payroll, we can refer to a particular payroll cycle by the check date, the pay end date, or the run ID.  In some organizations, there may be a one-to-one correspondence among these values and they are synonyms.  In that case, we should listen to how people label each payroll cycle and use that method consistently.

In other organizations, there might be one-to-many correspondences.  (My organization has two pay end dates for each check date and each pay end date has its own run ID.)  In that case, we should listen to how people group payrolls, if they do, and use that method to process payrolls in groups or to differentiate related payrolls.

Parameter Design

So far I’ve discussed our design as a choice between calculating what we think the user wants and asking the user what value to use, or something in between.  We could take a step back and have the run control page ask the user how to indicate the value to use.

Some Peoplesoft HCM search pages let us pick an employee by ID number, name, department, or other data.  We could let the user choose whether to supply the pay end date, check date, or run ID.  We could let the user choose to have the program calculate the as-of-date, perhaps by a menu of formulae, or to have the program accept a date from the user.

A benefits report is usually about the status of benefit enrollments as of the run date.  In the second half of December it is about the status of benefit enrollments as of January 1 of the next year.  Here are our alternatives.

  1. Program the report to use the run date as the as-of-date.  On December 15, change it to use January 1.  On January 1, change it back.  In some years, forget to change it back.
  2. Program the report to use the run date as the as-of-date in production.  In December, let the programmer run it on (my) desktop as of January 1 whenever the HR department needs it.
  3. Have the program calculate the as-of-date with the algorithm, “if run date is between December 15 and December 31 of the current year, then as-of-date is January 1 of next year, otherwise as-of-date is run date.”  Don’t support the short-term benefit enrollments of new employees.
  4. Let the user enter the as-of-date.
  5. Let the user choose between “today” and entering the as-of-date.
  6. Give the user a pull-down menu with the choices “today” and “January 1.”
  7. Give the user a checkbox for “January 1.”  Leaving the box unchecked means “today.”

I am not proud to admit I have done the first and second.  The third eliminates options that the user may need (running “January 1” on December 14, running “December 16” on December 16).  The fourth and fifth seem like more fuss than the user should have to do.   I have six weeks left to choose between the sixth and seventh.  Seventh is easier for me, but I’m going to ask my customer which one is better.

Configurability

My usual approach to a new application is to determine the minimum guidance it needs from its user.  Peoplesoft itself evolved in the opposite direction, with every release giving us more flexibility and fitting the needs of all its customers more closely.  Sometimes I wonder whether to emulate that approach.

We could respond to a request for a five column report with a program that produces a report of a user’s choice of columns from a menu of twenty, in any layout, sorted in any order.  Yes, I know we would be halfway to recreating PS Query or Crystal Reports.  But we would also be 90% of the way to finishing our next report request.

There are other aspects to configure.  We could allow a choice of detail, summary (subtotals), or both.  We could allow a choice of name format (“Alexander, Steven J.” versus “Steven J. Alexander.”).  We could allow a choice of page headers, thousand-separators, dollar-signs, and negative numbers in parentheses (better for printouts) versus one-time headers and simpler currency formats (better for spreadsheets).

Output Standards

Most customers know what they want for output and don’t care much about the input issues we’ve discussed.  However, there may be conventions or standards regarding output that the organization should adopt.

First, a program that may or may not output anything should always output something, even if it’s a message that there was nothing to report.  A program that might output more than a page should always identify its last page.  I always number each page and print “End of report” as the program ends to meet both requirements.

Second, a report should always identify itself sufficiently so that any reader at any time knows what the data means.  The minimum is a title and run date.  It’s better to, in effect, repeat the question that the report is answering.  Here’s an example of a gradually improving selection of report descriptions.

  1. List of employees
  2. List of highly paid employees
  3. List of employees paid over $100,000 per year.
  4. List of employees in the Sales Department paid over $100,000 per year.
  5. List of current and past employees of the Sales Department who were paid over $100,000 in the 12 months ending October 31, 2009.

Repeating the question becomes more and more important as the number of systems and reports increases.  There’s bound to be reports that cover the same topic with slight differences in their approaches.  It’s best to avoid two hour research projects that end like this:

  • Joe Smith appeared in the first report because it was run on October 31 – his last day – and not in the second report because it was run on November 30.
  • The revenue included sales tax in the first report but not in the second report.
  • The first report was all expenses incurred by employees of the Sales Department, no matter which department paid them.  The second report was all expenses paid by the Sales Department for any employee in the company.

Blog Housekeeping

I disabled comments on this blog.  I was getting fifty spam comments per day, and rarely any reader comments.  It frees up my time for writing to not have the chore of skimming and deleting spam.  If you, a real person, wish to comment on my posts or communicate with me, please check the About page for my e-mail address.