Contents
New technology, such as AI and ChatGPT, is fascinating. It has the potential to revolutionize the way we work and live, but it’s important to remember that the applications and implications of these technologies are initially unknown. We must explore and experiment with them to truly understand their capabilities and limitations.
Take ChatGPT, for example; it’s a cutting-edge language model trained on a massive amount of text data. It’s used in various applications, from natural language processing to coding. But, as with any new technology, it’s important to remember that we’re still figuring out the best ways to use it. For example, in IT, we’re still exploring how ChatGPT can assist developers in coding tasks and how it can be integrated into service management platforms like ServiceNow.
What is ChatGPT
ChatGPT is a cool new technology that’s shaking up the IT world. It’s a language model trained on a ton of text data, meaning it can generate text all on its own. This might not sound like a big deal, but it’s powerful.
One of the most exciting things about ChatGPT is that it can be used to generate code. That’s right, you heard me right: code! As a developer, I know that writing code can sometimes be a pain in the butt. There’s always so much tedious boilerplate to write, and it’s easy to make mistakes. But with ChatGPT, you can feed it a bunch of examples of the type of code you want it to write, and it’ll spit out something pretty darn similar. This means that developers can spend less time on the boring stuff and more on the fun stuff.
ChatGPT and ServiceNow
Regarding ChatGPT and coding on the ServiceNow platform, a big question is whether it has the right know-how. Sure, ChatGPT can write code in many programming languages, including JavaScript, that ServiceNow uses. Plus, it can be taught about a specific field even more. But can a machine get the little details and complexities of working on ServiceNow, which is always changing and needs a deep understanding of its architecture and features?
Another thing to think about is how ChatGPT could affect developers’ jobs. Will it make their work easier and more efficient or lead them to lose their jobs? It’s too early to tell; however, more companies are using AI in their processes. As we dive deeper into ChatGPT’s capabilities and potential uses on ServiceNow, it’ll be exciting to see how it can change how we approach coding.
ChatGPT and Me
I had a new requirement that required an update to some code in ServiceNow. The code was not in a great state, and before I implemented the new requirement, I thought I would refactor it first. After refactoring the code myself, I wondered how it would compare to code improved by ChatGPT. After modifying the code to remove the organisational context, I entered it into ChatGPT. I gave the AI no context, just as I have given you no context.
(function runTransformScript(source, map, log, target /*undefined onStart*/ ) { if (source.u_classification == "CEO" || source.u_classification == "CTO" || source.u_classification == "CXO" || source.u_classification == "CIO" || source.u_classification == "CFO" || source.u_classification == "Executive" || source.u_classification == "President" || source.u_classification == "Vice President" || source.u_classification == "Manager" ) { var isMember = new GlideRecord('sys_user_grmember'); isMember.addQuery('user', target.sys_id); isMember.addQuery('group', 'abcdef1234567890abcdef1234567890'); //APPROVERS GROUP isMember.query(); if (isMember.next()) { gs.log("Position User: " + source.u_current_occupant + " Action: None"); } else { var addMember = new GlideRecord('sys_user_grmember'); addMember.initialize(); addMember.user = target.sys_id; addMember.group = 'abcdef1234567890abcdef1234567890'; //APPROVERS GROUP addMember.insert(); gs.log("Position User: " + source.u_current_occupant + " Action: Add"); } } else { var delMember = new GlideRecord('sys_user_grmember'); delMember.addQuery('user', target.sys_id); delMember.addQuery('group', 'abcdef1234567890abcdef1234567890'); //APPROVERS GROUP delMember.query(); while (delMember.next()) { delMember.deleteRecord(); gs.log("Position User: " + source.u_current_occupant + " Action: Delete"); } } })(source, map, log, target);The SN Nerd
This script is a transformation script that is intended to be run in the context of a ServiceNow instance. The script checks the “u_classification” field of the “source” record and compares it to a set of specific values (e.g. “CEO”, “CTO”, “CXO”, etc.). If the value matches one of the specified values, the script checks if the “target” user is already a member of a specific group (group ID: “abcdef1234567890abcdef1234567890”). If the user is not a member of the group, it adds the user to the group. If the value does not match any of the specified values, the script checks if the “target” user is a member of the specific group and removes the user from the group if they are a member. The script also logs the action taken for each user.
ChatGPT
ChatGPT has given an accurate summary of my script. It was an onAfter Transform Script to add or remove users to a group based on a user’s position.
Now, let’s start to put the AI through its paces.
AI, Refactor my code!
Refactor my code
The SN Nerd
Here is a refactored version of the code that uses an array to check for “u_classification” values, and also moves the group ID to a variable for better readability:
(function runTransformScript(source, map, log, target /*undefined onStart*/ ) { var groupId = 'abcdef1234567890abcdef1234567890'; var positions = ["CEO", "CTO", "CXO", "CIO", "CFO", "Executive", "President", "Vice President", "Manager"]; var isMember = new GlideRecord('sys_user_grmember'); isMember.addQuery('user', target.sys_id); isMember.addQuery('group', groupId); isMember.query(); if(positions.includes(source.u_classification)) { if (!isMember.next()) { var addMember = new GlideRecord('sys_user_grmember'); addMember.initialize(); addMember.user = target.sys_id; addMember.group = groupId; addMember.insert(); gs.log("Position User: " + source.u_current_occupant + " Action: Add"); } else { gs.log("Position User: " + source.u_current_occupant + " Action: None"); } } else { while (isMember.next()) { isMember.deleteRecord(); gs.log("Position User: " + source.u_current_occupant + " Action: Delete"); } } })(source, map, log, target);This version uses the
ChatGPTincludes()
method to check if the “u_classification” field of the “source” record is in an array of possible values, instead of checking it against a list of hardcoded values. It also moves the group ID to a variable at the top, making it easier to change the group ID in one place.
How did it do?
Using the term ‘refactor’ has resulted in an improved snippet of JavaScript code but not perhaps improved as much as I would have hoped. It has failed to incorporate many ServiceNow Best Practices and nuances. Globally scoped Server side code uses Javascript ES5 syntax, which does not support includes(). If you are lucky enough to be on the Tokyo version of the platform and have developed in application scope, ES6 syntax is supported. There are benefits to developing new code in the application scope, as you get access to more features as the product evolves. However, this code was not in the application scope in this case. But how was the AI to know that?
Let’s help it out a little bit more.
refactor my code using es5 syntax, adhering to servicenow best practice
SN Nerd
(function runTransformScript(source, map, log, target) { var groupId = 'abcdef1234567890abcdef1234567890'; var positions = ["CEO", "CTO", "CXO", "CIO", "CFO", "Executive", "President", "Vice President", "Manager"]; var isMember = new GlideRecord('sys_user_grmember'); isMember.addQuery('user', target.sys_id); isMember.addQuery('group', groupId); isMember.query(); if(positions.indexOf(source.u_classification) !== -1) { if (!isMember.next()) { var addMember = new GlideRecord('sys_user_grmember'); addMember.initialize(); addMember.user = target.sys_id; addMember.group = groupId; addMember.insert(); gs.log("Position User: " + source.u_current_occupant + " Action: Add"); } else { gs.log("Position User: " + source.u_current_occupant + " Action: None"); } } else { while (isMember.next()) { isMember.deleteRecord(); gs.log("Position User: " + source.u_current_occupant + " Action: Delete"); } } })(source, map, log, target);This version uses the
ChatGPTindexOf()
method to check if the “u_classification” field of the “source” record is in an array of possible values, instead ofincludes()
method that is not supported in es5. It also keeps the group ID as a variable at the top, making it easier to change the group ID in one place. As a best practice, we are not using the ‘let’ or ‘const’ keywords which are not supported by es5.
While we now have code that will run in an ES5 JavaScript environment, there have not been any new changes around ServiceNow Best Practices. We are going to have to be more explicit next time.
Looking more deeply at the code, I have made the following observations:
- The sys_id is stored in a variable instead of a System Property
- indexOf() on a GlideElement object will return undefined, as it is not operating on a string
- getValue() can be used instead of referencing the field (glide element object)
- Using the transform log API rather than gs.log() would be more performant
- Naming best practices have not been applied
Let’s tell the AI to refactor with these in mind.
Applying Best Practices
Since ChatGPT is unaware of some ServiceNow Best Practices or did not consider them important enough to incorporate into the refactoring process, let’s be explicit about it this time.
refactor the code using ES5 syntax. Store groupId in a system property, use getValue() instead of dot walking and use the transform log api instead of gs.log. Apply best practice to naming conventions.
SN Nerd
Here is a refactored version of the code using ES5 syntax and adhering to ServiceNow best practices, including storing the group ID in a system property, using the
getValue()
method instead of dot notation, and using the transform log API instead ofgs.log()
:(function runTransformScript(source, map, log, target) { var groupId = gs.getProperty("approvers_group_sys_id"); var positions = ["CEO", "CTO", "CXO", "CIO", "CFO", "Executive", "President", "Vice President", "Manager"]; var isMemberGR = new GlideRecord('sys_user_grmember'); isMemberGR.addQuery('user', target.sys_id); isMemberGR.addQuery('group', groupId); isMemberGR.query(); var currentOccupant = source.getValue('u_current_occupant'); var classification = source.getValue('u_classification'); if(positions.indexOf(classification) !== -1) { if (!isMemberGR.next()) { var addMemberGR = new GlideRecord('sys_user_grmember'); addMemberGR.initialize(); addMemberGR.setValue('user', target.sys_id); addMemberGR.setValue('group', groupId); addMemberGR.insert(); log.info("Position User: " + currentOccupant + " Action: Add"); } else { log.info("Position User: " + currentOccupant + " Action: None"); } } else { while (isMemberGR.next()) { isMemberGR.deleteRecord(); log.info("Position User: " + currentOccupant + " Action: Delete"); } } })(source, map, log, target);This version uses the
ChatGPTgetValue()
method to get the value of the “u_classification” and “u_current_occupant” fields of the “source” record and store it in variables, this is a best practice instead of using dot notation to access the fields. It also uses thegs.getProperty()
method to get the group ID from a system property, which makes it easier to change the group ID in one place. It also uses thelog.info()
method of the transform log API, which is the recommended way to log messages in a transform script. And also the naming conventions are followed, variable and function names are in camelCase.
The code is looking better now.
If it knew log.info() was the recommended method for logging in transform scripts, why didn’t it incorporate this in any of the previous refactors?
Adding in a new requirement
Despite some flaws, I am still very impressed with how ChatGPT has assisted me with improving code.
Unsurprisingly, my new fictional requirement is adding a new position, “Chief Artificial Intelligence Officer”, to the approver’s group.
modify my code to also check for postion “CAIO”
SN Nerd
Here is the modified version of the code that also checks for the position “CAIO”:
(function runTransformScript(source, map, log, target) { var groupId = gs.getProperty("approvers_group_sys_id"); var positions = ["CEO", "CTO", "CXO", "CIO", "CAIO", "CFO", "Executive", "President", "Vice President", "Manager"]; var isMemberGR = new GlideRecord('sys_user_grmember'); isMemberGR.addQuery('user', target.sys_id); isMemberGR.addQuery('group', groupId); isMemberGR.query(); var currentOccupant = source.getValue('u_current_occupant'); var classification = source.getValue('u_classification'); if(positions.indexOf(classification) !== -1) { if (!isMemberGR.next()) { var addMemberGR = new GlideRecord('sys_user_grmember'); addMemberGR.initialize(); addMemberGR.setValue('user', target.sys_id); addMemberGR.setValue('group', groupId); addMemberGR.insert(); log.info("Position User: " + currentOccupant + " Action: Add"); } else { log.info("Position User: " + currentOccupant + " Action: None"); } } else { while (isMemberGR.next()) { isMemberGR.deleteRecord(); log.info("Position User: " + currentOccupant + " Action: Delete"); } } })(source, map, log, target);This version added the “CAIO” position to the
positions
array, so that the script will also check for that value in the “u_classification” field of the “source” record. The script will now add the target user to the specific group if the “u_classification” field matches any of the values in thepositions
array, and remove the user from the group if the “u_classification” field does not match any of the values in the array.We can see it has added our CAIO to the list of positions.
ChatGPT
Conclusion
As I’ve shown through my experimentations above, ChatGPT has the potential to be a powerful tool for ServiceNow developers. It can help us improve our code by suggesting changes and writing new code that adheres to best practices, provided we know what they are. However, it’s important to remember that ChatGPT is still an AI and doesn’t fully understand the ins and outs of the ServiceNow platform. It’s up to us developers to ensure that the code it generates best fits our specific use case.
While ChatGPT can be an excellent tool for coding, it’s important to remember that it’s not a magic wand. Just like seeing everything as a nail when you use a hammer, relying too heavily on ChatGPT for all our coding needs could lead to issues. Instead, it’s best to use it as an assistive tool to improve our skills and knowledge.
It’s also worth noting that ChatGPT’s capabilities extend beyond just coding. We, developers, can use it to assist with documentation, testing, and project management. The possibilities are endless. And who knows, maybe this very conclusion was assisted by ChatGPT. The future is exciting, and it’s an exciting time to be a ServiceNow developer.
4 comments
Great article, I’m wondering about how ChatGPT, SN, and chat responses can be leveraged. Lots of potential, I’ve been using it for documentation and have been impressed at how close it is to exactly what I want.
Have you checked out Github Copilot? I’ve started using it for SN development (via VSCode) and it’s pretty slick. I love being able to write a comment in plain English and have it write out the code inline for me. It’s like autocomplete on overdrive haha
I’ve played around with vscode-chatgpt and Genie in vscode.
The problem with getValue() is that is does not return an empty string if the field is blank. Instead it returns the null object. So concatenation with another string results in concatenation of “null” instead of “”.
For example, if your positions array included a blank value “” to signify that an empty classification required the user to be added to the group (unlikely but bear with me) then this new code would not work.