A few years ago, I helped a client modify and enhance applications in key business processes like marketing, accounting, inventory management, order processing and customer service. I wasn’t an expert in application design or coding; my specialty was system software like CICS, Db2, VSAM and MVS, but I did know the COBOL, PLI and Assembler programming languages. The client had no one who knew system software, and very few who knew Assembler. I’d participated in various application development and design projects in areas where they needed improvement. They made me a great offer, knowing my strengths and weaknesses, and I took their offer.
The first project I worked on was the implementation of encryption into this client’s applications—a major effort that encompassed almost all of their applications, and was a resounding success that won the IT department corporate recognition. The trend continued through the course of several additional projects, most of which involved the implementation of new technology, and I was having a blast in playing a key role to each of these endeavors. The people I worked with each had their own area of business process expertise. Each one was conscientious and proficient, and each one was a pleasure to work with. I had found my happy place.
One of the staff members—who specialized in accounts receivable and in particular credit repayment processing in a three-payment-in-three-month manner—developed health problems that continued for a lengthy amount of time. This led management to allow her term of employment to expire, leaving them with little or no expertise in this area, and ultimately unable to find any replacement. So when the accounts receivable director met with the IT director to discuss the numerous problems that had caused the application to malfunction in certain cases, and even worse, created significant customer dissatisfaction via invalid late fee charges or late payment notices, it was unclear what the plan of action would be.
Any Programmer Will Do?
IT management hadn’t bothered to replace their lost specialist, nor had anyone been trained to take her place, so due to my track record I was assigned to the project. The accounts receivable application was coded to merge late fee assessments with delinquency-processing code in a program that handled credit orders paid via installment plans. Initially considered a minor project, the complexity of existing code and late fee processing should have tripped red flags as work got underway. There were also a number of business rules—mostly undocumented—that really complicated programming. For example:
If full payment comes in after the due date, leaving only a late fee as due, the late fee must be rolled into the following payment, because a late fee can’t make an account past due.
If the balance due is less than a dollar, it isn’t considered past due, and is rolled into the next payment.
If the late fee is less than a dollar and the only amount due, it’s rolled into the next payment.
In the final payment, all due amounts remain and nothing is rolled. Late fees may be assessed.
Merchandise returns prior to first due date are subtracted from the first installment. If the refund is greater than first payment, the remainder is applied to second payment, and so forth.
Late fees assessed vary from state to state based on statutes.
The above rules are only a sample of late fee processing rules. And there’s interdependency between rules; for example, a merchandise return reduces balance due, which can cause it to be rolled into the next installment, which changes the date a late fee is assessed. The rules also change from first payment to second payment to last payment.
These are only a few examples of the cesspool I found myself in, but it’s remarkably representative of what became my Achilles heel and a vital concept in application development on the mainframe, midrange, server, cellphone or any other platform which can be programmed to provide functions rich in usability and convenience, or processes vital to an enterprise’s business operations.
Programming Skills Alone Don’t Make a Programmer
What a godsend it would’ve been to have had in-depth training and enlightenment on how accounts receivable worked! Who would ever have imagined these sort of variations existed? And how would anyone have known even the most obvious of exceptions without having some sort of experience with accounts receivable? Instead, these issues only arose during quality assurance tests after a number of disastrous runs. Of course, none of these exceptions or variations were documented in any way; they were only stored in the heads of a few management members or lead supervisors.
The plethora of business rules and exceptions created a plethora of scenarios that existed in three different situations: first payments, following payments and final payments. Numerous issues emerged as unanticipated exceptions or results arose due to combinations of payments or rules producing unintended outcomes. There were far more scenarios than projected, which were only apparent as new code was run against production database copies and compared against real production. It took massive amounts of effort and time to isolate all discrepancies, and due to rule interdependencies, everything was very convoluted. Business rules were modified due to new exceptions; what had been considered a minor project became major.
By the time this code was substantially stable and deemed ready for production, a software freeze put it on the shelf for a couple of months. When the freeze was lifted, one final, full-scale test was run before cutting over. Perhaps because of elapsed time, unique transactions or because they just hadn’t been caught, new errors popped up. The first few fixes were easy and quick, but then a new, unique situation arose. A/R and QA experts huddled to determine expected results, with A/R championing one answer, QA advocating another, but deferring to A/R as the final authority.
So, I made changes to produce A/R’s results. QA testing revealed new errors; I corrected those glitches, and other code broke. An incredibly frustrating and exhausting series of “fix something, break something else” sequences became worse and worse. An application on the verge of production was now riddled with errors, contradictions and inconsistencies. Finally, everyone gathered in a room to follow the code with changes all the way through—a scenario which coincidentally turned out to be the one A/R and QA had disagreed on. Prior to running the scenario, A/R calculated their answer, helpful in following the code. A/R’s answer turned out to be what QA had maintained all along was correct, and A/R conceded they’d been wrong.
All of a sudden the “fix something, break something else” phenomenon made sense. Code written to produce an erroneous but A/R-verified result set off a cascade of events: Every code change designed to fix errors caused by the misguided code propagated inconsistencies that created errors. Essentially, the bad code caused good code to go bad, and resulting fixes caused errors because they were based on bad code, which was ultimately based on a bad answer.
Being a Good Programmer Isn’t Enough
Had this client’s management provided me in-depth application training, this project would have gone much better, because the exception processing logic would’ve been anticipated and coded from the start. “Knowing thy enemy” as the adage goes, would have allowed me to code for many of the exceptions during initial coding. They’d never have reared their ugly heads, and I’d have been able to anticipate more errors, because I would’ve understood the interdependencies. This project proved that throwing a body at a project to get it done doesn't work; qualifications and training count for a lot, too.
There Must Be Unanimity Between Users
More than anything else, the disconnect between A/R and QA shows why heavy investment in time and up-front analysis and design really pays off. Not all scenarios would’ve been identified, but a lot of them would’ve, probably including the misguided A/R result. But most scenarios were only discovered through testing. Correct results, relevant accounts, simulated dates and everything involved in this business process should’ve gotten up-front consensus from the entire development team—including A/R, QA and IT.