Gli esercizi concetto sono esercizi progettati per insegnare concetti (di programmazione) specifici. I concetti insegnati dagli esercizi concetto formano un sillabo. Per maggiori informazioni su come progettare un sillabo, consulta la documentazione sul sillabo.
Puoi creare rapidamente la struttura di un nuovo esercizio concetto eseguendo i seguenti comandi dalla directory principale della traccia:
bin/fetch-configlet
bin/configlet create --concept-exercise <slug>
Per maggiori informazioni, consulta la documentazione di configlet create
I metadati degli esercizi concetto sono definiti nella chiave exercises.concept del file config.json. I metadati definiscono l'UUID, lo slug e altro ancora dell'esercizio.
{
"exercises": {
"concept": [
{
"uuid": "93fbc7cf-3a7e-4450-ad22-e30129c36bb9",
"slug": "cars-assemble",
"name": "Cars, Assemble!",
"concepts": ["if-statements", "numbers"],
"prerequisites": ["basics"]
}
]
}
}
Ogni esercizio concetto ha la propria directory all'interno della directory exercises/concept della traccia. Il nome della directory dell'esercizio concetto deve corrispondere alla proprietà slug dell'esercizio concetto, come definito nel file config.json.
Un esercizio concetto ha quattro tipi di file:
Questi file vengono presentati allo studente per aiutarlo a comprendere l'esercizio.
.docs/introduction.md: introduce il concetto o i concetti che l'esercizio insegna allo studente (obbligatorio).docs/instructions.md: fornisce le istruzioni per l'esercizio (obbligatorio).docs/hints.md: fornisce suggerimenti allo studente per aiutarlo a sbloccarsi in un esercizio (obbligatorio)Questi file non vengono presentati allo studente, ma servono a definire i metadati dell'esercizio.
.meta/config.json: contiene metainformazioni sull'esercizio (obbligatorio).meta/design.md: descrive la progettazione dell'esercizio (obbligatorio)Questi file descrivono gli approcci per l'esercizio.
.approaches/introduction.md: introduzione agli approcci più comuni per l'esercizio (facoltativo).approaches/config.json: metadati per gli approcci (facoltativo).approaches/<approach-slug>/content.md: descrizione dell'approccio (facoltativo).approaches/<approach-slug>/snippet.txt: frammento che mostra l'approccio (facoltativo)Questi file descrivono gli articoli per l'esercizio.
.articles/config.json: metadati per gli articoli (facoltativo).articles/<article-slug>/content.md: descrizione dell'articolo (facoltativo).articles/<article-slug>/snippet.md: frammento che mostra l'articolo (facoltativo)I file specifici del linguaggio, come i file di implementazione e di test. I nomi di questi file dipendono dalla traccia.
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 (exemplar implementation)
├── CarsAssemble.cs (stub implementation)
└── CarsAssemblyTests.cs (tests)
Preferiamo un approccio di "unione ottimistica" per i nuovi esercizi, in cui le tracce possono sviluppare esercizi in uno stato di «work in progress». Lo stato minimo valido, che passerà i controlli di configlet e ti permetterà di fare il merge, è:
config.json della traccia, con status impostato su wip..meta/config.json valido.docs/introduction.md.docs/instructions.md.docs/hints.md.docs/introduction.md
Scopo: Introdurre il concetto o i concetti che l'esercizio insegna allo studente.
Presenza: Obbligatorio
about.md del concetto.Ad esempio, l'introduzione di un esercizio sulle «stringhe» potrebbe descrivere una stringa come una semplice «sequenza di caratteri Unicode» o una «serie di byte», dire agli utenti come creare una stringa e spiegare che una stringa ha metodi che possono essere usati per manipolarla. A meno che lo studente non abbia bisogno di comprendere dettagli più sottili per risolvere l'esercizio, questo tipo di spiegazione breve (insieme a un esempio della sua sintassi) dovrebbe essere sufficiente per permettere allo studente di risolvere l'esercizio.
# 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
Scopo: Template da cui generare un file introduction.md.
Presenza: Facoltativo
Il documento introduction.md introduce il concetto o i concetti dell'esercizio allo studente. Ogni concetto ha anche il proprio documento introduction.md, che non viene mostrato al di fuori del contesto di un esercizio.
Se l'introduzione del concetto deve essere inclusa testualmente nell'introduzione dell'esercizio, si può usare un file introduction.md.tpl. Questo file permette di fare riferimento alle introduzioni dei concetti tramite segnaposto: %{concept:<concept-slug>}.
configlet può generare un file introduction.md da un file template. Il file generato avrà i segnaposto dei concetti sostituiti dal contenuto di introduction del concetto.
Il sito di Exercism conosce solo il documento introduction.md. È responsabilità della traccia generare il file introduction.md quando si usa un file template.
Le tracce possono decidere per ogni esercizio se usare o meno un template. In alcuni casi, usare testualmente l'introduzione del concetto potrebbe non essere ottimale. Scegli sempre ciò che offre la migliore esperienza di apprendimento allo studente.
# Introduction
%{concept:variables}
.docs/instructions.md
Scopo: Fornire le istruzioni per l'esercizio.
Presenza: Obbligatorio
Questo file è diviso in due parti.
Ogni attività deve rispettare il seguente standard:
## 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),Diamo molta importanza al rendere i contenuti di Exercism sicuri per tutti, e quindi spesso pecchiamo di prudenza nel decidere se una storia sia appropriata o meno. Pur essendo attenti a ciò che facciamo il merge, sappiamo che è difficile essere consapevoli di ciò che potrebbe essere percepito come problematico, quindi assumeremo sempre che tu stia agendo in buona fede e faremo del nostro meglio per individuare eventuali problemi in revisione in modo non conflittuale. Se vuoi verificare una storia con noi, menziona @exercism/leadership e la esamineremo insieme. Ecco alcuni punti guida:
# 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
Scopo: Fornire suggerimenti allo studente per aiutarlo a sbloccarsi in un esercizio.
Presenza: Obbligatorio
## General.instructions.md (ad esempio ## 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`).Visualizzare i suggerimenti non sarà un percorso «consigliato» e ne scoraggeremo (con delicatezza) l'uso, a meno che lo studente non riesca a progredire senza di essi. Per questo vale la pena considerare che lo studente che li legge sarà un po' confuso, sopraffatto e forse frustrato.
# 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
Scopo: Descrivere la progettazione dell'esercizio.
Presenza: Obbligatorio
Questo file contiene informazioni sulla progettazione dell'esercizio, che includono cose come il suo obiettivo, i suoi obiettivi didattici, cosa non insegnare ed altro ancora. Queste informazioni possono essere estratte dalla relativa issue di GitHub dell'esercizio.
Esiste per informare i futuri manutentori o contributori sull'ambito e sui limiti di un esercizio, per evitare la naturale tendenza a rendere gli esercizi sempre più complessi nel 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
Scopo: Contiene metainformazioni sull'esercizio.
Presenza: Obbligatorio
Questo file contiene metainformazioni sull'esercizio:
authors: il nome utente GitHub (o i nomi utente) degli autori dell'esercizio (obbligatorio)
contributors: il nome utente GitHub (o i nomi utente) dei contributori dell'esercizio (facoltativo)
forked_from: da quale esercizio o esercizi è stato forkato (obbligatorio se l'esercizio è forkato)files: le posizioni dei file usati in questo esercizio, relative alla directory dell'esercizio (obbligatorio)
solution: il/i file di implementazione stub (obbligatorio)test: il/i file di test (obbligatorio)exemplar: il/i file di implementazione esemplare (obbligatorio)editor: altri file mostrati in sola lettura nell'editor (facoltativo)invalidator: i file che, quando vengono modificati, rendono una soluzione obsoleta (facoltativo)language_versions: i requisiti di versione del linguaggio (facoltativo)blurb: una breve descrizione di questo esercizio. La sua lunghezza deve essere <= 350. Il Markdown non è supportato (obbligatorio)source: la fonte su cui si basa questo esercizio (facoltativo)source_url: l'URL della fonte su cui si basa questo esercizio (facoltativo)representer: metainformazioni relative a come il representer elabora questo file (facoltativo)
version: un numero intero per la versione del representer da usare per l'esercizio (obbligatorio se la chiave padre è presente)icon: lo slug dell'icona (vedi l'elenco completo delle icone). Se non specificato, verrà usato lo slug dell'esercizio (facoltativo)custom: qualsiasi dato non standard specifico dell'esercizio. Può essere usato per personalizzare il comportamento degli strumenti della traccia per ogni esercizio (facoltativo)Se qualcuno è sia autore sia contributore, elencalo solo come autore.
{
"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"
}
Supponiamo che l'utente FSharpForever abbia scritto un esercizio chiamato log-levels per la traccia F#. PythonProfessor adatta l'esercizio per la traccia Python. In seguito, l'utente GladToHelp migliora l'esercizio.
{
"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
}
}
Nota che:
forked_from sia corretto.language_versions è una stringa libera che le tracce sono libere di usare ed interpretare come preferiscono..approaches/introduction.md
Scopo: Introduzione agli approcci più comuni per l'esercizio
Presenza: Facoltativo
Questo file descrive gli approcci più comuni per l'esercizio. Consulta la documentazione per maggiori informazioni su cosa dovrebbe contenere questo file.
# 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
Scopo: Metadati per gli approcci
Presenza: Facoltativo (obbligatorio quando esiste un'introduzione agli approcci o un approccio)
Questo file contiene metainformazioni sugli approcci dell'esercizio:
introduction: il nome utente GitHub (o i nomi utente) degli autori dell'introduzione agli approcci dell'esercizio (facoltativo)
authors: il nome utente GitHub (o i nomi utente) degli autori dell'introduzione agli approcci dell'esercizio (obbligatorio)
contributors: il nome utente GitHub (o i nomi utente) dei contributori dell'introduzione agli approcci dell'esercizio (facoltativo)
approaches: un array che elenca gli approcci dettagliati (facoltativo)
uuid: un UUID V4 che identifica univocamente l'approccio. L'UUID deve essere univoco sia all'interno della traccia sia in tutte le tracce, e non deve mai cambiareslug: lo slug dell'approccio, che è una stringa in minuscolo e in kebab-case. Lo slug deve essere univoco tra tutti gli slug degli approcci all'interno della traccia. La sua lunghezza deve essere <= 255.title: il titolo dell'approccio. La sua lunghezza deve essere <= 255.blurb: una breve descrizione di questo approccio. La sua lunghezza deve essere <= 350. Il Markdown non è supportato (obbligatorio)authors: il nome utente GitHub (o i nomi utente) degli autori dell'approccio dell'esercizio (obbligatorio)
contributors: il nome utente GitHub (o i nomi utente) dei contributori dell'approccio dell'esercizio (facoltativo)
tags: specifica le condizioni per cui una soluzione inviata viene collegata a un approccio. (facoltativo)
all: un array di tag che devono essere tutti presenti in una soluzione inviata (facoltativo, a meno che any non abbia elementi)any: un array di tag di cui almeno uno deve essere presente in una soluzione inviata (facoltativo, a meno che all non abbia elementi)not: nessuno dei tag deve essere presente in una soluzione inviata (facoltativo){
"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
Scopo: Descrizione dettagliata dell'approccio
Presenza: Facoltativo (obbligatorio per gli approcci)
Questo file contiene una descrizione dettagliata dell'approccio. Consulta la documentazione per maggiori informazioni su cosa dovrebbe contenere questo file.
# 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
Scopo: Frammento che mostra l'approccio
Presenza: Facoltativo (obbligatorio per gli approcci)
Questo file contiene un piccolo frammento che mostra l'approccio. Il frammento viene mostrato nella pagina di approfondimento di un esercizio.
Il suo numero di righe deve essere <= 8.
Consulta la documentazione per maggiori informazioni su cosa dovrebbe contenere questo file.
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
Scopo: Metadati per gli articoli
Presenza: Facoltativo (obbligatorio quando esiste un articolo)
Questo file contiene metainformazioni sugli articoli dell'esercizio:
articles: un array che elenca gli articoli dettagliati (facoltativo)
uuid: un UUID V4 che identifica univocamente l'articolo. L'UUID deve essere univoco sia all'interno della traccia sia in tutte le tracce, e non deve mai cambiareslug: lo slug dell'articolo, che è una stringa in minuscolo e in kebab-case. Lo slug deve essere univoco tra tutti gli slug degli articoli all'interno della traccia. La sua lunghezza deve essere <= 255.title: il titolo dell'articolo. La sua lunghezza deve essere <= 255.blurb: una breve descrizione di questo articolo. La sua lunghezza deve essere <= 350. Il Markdown non è supportato (obbligatorio)authors: il nome utente GitHub (o i nomi utente) degli autori dell'articolo dell'esercizio (obbligatorio)
contributors: il nome utente GitHub (o i nomi utente) dei contributori dell'articolo dell'esercizio (facoltativo)
{
"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
Scopo: Descrizione dettagliata dell'approccio
Presenza: Facoltativo (obbligatorio per gli approcci)
Questo file contiene una descrizione dettagliata dell'approccio. Consulta la documentazione per maggiori informazioni su cosa dovrebbe contenere questo file.
# 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
Scopo: Frammento che mostra l'approccio
Presenza: Facoltativo (obbligatorio per gli articoli)
Questo file contiene un piccolo frammento che mostra l'articolo. Il frammento viene mostrato nella pagina di approfondimento di un esercizio.
Il suo numero di righe deve essere <= 8.
Consulta la documentazione per maggiori informazioni su cosa dovrebbe contenere questo file.
| Method | Mean | Allocated |
| -----: | --------: | --------: |
| Linq | 29.133 ns | 80 B |
| Array | 4.806 ns | - |
Scopo: Fornire un punto di partenza per gli studenti.
Presenza: Obbligatorio
"files.solution" del file .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
Scopo: Verificare la correttezza di una soluzione.
Presenza: Obbligatorio
instructions.md."files.test" del file .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
Scopo: Fornire l'implementazione obiettivo a cui uno studente dovrebbe puntare.
Presenza: Obbligatorio
"files.exemplar" del file .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
Scopo: Assicurare che i test possano essere eseguiti.
Presenza: Obbligatorio se i file predefiniti non bastano per eseguire i test
Alcuni linguaggi richiedono file aggiuntivi perché i test possano essere eseguiti. Esempi sono i file di progetto di C# e i file package.json di Node, senza i quali non sarà possibile eseguire i test.
Alcuni file non sono specifici dei singoli esercizi, ma si applicano invece a tutti gli esercizi. Consulta la documentazione per maggiori informazioni.
Gli esercizi concetto dovrebbero essere denominati in base alla loro storia/tema, non in base ai loro concetti.
Buoni esempi di nomi:
Tim from MarketingLucian's Luscious LasagnaCalculator ConundrumNomi non ammessi:
Booleans: usa il nome di un concetto, non un nome di storiaExercise #1: un esercizio non è una storia/temaQuando si fa il fork di un esercizio senza modifiche sostanziali, usa il nome originale quando possibile.
Ogni esercizio ha anche uno slug, che è una versione normalizzata del nome dell'esercizio secondo le seguenti regole:
[a-z0-9-]+)two-fer invece di 2-fer)Buoni esempi di slug:
tim-from-marketinglucians-luscious-lasagnacalculator-conundrumSlug non ammessi:
TIM-FROM-MARKETING: non usa lettere minuscole (cioè tim-from-marketing)TimFromMarketing: non usa il kebab-case (cioè tim-from-marketing)floating-point-numbers: usa il nome di un concetto, non un nome di storiaC'è una differenza nel modo in cui la documentazione degli esercizi viene presentata allo studente quando si usa l'editor nel browser rispetto a quando si usa la CLI. Consulta questo documento per maggiori informazioni.
Ogni esercizio ha una icona di accompagnamento.
Per impostazione predefinita, l'icona visualizzata è quella il cui nome corrisponde allo slug dell'esercizio.
È possibile sovrascrivere questa impostazione specificando la proprietà icon nel file .meta/config.json dell'esercizio.
Se stai forkando un esercizio esistente, probabilmente esiste già un'icona per quell'esercizio. In caso contrario, apri una issue nel repository website-icons.