1  Guia de desenvolvimento de pacotes

A rOpenSci aceita pacotes que atendam às nossas diretrizes por meio de um processo simplificado de Revisão por Pares de Software. Para garantir um estilo consistente em todas as nossas ferramentas, escrevemos este capítulo destacando nossas diretrizes para o desenvolvimento de pacotes. Leia e aplique também nosso capítulo sobre integração contínua (CI). Outras orientações para depois do processo de revisão são fornecidas na terceira seção deste livro, começando com um capítulo sobre colaboração.

Recomendamos que as pessoas desenvolvedoras de pacotes leiam o livro completo de Hadley Wickham e Jenny Bryan sobre desenvolvimento de pacotes, que está disponível gratuitamente on-line (em inglês). Nosso guia é parcialmente redundante em relação a outros recursos, mas destaca as diretrizes da rOpenSci.

Para saber por que vale a pena enviar um pacote para a rOpenSci para atender às diretrizes, dê uma olhada em motivos para submeter.

1.1 Nome do pacote e metadados

1.1.1 Como nomear seu pacote

  • Recomendamos fortemente nomes curtos e descritivos em letras minúsculas. Se o seu pacote tratar de um ou mais serviços comerciais, verifique se o nome não viola as diretrizes de marca. Você pode verificar se o nome do seu pacote está disponível, é informativo e não é ofensivo usando a função pak::pkg_name_check(); use também um mecanismo de pesquisa para ver se é ofensivo em um idioma diferente do inglês. Em particular, não escolha um nome de pacote que já esteja sendo usado no CRAN ou no Bioconductor.

  • Existe um equilíbrio entre as vantagens de um nome de pacote exclusivo e um nome de pacote menos original.

    • Um nome de pacote mais exclusivo pode ser mais fácil de rastrear (para você e nós avaliarmos o uso do pacote, por exemplo, menos falsos positivos ao digitar seu nome na pesquisa de código do GitHub) e pesquisar (para quando as pessoas usuárias perguntarem “como usar o pacote blah” em um mecanismo de pesquisa).
    • Por outro lado, um nome único demais pode fazer com que o pacote seja menos detectável (ou seja, não seja possível encontrá-lo ao pesquisar “como fazer isso em R”). Isso pode ser um argumento para nomear seu pacote com algo muito próximo ao tópico, como geojson).
  • Encontre outros aspectos interessantes sobre como nomear seu pacote neste texto do blog do Nick Tierney (em inglês) e, caso você mude de ideia, descubra como renomear seu pacote nesta outra postagem do blog do Nick.

1.1.2 Criando metadados para seu pacote

Recomendamos que você use o pacote codemetar para criar e atualizar um arquivo JSON CodeMeta para seu pacote por meio de codemetar::write_codemeta(). Ele incluirá automaticamente todas as informações úteis, incluindo tópicos do GitHub. O CodeMeta usa termos do Schema.org, portanto, à medida que ganha popularidade, os metadados JSON do seu pacote podem ser usados por serviços de terceiros, talvez até por mecanismos de pesquisa.

1.2 Plataformas

  • Os pacotes devem funcionar em todas as principais plataformas (Windows, macOS, Linux). Pode haver exceções para pacotes que interajam com funções específicas do sistema ou que adaptem utilitários que só funcionam em plataformas limitadas, mas deve-se fazer todo o possível para garantir a compatibilidade entre plataformas, incluindo a compilação específica em cada sistema ou a containerização de utilitários externos.

1.3 API do pacote

1.3.1 Nomeando funções e argumentos

  • A nomenclatura das funções e dos argumentos deve ser escolhida de modo a trabalhar em conjunto para formar uma API de programação comum e lógica que seja fácil de ler e de autocompletar.

    • Considere um esquema de nomenclatura objeto_verbo() para as funções do seu pacote que usam um tipo de dados comum ou interagem com uma API comum. objeto refere-se aos dados/API e verbo a ação principal. Esse esquema ajuda a evitar conflitos de nome com pacotes que podem ter verbos semelhantes e torna o código legível e fácil de preencher automaticamente. Por exemplo, em stringi as funções que começam com stri_ manipulam strings (stri_join(), stri_sort(), e em googlesheets funções que começam com gs_ são chamadas para a API do Google Sheets (gs_auth(), gs_user(), gs_download()).
  • Para funções que manipulam um objeto/dado e retornam um objeto/dado do mesmo tipo, faça com que o objeto/dado seja o primeiro argumento da função para aumentar a compatibilidade com o operador pipe (|> do R base, %>% do pacote magrittr).

  • Recomendamos fortemente usar snake_case em vez de todos os outros estilos, a menos que esteja fazendo a portabilidade de um pacote que já esteja sendo amplamente utilizado.

  • Evite conflitos de nomes de funções com pacotes básicos ou outros pacotes populares (por exemplo ggplot2, dplyr, magrittr, data.table)

  • A nomenclatura e a ordem dos argumentos devem ser consistentes entre as funções que usam entradas semelhantes.

  • As funções do pacote que importam dados não devem importar dados para o ambiente global, mas, em vez disso, devem retornar objetos. As atribuições ao ambiente global devem ser evitadas em geral.

1.3.2 Mensagens do console

  • Use o pacote cli ou as ferramentas do R básico (message() e warning()) para se comunicar com as pessoas que usam suas funções.

  • Os destaques do pacote cli incluem: empacotamento automático, respeito a convenção NO_COLOR, muitos elementos semânticos e ampla documentação. Mais informações neste texto em inglês.

  • Por favor, não use print() ou cat() a menos que seja para um print.*() ou str.*(), pois esses métodos de impressão de mensagens são mais difíceis de serem silenciados.

  • Forneça uma maneira de suprimir a verbosidade, de preferência em nível de pacote: torne a criação de mensagens dependente de uma variável ou opção de ambiente (como “usethis.quiet” no pacote usethis), em vez de um parâmetro da função. O controle das mensagens poderia ser feito em vários níveis (“nenhum”, “informar”, “debugar”) em vez de ser lógico (nenhuma mensagem / todas as mensagens). O controle da verbosidade é útil para quem utiliza a função, mas também em testes. Você pode encontrar mais comentários interessantes nesta issue do guia de design do tidyverse

  • Você pode fornecer traduções para as mensagens do seu pacote. O pacote potools pode te ajudar com essa tarefa.

1.3.3 Interfaces interativas/gráficas

Se estiver fornecendo uma interface gráfica de usuário (GUI) (como um aplicativo Shiny), para facilitar o fluxo de trabalho, inclua um mecanismo para reproduzir automaticamente as etapas realizadas na GUI. Isso pode incluir a geração automática de código para reproduzir os mesmos resultados, a saída de valores intermediários produzidos na ferramenta interativa ou simplesmente um mapeamento claro e bem documentado entre as ações da GUI e as funções usadas. (Consulte também a seção “Testes” abaixo).

O pacote tabulizer por exemplo, tem um fluxo de trabalho interativo para extrair tabelas, mas também pode extrair apenas coordenadas para que seja possível executar novamente como um script. Além disso, dois exemplos de aplicativos brilhantes que geram código são https://gdancik.shinyapps.io/shinyGEO/ e https://github.com/wallaceEcoMod/wallace/.

1.3.4 Verificação de entrada

Recomendamos que seu pacote use um método consistente de sua escolha para verificação de entradas (inputs) – seja o R básico, um pacote em R ou ajudantes personalizados.

1.3.5 Pacotes que envolvem recursos da Web (clientes de API)

Se o seu pacote acessar uma API da Web ou outro recurso da Web,

  • Certifique-se de que as solicitações enviem um agente de usuário, ou seja, uma maneira de identificar o que (seu pacote) ou quem enviou a solicitação. Deve ser possível substituir o agente de usuário padrão do pacote. Idealmente, o agente de usuário deve ser diferente nos serviços de integração contínua e no desenvolvimento (com base, por exemplo, nos nomes de usuário do GitHub das pessoas desenvolvedoras).
  • Você pode escolher padrões diferentes (melhores) do que os da API e, nesse caso, deve documentá-los.
  • Seu pacote deve ajudar com a paginação, permitindo que os usuários não se preocupem com isso, pois o pacote faz todas as solicitações necessárias.
  • Seu pacote deve ajudar a limitar a taxa de acordo com as regras da API.
  • Seu pacote deve reproduzir erros de API e possivelmente explicá-los em mensagens de erro informativas.
  • Seu pacote pode exportar funções de alto nível e funções de baixo nível, sendo que estas últimas permitem que os usuários chamem os pontos de acesso (endpoints) da API diretamente com mais controle (como gh::gh()).

Para obter mais informações, consulte a postagem do blog: Por que você deve (ou não deve) criar um cliente de API (em inglês).

1.3.6 Pacotes que envolvem software externo

  • Documente claramente como instalar o pacote, incluindo todos os pacotes ou bibliotecas externas necessários, incluindo, quando aplicável, etapas explícitas em sistemas operacionais comuns.
  • Forneça uma função de relatório de situação (sitrep) para verificar se o software foi instalado, com dicas caso algo esteja faltando. Exemplo do pacote greta.
  • Se possível, forneça uma função que ajude na instalação. Exemplo no pacote hugodown.

1.4 Estilo de código e práticas recomendadas

  • Para obter mais informações sobre como estilizar seu código, nomear funções e scripts R dentro da seção R/ recomendamos a leitura do capítulo R Code do livro R Packages (em inglês). Recomendamos o uso do Air ou do pacote styler para automatizar parte do estilo do código. Também sugerimos a leitura do Guia de estilo do Tidyverse (em inglês).

  • Você pode optar por usar = ao invés de <- desde que seja consistente com uma escolha em seu pacote. Recomendamos evitar o uso de -> para atribuição em um pacote. Se você usar <- em seu pacote e também usar R6 nesse pacote, você será forçado a usar = para atribuição em seu R6Class - isso não é considerado uma inconsistência porque você não pode usar <- nesse caso.

  • Você pode usar o pacote lintr para identificar algumas possíveis áreas de melhoria. Exemplo de fluxo de trabalho.

1.5 Arquivo CITATION

  • Se o seu pacote ainda não tiver um arquivo CITATION, você poderá criar um com usethis::use_citation() e preenchê-lo com os valores gerados pela função citation().

  • O CRAN exige que os arquivos CITATION sejam declarados como itens bibentry e não na forma previamente aceita de citEntry().

  • Se você arquivar cada versão de seu repositório do GitHub no Zenodo, adicione a tag DOI principal do Zenodo ao arquivo CITATION.

  • Se um dia depois de revisão na rOpenSci você publicar um artigo sobre seu pacote, adicione-o ao arquivo CITATION.

  • Menos relacionado ao seu pacote em si, mas ao que o apoia: se o seu pacote envolve um recurso específico, como uma fonte de dados ou, digamos, um algoritmo estatístico, lembre as pessoas que utilizam o software sobre como citar esse recurso por meio de, por exemplo, citHeader(). Talvez até mesmo adicione a referência do recurso.

Como exemplo, veja o arquivo CITATION do dynamite que faz referência ao manual do R, bem como a outras publicações associadas.

citHeader("To cite dynamite in publications use:")

bibentry(
  key = "dynamitepaper",
  bibtype  = "Misc",
  doi = "10.48550/ARXIV.2302.01607",
  url = "https://arxiv.org/abs/2302.01607",
  author = c(person("Santtu", "Tikka"), person("Jouni", "Helske")),
  title = "dynamite: An R Package for Dynamic Multivariate Panel Models",
  publisher = "arXiv",
  year = "2023"
)

bibentry(
  key = "dmpmpaper",
  bibtype  = "Misc",
  title    = "Estimating Causal Effects from Panel Data with Dynamic 
    Multivariate Panel Models",
  author = c(person("Santtu", "Tikka"), person("Jouni", "Helske")),
  publisher = "SocArxiv",
  year     = "2022",
  url      = "https://osf.io/preprints/socarxiv/mdwu5/"
)

bibentry(
  key = "dynamite",
  bibtype  = "Manual",
  title    = "Bayesian Modeling and Causal Inference for Multivariate
    Longitudinal Data",
  author = c(person("Santtu", "Tikka"), person("Jouni", "Helske")),
  note  = "R package version 1.0.0",
  year     = "2022",
  url      = "https://github.com/ropensci/dynamite"
)

1.6 README

  • Todos os pacotes devem ter um arquivo README, denominado README.md na raiz do repositório. O README deve incluir, de cima para baixo:

    • O nome do pacote.
    • Selos (badges) para integração contínua e cobertura de testes, o selo para revisão por pares da rOpenSci assim que ele for iniciado (veja abaixo), um selo do repostatus.org e quaisquer outros selos (por exemplo do R-universe).
    • Uma breve descrição dos objetivos do pacote (o que ele faz? por que seria interessante usá-lo?), com links descritivos para todas as vinhetas (vignettes), a menos que o pacote seja pequeno e haja apenas uma vinheta repetindo o README. Certifique-se também de que as vinhetas sejam renderizadas e legíveis, consulte a seção “site de documentação”).
    • Instruções de instalação usando, por exemplo, o pacote remotes, pacote pak ou R-universe.
    • Qualquer configuração adicional necessária (tokens de autenticação, etc.).
    • Breve demonstração de uso.
    • Se aplicável, como o pacote se compara a outros pacotes semelhantes e/ou como ele se relaciona com outros pacotes.
    • Informações de citação, ou seja, direcione a forma de citação preferida no README adicionando o texto padrão “aqui está como citar meu pacote”. Veja, por exemplo o README do pacote ecmwfr.

Se você usar outro selo de status de repositório, como o ciclo de vida, adicione também um selo do repostatus.org. Exemplo de um README de repositório com dois selos de status de repositório.

  • Depois de enviar um pacote e ele ter sido aprovado na verificação editorial, adicione um selo de revisão por pares por meio do
[![rOpenSci software peer-review](https://badges.ropensci.org/<issue_id>_status.svg)](https://github.com/ropensci/software-review/issues/<issue_id>)

onde issue_id é o número da Issue no repositório software-review. Por exemplo, o selo para rtimicropem usa o número 126, pois é o número da Issue de revisão. O selo indicará primeiro “under review” (em revisão) e depois “peer-reviewed” (revisado por pares) assim que o seu pacote tiver sido integrado (Issue marcada como “approved” (aprovada) e fechada), e será vinculado à Issue de revisão.

  • Se o seu README tiver muitos selos, considere ordená-los em uma tabela HTML para facilitar a obtenção de informações. Veja exemplos no repositóriondrake e no repositório qualtRics. As seções possíveis são:

  • Se o seu pacote se conectar a uma fonte de dados ou serviço on-line, ou envolver outro software, considere que o README do seu pacote pode ser o ponto de partida de quem usa o utiliza pela primeira vez. Ele deve fornecer informações suficientes para entender a natureza dos dados, do serviço ou do software e fornecer links para outros dados e documentação relevantes. Por exemplo, um README não deve se limitar a dizer: “Fornece acesso ao GooberDB”, mas também incluir, “…, um repositório on-line de avistamentos de Goober na América do Sul. Mais informações sobre o GooberDB e a documentação da estrutura e dos metadados do banco de dados podem ser encontradas em link”.

  • Recomendamos não criar o README.md diretamente, mas a partir de um README.Rmd (um arquivo R Markdown) se você tiver algum código de demonstração. A vantagem do .Rmd é que você pode combinar texto com código que pode ser facilmente atualizado sempre que seu pacote for atualizado.

  • Considere o uso da função usethis::use_readme_rmd() para obter um modelo para o arquivo README.Rmd e para configurar automaticamente uma verificação para garantir que o arquivo README.md seja sempre mais recente que o README.Rmd antes de fazer um commit.

  • Exemplos extensos devem ser mantidos em uma vinheta. Se você quiser tornar as vinhetas mais acessíveis antes de instalar o pacote, sugerimos criar um site para seu pacote.

  • Adicionar um código de conduta e as diretrizes de contribuição.

  • Veja o README do pacote gistr para um bom exemplo de README a ser seguido em um pacote pequeno, e o README do pacote bowerbird para um bom exemplo de README para um pacote maior.

1.7 Documentação

1.7.1 Geral

  • Todas as funções exportadas de pacote devem ser totalmente documentadas com exemplos.

  • Se houver possível sobreposição ou confusão com outros pacotes que forneçam funcionalidade semelhante ou que tenham um nome semelhante, adicione uma nota no README, na vinheta principal e, potencialmente, no campo Descrição do DESCRIPTION. Exemplos em README do rtweet, README do rebird e o pacote slurmR (que não é parte da rOpenSci).

  • O pacote deve conter documentação geral para ?pacote(ou ?`pacote-package` se houver um conflito de nomes). Opcionalmente, você pode usar ambos ?pacote e ``?pacote-package`` para o arquivo de manual do pacote, usando a etiqueta@aliasesdo roxygen. [usethis::use_package_doc()`](https://usethis.r-lib.org/reference/use_package_doc.html) adiciona o modelo para a documentação geral.

  • O pacote deve conter pelo menos um HTML que ofereça uma cobertura substancial das funções do pacote, ilustrando casos de uso realistas e como as funções devem interagir. Se o pacote for pequeno, a vinheta e o README poderão ter conteúdo muito semelhante.

  • Como no caso de um README, a documentação geral ou as vinhetas podem ser o primeiro ponto de entrada para quem usa o pacote. Se o seu pacote se conectar a uma fonte de dados ou a um serviço on-line, ou envolver outro software, ele deverá fornecer informações suficientes para entender a natureza dos dados, do serviço ou do software e fornecer links para outros dados e documentação relevantes. Por exemplo, a introdução ou a documentação de uma vinheta não deve se limitar a dizer: “Fornece acesso ao GooberDB”, mas também incluir: “…, um repositório on-line de avistamentos de Goober na América do Sul. Mais informações sobre o GooberDB e a documentação da estrutura e dos metadados do banco de dados podem ser encontradas no link”. Qualquer vinheta deve descrever o conhecimento necessário para que seja possível entender a vinheta antecipadamente.

A vinheta geral deve apresentar uma série de exemplos que progridam em complexidade, do uso básico ao avançado.

  • A funcionalidade que provavelmente será usada apenas para desenvolvimento mais avançado pode ser melhor colocada em uma vinheta separada (por exemplo, a programação usando NSE (non-standard evaluation) com dplyr).

  • O README, a documentação geral do pacote, as vinhetas, os sites etc. devem ter informações suficientes no início para obter uma visão geral de alto nível do pacote e dos serviços/dados aos quais ele se conecta e fornecer navegação para outras partes relevantes da documentação. Isso é para seguir o princípio de vários pontos de entrada ou seja, levar em conta o fato de que qualquer parte da documentação pode ser o primeiro encontro que alguém tem com o pacote e/ou com a ferramenta/dados que ele envolve.

  • A(s) vinheta(s) deve(m) incluir citações de software e documentos, quando apropriado.

  • Se o seu pacote fornecer acesso a uma fonte de dados, exigimos que o arquivo DESCRIPTION contenha (1) uma breve identificação e/ou descrição da organização responsável pela emissão dos dados; e (2) o URL com link para uma página pública que forneça, descreva ou permita o acesso aos dados (que muitas vezes pode ser diferente do URL que leva diretamente à fonte de dados).

  • Use mensagens de inicialização de pacote somente quando necessário (mascaramento de função, por exemplo). Evite mensagens de inicialização de pacotes como “Esse é o pacote 2.4-0” ou orientação de citação, pois elas podem ser irritantes para quem o utiliza. Confie na documentação para obter essa orientação.

  • Você pode optar por ter uma seção README sobre casos de uso do seu pacote (outros pacotes, publicações em blogs etc.), exemplo.

1.7.2 roxygen2 use

  • Solicitamos que todos os envios usem o roxygen2 para a documentação. O roxygen2 é um pacote R que compila automaticamente os arquivos .Rd para a pasta man em seu pacote a partir de etiquetas escritas acima de cada função. O roxygen2 tem suporte à sintaxe Markdown. Uma das principais vantagens de usar o roxygen2 é que seu NAMESPACE sempre será gerado automaticamente e estará atualizado.

  • Mais informações sobre o uso da documentação do roxygen2 estão disponíveis no capítulo sobre documentação de funções do livro R Packages (em inglês) e no próprio site do roxygen2.

  • Se você estivesse escrevendo o .Rd diretamente sem o roxygen2, o Rd2roxygen contém funções para converter o .Rd em documentação do roxygen.

  • Todas as funções devem documentar o tipo de objeto retornado com a etiqueta @return.

  • O valor padrão de cada parâmetro deve ser claramente documentado. Por exemplo, em vez de escrever “Um valor lógico que determina se …”, você deve escrever “Um valor lógico (por padrão TRUE) que determina se …”. Também é uma boa prática indicar os valores padrão diretamente na definição da função:

f <- function(a = TRUE) {
  # código da função
}

1.7.3 Exemplos de conjuntos de dados

Para documentar a interface do seu pacote, talvez seja necessário usar conjuntos de dados de exemplo. Você pode usar conjuntos de dados básicos do R (no pacote datasets), como penguins, ou redistribuir e documentar os dados com as devidas atribuições. Tenha o cuidado de escolher dados que estejam em conformidade com o código de conduta da rOpenSci e que, em geral, não sejam prejudiciais ou alienantes para ninguém.

1.7.4 URLs na documentação

Esta subseção é particularmente relevante para quem deseja enviar seu pacote para o CRAN. O CRAN verificará os URLs em sua documentação e não permite códigos de status de redirecionamento, como 301. Você pode usar o pacote urlchecker para reproduzir essas verificações e, em particular, substituir os URLs pelos URLs para os quais eles redirecionam. Outras pessoas já usaram a opção para escapar de alguns URLs (alterar <https://ropensci.org/> para https://ropensci.org/, ou \url{https://ropensci.org/} para https://ropensci.org/.), mas se você fizer isso, precisará implementar algum tipo de verificação de URL para evitar que eles sejam quebrados sem que você perceba. Além disso, os links não poderão ser clicados nos documentos locais.

1.8 Site de documentação

Recomendamos a criação de um site de documentação para seu pacote usando o pacote pkgdown. O livro R packages (em inglês) apresenta um capítulo sobre pkgdown e também o pkgdown tem seu próprio site de documentação.

Há alguns elementos que gostaríamos de destacar aqui.

1.8.1 Implementação automática do site de documentação

Você só precisa se preocupar com a implementação automática (automatic deployment) do seu site até a aprovação e a transferência do repositório do seu pacote para a organização ropensci; de fato, depois disso, um site pkgdown será criado para o seu pacote após cada push para o repositório do GitHub. Você pode encontrar o status dessas compilações em https://dev.ropensci.org/job/package_name por exemplo para magick; e o site em https://docs.ropensci.org/package_name por exemplo para magick. A construção do site usará seu arquivo de configuração pkgdown, se você tiver um, exceto para o estilo que usará o arquivo de modelo do pacoterotemplate. O site resultante terá uma barra de pesquisa local. Pedimos que informe erros, perguntas e solicitações de recursos sobre a implementação automática em https://github.com/ropensci/docs/ e sobre o modelo em https://github.com/ropensci/rotemplate/.

Se as vinhetas do seu pacote precisarem de credenciais (chaves de API, tokens, etc.) para serem ativadas, talvez você queira renderizar as vinhetas previamente, já que as credenciais não podem ser usadas no servidor de documentos.

Antes do envio e da transferência do pacote, você pode usar a abordagem documentada por pkgdown ou o pacote tic para a implantação automática do site do pacote. Isso evitaria o incômodo de executar (e lembrar de executar) pkgdown::build_site() toda vez que o site precisar ser atualizado. Primeiro, consulte nosso capítulo sobre integração contínua se você não estiver familiarizado com a integração contínua. De qualquer forma, não se esqueça de atualizar todas as ocorrências do URL do site após a transferência para a organização ropensci.

1.8.2 Idioma

Se a documentação do seu pacote estiver escrita em um idioma diferente do inglês (mas suportado pelo sistema de revisão por pares do software rOpenSci), você poderá declarar esse idioma para que o site do pkgdown seja localizado.

Porém, ainda não é possível obter um site pkgdown multilíngue diretamente.

1.8.3 Agrupamento de funções no índice

Quando seu pacote tiver muitas funções, é conveniente que apareçam agrupadas no índice da documentação, o que pode ser feito de forma mais ou menos automática.

Se você usa o roxygen2 acima da versão 6.1.1, deve usar a tag @family na documentação de suas funções para indicar o agrupamento. Isso lhe dará links entre as funções na documentação local do pacote instalado (seção “See also”) e permitirá que você use a função has_concept do pacote pkgdown no arquivo de configuração do seu site. Exemplo não relacionado a rOpenSci, cortesia de optiRum: tag family, arquivo de configuração do pkgdown e seção no índice resultante. Para personalizar o texto do título da referência cruzada criada pelo roxygen2 (Other {family}:), consulte a documentação do roxygen2 sobre como fornecer uma lista rd_family_title no arquivo man/roxygen/meta.R.

De forma menos automática, veja o exemplo do website do pacote drake e arquivo de configuração associado.

1.8.4 Marca de autoria

Você pode tornar os nomes de (algumas) das pessoas autoras clicáveis, adicionando um URL, e pode até mesmo substituir os nomes por um logotipo (pense na rOpenSci… ou na sua organização/empresa!). Veja a documentação do pkgdown.

1.8.5 Ajustando a barra de navegação

Você pode tornar o conteúdo do seu site mais fácil de navegar ajustando a barra de navegação, consulte a documentação do pkgdown. Em particular, observe que, se você nomear a vinheta principal de seu pacote como “pkg-name.Rmd”, ela poderá ser acessada na barra de navegação como Para começar (Get started) em vez de via Artigos > Título da vinheta (Articles > Vignette Title).

1.8.6 Renderização matemática

Consulte a documentação do pkgdown. Nosso modelo é compatível com essa configuração.

1.9 Autoria

O arquivo DESCRIPTION de um pacote deve listar as pessoas que participaram da autoria e que colaboraram com o pacote, usando o parâmetro Authors@R para indicar suas funções (author/creator/contributor, etc.) e usando o campo de comentário para indicar o ID do ORCID de cada pessoa e o ID ROR de cada organização, se houver. Veja esta seção de “Escrevendo extensões R” para obter detalhes.
Se você achar que as pessoas que revisaram fizeram uma contribuição substancial para o desenvolvimento do seu pacote, poderá listá-los na seção Authors@R com o tipo de contribuição "rev", da seguinte forma:

    person("Bea", "Hernández", role = "rev",
    comment = "Bea revisou o pacote (v. X.X.XX) para rOpenSci, veja <https://github.com/ropensci/software-review/issues/116>"),

Somente inclua revisores(as) depois de pedir seu consentimento. Leia mais nesta postagem do blog Thanking Your Reviewers: Gratitude through Semantic Metadata (“Agradecendo as revisões: Gratidão por meio de metadados semânticos”). Por favor, não liste pessoas editoras como colaboradoras. Sua participação e contribuição para a rOpenSci já são agradecimentos suficientes!

1.9.1 Autoria do código incluído no pacote

Muitos pacotes incluem códigos de outros softwares. Se arquivos inteiros ou funções individuais forem incluídos de outros pacotes, os pacotes rOpenSci devem seguir a Política de Repositório do CRAN:

A propriedade dos direitos autorais e de propriedade intelectual de todos os componentes do pacote deve ser clara e inequívoca (inclusive a partir da especificação de autoria no arquivo DESCRIPTION). Quando o código for copiado (ou derivado) do trabalho de outros (inclusive do próprio R), deve-se tomar cuidado para que quaisquer declarações de direitos autorais/licenças sejam preservadas e a autoria não seja deturpada.

De preferência, um campo ‘Authors@R’ seria usado com funções ‘ctb’ para quem tem a autoria deste código. Como alternativa, o campo “Autor” deve listar essas pessoas como colaboradoras.

Quando os direitos autorais forem detidos por uma entidade que não seja as pessoas autoras do pacote, isso deve ser indicado preferencialmente por meio das funções ‘cph’ no campo ‘Authors@R’ ou usando um campo ‘Copyright’ (se necessário, referindo-se a um arquivo inst/COPYRIGHTS).

As marcas registradas devem ser respeitadas.

1.10 Licença

O pacote precisa ter uma licença aceita pelo CRAN ou OSI. O livro R packages (em inglês) inclui uma seção útil sobre licenças.

Se o seu pacote agrupar código de outras fontes, você também precisará reconhecer a autoria do código original no seu arquivo DESCIPTION, geralmente com uma função de detentor de direitos autorais: role = "cph". Para saber como atualizar seu arquivo DESCRIPTION, consulte o livro R packages (em inglês).

1.11 Testes

  • Todos os pacotes devem passar nas verificações do R CMD check/devtools::check() em todas as principais plataformas.

  • Todos os pacotes devem ter um conjunto de testes que abranja a funcionalidade principal do pacote. Os testes também devem abranger o comportamento do pacote em caso de erros.

  • É uma boa prática escrever testes unitários para todas as funções e para todo o código do pacote em geral, garantindo que a funcionalidade principal seja coberta. Se a cobertura de testes em seu pacote está abaixo de 75%, provavelmente exigirá testes adicionais ou explicações antes de ser enviado para revisão.

  • Recomendamos o uso do pacote testthat para escrever testes. Uma alternativa é o tinytest.

  • Se esforce para escrever testes ao escrever cada nova função. Isso atende à necessidade óbvia de ter um teste adequado para o pacote, mas permite que você pense sobre as várias maneiras pelas quais uma função pode falhar e programe defensivamente contra essas falhas. Mais informações sobre testes.

  • Os testes devem ser fáceis de entender e ser tão autocontidos quanto possível. Ao usar o testthat, evite usar código fora do test_that() (como etapas de pré-processamento). Recomendamos a leitura da seção “high-level principles for testing” (princípios de alto nível para testes) no livro R Packages.

  • Os pacotes com aplicativos Shiny devem usar uma estrutura de testes unitários, como shinytest2 ou shinytest para testar se as interfaces interativas se comportam conforme o esperado.

  • Para testar as funções que criam gráficos, sugerimos usar o vdiffr, uma extensão do pacote testthat que se baseia em testes com snapshots do testthat.

  • Se o seu pacote interagir com recursos da Web (APIs da Web e outras fontes de dados na Web), você poderá achar o livro HTTP testing in R, de Scott Chamberlain e Maëlle Salmon relevante. Alguns pacotes que ajudam nos testes de HTTP (e seus clientes HTTP correspondentes) são:

  • O pacote testthat tem uma função skip_on_cran() que você pode usar para não executar testes no CRAN. Recomendamos usar isso em todas as funções que são chamadas de API, pois é muito provável que elas falhem no CRAN. Esses testes ainda devem ser executados na integração contínua. Observe que a partir do testthat 3.1.2 skip_if_offline() chama automaticamente skip_on_cran(). Mais informações sobre em CRAN preparedness for API wrappers (Preparação do CRAN para utilização de APIs).

  • Se o seu pacote interagir com um banco de dados, você poderá achar o pacote dittodb útil.

  • Depois de configurar a integração contínua (CI) use o relatório de cobertura de código do seu pacote (veja esta seção do nosso livro) para identificar linhas não testadas e adicionar mais testes.

  • Mesmo que você use a integração contínua, recomendamos que você execute testes localmente antes de enviar seu pacote (talvez seja necessário definir Sys.setenv(NOT_CRAN="true")).

1.12 Exemplos

  • Inclua exemplos abrangentes na documentação. Além de demonstrar como usar o pacote, eles podem funcionar como uma maneira fácil de testar a funcionalidade do pacote antes de haver testes adequados. No entanto, lembre-se de que exigimos testes em pacotes contribuídos.

  • Você pode executar exemplos com devtools::run_examples(). Observe que quando você executa o R CMD CHECK ou equivalente (por exemplo, devtools::check()), seus exemplos que não estão incluídos no \dontrun{} ou \donttest{} são executados. Consulte a seção tabela de resumo na documentação do roxygen2.

  • Para evitar que os exemplos sejam executados no CRAN (por exemplo, se requerem autenticação), você precisa usar \dontrun{}. No entanto, para uma primeira submissão, o CRAN não permitirá que você pule todos os exemplos. Nesse caso, você pode adicionar alguns pequenos exemplos de brinquedo, ou envolver o código de exemplo com try(). Consulte também a etiqueta @exampleIf do roxygen2.

  • Além de executar exemplos localmente em seu próprio computador, é altamente recomendável que você execute exemplos em um dos sistemas de integração contínua. Mais uma vez, os exemplos que não estão incluídos em \dontrun{} ou \donttest{} serão executados, mas para aqueles que estão, você pode configurar suas compilações de integração contínua para executá-los por meio dos argumentos de verificação do R CMD --run-dontrun e/ou --run-donttest.

1.13 Dependências de pacotes

  • Em geral, é melhor ter menos dependências.

  • Considere as vantagens e desvantagens envolvidas no fato de depender de um pacote. Por um lado, o uso de dependências reduz o esforço de codificação e pode se basear em funcionalidades úteis desenvolvidas por outras pessoas, especialmente se a dependência executar tarefas complexas e tiver alto desempenho, e/ou for bem avaliada e testada. Por outro lado, ter muitas dependências sobrecarrega a pessoa mantenedora ao ter que acompanhar as alterações nesses pacotes, arriscando a sustentabilidade de longo prazo do seu pacote. Isso também aumenta o tempo e o tamanho da instalação, o que leva em consideração principalmente o seu ciclo de desenvolvimento e o de outras pessoas, bem como os sistemas de compilação automatizados. Pacotes “pesados” - aqueles com muitas dependências e aqueles com grandes quantidades de código compilado - aumentam esse custo.

  • As abordagens para reduzir as dependências incluem:

    • Se você usar apenas algumas funções de uma dependência grande ou pesada, poderá copiá-las para seu próprio pacote. (Consulte a seção Autoria acima para saber como reconhecer a autoria original do código copiado). Por outro lado, funções complexas com muitos casos especiais (por exemplo, analisadores sintáticos) exigem testes e verificações consideráveis.

      • Um exemplo comum disso é o retorno de “tibbles” no estilo tidyverse em funções do pacote que fornecem dados. É possível evitar o uso do pacote tibble retornando um tibble criado pela modificação de um data.frame da seguinte forma:

        class(df) <- c("tbl_df", "tbl", "data.frame") 

        (Observe que essa abordagem deve ser usada e testada com muito cuidado, especialmente porque pode quebrar o comportamento esperado de objetos reclassificados).

    • Certifique-se de que esteja usando o pacote em que a função está definida, e não aquele em que ela é reexportada. Por exemplo, muitas funções do devtools podem ser encontradas em pacotes especializados menores, como sessioninfo. A função %>% deve ser importada do pacote magrittr onde ela é definida, em vez do mais pesado dplyr , que a reexporta.

    • Algumas dependências são preferidas porque fornecem uma interpretação mais fácil de nomes de funções e sintaxe mais fáceis do que as soluções básicas do R. Se esse for o principal motivo para usar uma função em uma dependência pesada, considere a possibilidade de envolver a abordagem do R básico em uma função interna bem nomeada em seu pacote. Veja, por exemplo, o script em R do rlang que fornece funções com uma sintaxe semelhante às funções purrr.

    • Se as dependências tiverem funcionalidades sobrepostas, verifique se você pode confiar em apenas uma delas.

    • Mais dicas de gerenciamento de dependências podem ser encontradas no capítulo “Dependencies: Mindset and Background” do livro R packages (em inglês) e em um post do Scott Chamberlain.

  • Usar Imports em vez de Depends para pacotes que fornecem funções de outros pacotes. Certifique-se de listar os pacotes usados para o teste (testthat) e a documentação (knitr, roxygen2) em seu Suggests das dependências do pacote (se você usar usethis para adicionar a infraestrutura de teste via usethis::use_testthat() ou uma vinheta via usethis::use_vignette(), os pacotes necessários serão adicionados ao DESCRIPTION). Se você usar algum pacote nos exemplos ou testes do seu pacote, certifique-se de listá-lo em Suggests se ainda não estiver listado em Imports.

  • Verifique o status de desenvolvimento de todas as dependências que você adicionar. Especialmente para pacotes hospedados no GitHub, é muito útil verificar se eles são mantidos ativamente e se não foram arquivados.

  • Se o seu pacote (não do Bioconductor) depender de pacotes do Bioconductor, certifique-se de que as instruções de instalação no README e na vinheta sejam claras o suficiente, mesmo para uma pessoa não esteja familiarizada com o ciclo de publicação do Bioconductor.

    • É necessário usar o BiocManager (recomendado)? Documente isso.

    • A instalação automática de pacotes do Bioconductor usando install.packages() é suficiente? Nesse caso, mencione que é necessário executar setRepositories() se ainda não tiver definido os repositórios necessários do Bioconductor.

    • Se o seu pacote depender do Bioconductor após uma determinada versão, mencione isso na DESCRIPTION e nas instruções de instalação.

  • Especificar dependências mínimas (por exemplo glue (>= 1.3.0) em vez de apenas glue) deve ser uma escolha consciente. Se tiver certeza de que seu pacote quebrará abaixo de uma determinada versão de dependência, especifique-a explicitamente. Mas se não souber, então não há necessidade de especificar uma dependência mínima. Nesse caso, quando um usuário relatar um bug que esteja explicitamente relacionado a uma versão mais antiga de uma dependência, resolva-o. Um exemplo de prática ruim seria, ao desenvolver o pacote, considerar as versões atuais de suas dependências como sendo a versão mínima. Isso forçaria desnecessariamente todos a atualizar (causando problemas com outros pacotes) quando não há um bom motivo por trás dessa escolha de versão.

  • Na maioria dos casos em que é necessário expor as funções das dependências, você deve importar e reexportar essas funções individuais em vez de listá-las no campo Depends. Por exemplo, se as funções do seu pacote produzem objetos do tipo raster, você pode reexportar do pacote raster apenas as funções de impressão e plotagem.

  • Se seu pacote usar uma dependência de sistema, você deve

    • Indicá-la no DESCRIPTION;

    • Verifique se ele está listado por sysreqsdb para permitir que ferramentas automáticas o instalem, ou envie uma contribuição caso contrário;

    • Verificar se está listado em um script configure (exemplo) e que fornecerá uma mensagem de erro útil caso não seja encontrado (exemplo). Os scripts configure podem ser desafiadores, pois geralmente exigem soluções improvisadas para fazer com que as diversas dependências do sistema funcionem em todos os sistemas. Use exemplos (mais aqui) como ponto de partida, mas observe que é comum encontrar bugs e casos extremos e, muitas vezes, violar as políticas do CRAN. Não hesite em pedir ajuda em nosso fórum.

1.15 Controle de versão

1.16 Problemas diversos do CRAN

Esta é uma coleção de problemas do CRAN que vale a pena evitar desde o início.

  • Certifique-se de que as palavras do título do seu pacote comecem com letra maiúscula (o que em inglês é chamado de Title Case.
  • Não coloque um ponto final no final do título.
  • Não coloque “no R” ou “com R” em seu título, pois isso é óbvio nos pacotes hospedados no CRAN. Se, mesmo assim, quiser que essas informações sejam exibidas em seu site, verifique a documentação do pkgdown para saber como substituir isso.
  • Evite iniciar a descrição com o nome do pacote ou “Este pacote …”.
  • Certifique-se de incluir links para sites se você envolver uma API da Web, extrair dados de um site etc. na seção Description do seu arquivo DESCRIPTION. Os URLs devem ser colocados entre colchetes angulares (<>), por exemplo <https://www.r-project.org>.
  • Em ambos os Title e Description, os nomes de pacotes ou outros softwares externos devem ser colocados entre aspas simples (por exemplo, Integração do ‘Rcpp’ para a biblioteca de álgebra linear com modelo ‘Armadillo’).
  • Evite testes e exemplos que sejam demorados. Considere usar testthat::skip_on_cran nos testes para pular coisas que demoram muito, mas ainda assim testá-las localmente e em integração contínua.
  • Inclua arquivos de nível superior, como paper.md e arquivos de configuração de integração contínua, no arquivo .Rbuildignore.

Para obter mais dicas, consulte a lista colaborativa mantida pelo ThinkR, “Prepare-se para o CRAN”.

1.16.1 Verificações do CRAN

Quando seu pacote estiver no CRAN, ele será checado regularmente em diferentes plataformas. As falhas nessas verificações, quando não são falsos positivos, podem levar a equipe do CRAN a entrar em contato com você. Você pode monitorar o estado das verificações do CRAN por meio

1.17 Problemas do Bioconductor

Se você pretende que seu pacote seja enviado para o Bioconductor ou se o pacote estiver no Bioconductor, consulte as Diretrizes de empacotamento do Bioconductor e o livro de desenvolvimento atualizado.

1.18 Orientações adicionais

1.18.1 Aprendendo sobre o desenvolvimento de pacotes

1.18.1.1 Livros

1.18.1.2 Tutoriais

1.18.1.3 Blogs

1.18.1.4 MOOCs

Existe um especialização do Coursera correspondente ao livro escrito por Roger Peng, Sean Kross e Brooke Anderson, com um curso específico sobre pacotes R.