class: center, middle, inverse, title-slide .title[ # Pacotes 📦 ] .author[ ###
] --- # Objetivos de aprendizagem 1. Preparando o ambiente de desenvolvimento 1. Fundamentos de desenvolvimento de pacotes em R 1. Dados 1. Documentação 1. Testes unitários e consistência de código 1. Disponibilizando seu pacote --- class: middle, center, inverse # Sobre a Curso-R --- # A empresa .pull-left[ <img src="https://d33wubrfki0l68.cloudfront.net/295643c6243701ae6a9bac3fb8ad467ff0ce3c84/d1785/img/logo/cursor1-41.png" width="80%" style="display: block; margin: auto;" /> <br> <br> <img src="img/logo_r6.png" width="1344" style="display: block; margin: auto;" /> ] .pull-right[ <img src="img/produtos.png" width="80%" style="display: block; margin: auto;" /> ] --- # Nossos cursos .pull-left[ <div class="container center"> <div class="card"> <h2>Programação em R</h2> <hr style = "background-color: #3bb44a;"/> <p><a href = "https://loja.curso-r.com/introduc-o-a-programac-o-com-r.html">Introdução à programação com R</a></p> <p><a href = "https://loja.curso-r.com/r-para-ciencia-de-dados-i.html">R para Ciência de dados I</a></p> <p><a href = "https://loja.curso-r.com/r-para-ciencia-de-dados-ii.html">R para Ciência de dados II</a></p> <p><a href = "https://loja.curso-r.com/pacotes.html">Pacotes</a></p> </div> </div> <br> <div class="container center"> <div class="card"> <h2>Modelagem</h2> <hr style = "background-color: #996699;"/> <p><a href = "https://loja.curso-r.com/modelos-lineares.html">Regressão Linear</a></p> <p><a href = "https://loja.curso-r.com/introduc-o-ao-machine-learning.html">Machine Learning</a></p> <p><a href = "https://loja.curso-r.com/modelagem-de-series-temporais.html">Séries Temporais</a></p> <p><a href = "https://loja.curso-r.com/modelagem-n-o-supervisionada.html">Modelagem Não Supervisionada</a></p> </div> </div> ] .pull-right[ <div class="container center"> <div class="card"> <h2>Comunicação e automação</h2> <hr style = "background-color: #ff6699;"/> <p><a href = "https://loja.curso-r.com/visualizac-o-de-dados.html">Visualização de dados</a></p> <p><a href = "https://loja.curso-r.com/relatorios-e-apresentacoes-automaticas.html">Relatórios e apresentações automáticas</a></p> <p><a href = "https://loja.curso-r.com/construindo-dashboards-i.html">Dashboards em Shiny I</a></p> <p><a href = "https://loja.curso-r.com/construindo-dashboards-ii.html">Dashboards em Shiny II</a></p> <p><a href = "https://loja.curso-r.com/deploy-colocando-seu-trabalho-em-produc-o.html">Deploy: colocando seu trabalho em produção</a></p> </div> </div> <br><br> <div class="container center"> <div class="card"> <h2>Extração de dados</h2> <hr style = "background-color: #eeba30;"/> <p><a href = "https://www.curso-r.com/cursos/web-scraping/">Web scraping</a></p> </div> </div> ] --- class: middle, center, inverse # Sobre o curso --- # Informações gerais - As aulas vão das 19:00 às 22:00, com uma pausa de 10 min em torno das 20:30 - As aulas serão gravadas e disponibilizadas no Google Classroom - Podem mandar dúvidas no chat do Zoom ou abrir o microfone para perguntar - Teremos um trabalho final para ser entregue duas semanas após o fim do curso ### Informações de vocês - Nós gostaríamos de saber sobre vocês (**escreva no chat**): 1. Qual é o seu nome? 1. Com o que você trabalha? 1. Qual é o seu pacote favorito? 1. Como imagina usar pacotes no futuro? --- # Pratique - Não se preocupe com estilos de estudo. Use o que te deixar mais confortável. - Estude um pouco todo dia. Se você tem apenas uma hora para estudar na semana, faça 3 sessões de 20 minutos em dias diferentes. - Se teste! Coloque em prática o que você aprendeu resolvendo exercícios ou inserindo o R no seu dia-a-dia. <img src="img/cat-computer.gif" style="display: block; margin: auto;" /> --- # Tirando dúvidas - Sempre ofereceremos monitoria 30 minutos antes do início de cada aula - Fora do horário de aula ou monitoria: - perguntas gerais sobre o curso deverão ser feitas no Classroom - perguntas sobre R, principalmente as que envolverem código, deverão ser enviadas no [nosso discourse](https://discourse.curso-r.com/) - [Veja aqui dicas de como fazer uma boa pergunta](https://discourse.curso-r.com/t/como-escrever-uma-boa-pergunta/542) ### Por que usar o discourse? - Muito melhor para escrever textos que possuem códigos. Com ele, podemos usar o pacote `{reprex}`! - Saber pesquisar sobre erros e fazer a pergunta certa é essencial para aprender e resolver problemas de programação - No discourse, teremos mais pessoas acompanhando e respondendo as dúvidas - Em um ambiente aberto, as suas dúvidas vão contribuir com a comunidade --- class: middle, center, inverse # Preparando o ambiente de desenvolvimento --- # Check-list antes de começar a aula - [R](https://livro.curso-r.com/1-1-instalacao-do-r.html) e [RStudio](https://livro.curso-r.com/1-1-instalacao-do-r.html) instalados - [Ferramentas de desenvolvimento](https://r-pkgs.org/setup.html#setup-tools): - Windows: [RTools instalado](https://livro.curso-r.com/1-3-instalacao-adicionais.html#rtools) - Linux: [r-base-dev](https://livro.curso-r.com/1-3-instalacao-adicionais.html#rtools) - MacOS: [Xcode command line tools](https://docs.brew.sh/Installation#macos-requirements) ```r devtools::has_devel() ``` ``` #> Your system is ready to build packages! ``` - [Pacotes necessários instalados](https://github.com/curso-r/main-pacotes#pacotes-necess%C3%A1rios) - [Git instalado](https://git-scm.com/) - [Conta no GitHub criada](https://github.com/) --- # Os arquivos .RData e .Rhistory Em sua configuração padrão, a IDE manterá na "memória" todos os últimos comandos executados, todos os dados utilizados e todos os objetos criados. Ao fechar e abrir o RStudio, essas informações serão recarregadas na memória como se o usuário nunca tivesse saído do programa. Esse recurso é tornado possível pela criação de dois arquivos ocultos: `.RData` e `.Rhistory`. O primeiro abriga absolutamente todos os objetos criados por uma sessão R, enquanto o segundo contém uma lista com os últimos comandos executados. Ao reabrir o RStudio, o conteúdo armazenados nestes arquivos será carregado no ambiente de trabalho atual como se nada tivesse acontecido. .footnote[Leia mais [neste capítulo do livro Zen do R](https://curso-r.github.io/zen-do-r/rdata-rhistory.html)] --- # Por que desistir do .RData e .Rhistory - Se todos os resultados parciais de uma análise estiverem disponíveis a qualquer momento, **diminui o incentivo para a escrita de código reprodutível** - Se todo o histórico de comandos for acessível, acaba a necessidade de experimentos controlados - Ao dependermos ativamente do `.Rdata`, **se acidentalmente sobrescrevemos um objeto** relevante e o código para recriá-lo não estiver mais acessível, **não haverá nenhuma forma confiável de recuperá-lo** - A menos que pretendamos sentar com colegas para explicar como utilizar os objetos do `.RData` e do `.Rhistory`, **não pode-se esperar que outra pessoa seja capaz de reproduzir uma análise** - O R trata todos os objetos guardados na memória igualmente. Isso significa que ele também irá armazenar nos arquivos ocultos todas as bases de dados da sessão. Assim, o `.RData` **pode ser um arquivo de múltiplos gigabytes** --- # Como desabilitar .RData e .Rhistory - Na barra superior: **Tools > Global Options...** <img src="https://curso-r.github.io/zen-do-r/static/rdata-rhistory/config.png" width="40%" style="display: block; margin: auto;" /> --- class: middle, center, inverse # Fundamentos de desenvolvimento de pacotes em R --- # O que é? Um pacote do R é uma forma específica de organizar seus código, seguindo o protocolo descrito pela R Foundation: > _Pacotes são a unidade fundamental de código R reprodutível._ > > — Wickham & Bryan .pull-left[ - Pacotes incluem: - Funções em R - Documentação sobre como usá-las - Testes - Dados de exemplo ] .pull-right[ <img src="img/pacote.gif" style="display: block; margin: auto;" /> ] --- # Por quê? Por que aprender a fazer um pacote se scripts funcionam bem o suficiente? Por que divulgar meus pacotes em algum serviço open source? - Compartilhar código é sempre uma boa ideia para que a comunidade se beneficie dos avanços individuais de quem a compõe - Para programar melhor, precisamos receber ajuda e sugestões de outras pessoas mais experientes - É muito mais fácil usar controle de versão e integração contínua se você estiver programando um pacote - Reprodutibilidade (no caso, outra pessoa pode reproduzir os seus resultados sem precisar do seu computador) --- # Vantagens - Padroniza a organização dos códigos nos projetos - Integra com pacotes que aceleram desenvolvimento - Motiva e facilita a documentação do código - Facilita o compartilhamento e a reutilização de códigos em outros projetos e com outras pessoas > _Qualquer coisa que possa ser automatizada, deve ser automatizada._ > > — Wickham & Bryan .footnote[Fonte: [R Packages](https://r-pkgs.org/intro.html)] --- # Simplificando tudo: usethis O pacote `{usethis}` ajuda com todo o fluxo de desenvolvimento em R. Ele ajuda a criar arquivos, projetos, usar o Git, criar repositórios no GitHub e muito mais. <img src="https://raw.githubusercontent.com/allisonhorst/stats-illustrations/master/rstats-artwork/usethis.png" width="70%" style="display: block; margin: auto;" /> --- # Pacote usethis O pacote `{usethis}` realiza ações que são possíveis de fazer manualmente, mas que __demandariam muitos cliques__ e são sujeitas a __erros humanos__. Alguns exemplos de poderes do usethis: - Criar um projeto com estrutura de pacotes - Adicionar uma dependência no pacote - Integrar o pacote com Git e GitHub - Adicionar uma GitHub Action ao pacote Apresentaremos várias funções do `{usethis}` ao longo do curso! --- # Criando um pacote Para criar um pacote, usamos a função `usethis::create_package()` - Você deve passar um caminho como `~/Documents/meupacote` e uma nova pasta chamada `meupacote` será criada dentro da pasta `Documents`. Essa pasta será tanto um `Rproj` quanto um pacote, ambos chamados `meupacote` - **Dica geral:** não adicione acentos, caracteres especiais e espaços no nome dos caminhos, arquivos, funções, pacotes, etc. ```r # Saída no próximo slide usethis::create_package("~/Documents/meupacote") ``` --- ``` #> ✔ Creating '/Users/clente/Documents/meupacote/' #> ✔ Setting active project to '/Users/clente/Documents/meupacote' #> ✔ Creating 'R/' #> ✔ Writing 'DESCRIPTION' #> Package: meupacote #> Title: What the Package Does (One Line, Title Case) #> Version: 0.0.0.9000 #> Authors@R (parsed): #> * First Last <first.last@example.com> [aut, cre] (YOUR-ORCID-ID) #> Description: What the package does (one paragraph). #> License: `use_mit_license()`, `use_gpl3_license()` or friends to #> pick a license #> Encoding: UTF-8 #> Roxygen: list(markdown = TRUE) #> RoxygenNote: 7.2.1 #> ✔ Writing 'NAMESPACE' #> ✔ Writing 'meupacote.Rproj' #> ✔ Adding '^meupacote\\.Rproj$' to '.Rbuildignore' #> ✔ Adding '.Rproj.user' to '.gitignore' #> ✔ Adding '^\\.Rproj\\.user$' to '.Rbuildignore' #> ✔ Opening '/Users/clente/Documents/meupacote/' in new RStudio session #> ✔ Setting active project to '<no active project>' ``` --- # Nomes Suponha que você criou uma função incrível que você quer compartilhar com o mundo. Ela tem várias funções auxiliares e um comportamento complexo o suficiente para depender de uma documentação... Você precisa criar um pacote. Mas qual deve ser o seu nome? > _Há apenas duas coisas difíceis na Ciência da Computação: invalidação de cache e dar nome para as coisas._ > > — Phil Karlton Os melhores nomes são simples e descritivos. Pense em algo que possa ser procurado facilmente no Google e que, preferencialmente, seja em inglês (a menos que você não ache que pessoas de outro país usarão o seu pacote). Evite usar letras maiúsculas ou mesmo números pois isso pode confundir os usuários. Você definitivamente ganha pontos extras se conseguir inserir alguma brincadeira com a letra R no nome (`stringr`, `decryptr`, `plyr`, `purrr`, etc.). --- # Dica para pesquisar nomes ```r available::available("chess", browse = FALSE) ``` ``` #> ── chess ───────────────────────────────────────────────────────────────── #> Name valid: ✔ #> Available on CRAN: ✖ #> Available on Bioconductor: ✔ #> Available on GitHub: ✖ #> Abbreviations: http://www.abbreviations.com/chess #> Wikipedia: https://en.wikipedia.org/wiki/chess #> Wiktionary: https://en.wiktionary.org/wiki/chess #> Sentiment:??? ``` --- # Estrutura básica do pacote Essa é a estrutura criada quando usamos a função `usethis::create_package()`: - `meupacote.Rproj`: este arquivo faz com que este diretório seja um projeto na RStudio IDE - `DESCRIPTION`: define o nome, descrição, versão, licença, dependências e outras caracaterísticas do seu pacote - `R/`: aqui ficam as funções desenvolvidas em R - `.Rbuildignore`: Lista arquivos que não devem ser incluídos ao compilar o pacote R a partir do código-fonte <!-- usethis::use_build_ignore("..") ajuda a adicionar arquivos no .Rbuildignore--> - `NAMESPACE`: __Não editar manualmente__. Ele declara as funções que o pacote exporta para uso externo e as funções externas que seu pacote importa de outros pacotes - `.gitignore`: Lista de arquivos que não devem ser considerados pelo Git --- # Diretório de trabalho O arquivo `meupacote.Rproj` indica para o RStudio que aquele diretório será a raiz de um projeto e que, sempre que o projeto estiver aberto, será utilizado por padrão como o diretório de trabalho. - *Working directory* é a pasta em que o R vai procurar arquivos na hora de ler informações ou gravar arquivos na hora de salvar objetos - Se você não souber qual é o seu diretório de trabalho, você pode descobri-lo usando a função `getwd()`. Ela vai devolver uma string com o caminho do seu diretório de trabalho Fixar o diretório de trabalho como a pasta raiz do projeto, ao lado da regra de manter todos os arquivos dentro da pasta do projeto, garante que sua análise poderá ser executada por qualquer pessoa e em qualquer computador sem a preocupação de ajustar caminhos até os arquivos utilizados ou criados pelo seu código. --- # Licenças de software - O pacote `{usethis}` possui funcões para declarar licenças como, por exemplo: ```r usethis::use_cc0_license() ``` - CC0: "sem direitos reservados", permite que o trabalho seja colocado em domínio público. Qualquer pessoa pode usar, modificar, distribuir e vender o seu trabalho sem restrição de direitos autorais ```r usethis::use_mit_license() ``` - MIT: curta e permissiva, exige apenas manutenção dos direitos autorais. Modificações e trabalhos maiores podem ser distribuídos sob outros termos de uso ```r usethis::use_gpl3_license() ``` - GPLv3: chamada *software livre* exige que o código-fonte dos derivados seja distribuído sob a mesma licença. Direitos autorais devem ser preservados. - O help é útil: `?usethis::use_mit_license`, e também o site [Choose a License](https://choosealicense.com/licenses/). --- # Verificando o pacote automaticamente Pacotes do R possuem regras e boas práticas. A função `devtools::check()` verifica se estmos seguindo essas regras, ou se estamos devendo alguma coisa. 1. Observe a estrutura do diretório 1. Carregue o pacote com `devtools::load_all()` (**CTRL + SHIFT + L**) 1. Cheque se está tudo OK com o seu pacote com `devtools::check()` 1. Adicione uma licença no pacote (com `usethis::use_***_license()`) para corrigir o alerta 1. Adicione suas informações no `DESCRIPTION`: nome, descrição do pacote, etc. --- # A pasta R/ Dentro de um pacote, a pasta `R/` só pode ter arquivos R com funções. - Uma função é responsável por executar uma tarefa pequena, mas muito bem. Quando trabalhamos com funções, nossas operações ficam mais confiáveis. - A ideia da pasta `R/` é guardar em um local comum tudo aquilo que nós utilizamos como ferramenta interna para nossas análises, bem como aquilo que queremos que outras pessoas possam usar no futuro. - Podemos usar `usethis::use_r("nome-do-arquivo")` para que um arquivo seja criado antes começarmos a escrever uma função. - Assim que escrevermos/modificarmos alguma função, podemos carregá-las e testá-las manualmente com `devtools::load_all()` --- # O que é uma função? Quando queremos encapsular um bloco de códigos para usar posteriormente, fazemos uma função. Exemplo de função: ```r juros_compostos <- function(x, tx = 0.01, tempo = 12) { resultado <- x * (1 + tx) ^ tempo resultado } juros_compostos(10) ``` ``` #> [1] 11.26825 ``` ```r juros_compostos(100, .02, 5) ``` ``` #> [1] 110.4081 ``` - O parâmetro `x` é __obrigatório__. - Os parâmetros `tx` e `tempo` são __opcionais__. --- # Vantagens ao usar funções - Um código bem encapsulado reduz a necessidade de objetos intermediários (`base_tratada`, `base_filtrada` etc.) pois para gerar um deles basta a aplicação de uma função. - Programas com funções normalmente são muito mais enxutos e limpos do que *scripts* soltos, pois estes estimulam repetição de código. - Ao encontrar um problema no código, haverá apenas um lugar para consertar; se surgir a necessidade de modificar uma propriedade, haverá apenas um lugar para editar; se aquele código se tornar obsoleto, haverá apenas um lugar para deletar. .footnote[Leia mais [neste capítulo do livro R for Data Science](https://r4ds.had.co.nz/functions.html)] --- # Pacotes externos Sem os inúmeros pacotes criados pela comunidade, o R provavelmente já estaria no porão da Ciência de Dados. Por isso, é a primeira coisa que escrevemos nos nossos *scripts* quase sempre é `library(algumPacoteLegal)`. Quando lidamos com pacotes, a função `library()` não pode ser utilizada, e todas as funções devem ter seus pacotes de origem explicitamente referenciados pelo operador `::`. - O código, no total, executa um pouco mais rápido porque são carregadas menos funções no ambiente global (isso é especialmente importante em aplicações interativas feitas em Shiny). - As dependências do código estão sempre atualizadas porque elas estão diretamente atreladas às próprias funções sendo utilizadas. - `usethis::use_package()`: adiciona pacotes que foram instalados via CRAN - `usethis::use_dev_package()`: adiciona pacotes que não foram instalados via CRAN - Para escrever `dplyr::`, por exemplo, basta digitar `d`, `p`, `l` e apertar TAB uma vez. Com os `::`, as sugestões passarão a ser somente de funções daquele pacote. --- # Prática - Como podemos transformar o código a seguir em uma função que fará parte de um pacote? - Exemplo: calcular a população e expectativa de vida média de países em um determinados anos e continente. ```r library(tidyverse) library(dados) dados_gapminder |> filter(continente %in% "Europa", ano >= 2000) |> group_by(ano) |> summarise( pop = sum(populacao) / 1e6, vida = mean(expectativa_de_vida), .groups = "drop" ) ``` --- # Prática __Passo 1__: Adicionar os quatro pontos `::` ```r library(tidyverse) library(dados) dados::dados_gapminder |> dplyr::filter(continente %in% "Europa", ano >= 2000) |> dplyr::group_by(continente, ano) |> dplyr::summarise( pop = sum(populacao) / 1e6, vida = mean(expectativa_de_vida), .groups = "drop" ) ``` --- # Prática __Passo 2__: Declarar as dependências com a função `usethis::use_package()`. Não precisaremos mais do `library()`! Vamos **remover** isso do código da função... ```r library(tidyverse) library(dados) ``` E declararemos as dependências... faremos isso no console, e não no código da função! ```r usethis::use_package("dplyr") usethis::use_package("dados") ``` --- # Prática __Passo 3__: Adicionar o código dentro de uma função. Chamaremos de `calcular_estatisticas()`. ```r calcular_estatisticas <- function() { dados::dados_gapminder |> dplyr::filter(continente %in% "Europa", ano >= 2000) |> dplyr::group_by(continente, ano) |> dplyr::summarise( pop = sum(populacao) / 1e6, vida = mean(expectativa_de_vida), .groups = "drop" ) } ``` --- # Prática __Passo 4__: Quais são os argumentos da nossa função? ```r calcular_estatisticas <- function(continentes, ano_minimo) { dados::dados_gapminder |> dplyr::filter(continente %in% continentes, ano >= ano_minimo) |> dplyr::group_by(continente, ano) |> dplyr::summarise( pop = sum(populacao) / 1e6, vida = mean(expectativa_de_vida), .groups = "drop" ) } calcular_estatisticas(continentes = c("Oceania", "Ásia"), ano_minimo = 2005) ``` ``` #> # A tibble: 2 × 4 #> continente ano pop vida #> <fct> <int> <dbl> <dbl> #> 1 Ásia 2007 3812. 70.7 #> 2 Oceania 2007 24.5 80.7 ``` --- # Prática __Passo 5__: E se eu quiser que a função funcione caso os argumentos não sejam informados? ```r calcular_estatisticas <- function(continentes = "Europa", ano_minimo = 2000) { dados::dados_gapminder |> dplyr::filter(continente %in% continentes, ano >= ano_minimo) |> dplyr::group_by(continente, ano) |> dplyr::summarise( pop = sum(populacao) / 1e6, vida = mean(expectativa_de_vida), .groups = "drop" ) } calcular_estatisticas(continentes = c("Europa", "Américas")) ``` ``` #> # A tibble: 4 × 4 #> continente ano pop vida #> <fct> <int> <dbl> <dbl> #> 1 Américas 2002 850. 72.4 #> 2 Américas 2007 899. 73.6 #> 3 Europa 2002 578. 76.7 #> 4 Europa 2007 586. 77.6 ``` --- # Exercício - Criar um arquivo onde iremos escrever a função para o pacote. Dica: use a função `usethis::use_r("nome-do-arquivo")`! - Copiar o código disponível em [git.io/JO8NV](https://git.io/JO8NV) e cole no arquivo criado. - Adaptar o código e o transforme em uma função. Não esqueça das dependências - Verificar que o arquivo onde sua função foi escrita está no diretório `R/` e que as dependências estão descritas no arquivo `DESCRIPTION` - Carregar o pacote com `devtools::load_all()`, e confira se está tudo ok com `devtools::check()`! ### Outros exercícios para casa - [Exercício: git.io/JO8Nr](https://git.io/JO8Nr) - [Desafio: git.io/JO8NP](https://git.io/JO8NP) .footnote[Fonte: dados do [pacote brasileirão](https://blog.curso-r.com/posts/2021-03-02-brasileirao/)] --- # Recomendações Algumas recomendação sobre como organizar seu código: - Evite usar `.` no nome das suas funções (hoje em dia usar `_` é muito mais comum) - Use nomes descritivos para as funções, pois isso facilita a manutenção e o uso do pacote - Tente se limitar a 80 caracteres por linha porque isso permite que seu código caiba confortavelmente em qualquer tela - Não use `library()` ou `require()`, pois isso vai causar problemas (use a notação `pacote::funcao()`) - **Nunca** use `source()`, todo o código já será carregado automaticamente com `devtools::load_all()` - Não carregar "metapackages" (como o tidyverse) --- class: inverse, center, middle # Dados --- # Dados Se você quiser inserir dados ao seu pacote, você pode utilizar a função `usethis::use_data()`. Ela criará uma pasta `data/` na raiz do seu pacote, caso ela não exista ainda, e salvará nela o objeto `meus_dados` em formato `.rda`. Arquivos `.rda` são extremamente estáveis, compactos e podem ser carregados rapidamente pelo R, tornando este formato o principal meio de guardar dados de um pacote. --- # Breve retorno Passo 6: adicionando bases de dados ao pacote. Ao executar o comando abaixo no Console, a base é salva como um `.rda` e podemos invocar o objeto diretamente na nossa função. ```r partidas_brasileirao <- readr::read_csv2("https://git.io/JOqUN") usethis::use_data(partidas_brasileirao) ``` ``` ✓ Setting active project to '/home/clente/Documents/meupacote' ✓ Adding 'R' to Depends field in DESCRIPTION ✓ Saving 'partidas_brasileirao' to 'data/partidas_brasileirao.rda' ● Document your data (see 'https://r-pkgs.org/data.html') ``` ```r encontrar_pior_ano_time <- function(time) { partidas_brasileirao |> dplyr::group_by(temporada, quem_ganhou) |> dplyr::filter(quem_ganhou != "Empate", quem_ganhou %in% time) |> dplyr::count(quem_ganhou, sort = TRUE, name = "n_vitorias") |> dplyr::ungroup() |> dplyr::filter(n_vitorias == min(n_vitorias)) |> dplyr::rename("time" = quem_ganhou) } ``` --- # Manipulando dados crus Se a base que você quiser colocar no pacote for o resultado de um processo de manipulação de uma base crua, você pode salvar a base crua e o código desse processo na pasta `data-raw`. Para isso, utilize a função `usethis::use_data_raw("meus_dados")`. Ela criará uma pasta `data-raw/` na raiz do seu pacote, caso ela não exista ainda, e um arquivo `meus_dados.R` onde você colocará o código de manipulação da base crua. --- # Qual a diferença entre R/ e data-raw/? `data-raw` - A pasta `data-raw/` é sua caixa de areia - Apesar de existirem formas razoáveis de organizar seus pacotes aqui, nessa parte você será livre `R/` - Já a pasta `R/` conterá funções bem organizadas e documentadas - Por exemplo, uma função que ajusta um modelo estatístico, outra que arruma um texto de um jeito patronizado, ou uma que contém seu tema customizado do `{ggplot2}` - Dentro dessa pasta você não deve carregar outros pacotes com `library()`, mas sim usar o operador `::` --- class: middle, center, inverse # Documentação --- # Documentação de funções Se quisermos adicionar documentação ao nosso pacote (as instruções que aparecem quando vamos usar uma função ou o documento mostrado quando rodamos `?função()`) precisamos usar um comentário especial: `#'` ```r #' Título da função #' #' Descrição da função #' #' @param a primeiro parâmetro #' @param b segundo parâmetro #' #' @return descrição do resultado #' #' @export fun <- function(a, b) { a + b } ``` --- # Documentação de funções - O parâmetro `@export` indica que a função ficará disponível quando rodarmos `library(meupacote)`. Não se esqueça de exportar todas (e somente) as funções públicas! - O RStudio disponibiliza um atalho para criar a estrutura da documentação de uma função. No menu superior, clique em `Code` -> `Insert Roxygen Skeleton`. - Para deixar a documentação das suas funções acessível (no help do R), use a função `devtools::document()` (**CTRL + SHIFT + D**). - Ao executar `devtools::check()`, a documentação já é atualizada e disponibilizada de brinde --- # Documentação de bases de dados ```r #' Título da base #' #' Descrição da base #' #' @format Uma lista que descreve as colunas: #' \describe{ #' \item{col1}{Descrição da coluna 1} #' \item{col2}{Descrição da coluna 2} #' ... #' } #' @source Origem dos dados "base" ``` - `@format` descreve o formato da base (número de colunas, linhas, etc.) e pode conter uma lista que explica o significado de cada coluna - `@source` é a fonte, muitas vezes um `\url{}` - **Nunca** coloque `@export` em uma base de dados --- # Acentos, encoding e variáveis globais Prefira manter os arquivos em inglês para que seu pacote possa ser submetido ao CRAN. - Se quiser fazer um pacote com documentação em português, tente escrever sem acentos ou escapar strings (veja `abjutils::escape_unicode()`). O `devtools::check()` vai te alertar caso essa regra seja violada O _encoding_ (codificação) dos arquivos deve ser **sempre** UTF-8 para evitar problemas entre plataformas. - Se tiver problemas com isso, tente **File > Reopen with Encoding...**, ou **File > Save with Encoding...**, ou **Tools > Project Options... > Code Editing > Text encoding** Variáveis globais são normalmente uma má prática em código R, então a `devtools::check()` vai reclamar se encontrar algo do tipo; o problema é que as colunas modificadas em funções do `{dplyr}` são caracterizadas como globais. - A solução é criar um arquivo com uma linha como a abaixo contendo todas as variáveis que fizerem a `devtools::check()`reclamar ```r utils::globalVariables(c("variavel1", "variavel2")) ``` --- # Boas práticas no desenvolvimento - Não rode as funções diretamente. Utilize sempre a função `devtools::load_all()`. Ela carrega todas as funções da pasta `R/` e as bases salvas na pasta `data/`. Isso diminuirá a chance de elas estarem sendo afetadas por valores externos que estão no seu *Environment*. - Limpe o seu *Environment* sempre que possível. Um atalho útil: **CTRL + SHIFT + F10**. - Para deixar a documentação das suas funções acessível (no help do R), use a função `devtools::document()`. - Se você precisar instalar o seu pacote (equivalente ao que fazemos com pacotes do CRAN quando rodamos `install.packages()`), use a função `devtools::install()`. Ela deve ser utilizada quando o seu pacote estiver pronto (ou pelo menos alguma versão dele). <!-- Acho que tem mais coisa aqui, mas isso tudo já é bem bom --> --- # Documentação na prática Passo 7: Pratique o que aprendemos sobre documentação de pacotes! 1. Execute e observe o resultado de `devtools::check()`. Lá terão indicações do que devemos fazer 1. Crie uma lista de variáveis globais e adicione os elementos que aparecem no check em _Undefined global functions or variables_ 1. Documente a base de dados 1. Documente as funções do pacote 1. Execute e observe novamente o resultado de `devtools::check()`. O objetivo é obter: .center[`0 errors ✓ | 0 warnings ✓ | 0 notes ✓`] --- class: middle, center, inverse # Git e GitHub --- # Git - Git é um **sistema de versionamento**, criado por Linus Torvalds, autor do Linux. - É capaz de guardar o histórico de alterações de todos os arquivos dentro de uma pasta, que chamamos de repositório. - Funciona como o "*Track changes*" do word, mas muito melhor. - Torna-se importante à medida que seu trabalho é __colaborativo__. - Git é um software que você instala no computador. - Arquivo `.gitignore`: Lista arquivos que deverão ser ignorados ao versionar o pacote com Git. <br> <img src="img/git.png" width="30%" style="display: block; margin: auto;" /> --- # GitHub - GitHub é um site onde você coloca e compartilha repositórios Git. - Utilizado por milhões de pessoas em projetos de código aberto ou fechado. - Útil para colaborar com outros programadores em projetos de ciência de dados. - Existem alternativas, como [GitLab](https://about.gitlab.com/) e [BitBucket](https://bitbucket.org/product). - GitHub é um site que você acessa na internet. <br> <img src="img/github.png" width="40%" style="display: block; margin: auto;" /> --- # Pacotes e GitHub .pull-left[ Pacotes do R e repositórios do GitHub são melhores amigos <br> O grande cupido dessa amizade é o `{usethis}` <br> Após deixar o pacote no GitHub, outras pessoas poderão instalá-lo usando a função `remotes::install_github("org/repo")` ] .pull-right[ <img src="img/hug.gif" width="90%" style="display: block; margin: auto;" /> ] --- # Fluxo de trabalho O diagrama abaixo exemplifica o fluxo de trabalho de um projeto com versionamento. <img src="img/fluxo_github_rstudio.png" width="70%" style="display: block; margin: auto;" /> --- # Configurando o Git e GitHub no RStudio .pull-left[ #### Usando protocolo https - ⬜ Ter o pacote `usethis` instalado - ⬜ Se apresentar para o `git` - ⬜ Criar um GitHub Token/PAT - ⬜ Armazenar o GitHub Token/PAT - ⬜ Reiniciar o RStudio ] .pull-right[ #### Usando protocolo ssh - ⬜ Todas as etapas para o protocolo https (listadas ao lado) - ⬜ Criar as chaves SSH no RStudio - ⬜ Adicionar a chave ssh no ssh-agent - ⬜ Adicionar as chaves públicas no GitHub - ⬜ Alterar o protocolo padrão no arquivo `.Rprofile` - ⬜ Reiniciar o RStudio Obs: Se você utiliza Linux, recomendamos usar `ssh`. ] --- # Configure seu usuário do Git Antes de começarmos a versionar o código do nosso pacote, vamos configurar o Git e o GitHub no RStudio. Esse processo precisa ser feito apenas uma vez! ```r usethis::use_git_config( user.name = "SEU NOME NO GITHUB", user.email = "seu_email_no@github.com" ) ``` - Em `user.name`, pode ser seu nome mesmo, não precisa ser o nickname. - O `user.email` precisa ser o que está vinculado à sua conta do GitHub. --- # Configure o Personal Access Token - Ao conectar com o GitHub, você será instruída(o) a criar um *Personal Access Token* (PAT). - O PAT serve para autenticar ao GitHub, podendo ser utilizado como senha de acesso ou internamente para automatizar tarefas (como criar um repositório). - Para criar um novo PAT, use a função `usethis::create_github_token()`. Uma janela do navegador será aberta, e você deve autenticar no GitHub (se necessário), criar o novo token, e copiá-lo. ```r usethis::create_github_token() ``` --- # Armazenar o Personal Access Token #### Método 1 - `gitcreds::gitcreds_set()` .pull-left[ ```r gitcreds::gitcreds_set() # -> Your current credentials for 'https://github.com': # protocol: https # host : github.com # username: beatrizmilz # password: <-- hidden --> # # -> What would you like to do? # 1: Keep these credentials # 2: Replace these credentials # 3: See the password / token ``` ] .pull-right[ Siga as instruções e cole o PAT quando for solicitado as credenciais. ```r # -> Adding new credentials... # -> Removing credetials from cache... # -> Done. ``` ] --- # Armazenar o Personal Access Token #### Método 2 - Armazenar manualmente no `.Renviron` - Use a função `usethis::edit_r_environ()` para abrir o arquivo `.Renviron` para salvar seu token. ```r usethis::edit_r_environ() # ● Modify 'C:/Users/beatr/Documents/.Renviron' # ● Restart R for changes to take effect ``` - Crie uma nova linha na forma `GITHUB_PAT=SEU_TOKEN`, adicione o token, **pule uma linha** e salve o arquivo. Se certifique que o arquivo termina com uma linha vazia! Use essa estrutura, substituindo os 0 pelo código copiado na etapa anterior: ```r GITHUB_PAT="0000000000000000000000000000000000000000" ``` --- # Checando se a configuração deu certo - Lembre-se de reiniciar sua sessão do R! - **Reinicie o R usando o RStudio**: CTRL + SHIFT + F10 - Utilize a função `usethis::git_sitrep()` e leia o resultado que aparece no console. A mensagem abaixo foi cortada para mostrar os trechos de interesse! ```r usethis::git_sitrep() #> Git config (global) #> ● Name: 'SEU NOME DEVE APARECER AQUI' #> ● Email: 'SEU EMAIL DEVE APARECER AQUI' #> GitHub #> ● Default GitHub host: 'https://github.com' #> ● Personal access token for 'https://github.com': '<discovered>' ***IMPORTANTE ESTAR COMO DISCOVERED*** #> ● GitHub user: 'SEU NOME DE USUÁRIO(A) DEVE APARECER AQUI' #> ● Token scopes: 'gist, repo, user, workflow' #> ● Email(s): 'SEU EMAIL DEVE APARECER AQUI' ``` --- # Configurando com o SSH (Parte 1) .pull-left[ - Se você utiliza Linux, recomendamos usar o protocolo `ssh`. - Além das etapas anteriores (se apresentar para o `git` e configurar o PAT), é necessário seguir os seguintes passos: ** CRIANDO UMA CHAVE SSH** - No RStudio, clique em `Tools` -> `Global Options...` -> `Git/SVN`. No campo `SSH RSA Key`, clique em `Create RSA Key`. Referência: https://happygitwithr.com/ssh-keys.html ] .pull-right[ <img src="img/ssh/etapa-1.png" width="90%" style="display: block; margin: auto;" /> ] --- # Configurando com o SSH (Parte 2) .pull-left[ ** CRIANDO UMA CHAVE SSH** - Não altere o primeiro campo, mas você pode adicionar uma senha caso queira. Porém você precisará informar essa senha todas as vezes que quiser fazer algumas ações como Pull ou Push. Clique em `Create`. A sua senha será criada e aparecerá uma caixinha com ela. Pode clicar em `Close`. Após fechar, veja se o campo `SSA RSA KEY` está preenchido. Referência: https://happygitwithr.com/ssh-keys.html ] .pull-right[ <img src="img/ssh/etapa-2.png" width="90%" style="display: block; margin: auto;" /> ] --- # Configurando com o SSH (Parte 3) .pull-left[ **Verificando se o ssh-agent está funcionando** Referência: https://happygitwithr.com/ssh-keys.html#add-key-to-ssh-agent ] .pull-right[ - **Mac OS ou Linux** - no terminal, escreva: ``` eval "$(ssh-agent -s)" ``` - **Windows** - no Git Bash shell, escreva: ``` eval $(ssh-agent -s) ``` <br><br><br><br> A resposta esperada, nessa etapa, é algo como: ``` Agent pid 14198 ``` ] --- # Configurando com o SSH (Parte 4) .pull-left[ **Adicionando a chave ssh no ssh-agent** - Se você definiu uma senha ao criar a chave ssh, ela será solicitada nessa etapa. - **Linux** - no terminal, escreva: ``` ssh-add ~/.ssh/id_rsa ``` - **Mac OS** - no terminal, escreva: ``` ssh-add -K ~/.ssh/id_rsa ``` - **Windows** - no Git Bash shell, escreva: ``` ssh-add ~/.ssh/id_rsa ``` <br> Referência: https://happygitwithr.com/ssh-keys.html#add-key-to-ssh-agent ] .pull-right[ A resposta esperada, nessa etapa, é algo como: ``` Identity added: /home/bea/.ssh/id_rsa ``` <img src="img/ssh/etapa-5.png" width="100%" style="display: block; margin: auto;" /> ] --- # Configurando com o SSH (Parte 5) **Adicionando a chave pública no GitHub** - No GitHub, vá em `Settings` -> `SSH and GPG keys` -> `New ssh key` (ou clique aqui: https://github.com/settings/ssh/new ) - No RStudio, clique em `Tools` -> `Global Options...` -> `Git/SVN`. No campo `SSH RSA Key`, clique em `View Public Key`. - Uma janela vai abrir com a chave pública e você deve copiar o conteúdo todo. - No campo `Title`, escreva algo que ajude você a lembrar em qual computador essa chave está sendo usada. No campo `Key`, cole todo o conteúdo copiado na etapa anterior. Clique em `Add SSH key`. <br> Referência: https://happygitwithr.com/ssh-keys.html#add-key-to-ssh-agent --- # Configurando com o SSH (Parte 6) **Dicas** - Confira se está funcionando executando o seguinte código na aba Terminal, no RStudio: ``` ssh -T git@github.com ``` - Ao clonar um projeto, é importante utilizar o protocolo que foi configurado. O protocolo padrão utilizado pelo usethis é o `https`. Para alterar para o `ssh` , altere no `.Rprofile` o protocolo padrão a ser utilizado: - Abrir o arquivo o `.Rprofile`: ``` usethis::edit_r_profile() ``` - Adicione a seguinte linha neste arquivo: ``` options(usethis.protocol = "ssh") ``` - Salve o arquivo e reinicie o RStudio. <br> Referência: https://usethis.r-lib.org/reference/git_protocol.html --- # Versione com o Git e o GitHub ```r usethis::use_git() ``` - Rodando o comando acima na pasta do projeto (a nova aba do RStudio que apareceu) você adiciona controle de versão. - Você receberá algumas instruções para seguir, mas está tudo certo. ```r usethis::use_github() ``` - O comando acima sincroniza a pasta com o GitHub. - Mais uma vez, você receberá algumas instruções, mas lembre-se de alterar para o protocolo `ssh` caso tenha feito a configuração usando esse protocolo. Para isso, use o argumento `protocol = ssh`. --- # Stage & Commit <img src="img/passo_3_commit_1.gif" width="50%" style="display: block; margin: auto;" /> - Nesta etapa, você estará descrevendo as modificações que fez nos arquivos selecionados. - __Observação__: o ato de clicar no item é o passo de Stage. --- # Push <img src="img/passo_4_push.gif" width="50%" style="display: block; margin: auto;" /> - *Push* (ou *dar push*) significa atualizar o seu repositório remoto (GitHub) com os arquivos que você *commitou* no passo anterior. --- # Extra: Pull <img src="img/passo_5_pull.gif" width="50%" style="display: block; margin: auto;" /> - *Pull* é a ação inversa do *Push*: você trará a versão mais recente dos arquivos do seu repositório remoto (GitHub) para a sua máquina (caso você tenha subido uma versão de um outro computador ou uma outra pessoa tenha subido uma atualização). --- # Resumo 1. Repositório: Criar projeto/pacote 2. Adicionar Git 3. Adicionar GitHub 4. Commit: Edite e "Commite" as mudanças no código 5. Push: Suba os commits para o GitHub 6. Pull (extra): Baixe o estado atual do projeto ### Cuidados - Se uma base de dados tem mais do que 50Mb de tamanho, ela não deveria estar no seu repositório. - Nem sempre o comando Pull dá certo. Às vezes, você e a colega de trabalho fizeram mudanças no mesmo arquivo e, quando vão juntar, ocorre um conflito. --- class: middle, center, inverse name: testes-unitarios # Comunicação --- .pull-left[ # O arquivo README.md O arquivo `README.md` é importante pois contém informações como: logo (opcional!), introdução (o que ele faz?), instruções de instalação, exemplos de uso, etc. A função `usethis::use_readme_rmd()` cria um arquivo `README.Rmd`. Esse arquivo já possui uma estrutura para facilitar o preenchimento das informações. O arquivo gerado é um **RMarkdown** (`.Rmd`), e portanto precisamos converter para **Markdown** (`.md`). Para isso podemos usar a função `devtools::build_readme()`. <!-- Citamos aqui o botão knit? --> ] .pull-right[ <img src="img/readme-chess.png" width="90%" style="display: block; margin: auto;" /> .footnote[Fonte da imagem: [README do pacote {chess}](https://github.com/curso-r/chess)] ] --- .pull-left[ # Vignettes É muito comum a construção de *vignettes* para documentar o pacote. Elas são documentos em HTML melhor formatados do que a tradicional documentação do R. Você pode usar a função `usethis::use_vignette()` para criar *vignettes*. <br> Atenção: Caso você use alguma distribuição Linux e retornar a seguinte mensagem no `devtools::check()`, você precisa instalar o [qpdf](https://sourceforge.net/projects/qpdf/). ``` > ‘qpdf’ is needed for checks on size reduction of PDFs ``` <!-- ### Outros --> <!-- Se você precisar construir sites, relatórios, dashboards estáticos (flexdashboard) dentro do seu pacote, você pode criar uma pasta chamada `docs/` na raiz do seu projeto para guardar esses arquivos. --> <!-- Veremos também como criar um site do pacote criado com o `{pkgdown}`. --> ] .pull-right[ <img src="img/vignette-chess.png" width="90%" style="display: block; margin: auto;" /> .footnote[Fonte da imagem: [Exemplo de vignette do pacote {chess}](https://github.com/curso-r/chess)] ] --- # Criando um site para o pacote com {pkgdown} .pull-left[ O pacote pkgdown permite criar um site para o pacote. Para criar, use a função a seguir uma vez, para configurar o pacote para usar o pkgdown: ```r usethis::use_pkgdown() ``` ] .pull-right[ <img src="img/pkgdownchess.png" width="90%" style="display: block; margin: auto;" /> .footnote[Fonte da imagem: [Site do pacote {chess}](https://github.com/curso-r/chess)] ] --- # Criando um site para o pacote com {pkgdown} (cont.) Conteúdo do site será gerado a partir dos documentos já existentes no pacote: - O conteúdo do site estará no diretório `docs/`. - O arquivo `README.md` será usado para criar a página principal do site; - A documentação das funções serão usadas para criar a seção 'references' - As vignettes serão usadas para criar a seção 'articles' O site não é atualizado automaticamente. Caso mude algo nos itens descritos acima, você deve atualizar o site usando a função: ```r pkgdown::build_site() ``` --- # Criando um site para o pacote com {pkgdown} (cont.) - Os passos anteriores geram o conteúdo do site no diretório `docs/`, mas para que o site do pacote fique disponível na internet para que outras pessoas consultem é necessário: - O pacote estar vinculado a um repositório no GitHub (falamos disso na seção passada) - No repositório do pacote, clique em **Settings**, e no menu lateral escolha **Pages** - Em **Source**, selecione **Deploy from a branch**, escolha o diretório `docs/` e clique em **save** <img src="img/githubpages.png" width="50%" style="display: block; margin: auto;" /> - O endereço do site será `https://seu-username.github.io/nome-repositorio/` --- class: middle, center, inverse name: testes-unitarios # Testes unitários .footnote[Leia mais [neste capítulo do livro Zen do R](https://curso-r.github.io/zen-do-r/testes.html).] --- # Testes Se quisermos verificar que todo o pacote continua funcionando mesmo depois fazer alguma alteração, precisamos de testes automatizados. Para isso, basta rodar `usethis::use_testthat()` (apenas uma vez por pacote) e depois `usethis::use_test("nome_do_teste")` (para cada novo arquivo de testes que quiser criar). Com o pacote testthat podemos criar quantos arquivos de testes quisermos, cada um com um número ilimitado de testes e sub-testes. Quando tivermos todos os testes prontos, basta rodar `devtools::test()`. Atalho: **Ctrl + Shift + T**. --- # Expectativas - Um arquivo de testes tem duas estruturas principais: **testes** e **expectativas** - Um teste, declarado com `test_that()`, indica um bloco de testes cujo objetivo é garantir que uma funcionalidade foi implementada corretamente - Uma expectativa, declarada com `expect_*()`, realiza uma verificação dentro do teste, comparando o valor retornado pela expressão com alguma referência - Um teste precisa ser independente dos outros (inclusive do mesmo arquivo!) e ter um objetivo definido, declarado através de sua **descrição** - A independência dos testes é importante porque eles serão executados em paralelo, mesmo que digam respeito à mesma função e estejam no mesmo arquivo - Alguns tipos importantes de expectativas: `equal`, `error`, `true`, `length`, `lt`, `lte`, `gt`, `gte`, `message`, `null`, `output`, `snapshot`, `warning` --- # Exemplo de teste Considerando a função: ```r tira_media <- function(x, rm_na = TRUE) { purrr::reduce(x, sum, na.rm = rm_na)/conta_itens(x, rm_na) } ``` Podemos escrever os seguintes testes: ```r test_that("taking the mean works", { expect_equal(tira_media(c(1, 2, 3, 4, NA, 6)), 3.2) expect_equal(tira_media(c(1, 2, 3, 4, 6)), 3.2) }) test_that("rm_na works as expected", { expect_output(tira_media(c(1, 2, NA), rm_na = FALSE), NA) expect_equal(tira_media(c(NA, NA, NA)), NaN) }) ``` --- # Testes na prática Passo 8: Pratique o que aprendemos sobre testes! 1. Use a função `usethis::use_testthat()` para preparar o pacote 1. Abra o arquivo da função que deseja escrever testes, e use a função `usethis::use_test()` para criar o arquivo onde o teste será escrito 1. Desenvolva um teste para a função 1. Execute e observe novamente o resultado de `devtools::check()`. O objetivo é obter: .center[`0 errors ✓ | 0 warnings ✓ | 0 notes ✓`] --- class: middle, center, inverse name: ci # Integração contínua --- # Integração contínua - Dado um certo código e um método consistente de testá-lo, faz todo sentido **automatizar** o processo - Integração contínua normalmente envolve garantir que a versão mais recente do software está atendendo os padrões de qualidade - Hoje vamos falar sobre o **GitHub Actions** porque ele se conecta facilmente com o GitHub .pull-left[ Alguns exemplos: - Vários pacotes usam para fazer executar o check e testes: [{readr}](https://github.com/tidyverse/readr/tree/master/.github/workflows), [{dplyr}](https://github.com/tidyverse/dplyr/tree/master/.github/workflows), [{usethis}](https://github.com/r-lib/usethis/tree/master/.github/workflows), e muitos outros - Pacote [{mananciais}](https://beatrizmilz.github.io/mananciais/) - atualiza diariamente a base de dados - Página [Materiais sobre R](https://materiais-estudo-r.netlify.app/) - atualiza o site sempre que há mudança na base de dados ] .pull-right[ <br><br> <img src="https://avatars.githubusercontent.com/u/44036562?s=200&v=4" style="display: block; margin: auto;" /> ] --- # GitHub Actions > GitHub Actions ajuda a automatizar tarefas dentro de seu ciclo de vida de desenvolvimento de software https://docs.github.com/pt/actions - Um **workflow** não passa de um processo bem-definido que será executado no repositório ao qual ele pertence - Ele é definido a partir de um arquivo YAML dentro da pasta `.github/workflows` - É comum definir workflows para testagem de pacotes, geração de documentação, atualização de dados, etc. - O workflow é, essencialmente, um duende mágico que baixa o nosso repositório em um **servidor do GitHub** e executa os comandos especificados - O plano gratuito já funciona para bastante coisa, mas cuidado com os **custos** das máquinas MacOS --- # Estrutura - Um workflow tem alguns componentes importantes: - **Event**: gatilhos que ativam o workflow, podendo ser desde um push ao repositório até uma hora do dia - **Job**: sequências completas de comandos que podem ser executadas paralelamente entre si - **Step**: uma tarefa dentro de um job, composta por ações - **Use**: passos importados de outro repositório (úteis para setup) - **Action**: o átomo do workflow, um comando a ser executado pelo "duende mágico" - Também é comum definir **env**, variáveis de ambiente para o workflow --- # Exemplo de workflow ```yaml on: [push] # Event jobs: R-CMD-check: # Job runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 # Use - uses: r-lib/actions/setup-r@v2 # Use - name: Install dependencies # Step run: | # Action install.packages(c("remotes", "rcmdcheck")) remotes::install_deps(dependencies = TRUE) shell: Rscript {0} - name: Check # Step run: rcmdcheck::rcmdcheck(args = "--no-manual") # Action shell: Rscript {0} ``` --- # Integração contínua com GitHub Actions Para utilizar o GitHub Actions, usamos arquivos `.yaml` que armazenam informações os fluxos de trabalho. - **Eventos**: Um evento é uma atividade que aciona um fluxo de trabalho. Por exemplo: - Quando o repositório recebe uma alteração (`on: push`) - Quando um Pull Request é criado (em outras palavras, alguém está enviando uma contribuição para o repositório) (`on: pull_request`) - Eventos programados. Ex: a cada hora, todos os dias, uma vez por semana, uma vez por mês, etc. O site [CronTab](https://crontab.guru/) é muito útil para isso. - Quando acionado "manualmente", ou via API (`on: workflow_dispatch`) - **Trabalho**: Um evento aciona automaticamente o fluxo de trabalho, que contém um trabalho. Em seguida, o trabalho usa etapas para controlar a ordem em que as ações são executadas. Exemplo de ações executadas: - Executar testes - Executar um script `.R` --- # Integração contínua com GitHub Actions (cont.) - Recomendação: partir de um arquivo de workflow já existente, e alterar o que for necessário. - [Neste repositório](https://github.com/r-lib/actions/tree/master/examples#readme), estão disponíveis alguns exemplos de workflows de GitHub Actions que podemos usar com pacotes em R - Os arquivos `.yaml` devem estar em um diretório específico do pacote: `pacote/.github/workflows/nome-do-workflow.yaml` - O pacote {usethis} também pode nos ajudar nisso. O código a seguir cria o arquivo `.yaml` apresentado no último slide, usado para fazer uma checagem simples no pacote: ```r usethis::use_github_action("check-release") ``` --- # Exemplo de workflow <img src="img/action.png" width="60%" style="display: block; margin: auto;" /> .footnote[[Veja os logs do Exemplo!](https://github.com/beatrizmilz/materiais_estudo_R/runs/2328985236?check_suite_focus=true)] --- # Regras para colocar um pacote no CRAN <!-- Antes desse slide o Caio vai escrever sobre o R-Hub --> Um pacote é uma coleção de código, dados, documentação e testes que qualquer pessoa pode instalar em sua máquina. Se quisermos criar apenas um conjunto de funções que provavelmente não serão utilizadas por muitas pessoas, podemos subir esse pacote para o GitHub e mantê-lo lá somente para garantir controle de versão. Mas se quisermos que o máximo número possível de pessoas tenha acesso ao nosso pacote, pode ser que precisemos subi-lo para o CRAN (Comprehensive R Archive Network). Neste caso precisaremos criar teste e documentação (em inglês) para nosso pacote. Use as funções `devtools::submit_cran()` e `usethis::use_release_issue()` para auxiliar no processo de submissão do pacote para o CRAN. --- class: middle, center, inverse # Resumo --- # Etapas iniciais - Criar um pacote usando a função `usethis::create_package("~/caminho/ate/o/nomepacote")` - No arquivo DESCRIPTION, adicionar o nome de quem criou o pacote, além do título e descrição do pacote. - Adicionar uma licença com `usethis::use_**_licence()` - Versionar o projeto usando `usethis::use_git()` - Crie um repositório no GitHub onde esse pacote será versionado utilizando `usethis::use_github()` - Para preparar o pacote para receber testes, use `usethis::use_testthat()` - Para criar o arquivo README, use a função `usethis::use_readme_rmd()` - Para criar um site para o pacote, use a função `usethis::use_pkgdown()` --- # Funções para repetir com frequência - `devtools::document()`: atualiza a documentação e o arquivo NAMESPACE - `devtools::load_all()`: simula o processo de instalação e carregamento do pacote. As funções criadas ficam disponíveis para uso - `devtools::check()`: verifica se o pacote está funcionando. Pode apresentar erros, avisos e notas. Leia as mensagens no console :) - Quando necessário: - `usethis::build_readme()`: atualizar o `README.md` - `pkgdown::build_site()`: atualizar o site do pacote --- # Desenvolvendo funções - Criar funções: a função `usethis::use_r("nome-do-arquivo")` cria o arquivo onde as funções devem ser escritas - Declare as dependências usando: - pipe `|>`: `usethis::use_pipe()` + `devtools::document()` + `devtools::load_all()` - Pacotes instalados via CRAN: `usethis::use_package("nome_do_pacote")` - Pacotes instalados via GitHub: `usethis::use_dev_package("nome_do_pacote")` - Documente suas funções no arquivo `.R` - Crie o arquivo de testes usando `usethis::use_test("nome-do-arquivo")` e escreva testes para as funções presentes nesse arquivo --- # Referências e materiais para estudo - [Zen do R](https://curso-r.github.io/zen-do-r/), livro em desenvolvimento pela Curso-R. - [R Packages](https://r-pkgs.org), livro aprofundado sobre desenvolvimento de pacotes. - [R for Data Science - capítulo sobre Funcões](https://r4ds.had.co.nz/functions.html) - [Materiais da R-Ladies SP sobre a Hacktoberfest 2020](https://r-ladies-sao-paulo.github.io/2020-hacktoberfest/). - [Folha de dicas do Git em Português](https://training.github.com/downloads/pt_BR/github-git-cheat-sheet/) --- class: middle, center, inverse Fim!