Shocker... Interpretation happens before reading, making reading the act of confirming something previously known.
The noggin looks at a word, says hey, I don't have to evaluate what's going on here. I know what it means... and poof, in a near automatic manner, it acknowledges something it already knew. This is not that, I know that. Ha!
That automatic reaction, however, doesn't extend to reading code. Instead, reading code goes through a more complex and extended process. It stores all the bits and pieces, looking up their relationship, then evaluating some meaning until assuring it's got it right.
Being no psychologist, that sort of sounds like coding closer to the act of reading human grammar can be a positive event. Let the brain do less work by being a more articulate coder. No?
Yeah, yeah but. Really, what does that even mean in the context of code, coder, even employer? Is it that if a line of code can "automatic" yield clarity, absolute certainty at minimized times, everyone gains from the efficiency? Because it's easier to read, to change, to modify, to... what?
In layman's terms, reading less means more times spent coding more... a happier boss upon seeing those new features.
Now, How is code even measured in respects to reading? As in, what is read unequivocally means what it says and nothing else. And not while having to read it a few times but, in a glimpse. That at-a-glance should reveal it all, possibly bypassing the need to look any further.
This opens the possibility that not everyone who reads code is at the same skill level, or interested in everything in one shot. Readers are there for all sorts of reasons... of which least, to me, is reading every character in every function all of the time, just to know what something is doing.
Lets do it! The goal? No room for misinterpretation while maximizing comprehension at-a-glance. Ah, another ambiguous adjective: at-a-glance. Let's define that.
at-a-glance: a quick look to identify something. Seconds are the key: 1, 2, maybe 3 seconds. A glimpse is all it takes to fully understand.
Through examples:
OOTB Incident BR "Abort changes on group".
(function executeRule (current, previous /*null when async*/ ) {
// Add your code here
var assigned_to = current.assigned_to;
var assignment_group = current.assignment_group;
var grp = new GlideRecord('sys_user_grmember');
grp.addQuery('group.sys_id', assignment_group);
grp.addQuery('user', assigned_to);
grp.query();
if (!grp.hasNext()) {
gs.addErrorMessage(gs.getMessage("Assigned to user {0} must be member of Assignment group {1} ", [assigned_to.getDisplayValue(), assignment_group.getDisplayValue()]));
current.setAbortAction(true);
}
})(current, previous);
The above piece is often considered a bite size, at-a-glance beauty in our space. It's smallish, has okay use of whitespace, doesn't do too much. Good, right? Maybe not so very much good.
Because the goal of reading human grammar is to confirm things already known, the heighten complexity of too many thoughts into one function hinder at-a-glance. This is the time when we begin to reason our way into why such function is easily understood.
That style leaves no choice but to inspect each line individually, deducing meaning along the way until morphing into a collective meaning. This happens, then that, this means that, then that is evaluated, until... got it! What does code do? wait, let me ready quickly again. Just to make sure. Hm.
Let's refactor that a little?
(function executeRule (current, previous /*null when async*/ ) {
isAssigneeAGroupMember(current)
? passThrough(current)
: showErrorAndAbortOperation(current);
})(current, previous);
Did that make it easier to digest? Does at-a-glance this time yield more meaning, less ambiguity than the first? Or are the 12 lines better than the 3 because the ternary is for "advanced" coders? An IF maybe?
The code shrunk, spotlighting just those parts that are of interest: this vs that. No need to delve into individual lines of code to understand the collective. At the top level nothing else matters. The knowledge that non group members fail the operation is enough. Great! No?
While somewhat more explicit, that last tidbit still leaves unanswered questions. What business case is being solved? There is no clear way to know because the Business Rule name is ambiguous, the code doesn't makes up for it either. Knowing that non group members trigger a failure is okay but, what was solved? Why is that code there?
The reader has to interpret the why, has to interpret the use case to answer why the code is there. For my taste, it's too implicit. Aha! Comments!? A little documentation will solve that, right? Yeah, now I'm reading both comments, plus the code to verify they match. Then, there is all that noise of comments distracting the eyes. The code doesn't even match the BR name. huh
The use case is there in those 3 lines and once found, it can be used to explicitly reveal what the code solves. We can answer the boss when asked: what "Abort changes on group" does... well... it prevents non group members from processing the record and prompting them of it.
Think of it as a use case:
As a tech, when an assignee changes, and record is submitted, prompt that only group members can be selected, then abort the transaction.
It is as important to quickly digest code as it is to reveal what is being solved. The "what is being solved" is significant because can become the function names that then replaces comments, reduces clutter and ambiguity. They encapsulate use cases into easily consumable little things.
It is only when the name is insufficient to individual readers, that it is necessary to inspect within the functions themselves. This helps by decreasing reading times to what's of importance.
The final at-a-glance for an entry point function in a Business Rules using human-grammar-like is:
(function executeRule (current, previous /*null when async*/ ) {
preventProcessingForNonGroupMembers(current); //there is that use case from before
})(current, previous);
If what's inside function preventProcessingNonGroupMembers is important, it's the contents of the second code sample... the ternary in the second code sample. And so on. No one function after does more than exactly one thing: the use case it solves.
Style inside each function can vary (function application, composition, temp variables, etc.) but, the point is that as human grammar in code increases, the easier it becomes to interpret with certainty at-a-glance. It's like asking what does a one page of words mean, as opposed to one word.
If the problem is "does the function do what it says it does", then the problem is beyond names...
Happy snowing...
Top comments (1)
Hi, Javier. I have gone through some of your articles in ServiceNow. Please suggest a book to implement best coding practices. Thanks.