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.
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
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.
{
"exercises": {
"concept": [
{
"uuid": "93fbc7cf-3a7e-4450-ad22-e30129c36bb9",
"slug": "cars-assemble",
"name": "Cars, Assemble!",
"concepts": ["if-statements", "numbers"],
"prerequisites": ["basics"]
}
]
}
}
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:
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)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)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)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)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.
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)
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, é:
config.json da trilha, com o status definido como wip..meta/config.json válido.docs/introduction.md.docs/instructions.md.docs/hints.md.docs/introduction.md
Objetivo: Apresentar o(s) conceito(s) que o exercício ensina ao estudante.
Presença: Obrigatória
about.md do conceito.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.
# 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
```
.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.
# Introduction
%{concept:variables}
.docs/instructions.md
Objetivo: Fornecer instruções para o exercício.
Presença: Obrigatória
Este arquivo é dividido em duas partes.
Cada tarefa deve seguir o seguinte padrão:
## 1. Do X, ## 2. Do Y).## 1. Check if an appointment has already passed).Implement method X(...) that takes an A and returns a Z),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:
# 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
```
.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
## General.instructions.md (por exemplo, ## 2. Do Y).## 2. Check if a book can be borrowed).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.
# 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
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.
# 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.
.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)
contributors: O(s) nome(s) de usuário do GitHub do(s) colaborador(es) do exercício (opcional)
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)
solution: o(s) arquivo(s) de implementação stub (obrigatório)test: o(s) arquivo(s) de teste (obrigatório)exemplar: o(s) arquivo(s) de implementação exemplar (obrigatório)editor: outros arquivos mostrados como somente leitura no editor (opcional)invalidator: arquivos que, quando alterados, fazem uma solução ficar desatualizada (opcional)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.
{
"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"
}
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:
forked_from esteja correto.language_versions é uma string de formato livre que as trilhas podem usar e interpretar como quiserem..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.
# 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.
.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)
contributors: O(s) nome(s) de usuário do GitHub do(s) colaborador(es) da introdução de abordagem do exercício (opcional)
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 mudarslug: 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)
contributors: O(s) nome(s) de usuário do GitHub do(s) colaborador(es) da abordagem do exercício (opcional)
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){
"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"]
}
]
}
.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.
# 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.
.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.
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);
.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 mudarslug: 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)
contributors: O(s) nome(s) de usuário do GitHub do(s) colaborador(es) do artigo do exercício (opcional)
{
"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"]
}
]
}
.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.
# 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 | - |
.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.
| Method | Mean | Allocated |
| -----: | --------: | --------: |
| Linq | 29.133 ns | 80 B |
| Array | 4.806 ns | - |
Objetivo: Fornecer um ponto de partida para os estudantes.
Presença: Obrigatória
"files.solution" do arquivo .meta/config.json.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
Objetivo: Verificar se uma solução está correta.
Presença: Obrigatória
instructions.md."files.test" do arquivo .meta/config.json.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
Objetivo: Fornecer a implementação alvo que o estudante deve buscar.
Presença: Obrigatória
"files.exemplar" do arquivo .meta/config.json.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
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.
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.
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 MarketingLucian's Luscious LasagnaCalculator ConundrumNomes não permitidos:
Booleans: usa um nome de conceito, não um nome de históriaExercise #1: um exercício não é uma história/temaAo derivar um exercício sem grandes mudanças, use o nome original quando possível.
Cada exercício também tem um slug, que é uma versão normalizada do nome do exercício usando as seguintes regras:
[a-z0-9-]+)two-fer em vez de 2-fer)Bons exemplos de slugs:
tim-from-marketinglucians-luscious-lasagnacalculator-conundrumSlugs 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óriaHá 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.
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.