Exercícios de conceito


Exercícios de conceito são exercícios criados para ensinar conceitos específicos (de programação). Os conceitos ensinados pelos exercícios de conceito formam um programa de estudos. Para saber mais sobre como projetar um programa de estudos, consulte a documentação do programa de estudos.

Note

Você pode criar rapidamente a estrutura inicial de um novo Exercício de conceito executando os seguintes comandos no diretório raiz da trilha:

bin/fetch-configlet
bin/configlet create --concept-exercise <slug>

Para saber mais, consulte a documentação do configlet create

Metadados

Os metadados de um Exercício de conceito são definidos na chave exercises.concept do arquivo config.json. Os metadados definem o UUID, o slug e outras informações do exercício.

Exemplo

{
  "exercises": {
    "concept": [
      {
        "uuid": "93fbc7cf-3a7e-4450-ad22-e30129c36bb9",
        "slug": "cars-assemble",
        "name": "Cars, Assemble!",
        "concepts": ["if-statements", "numbers"],
        "prerequisites": ["basics"]
      }
    ]
  }
}

Arquivos

Cada Exercício de conceito tem seu próprio diretório dentro do diretório exercises/concept da trilha. O nome do diretório do Exercício de conceito deve corresponder à propriedade slug do Exercício de conceito, conforme definido no arquivo config.json.

Um Exercício de conceito tem quatro tipos de arquivos:

Arquivos de documentação

Esses arquivos são apresentados ao estudante para ajudar a explicar o exercício.

  • .docs/introduction.md: apresenta o(s) conceito(s) que o exercício ensina ao estudante (obrigatório)
  • .docs/instructions.md: fornece as instruções do exercício (obrigatório)
  • .docs/hints.md: fornece dicas ao estudante para ajudá-lo a sair de um bloqueio em um exercício (obrigatório)

Arquivos de metadados

Esses arquivos não são apresentados ao estudante, mas usados para definir metadados do exercício.

  • .meta/config.json: contém metainformações sobre o exercício (obrigatório)
  • .meta/design.md: descreve o design do exercício (obrigatório)

Arquivos de abordagem

Esses arquivos descrevem abordagens para o exercício.

  • .approaches/introduction.md: introdução às abordagens mais comuns para o exercício (opcional)
  • .approaches/config.json: metadados das abordagens (opcional)
  • .approaches/<approach-slug>/content.md: descrição da abordagem (opcional)
  • .approaches/<approach-slug>/snippet.txt: trecho que demonstra a abordagem (opcional)

Arquivos de artigo

Esses arquivos descrevem artigos para o exercício.

  • .articles/config.json: metadados dos artigos (opcional)
  • .articles/<article-slug>/content.md: descrição do artigo (opcional)
  • .articles/<article-slug>/snippet.md: trecho que demonstra o artigo (opcional)

Arquivos do exercício

Os arquivos específicos da linguagem, como os arquivos de implementação e de teste. Os nomes desses arquivos são específicos da trilha.

  • Suíte de testes: verifica a correção de uma solução (obrigatória)
  • Implementação stub: fornece um ponto de partida para os estudantes (obrigatória)
  • Implementação exemplar: fornece uma implementação idiomática que passa em todos os testes (obrigatória)
  • Arquivos adicionais: garantem que os testes possam ser executados (opcionais)

Exemplo

exercises
└── concept
    └── cars-assemble
        ├── .approaches
        |   ├── for-loop
        |   |   ├── content.md
        |   |   └── snippet.txt
        |   ├── config.json
        |   └── introduction.md
        ├── .articles
        |   ├── performance
        |   |   ├── content.md
        |   |   └── snippet.md
        |   └── config.json
        ├── .docs
        |   ├── introduction.md
        |   ├── instructions.md
        |   └── hints.md
        ├── .meta
        |   ├── config.json        
        |   ├── design.md
        |   └── Exemplar.cs (implementação exemplar)
        ├── CarsAssemble.cs (implementação stub)
        └── CarsAssemblyTests.cs (testes)

Especificação mínima válida

Preferimos uma abordagem de "mesclagem otimista" para novos exercícios, em que as trilhas podem desenvolver exercícios em um estado de "trabalho em andamento". O estado mínimo válido, que passará no configlet e permitirá que você faça a mesclagem, é:

  • Uma entrada válida no config.json da trilha, com o status definido como wip.
  • Um arquivo .meta/config.json válido
  • A presença dos seguintes arquivos, embora possam estar vazios:
    • .docs/introduction.md
    • .docs/instructions.md
    • .docs/hints.md
    • Implementação stub
    • Arquivo de teste

Arquivo: .docs/introduction.md

Objetivo: Apresentar o(s) conceito(s) que o exercício ensina ao estudante.

Presença: Obrigatória

  • As informações fornecidas devem dar ao estudante contexto suficiente para que ele descubra a solução por conta própria.
  • Deve ser fornecida apenas a informação necessária para entender os fundamentos do conceito e resolver o exercício. Informações extras devem ficar no documento about.md do conceito.
  • Links devem ser usados com moderação, se forem usados. Embora um link que explique um tópico complexo como recursão possa ser útil, para a maioria dos conceitos os links fornecerão mais informação do que o necessário, então o ideal é explicar as coisas de forma concisa no próprio texto.
  • Termos técnicos adequados devem ser usados para que o estudante consiga pesquisar mais informações com facilidade.
  • Exemplos de código devem ser usados apenas para introduzir sintaxe nova (os estudantes não devem precisar pesquisar exemplos de sintaxe na web). Em outros casos, forneça descrições ou links em vez de código.

Como exemplo, a introdução de um exercício de "strings" pode descrever uma string como apenas uma "sequência de caracteres Unicode" ou uma "série de bytes", dizer aos usuários como criar uma string e explicar que uma string tem métodos que podem ser usados para manipulá-la. A menos que o estudante precise entender detalhes mais sutis para resolver o exercício, esse tipo de explicação breve (junto com um exemplo de sintaxe) deve ser informação suficiente para o estudante resolver o exercício.

Exemplo

# Introduction

There are two primary ways to assign objects to names in Ruby - using variables or constants. Variables are always written in snake case. A variable can reference different objects over its lifetime. For example, `my_first_variable` can be defined and redefined many times using the `=` operator:

```ruby
my_first_variable = 1
my_first_variable = "Some string"
my_first_variable = SomeComplexObject.new
```

Arquivo: .docs/introduction.md.tpl

Objetivo: Modelo para gerar um arquivo introduction.md.

Presença: Opcional

O documento introduction.md apresenta o(s) conceito(s) do exercício ao estudante. Cada conceito também tem seu próprio documento introduction.md, que não é mostrado fora do contexto de um exercício.

Se a introdução do conceito deve ser incluída literalmente na introdução do exercício, um arquivo introduction.md.tpl pode ser usado. Esse arquivo permite referenciar introduções de conceitos por meio de placeholders: %{concept:<concept-slug>}.

O configlet pode gerar um arquivo introduction.md a partir de um arquivo de modelo. O arquivo gerado terá os placeholders de conceito substituídos pelo conteúdo de introduction do conceito.

O site do Exercism só conhece o documento introduction.md. É responsabilidade da trilha gerar o introduction.md quando um arquivo de modelo é usado.

As trilhas podem decidir por exercício se usam um modelo ou não. Em alguns casos, usar a introdução do conceito literalmente pode não ser o ideal. Sempre escolha o que proporciona a melhor experiência de aprendizado ao estudante.

Exemplo

# Introduction

%{concept:variables}

Arquivo: .docs/instructions.md

Objetivo: Fornecer instruções para o exercício.

Presença: Obrigatória

Este arquivo é dividido em duas partes.

  1. A primeira parte explica a "história" ou o "tema" do exercício. Em geral, não deve conter exemplos de código.
  2. A segunda parte fornece instruções claras do que o estudante precisa fazer, na forma de uma ou mais tarefas.

Cada tarefa deve seguir o seguinte padrão:

  • Começar com um título de segundo nível que começa com um número (por exemplo, ## 1. Do X, ## 2. Do Y).
  • O título deve descrever o que implementar, não como implementar (por exemplo, ## 1. Check if an appointment has already passed).
  • Descreva qual função/método o estudante precisa definir/implementar (por exemplo, Implement method X(...) that takes an A and returns a Z),
  • Forneça um exemplo de uso dessa função em código. Esses exemplos devem ser diferentes dos apresentados nos testes.

Damos muito valor a tornar o conteúdo do Exercism seguro para todos e, por isso, muitas vezes erramos pelo lado da cautela ao decidir se uma história é apropriada ou não. Embora sejamos cuidadosos com o que mesclamos, reconhecemos que é difícil ter consciência do que pode ser visto como problemático, então sempre presumimos que você está agindo de boa-fé e fazemos o nosso melhor para detectar quaisquer problemas na revisão de forma não confrontadora. Se você quiser verificar uma história com a gente, mencione @exercism/leadership e nós a analisaremos juntos. Aqui estão alguns pontos norteadores:

  • Tente garantir que a história seja acolhedora e possa ser entendida por todos. Se a história contiver piadas internas ou gírias regionais, tente pensar em frases alternativas.
  • Tente escrever exemplos que sejam inclusivos para todos. Por exemplo, considere usar nomes de outras culturas e gêneros variados.
  • Pergunte a si mesmo se você conhece alguém pessoalmente que se ofenderia com a história. Se for o caso, considere mudá-la para evitar isso.

Exemplo

# Instructions

In this exercise you're going to write some code to help you cook a brilliant lasagna from your favorite cooking book.

## 1. Calculate the remaining oven time in minutes

Define the `Lasagna#remaining_minutes_in_oven` method that takes the actual minutes the lasagna has been in the oven as a parameter and returns how many minutes the lasagna still has to remain in the oven, based on the expected oven time in minutes from the previous task.

```ruby
lasagna = Lasagna.new
lasagna.remaining_minutes_in_oven(30)
# => 10
```

Arquivo: .docs/hints.md

Objetivo: Fornecer dicas a um estudante para ajudá-lo a sair de um bloqueio em um exercício.

Presença: Obrigatória

  • Se o estudante ficar preso, permitiremos que ele clique em um botão para solicitar uma dica, que mostrará a parte relevante do arquivo.
  • As dicas devem ser em formato de lista com marcadores sob títulos.
  • As dicas devem ser suficientes para desbloquear quase qualquer estudante.
  • As dicas não devem explicitar a solução, mas apontar para um recurso que descreva a solução (por exemplo, linkar para a documentação da função a ser usada).
  • As dicas podem usar exemplos de código para explicar conceitos, mas não para esboçar a solução. Por exemplo, em um exercício de listas, elas podem mostrar um trecho de como uma determinada função de lista funciona, mas não de uma forma que possa ser copiada e colada diretamente na solução.
  • Dicas gerais sobre o exercício podem aparecer como uma lista Markdown sob o título ## General.
  • Dicas específicas de tarefa devem aparecer como uma lista Markdown sob títulos que correspondam ao título da tarefa no instructions.md (por exemplo, ## 2. Do Y).
  • Se não houver dicas gerais nem dicas para uma tarefa específica, os títulos devem ser omitidos. Todo título deve ser seguido por uma lista Markdown.
  • Priorize dicas específicas de tarefa em vez de dicas gerais, pois as dicas específicas de tarefa têm mais chance de desbloquear o estudante do que as dicas gerais.
  • Os títulos de tarefa devem descrever o o que da tarefa, não o como.
  • Os títulos de tarefa devem usar capitalização normal de frase (por exemplo, ## 2. Check if a book can be borrowed).
  • As tarefas devem ser explícitas sobre qual método/função/tipo implementar e seu valor esperado (por exemplo, Implement the 'canBorrowBook' function to check if a book can be borrowed. The function takes a book as its parameter and returns `true` if the book has not already been borrowed; otherwise, return `false`).

Ver as dicas não será um caminho "recomendado" e vamos desencorajar (gentilmente) o uso delas, a menos que o estudante não consiga progredir sem elas. Por isso, vale considerar que o estudante que as ler estará um pouco confuso/sobrecarregado e talvez frustrado.

Exemplo

# Hints

## General

- You need to define a [constant][constant] which should contain the [integer][integers] value specified in the recipe.

## 1. Calculate the remaining oven time in minutes

- You need to define a [method][methods] with a single parameter for the actual time so far.

[constants]: https://www.rubyguides.com/2017/07/ruby-constants/
[integers]: https://ruby-doc.org/core-2.7.0/Integer.html
[methods]: https://launchschool.com/books/ruby/read/methods

Arquivo: .meta/design.md

Objetivo: Descrever o design do exercício.

Presença: Obrigatória

Este arquivo contém informações sobre o design do exercício, incluindo coisas como seu objetivo, seus objetivos de ensino, o que não ensinar e mais. Essas informações podem ser extraídas da issue correspondente do exercício no GitHub.

Ele existe para informar futuros mantenedores ou colaboradores sobre o escopo e as limitações de um exercício, evitando a tendência natural de tornar os exercícios mais complexos com o tempo.

Exemplo

# Design

## Goal

The goal of this exercise is to teach the student the basics of programming in Ruby.

## Learning objectives

- Know what a variable is.
- Know how to define a variable.
- Know how to update a variable.

## Out of scope

- Memory and performance characteristics.
- Method overloads.

## Concepts

The Concepts this exercise unlocks are:

- `basics`: know what a variable is; know how to define a variable; know how to update a variable.

## Prerequisites

There are no prerequisites.

Arquivo: .meta/config.json

Objetivo: Contém metainformações sobre o exercício.

Presença: Obrigatória

Este arquivo contém metainformações sobre o exercício:

  • authors: O(s) nome(s) de usuário do GitHub do(s) autor(es) do exercício (obrigatório)
    • Incluindo revisores se suas revisões mudarem substancialmente o exercício (a ponto de parecer que "vocês chegaram lá juntos")
  • contributors: O(s) nome(s) de usuário do GitHub do(s) colaborador(es) do exercício (opcional)
    • Incluindo revisores se suas revisões forem significativas/acionáveis/aplicadas.
  • forked_from: De qual(is) exercício(s) ele foi derivado (obrigatório se o exercício for derivado)
  • files: Os locais dos arquivos usados neste exercício, relativos ao diretório do exercício (obrigatório)
  • language_versions: Requisitos de versão da linguagem (opcional)
  • blurb: Uma descrição curta deste exercício. Seu comprimento deve ser <= 350. Markdown não é suportado (obrigatório)
  • source: A fonte na qual este exercício se baseia (opcional)
  • source_url: A URL da fonte na qual este exercício se baseia (opcional)
  • representer: Metainformações relacionadas a como o representer processa este arquivo (opcional)
    • version: Um inteiro para a versão do representer a ser usada no exercício (obrigatório se a chave pai estiver presente)
  • icon: O slug do ícone (veja a lista completa de ícones). Se não for especificado, o slug do exercício será usado (opcional)
  • custom: Quaisquer dados não padronizados específicos do exercício. Pode ser usado para personalizar o comportamento das ferramentas da trilha por exercício (opcional)

Se alguém for ao mesmo tempo autor e colaborador, liste essa pessoa apenas como autor.

Exemplo mínimo

{
  "authors": ["FSharpForever"],
  "files": {
    "solution": ["Lasagna.fs"],
    "test": ["LasagnaTests.fs"],
    "exemplar": [".meta/Exemplar.fs"]
  },
  "blurb": "Learn the basics of F# by cooking Lucian's Luscious Lasagna"
}

Exemplo completo

Suponha que o usuário FSharpForever tenha escrito um exercício chamado log-levels para a trilha de F#. PythonProfessor adapta o exercício para a trilha de Python. Mais tarde, o usuário GladToHelp melhora o exercício.

{
  "authors": ["PythonProfessor"],
  "contributors": ["GladToHelp"],
  "files": {
    "solution": ["log_levels.py"],
    "test": ["log_levels_test.py"],
    "exemplar": [".meta/exemplar.py"],
    "editor": ["test_helper.py"]
  },
  "forked_from": ["fsharp/log-levels"],
  "language_versions": ">=3.7",
  "blurb": "Learn how to work with strings by processing log lines.",
  "source": "Wikipedia",
  "source_url": "https://en.wikipedia.org/wiki/Log_file",
  "representer": {
    "version": 2
  },
  "icon": "logs",
  "custom": {
    "parallel": true
  }
}

Observe que:

  • A ordem dos autores e colaboradores não é significativa e não tem significado.
  • Se você estiver derivando um exercício, não faça referência aos autores ou colaboradores originais. Apenas garanta que forked_from esteja correto.
  • Embora não seja comum, é possível derivar de vários exercícios.
  • language_versions é uma string de formato livre que as trilhas podem usar e interpretar como quiserem.

Arquivo: .approaches/introduction.md

Objetivo: Introdução às abordagens mais comuns para o exercício

Presença: Opcional

Este arquivo descreve as abordagens mais comuns para o exercício. Consulte a documentação para saber mais sobre o que deve constar neste arquivo.

Exemplo

# Introduction

The key to this exercise is to deal with C# strings being immutable, which means that a `string`'s value cannot be changed.
Therefore, to reverse a string you'll need to create a _new_ `string`.

## Using LINQ

```csharp
public static string Reverse(string input)
{
    return new string(input.Reverse().ToArray());
}
```

For more information, check the [LINQ approach][approach-linq].

## Which approach to use?

If readability is your primary concern (and it usually should be), the LINQ-based approach is hard to beat.

Arquivo: .approaches/config.json

Objetivo: Metadados das abordagens

Presença: Opcional (obrigatória quando existe uma introdução de abordagem ou uma abordagem)

Este arquivo contém metainformações sobre as abordagens do exercício:

  • introduction: O(s) nome(s) de usuário do GitHub do(s) autor(es) da introdução de abordagem do exercício (opcional)

    • authors: O(s) nome(s) de usuário do GitHub do(s) autor(es) da introdução de abordagem do exercício (obrigatório)
      • Incluindo revisores se suas revisões mudarem substancialmente a introdução de abordagem do exercício (a ponto de parecer que "vocês chegaram lá juntos")
    • contributors: O(s) nome(s) de usuário do GitHub do(s) colaborador(es) da introdução de abordagem do exercício (opcional)
      • Incluindo revisores se suas revisões forem significativas/acionáveis/aplicadas.
  • approaches: Um array que lista as abordagens detalhadas (opcional)

    • uuid: um UUID V4 que identifica exclusivamente a abordagem. O UUID deve ser exclusivo tanto dentro da trilha quanto entre todas as trilhas, e nunca deve mudar
    • slug: o slug da abordagem, que é uma string em letras minúsculas e kebab-case. O slug deve ser exclusivo entre todos os slugs de abordagem da trilha. Seu comprimento deve ser <= 255.
    • title: o título da abordagem. Seu comprimento deve ser <= 255.
    • blurb: Uma descrição curta desta abordagem. Seu comprimento deve ser <= 350. Markdown não é suportado (obrigatório)
    • authors: O(s) nome(s) de usuário do GitHub do(s) autor(es) da abordagem do exercício (obrigatório)
      • Incluindo revisores se suas revisões mudarem substancialmente a abordagem do exercício (a ponto de parecer que "vocês chegaram lá juntos")
    • contributors: O(s) nome(s) de usuário do GitHub do(s) colaborador(es) da abordagem do exercício (opcional)
      • Incluindo revisores se suas revisões forem significativas/acionáveis/aplicadas.
    • tags: Especifica as condições para quando uma submissão é vinculada a uma abordagem. (opcional)
      • all: Um array de tags que devem estar todas presentes em uma submissão (opcional, a menos que any não tenha elementos)
      • any: Um array de tags do qual pelo menos uma deve estar presente em uma submissão (opcional, a menos que all não tenha elementos)
      • not: nenhuma das tags deve estar presente em uma submissão (opcional)

Exemplo

{
  "introduction": {
    "authors": ["erikschierboom"]
  },
  "approaches": [
    {
      "uuid": "448fb2b4-18ab-4e55-aa54-ad4ed6d5f7f6",
      "slug": "span",
      "title": "Use Span<T>",
      "blurb": "Use Span<T> to efficiently reverse a string.",
      "authors": ["erikschierboom"]
    }
  ]
}

Arquivo: .approaches/<approach-slug>/content.md

Objetivo: Descrição detalhada da abordagem

Presença: Opcional (obrigatória para abordagens)

Este arquivo contém uma descrição detalhada da abordagem. Consulte a documentação para saber mais sobre o que deve constar neste arquivo.

Exemplo

# Span

```csharp
Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
    chars[input.Length - 1 - i] = input[i];
}
return new string(chars);
```

This `Span<T>` approach uses a `for` loop.

Arquivo: .approaches/<approach-slug>/snippet.txt

Objetivo: Trecho que demonstra a abordagem

Presença: Opcional (obrigatória para abordagens)

Este arquivo contém um pequeno trecho que demonstra a abordagem. O trecho é mostrado na página Dig Deeper de um exercício.

Seu número de linhas deve ser <= 8.

Consulte a documentação para saber mais sobre o que deve constar neste arquivo.

Exemplo

Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
    chars[input.Length - 1 - i] = input[i];
}
return new string(chars);

Arquivo: .article/config.json

Objetivo: Metadados dos artigos

Presença: Opcional (obrigatória quando existe um artigo)

Este arquivo contém metainformações sobre os artigos do exercício:

  • articles: Um array que lista os artigos detalhados (opcional)
    • uuid: um UUID V4 que identifica exclusivamente o artigo. O UUID deve ser exclusivo tanto dentro da trilha quanto entre todas as trilhas, e nunca deve mudar
    • slug: o slug do artigo, que é uma string em letras minúsculas e kebab-case. O slug deve ser exclusivo entre todos os slugs de artigo da trilha. Seu comprimento deve ser <= 255.
    • title: o título do artigo. Seu comprimento deve ser <= 255.
    • blurb: Uma descrição curta deste artigo. Seu comprimento deve ser <= 350. Markdown não é suportado (obrigatório)
    • authors: O(s) nome(s) de usuário do GitHub do(s) autor(es) do artigo do exercício (obrigatório)
      • Incluindo revisores se suas revisões mudarem substancialmente o artigo do exercício (a ponto de parecer que "vocês chegaram lá juntos")
    • contributors: O(s) nome(s) de usuário do GitHub do(s) colaborador(es) do artigo do exercício (opcional)
      • Incluindo revisores se suas revisões forem significativas/acionáveis/aplicadas.

Exemplo

{
  "articles": [
    {
      "uuid": "6db71962-62d5-448b-a980-c20ae41013ed",
      "slug": "performance",
      "title": "Optimizing performance",
      "blurb": "Explore how to most efficiently reverse a string and what the trade-offs are.",
      "authors": ["erikschierboom"]
    }
  ]
}

Arquivo: .articles/<article-slug>/content.md

Objetivo: Descrição detalhada do artigo

Presença: Opcional (obrigatória para artigos)

Este arquivo contém uma descrição detalhada do artigo. Consulte a documentação para saber mais sobre o que deve constar neste arquivo.

Exemplo

# Performance

In this document, we'll find out which approach is the most performant one.

## Benchmark results

| Method |      Mean |     Error |    StdDev |    Median | Allocated |
| -----: | --------: | --------: | --------: | --------: | --------: |
|   Linq | 29.133 ns | 0.5865 ns | 0.5486 ns | 28.984 ns |      80 B |
|  Array |  4.806 ns | 0.4999 ns | 1.4739 ns |  3.967 ns |         - |

Arquivo: .articles/<article-slug>/snippet.txt

Objetivo: Trecho que demonstra o artigo

Presença: Opcional (obrigatória para artigos)

Este arquivo contém um pequeno trecho que demonstra o artigo. O trecho é mostrado na página Dig Deeper de um exercício.

Seu número de linhas deve ser <= 8.

Consulte a documentação para saber mais sobre o que deve constar neste arquivo.

Exemplo

| Method |      Mean | Allocated |
| -----: | --------: | --------: |
|   Linq | 29.133 ns |      80 B |
|  Array |  4.806 ns |         - |

Arquivo: Implementação stub

Objetivo: Fornecer um ponto de partida para os estudantes.

Presença: Obrigatória

  • Projete o stub de forma que o estudante saiba onde adicionar código.
  • Defina stubs para qualquer sintaxe que não seja introduzida no exercício. Para a maioria dos exercícios, isso significa definir funções/métodos stub.
  • Para linguagens compiladas, considere ter código compilável, pois mensagens do compilador às vezes podem ser difíceis de entender para estudantes novos na linguagem.
  • O código deve ser o mais simples possível.
  • Use apenas recursos da linguagem introduzidos pelo exercício ou por seus pré-requisitos (e os pré-requisitos deles, e assim por diante).
  • O arquivo stub é mostrado ao estudante ao programar no navegador e é baixado para o sistema de arquivos do estudante ao usar a CLI.
  • Os caminhos relativos para o(s) arquivo(s) de implementação stub devem ser especificados na chave "files.solution" do arquivo .meta/config.json.

Exemplo

class Lasagna
  def remaining_minutes_in_oven(actual_minutes_in_oven)
    raise NotImplementedError, 'Please implement the Lasagna#remaining_minutes_in_oven method'
  end

  def preparation_time_in_minutes(layers)
    raise NotImplementedError, 'Please implement the Lasagna#preparation_time_in_minutes method'
  end
end

Arquivo: Testes

Objetivo: Verificar se uma solução está correta.

Presença: Obrigatória

  • Os testes não devem usar os exemplos do arquivo instructions.md.
  • O código deve ser o mais simples possível.
  • Use apenas recursos da linguagem introduzidos pelos pré-requisitos do exercício (e os pré-requisitos deles, e assim por diante).
  • O arquivo de testes não é mostrado ao estudante ao programar no navegador, mas é baixado para o sistema de arquivos do estudante ao usar a CLI.
  • Os caminhos relativos para o(s) arquivo(s) de teste devem ser especificados na chave "files.test" do arquivo .meta/config.json.

Exemplo

require 'minitest/autorun'
require_relative 'lasagna'

class LasagnaTest < Minitest::Test
  def test_remaining_minutes_in_oven
    assert_equal 15, Lasagna.new.remaining_minutes_in_oven(25)
  end

  def test_preparation_time_in_minutes_with_one_layer
    assert_equal 2, Lasagna.new.preparation_time_in_minutes(1)
  end

  def test_preparation_time_in_minutes_with_multiple_layers
    assert_equal 8, Lasagna.new.preparation_time_in_minutes(4)
  end
end

Arquivo: Implementação exemplar

Objetivo: Fornecer a implementação alvo que o estudante deve buscar.

Presença: Obrigatória

  • Esta implementação é o código alvo que queremos que o estudante busque.
  • Mentores verão este código como o "alvo" ao escrever feedback
  • A implementação deve usar apenas recursos da linguagem introduzidos pelo exercício ou por seus pré-requisitos (e os pré-requisitos deles, e assim por diante).
  • O arquivo exemplar não é mostrado ao estudante ao programar no navegador e não é baixado para o sistema de arquivos do estudante ao usar a CLI.
  • O arquivo exemplar será mostrado aos mentores ao comentar soluções ou representações.
  • Os caminhos relativos para o(s) arquivo(s) de implementação exemplar devem ser especificados na chave "files.exemplar" do arquivo .meta/config.json.

Exemplo

class Lasagna
  EXPECTED_MINUTES_IN_OVEN = 40
  PREPARATION_MINUTES_PER_LAYER = 2

  def remaining_minutes_in_oven(actual_minutes_in_oven)
    EXPECTED_MINUTES_IN_OVEN - actual_minutes_in_oven
  end

  def preparation_time_in_minutes(layers)
    layers * PREPARATION_MINUTES_PER_LAYER
  end
end

Arquivo: Arquivos adicionais

Objetivo: Garantir que os testes possam rodar.

Presença: Obrigatória se os arquivos padrão não forem suficientes para rodar os testes

Algumas linguagens exigem arquivos adicionais para que os testes rodem. Exemplos disso são os arquivos de projeto do C# e os arquivos package.json do Node, sem os quais não será possível rodar os testes.

Arquivos compartilhados

Alguns arquivos não são específicos de exercícios individuais, mas se aplicam a todos os exercícios. Consulte a documentação para saber mais.

Nomenclatura

Exercícios de conceito devem ser nomeados de acordo com sua história/tema, não de acordo com seu(s) conceito(s).

Bons exemplos de nomes:

  • Tim from Marketing
  • Lucian's Luscious Lasagna
  • Calculator Conundrum

Nomes não permitidos:

  • Booleans: usa um nome de conceito, não um nome de história
  • Exercise #1: um exercício não é uma história/tema

Ao derivar um exercício sem grandes mudanças, use o nome original quando possível.

Slugs

Cada exercício também tem um slug, que é uma versão normalizada do nome do exercício usando as seguintes regras:

  1. Use letras minúsculas.
  2. Use kebab-case.
  3. Use caracteres alfanuméricos latinos e hífens (Regexp: [a-z0-9-]+)
  4. Prefira dígitos escritos por extenso em vez de numerais, a menos que haja um motivo específico para preferir o numeral (por exemplo, two-fer em vez de 2-fer)

Bons exemplos de slugs:

  • tim-from-marketing
  • lucians-luscious-lasagna
  • calculator-conundrum

Slugs não permitidos:

  • TIM-FROM-MARKETING: não usa letras minúsculas (ou seja, tim-from-marketing)
  • TimFromMarketing: não usa kebab-case (ou seja, tim-from-marketing)
  • floating-point-numbers: usa um nome de conceito, não um nome de história

Apresentação

Há uma diferença na forma como a documentação do exercício é apresentada ao estudante ao usar o editor no navegador versus ao usar a CLI. Consulte este documento para saber mais.

Ícone

Cada exercício tem um ícone que o acompanha. Por padrão, o ícone exibido é o cujo nome corresponde ao slug do exercício. É possível substituir isso especificando a propriedade icon no arquivo .meta/config.json do exercício.

Se você estiver derivando um exercício existente, provavelmente já existe um ícone para esse exercício. Se não, por favor abra uma issue no repositório website-icons.