- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on â02-03-2019 01:11 PM
var grIncident = new GlideRecord('incident');
grIncident.addQuery('active=true^state=1');
grIncident.query();
while (grIncident.next()) {
// do some processing with the GlideRecord
gs.info('processing ' + grIncident.getDisplayValue());
}
function query(table, query, fn) {
var gr = new GlideRecord(table);
gr.addQuery(query);
gr.query();
while (gr.next()) {
fn(gr);
}
}â
function processNewIncident(grIncident) {
gs.info('processing ' + grIncident.getDisplayValue());
// do some processing with the GlideRecord
}
query('incident', 'active=true^state=1', processNewIncident);
function processClosedHighPriorityIncident(grIncident) {
gs.info('processing ' + grIncident.getDisplayValue());
}
query('incident',
'active=false' +
'^ priority=1 ^OR priority=2',
processClosedHighPriorityIncident);
No more repeating boilerplate code, and by encapsulating our processing of an individual GlideRecord into a separate function, separating the processing concern from the data retrieval concern (another best practice - Separation of Concerns or SoC) our code becomes more readable and maintainable.
- 1,180 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi John,
I looked for a way to PM you but, wasn't successful. Hope posting here is okay with you.
I've done Functional programming in SNow for quite a bit. This is inclusive of monads, functors, applicatives. I would love to try to find time to collaborate with you to see if better programming practices can brought into SNow. Seeing that you are trying to also tackle the same ideas as I, perhaps we can learn from one another even if it's here and there as time permits.
On to the post:
While functions are being passed around, the code is imperative. To move into functional programming, the code would have to be modified in various places, something along the lines of:
With Monads
var openIncidents = Maybe(Incident.All_ACTIVE)
.map(makeDB().retrieve)
.map(composeWhile(pipe([getValues(['number','short_description'])])));
With pipe
var openIncidents = pipe([makeDB().retrieve, composeWhile(pipe([getIds]))])(Incident.ALL_OPEN);
The code doesn't have to be point-free; however, the idea is that in functional programming function arity is nearly always singular, as opposed to varadic arity because those don't compose. More times than not functions are pure (no side effects), and there would be curried functions to separate such things as getDisplayValue from the value it extracts and how it does it, as to allow function composition. Also, all functions must always return a value.
The function query in your example would be turned into a factory and its while statement separated from the boiler plate of the GlideRecord, introducing the single responsibility principle. This leads to greater flexibility in how processing each record is done and when.
Calling gs.info within another function, while the point of the example understood, is not a functional technique. processClosedHighPriorityIncident would instead return grIncident.getDisplayValue and a trace function created to print the output.
For example, in the second sample I've provided, there would be an additional call to gs.debug to handle out put.
var openIncidents = pipe([makeDB().retrieve, composeWhile(pipe([getIds])),gs.debug])(Incident.ALL_OPEN);
With the monad, it would look like so:
Which would then used to compose functions.
var items = Maybe(Incident.All_ACTIVE)
.map(makeDB().retrieve)
.map(composeWhile(pipe([getValues(['number','short_description'])])))
.map(gs.debug);
A functional version of procrssClosedHighPriorityIncident would be more similar to:
var getValueUsingGlideFunction (functionName) {
return function getFromRecord (record) {
return record[functionName]();
}
}
Ultimately, the goal is to compose processes by stringing together functions, rather than introducing higher order varadic functions which still abide by imperative techniques.
Nevertheless, I've enjoyed what you've done and thank you for sharing! I wish there were more posts like yours.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Javier: Takes us for a ride in his 2019 Tesla Model S, engages Ludicrous mode, and accelerates 0-60 in 2.4 seconds.
John: Takes us for a leisurely ride around the park in a horse drawn carriage.
My apologies if I'm not moving fast enough for you, but this is the very first in a very long series of articles that based on the 8 month span between Part 1 and Part 2, will end some time after George R. R. Martin completes his A Song of Ice and Fire series.
Referencing things monads, functors, applicatives, pipe, arity, variadic, point-free, pure, composition, etc., at this point in the series (if ever?) is more likely to scare away what little audience I have.
That said, I appreciate the feedback! Regarding collaborating to improve programming practices on the platform, I'm afraid posts like this one the community will have to suffice.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
haha.
I'm so sorry. just got excited that someone else is doing what I'm doing. then feared the OOP techniques of the post would create a confusion for newer programmers into thinking it's functional, so I went full steam ahead.
I'll stay tuned to your future posts, and if you don't mind the tesla, add my two cents. That's enough of a collaboration for me đ