O que significa o underscore (_) no início de uma função em Script Include?
Durante o desenvolvimento de soluções na plataforma ServiceNow, é comum encontrarmos Script Includes que possuem funções iniciadas com um caractere underscore (_).
Por exemplo:
_validarUsuario: function(userId) {
// Lógica de validação
}
Mas você já se perguntou por que alguns desenvolvedores utilizam esse caractere antes do nome de uma função? Ele possui alguma funcionalidade especial? Impede que outros scripts executem o método?
Neste artigo, vamos entender o significado dessa convenção, sua finalidade e como ela se comporta em diferentes cenários dentro do ServiceNow.
1. O que significa o underscore (_) em uma função?
O underscore (_) no início do nome de uma função é uma convenção de nomenclatura utilizada para identificar métodos destinados ao uso interno de uma classe.
Na prática, isso significa que a função foi desenvolvida para ser utilizada por outros métodos do próprio Script Include, e não para ser consumida diretamente por códigos externos.
Considere os seguintes métodos:
getUserInfo: function(userId) {
// Método público
},
_validateUser: function(userId) {
// Método interno
}
Nesse exemplo, temos duas intenções diferentes:
-
getUserInfo(): método público, destinado a ser chamado por outros scripts. -
_validateUser(): método auxiliar, destinado a ser utilizado internamente pelo próprio Script Include.
Essa abordagem facilita a leitura, a manutenção e a organização do código.
Importante: utilizar underscore não significa automaticamente que um método se torna privado no sentido de encapsulamento da programação orientada a objetos.
2. Exemplo prático em um Script Include
Vamos imaginar um cenário em que precisamos consultar informações de um usuário na tabela sys_user.
Antes de realizar a consulta, queremos verificar se o parâmetro informado é válido.
Para isso, vamos criar o Script Include UserUtils.
var UserUtils = Class.create();
UserUtils.prototype = {
initialize: function() {
},
getUserInfo: function(userId) {
if (!this._validateUser(userId)) {
return {
success: false,
message: 'Usuário inválido.'
};
}
var grUser = new GlideRecord('sys_user');
if (!grUser.get(userId)) {
return {
success: false,
message: 'Usuário não encontrado.'
};
}
return {
success: true,
name: grUser.getValue('name'),
email: grUser.getValue('email')
};
},
_validateUser: function(userId) {
if (!userId)
return false;
return /^[0-9a-f]{32}$/i.test(String(userId));
},
type: 'UserUtils'
};
Entendendo o código
O Script Include possui dois métodos principais.
Método público: getUserInfo()
É responsável por receber o sys_id do usuário, executar a validação, consultar a tabela e retornar as informações encontradas.
Método interno: _validateUser()
É responsável exclusivamente por validar se o parâmetro informado possui o formato esperado de um sys_id.
Observe que o método público executa a validação utilizando:
this._validateUser(userId);
A palavra-chave this permite acessar o método definido no próprio objeto.
Essa separação é interessante porque cada método possui uma responsabilidade específica.
Observação: nesse exemplo, a validação verifica o formato do identificador. Ela não confirma a existência do usuário na base de dados. Essa verificação acontece posteriormente, durante a consulta com GlideRecord.
3. Uma função com underscore é realmente privada?
Essa é uma das principais dúvidas de quem começa a trabalhar com Script Includes.
A resposta depende da forma como o Script Include está sendo utilizado.
Em um Script Include tradicional, executado no servidor, o underscore funciona como uma convenção de nomenclatura e não impede tecnicamente que o método seja chamado externamente.
Por exemplo, mesmo tendo definido _validateUser() como método interno, seria possível executar o seguinte código em um Background Script:
var userUtils = new UserUtils();
var isValid = userUtils._validateUser(
'6816f79cc0a8016401c5a33be04be441'
);
gs.info(isValid);
Nesse caso, o JavaScript permite a execução do método, mesmo que seu nome comece com underscore.
Isso acontece porque o caractere _ faz parte do nome da propriedade e não representa um modificador de acesso privado da linguagem.
Portanto, o método continua acessível no contexto server-side, desde que as regras de acesso ao Script Include permitam sua utilização.
O underscore comunica uma intenção de encapsulamento, mas não impõe esse encapsulamento no JavaScript tradicional.
4. E quando utilizamos GlideAjax?
Aqui encontramos uma diferença importante.
Em Script Includes que estendem AbstractAjaxProcessor e são utilizados por GlideAjax, métodos iniciados com underscore são tratados como privados pelo mecanismo de chamada AJAX do ServiceNow.
Isso significa que eles não podem ser chamados diretamente pelo cliente utilizando sysparm_name.
Considere o exemplo abaixo.
Script Include: UserAjaxUtils
Configure o Script Include com a opção Client callable habilitada.
var UserAjaxUtils = Class.create();
UserAjaxUtils.prototype = Object.extendsObject(
global.AbstractAjaxProcessor, {
getUserName: function() {
var userId = this.getParameter('sysparm_user_id');
if (!this._validateUser(userId))
return 'Usuário inválido';
var grUser = new GlideRecord('sys_user');
if (grUser.get(userId))
return grUser.getValue('name');
return 'Usuário não encontrado';
},
_validateUser: function(userId) {
if (!userId)
return false;
return /^[0-9a-f]{32}$/i.test(String(userId));
},
type: 'UserAjaxUtils'
});
Observação: o exemplo utiliza global.AbstractAjaxProcessor, padrão comum em aplicações escopadas. O escopo e as permissões de acesso devem ser configurados conforme a aplicação.
Chamando o método público pelo Client Script
var gaUser = new GlideAjax('UserAjaxUtils');
gaUser.addParam('sysparm_name', 'getUserName');
gaUser.addParam('sysparm_user_id', g_form.getValue('requested_for'));
gaUser.getXMLAnswer(function(answer) {
console.log(answer);
});
Nesse cenário, o método getUserName() pode ser executado pelo GlideAjax, desde que o Script Include esteja corretamente configurado e acessível.
Internamente, ele executa:
this._validateUser(userId);
Entretanto, se tentássemos chamar diretamente o método _validateUser() pelo GlideAjax:
gaUser.addParam('sysparm_name', '_validateUser');
A chamada não seria permitida pelo mecanismo padrão do GlideAjax.
Isso ocorre porque o ServiceNow considera métodos com nomes iniciados por underscore como métodos privados para esse tipo de chamada.
Atenção: esse comportamento não transforma o método em uma função privada para todos os contextos do JavaScript. Ele representa uma restrição específica da interface de execução do GlideAjax.
5. Quais são as vantagens de utilizar underscore?
Adotar essa convenção durante o desenvolvimento pode trazer diversos benefícios.
Organização do código
Permite identificar rapidamente quais métodos representam funcionalidades públicas e quais são utilizados apenas como auxiliares.
Manutenção simplificada
Ajuda outros desenvolvedores a compreenderem quais métodos fazem parte da interface de utilização do Script Include.
Separação de responsabilidades
Incentiva a criação de métodos menores, especializados e reutilizáveis internamente.
Redução do acoplamento
Ao orientar outros scripts a consumirem apenas métodos públicos, reduzimos a dependência de implementações internas que podem mudar ao longo do tempo.
Padronização
Estabelece uma convenção consistente entre os desenvolvedores, especialmente em projetos com múltiplos profissionais trabalhando na mesma aplicação.
6. Quando devo utilizar o underscore?
Uma boa prática é utilizar underscore nos métodos auxiliares que não foram projetados para consumo externo.
Por exemplo:
| Método | Finalidade | Convenção |
|---|---|---|
getUserInfo() |
Consultar dados de um usuário | Público |
createIncident() |
Criar um incidente | Público |
calculateSLA() |
Calcular uma informação de SLA | Público |
_validateUser() |
Validar parâmetro de usuário | Interno |
_formatResponse() |
Padronizar um retorno | Interno |
_buildPayload() |
Montar um payload de integração | Interno |
_writeLog() |
Registrar logs internos | Interno |
Essa separação torna mais clara a arquitetura do Script Include.
Entretanto, lembre-se de que esses nomes representam uma intenção de uso. Em Script Includes tradicionais, não são uma garantia de restrição de acesso.
7. O underscore é obrigatório?
Não.
Para Script Includes tradicionais, a utilização do underscore é uma convenção de desenvolvimento, não uma exigência do JavaScript ou da plataforma.
Um método auxiliar pode funcionar perfeitamente sem o caractere.
Por exemplo:
validateUser: function(userId) {
return !!userId;
}
Porém, ao adotar uma convenção consistente, aumentamos a clareza do código e facilitamos sua manutenção.
Já nos Script Includes utilizados por GlideAjax, o prefixo possui uma implicação adicional: métodos iniciados com underscore não ficam disponíveis como métodos diretamente invocáveis pelo cliente.
8. Underscore é um mecanismo de segurança?
Não deve ser tratado como uma solução de segurança isolada.
Embora o GlideAjax não permita invocar diretamente métodos iniciados com underscore, isso não significa que toda a lógica interna esteja automaticamente protegida.
Métodos públicos ainda podem chamar esses métodos auxiliares, e o código deve implementar as verificações necessárias.
Portanto, ao desenvolver Script Includes, principalmente aqueles marcados como Client callable, considere também:
-
Validar os parâmetros recebidos.
-
Verificar as permissões do usuário antes de acessar ou modificar informações.
-
Restringir o acesso ao Script Include conforme a necessidade.
-
Evitar expor informações sensíveis em métodos públicos.
-
Nunca confiar exclusivamente no nome de uma função como mecanismo de autorização.
O underscore ajuda a organizar e delimitar a interface de utilização, mas não substitui controles adequados de segurança.
Conclusão
O caractere underscore (_) no início do nome de uma função é uma convenção bastante utilizada no desenvolvimento ServiceNow para identificar métodos destinados ao uso interno de Script Includes.
Sua principal finalidade é melhorar a organização do código e deixar claro quais funcionalidades foram desenvolvidas para utilização pública e quais devem permanecer como implementações auxiliares.
Entretanto, existe uma distinção fundamental:
Em Script Includes tradicionais: o underscore representa apenas uma convenção, não impedindo chamadas externas no servidor.
Em Script Includes utilizados pelo GlideAjax: métodos iniciados com underscore são considerados privados pelo mecanismo AJAX e não podem ser chamados diretamente a partir do Client Script.
Compreender essa diferença é importante para desenvolver soluções mais organizadas, reutilizáveis e alinhadas às boas práticas da plataforma ServiceNow.