Código SIL limpo

SIL é uma linguagem de programação para automatizar o trabalho no Atlassian Jira e Confluence. Você pode ler mais sobre o SIL aqui .

Costumo trabalhar com scripts escritos em SIL e gostaria de compartilhar com você meus pensamentos sobre como tornar o código SIL “limpo”.

Neste artigo, vou formular primeiro as regras que me orientam ao escrever o código SIL e, em seguida, dar um exemplo de código e refatorar usando essas regras.

regras


  1. As estruturas de nomes começam com uma letra maiúscula.
  2. Adicione elementos de matriz usando o método AddElement .
  3. Use rotinas definidas pelo usuário para dividir seu código em blocos lógicos e se livrar dos comentários no código.
  4. Traga código reutilizável para bibliotecas ( inclusões ).
  5. Declarar estruturas antes do restante da declaração da variável.
  6. Atribua nomes significativos a estruturas e variáveis; nesse caso, você não precisará adicionar comentários adicionais a estruturas e variáveis.
  7. Nomeie variáveis ​​e funções de acordo com o guia de estilo do Google Java .

Agora vamos ver um exemplo de código SIL.

string USER = currentUser();
// Response
struct returnData {
    string status;
}
// Project
struct space {
    string key;
}
// Inner part with content
struct storage {
    string value;
    string representation;
}
// Part for storage
struct body {
    storage storage;
}
// Main entity for sending to Confluence
struct reqData {
    string type;
    string title;
    space space;
    body body;
}
reqData data;
data.type = "page";
data.title = "Page for issue " + key + "  " + summary + ".";
data.space.key = project;
data.body.storage.value = "<p> Author:"+userFullName(USER) + " description: "  + description + "</p>";
data.body.storage.representation = "storage";
// Create request
HttpRequest request;
HttpHeader header = httpCreateHeader("Content-Type", "application/json");
HttpHeader authHeader = httpBasicAuthHeader("admin", "admin");
request.headers += header;
request.headers += authHeader;
logPrint("WARN", request);
//POST
string JSONData = toJson(data);
logPrint("WARN", JSONData);
returnData result = httpPost("http://192.168.54.203:8090/rest/api/content/", request, JSONData);
string errMsg = httpGetErrorMessage();
logPrint("ERROR", "Last error message: " + errMsg);
logPrint("WARN", result);
string COMMENT = "Page created in Confluence " + updated + " by " + userFullName(USER) + " Status : " +result.status + "."; 
addComment(key, USER, COMMENT);
//Return Status
return result.status;

É muito difícil olhar para o código para determinar rapidamente o que o código está fazendo. Os comentários no código também não ajudam muito. Vamos tentar alterar o código de acordo com as regras acima.

Primeiro, olhe para a estrutura. Aqui está um exemplo:

struct body {
    storage storage;
}

Vemos que o "armazenamento de armazenamento" parece incompreensível. Seria mais claro se o código fosse assim:

struct body {
    Storage storage;
}

Agora vemos que definimos um campo na estrutura sob o nome storage do tipo Storage. Para escrevermos esse código, precisamos colocar a primeira letra de cada estrutura em maiúscula:

// Response
struct ReturnData {
    string status;
}
// Project
struct Space {
    string key;
}
// Inner part with content
struct Storage {
    string value;
    string representation;
}
// Part for storage
struct Body {
    Storage storage;
}
// Main entity for sending to Confluence
struct ReqData {
    string type;
    string title;
    Space space;
    Body body;
}

Agora vamos renomear a estrutura para que o nome da estrutura esclareça por que é necessário e não precisaríamos adicionar comentários:

struct Space {
    string key;
}
struct Storage {
    string value;
    string representation;
}
struct Body {
    Storage storage;
}
struct CreateConfluencePageRequest {
    string type;
    string title;
    Space space;
    Body body;
}
struct CreateConfluencePageResponse {
    string status;
}

Na minha opinião, esses nomes não exigem comentários adicionais para estruturas. Também declararemos estruturas no início do código.

Usamos as Regras 1, 5, 6.

Agora, vejamos o código após a declaração das estruturas:

string USER = currentUser();
CreateConfluencePageRequest data;
data.type = "page";
data.title = "Page for issue " + key + "  " + summary + ".";
data.space.key = project;
data.body.storage.value = "<p> Author:"+userFullName(USER) + " description: "  + description + "</p>";
data.body.storage.representation = "storage";
// Create request
HttpRequest request;
HttpHeader header = httpCreateHeader("Content-Type", "application/json");
HttpHeader authHeader = httpBasicAuthHeader("admin", "admin");
request.headers += header;
request.headers += authHeader;
logPrint("WARN", request);
//POST
string JSONData = toJson(data);
logPrint("WARN", JSONData);
CreateConfluencePageResponse result = httpPost("http://192.168.54.203:8090/rest/api/content/", request, JSONData);
string errMsg = httpGetErrorMessage();
logPrint("ERROR", "Last error message: " + errMsg);
logPrint("WARN", result);
string COMMENT = "Page created in Confluence " + updated + " by " + userFullName(USER) + " Status : " +result.status + "."; 
addComment(key, USER, COMMENT);
//Return Status
return result.status;

Observando o código, não podemos entender rapidamente o que está acontecendo no código. Vamos primeiro tentar dividir o código em blocos lógicos:

getNewConfluencePageContent();
createHttpRequest();
createConfluencePage();
addCommentToJiraIssue();

Ou seja, primeiro obtemos o conteúdo da nova página no Confluence, depois criamos uma solicitação http, criamos uma página no Confluence e escrevemos um comentário na solicitação Jira de que a página no Confluence foi criada. Agora vamos implementar estas funções:

function getNewConfluencePageContent() {
    CreateConfluencePageRequest data;
    data.type = "page";
    data.title = "Page for issue " + key + "  " + summary + ".";
    data.space.key = project;
    data.body.storage.value = "<p> Author:"+userFullName(currentUser()) + " description: "  + description + "</p>";
    data.body.storage.representation = "storage";
    return toJson(data);
}

function createHttpRequest() {
    HttpRequest request;
    HttpHeader header = httpCreateHeader("Content-Type", "application/json");
    HttpHeader authHeader = httpBasicAuthHeader("admin", "admin");
    request.headers = addElement(request.headers, header);
    request.headers += addElement(request.headers, authHeader);
    logPrint("WARN", request);
    return request;
}

function createConfluencePage(string pageJson) {
    HttpRequest request = createHttpRequest();
    CreateConfluencePageResponse result = httpPost("http://192.168.54.203:8090/rest/api/content/", request, pageJson);
    logPrint("ERROR", "Last error message: " + httpGetErrorMessage());
    logPrint("WARN", result);
    return result;
}

function addCommentToJiraIssue(string resultStatus) {
    string COMMENT = "Page created in Confluence " + updated + " by " + userFullName(currentUser()) + " Status : " +resultStatus + "."; 
    addComment(key, currentUser(), COMMENT);
}

string pageJson = getNewConfluencePageContent();
CreateConfluencePageResponse result = createConfluencePage(pageJson);
addCommentToJiraIssue(result.status);
return result.status;

Removemos os blocos lógicos na função (Regra 2). Agora podemos simplesmente escrever o código assim:

string pageJson = getNewConfluencePageContent();
CreateConfluencePageResponse result = createConfluencePage(pageJson);
addCommentToJiraIssue(result.status);
return result.status;

Nosso código contém quatro blocos lógicos. Primeiro, obtemos o json da nova página, depois criamos a página no Confluence, adicionamos um comentário à solicitação e retornamos o status de criação da página ao Confluence. Essas quatro linhas nos dão uma visão de nível superior do que o script faz. Se queremos entender o conteúdo da página no Confluence, sempre podemos ir para getNewConfluencePageContent e ver o conteúdo dessa função. Essa função contém apenas código para criar o conteúdo da página e nada mais; portanto, ao estudar o código da função, não seremos distraídos por outras funcionalidades.

Podemos assumir que precisaremos criar páginas no Confluence, não apenas a partir de um script. Portanto, vamos criar o arquivo confluence_helper.incl e colocar todas as funções necessárias para criar uma página no Confluence para este arquivo:

struct Space {
    string key;
}
struct Storage {
    string value;
    string representation;
}
struct Body {
    Storage storage;
}
struct CreateConfluencePageRequest {
    string type;
    string title;
    Space space;
    Body body;
}
struct CreateConfluencePageResponse {
    string status;
}

function createHttpRequest() {
    HttpRequest request;
    HttpHeader header = httpCreateHeader("Content-Type", "application/json");
    HttpHeader authHeader = httpBasicAuthHeader("admin", "admin");
    request.headers = addElement(request.headers, header);
    request.headers += addElement(request.headers, authHeader);
    logPrint("INFO", request);
    return request;
}

function createConfluencePage(string confluenceUrl, string pageJson) {
    HttpRequest request = createHttpRequest();
    CreateConfluencePageResponse result = httpPost(confluenceUrl, request, pageJson);
    logPrint("ERROR", "Last error message: " + httpGetErrorMessage());
    logPrint("INFO", result);
    return result;
}

Tornei a função createConfluencePage mais geral, adicionando outro parâmetro confluenceUrl a ela. Assim, seguimos a Regra 4.

Agora, nosso script principal ficará assim:

include "confluence_helper.incl";

function getNewConfluencePageContent() {
    CreateConfluencePageRequest data;
    data.type = "page";
    data.title = "Page for issue " + key + "  " + summary + ".";
    data.space.key = project;
    data.body.storage.value = "<p> Author:"+userFullName(currentUser()) + " description: "  + description + "</p>";
    data.body.storage.representation = "storage";
    return toJson(data);
}

function addCommentToJiraIssue(string resultStatus) {
    string comment = "Page created in Confluence " + updated + " by " + userFullName(currentUser()) + " Status : " +resultStatus + "."; 
    addComment(key, currentUser(), comment);
}


const string CONFLUENCE_URL = "http://192.168.54.203:8090/rest/api/content/";

string pageJson = getNewConfluencePageContent();
CreateConfluencePageResponse result = createConfluencePage(CONFLUENCE_URL, pageJson);
addCommentToJiraIssue(result.status);
return result.status;

Na primeira linha, incluí o arquivo confluence_helper.incl para usar a função de criação de página no Confluence.

Salvei o endereço do Confluence em uma variável constante e alterei os nomes das variáveis ​​de acordo com o estilo de notação Google Java (Regra 7).

Parece-me que isso pode ser interrompido com a refatoração. Como resultado da refatoração, obtivemos uma função de criação de página reutilizável no Confluence, e nosso código se tornou mais legível e suportado.

All Articles