Software Developers and Common-Sense Logic
Why is it so hard to retain common sense when designing software?
Imagine a person who wakes up one morning and decides to make a trip to the local motor vehicle branch. He dresses up, finishes his breakfast, hops into his car, and drives to the branch. Once he arrives, he drives around looking for a free parking space. Not being able to find free parking space, he drives to the pay parking lot, parks there, and makes the payment for three hours (“you never know how big the lineup in the branch may be; better safe than sorry," he thinks to himself).
Then he enters the branch, and indeed, the lineup is quite large. He takes the number and sits down, waiting for his number to be called.
After about 40–45 minutes, finally his number is called. He swiftly approaches the teller, and when the teller asks, “How may I help you?” he replies, “I just came here to let you know that I don’t need my drivers license renewed today.”
OK, fine, the person is not in a hurry to renew his driver’s license. But why make an effort to let the motor vehicle administration know that no action is needed on their end? It really makes no sense to behave that way, right?
But why are we implementing this kind of logic in software?
It is painfully obvious how idiotic the above-described behaviour is. And yet, when we examine many examples of the logic implemented in software, we see that the same or similar line of reasoning seems perfectly acceptable to many software developers.
What am I talking about? Maybe a simple example could help:
Say we are tasked with implementing a module/component that will be responsible for processing an order. That block of code will need to know which product to process, what quantity of that product to process (i.e., one or more items), and whether the payment for that order has been accepted or not. Typically, the way we implement the status of the payment is by specifying a variable called payment_accepted; that variable will be of the boolean type (i.e., can only be either true or false; no other values allowed).
Here is how the implemented code might look:
def void process_order(product, quantity, payment_accepted) {
if(payment_accepted) {
// ship the order
} else {
return;
}
}
In the above code, we have defined the process_order module. That method takes three parameters (or, three arguments)—product, quantity, and payment_accepted.
Then, when the calling client sends the message to that module, the module first checks to see whether the payent was accepted. If it was, the module proceeds with the shipping of the product (here only indicated by a comment, for the sake of brevity). If the payment was not accepted, the module does nothing (i.e., it simply returns the execution control to the calling client). It makes sense, because we don’t want the system to start preparing the order to be shipped if the customer did not pay for the order.
The calling client may be implemented as follows:
def void accept_order(product, quantity) {
bool payment_accepted = false;
payment_accepted = process_payment(product, quantity);
process_order(product, quantity, payment_accepted);
}
Here we see that the implemented module is called accept_order, and it takes the product and the quantity as arguments. The first thing this module does is send the product and the quantity values to another module, called process_payment. After that module finishes, it returns the value to the boolean variable payment_accepted. We know, since it’s a boolean variable, that it can only contain true or false value.
The next thing we see is that the accept_order module sends the product, quantity, and payment_accepted values to the process_order module.
Here is where things get interesting. If we look a bit more closely, we see that the accept_order module is making a trip to the process_order module without knowing whether anything needs to be done or not. Suppose that the process_payment module informs the accept_order module that the payment was not accepted. Why would then the accept_order module bother taking the trip to the process_order module? It’s equivalent to the person we mentioned in the beginning making a trip to the motor vehicle branch to inform them that he does not want anything done. It’s wasteful.
And yet, after spending decades reviewing all kinds of code written in various programming languages, I keep seeing, over and over, the faulty and wasteful logic very similar to the above order processing logic. That really makes me stop dead in my tracks; are software developers really that oblivious to common-sense logic?
What’s your take? Please comment below.