Ejercicios de concepto


Los ejercicios de concepto son ejercicios diseñados para enseñar conceptos (de programación) específicos. Los conceptos que enseñan los ejercicios de concepto forman un temario. Para obtener más información sobre cómo diseñar un temario, consulta la documentación sobre el temario.

Note

Puedes generar rápidamente el esqueleto de un nuevo ejercicio de concepto ejecutando los siguientes comandos desde el directorio raíz del track:

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

Para obtener más información, consulta la documentación de configlet create

Metadatos

Los metadatos de un ejercicio de concepto se definen en la clave exercises.concept del archivo config.json. Los metadatos definen el UUID, el slug y otros datos del ejercicio.

Ejemplo

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

Archivos

Cada ejercicio de concepto tiene su propio directorio dentro del directorio exercises/concept del track. El nombre del directorio del ejercicio de concepto debe coincidir con la propiedad slug del ejercicio de concepto, tal como se define en el archivo config.json.

Un ejercicio de concepto tiene cuatro tipos de archivos:

Archivos de documentación

Estos archivos se muestran al estudiante para ayudarle a entender el ejercicio.

  • .docs/introduction.md: presenta al estudiante el concepto o los conceptos que enseña el ejercicio (obligatorio)
  • .docs/instructions.md: proporciona las instrucciones del ejercicio (obligatorio)
  • .docs/hints.md: proporciona pistas al estudiante para ayudarle a desbloquearse en un ejercicio (obligatorio)

Archivos de metadatos

Estos archivos no se muestran al estudiante, sino que se usan para definir los metadatos del ejercicio.

  • .meta/config.json: contiene metainformación sobre el ejercicio (obligatorio)
  • .meta/design.md: describe el diseño del ejercicio (obligatorio)

Archivos de enfoque

Estos archivos describen enfoques para el ejercicio.

  • .approaches/introduction.md: introducción a los enfoques más comunes para el ejercicio (opcional)
  • .approaches/config.json: metadatos de los enfoques (opcional)
  • .approaches/<approach-slug>/content.md: descripción del enfoque (opcional)
  • .approaches/<approach-slug>/snippet.txt: fragmento que muestra el enfoque (opcional)

Archivos de artículo

Estos archivos describen artículos para el ejercicio.

  • .articles/config.json: metadatos de los artículos (opcional)
  • .articles/<article-slug>/content.md: descripción del artículo (opcional)
  • .articles/<article-slug>/snippet.md: fragmento que muestra el artículo (opcional)

Archivos del ejercicio

Los archivos específicos del lenguaje, como los archivos de implementación y de test. Los nombres de estos archivos son específicos de cada track.

  • Conjunto de tests: verifica que una solución es correcta (obligatorio)
  • Implementación stub: proporciona un punto de partida para los estudiantes (obligatorio)
  • Implementación ejemplar: proporciona una implementación idiomática que pasa todos los tests (obligatorio)
  • Archivos adicionales: garantizan que los tests se pueden ejecutar (opcional)

Ejemplo

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 (implementación ejemplar)
        ├── CarsAssemble.cs (implementación stub)
        └── CarsAssemblyTests.cs (tests)

Especificación mínima válida

Preferimos un enfoque de «fusión optimista» para los ejercicios nuevos, en el que los tracks pueden desarrollar ejercicios en estado de «trabajo en curso». El estado mínimo válido, que pasa configlet y te permite fusionar, es:

  • Una entrada válida en el config.json del track, con el status establecido en wip.
  • Un archivo .meta/config.json válido
  • Los siguientes archivos presentes, aunque pueden estar vacíos:
    • .docs/introduction.md
    • .docs/instructions.md
    • .docs/hints.md
    • Implementación stub
    • Archivo de test

Archivo: .docs/introduction.md

Objetivo: Presentar al estudiante el concepto o los conceptos que enseña el ejercicio.

Presencia: Obligatorio

  • La información proporcionada debe dar al estudiante el contexto justo para que pueda idear la solución por sí mismo.
  • Solo se debe proporcionar la información necesaria para entender los fundamentos del concepto y resolver el ejercicio. La información adicional debe dejarse para el documento about.md del concepto.
  • Los enlaces deben usarse con moderación, o mejor aún, evitarse. Aunque un enlace que explique un tema complejo como la recursión puede ser útil, para la mayoría de los conceptos los enlaces proporcionarán más información de la necesaria, así que el objetivo debe ser explicar las cosas de forma concisa en el propio texto.
  • Deben usarse los términos técnicos adecuados para que el estudiante pueda buscar más información fácilmente.
  • Los ejemplos de código solo deben usarse para presentar sintaxis nueva (los estudiantes no deberían tener que buscar en la web ejemplos de sintaxis). En los demás casos, proporciona descripciones o enlaces en lugar de código.

Por ejemplo, la introducción a un ejercicio de «strings» podría describir un string como una «secuencia de caracteres Unicode» o una «serie de bytes», explicar a los usuarios cómo crear un string y explicar que un string tiene métodos que se pueden usar para manipularlo. A menos que el estudiante necesite entender detalles más matizados para resolver el ejercicio, este tipo de explicación breve (junto con un ejemplo de su sintaxis) debería ser información suficiente para que el estudiante resuelva el ejercicio.

Ejemplo

# 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
```

Archivo: .docs/introduction.md.tpl

Objetivo: Plantilla a partir de la cual generar un archivo introduction.md.

Presencia: Opcional

El documento introduction.md presenta al estudiante el concepto o los conceptos del ejercicio. Cada concepto también tiene su propio documento introduction.md, que no se muestra fuera del contexto de un ejercicio.

Si la introducción del concepto debe incluirse literalmente en la introducción del ejercicio, se puede usar un archivo introduction.md.tpl. Este archivo permite hacer referencia a las introducciones de los conceptos mediante marcadores de posición: %{concept:<concept-slug>}.

configlet puede generar un archivo introduction.md a partir de un archivo de plantilla. El archivo generado tendrá los marcadores de posición de conceptos reemplazados por el contenido de la introduction del concepto.

El sitio web de Exercism solo conoce el documento introduction.md. Es responsabilidad del track generar el introduction.md cuando se usa un archivo de plantilla.

Los tracks pueden decidir para cada ejercicio si usan una plantilla o no. En algunos casos, usar la introducción del concepto literalmente puede no ser lo óptimo. Opta siempre por lo que proporcione la mejor experiencia de aprendizaje al estudiante.

Ejemplo

# Introduction

%{concept:variables}

Archivo: .docs/instructions.md

Objetivo: Proporcionar las instrucciones del ejercicio.

Presencia: Obligatorio

Este archivo se divide en dos partes.

  1. La primera parte explica la «historia» o el «tema» del ejercicio. Por lo general, no debe contener ejemplos de código.
  2. La segunda parte proporciona instrucciones claras de lo que el estudiante debe hacer, en forma de una o más tareas.

Cada tarea debe cumplir el siguiente estándar:

  • Empezar con un encabezado de segundo nivel que comience por un número (p. ej., ## 1. Do X, ## 2. Do Y).
  • El encabezado debe describir qué implementar, no cómo implementarlo (p. ej., ## 1. Check if an appointment has already passed).
  • Describe qué función o método debe definir o implementar el estudiante (p. ej., Implement method X(...) that takes an A and returns a Z),
  • Proporciona un ejemplo de uso de esa función en código. Estos ejemplos deben ser distintos de los que aparecen en los tests.

Damos mucha importancia a que el contenido de Exercism sea seguro para todo el mundo, por lo que a menudo pecamos de cautelosos al decidir si una historia es apropiada o no. Aunque tenemos cuidado con lo que fusionamos, entendemos que es difícil ser consciente de lo que puede resultar problemático, así que siempre asumiremos que actúas de buena fe y haremos todo lo posible por detectar cualquier problema en la revisión de forma no confrontativa. Si quieres revisar una historia con nosotros, menciona a @exercism/leadership y la veremos juntos. Aquí tienes algunos puntos orientativos:

  • Intenta asegurarte de que la historia sea acogedora y que todo el mundo pueda entenderla. Si la historia contiene bromas internas o jerga regional, intenta pensar en frases alternativas.
  • Intenta escribir ejemplos que incluyan a todo el mundo. Por ejemplo, considera usar nombres de otras culturas y de géneros diversos.
  • Pregúntate si conoces personalmente a alguien a quien la historia pudiera ofender. Si es así, considera cambiarla para evitarlo.

Ejemplo

# 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
```

Archivo: .docs/hints.md

Objetivo: Proporcionar pistas al estudiante para ayudarle a desbloquearse en un ejercicio.

Presencia: Obligatorio

  • Si el estudiante se queda atascado, le permitiremos hacer clic en un botón para solicitar una pista, que mostrará la parte relevante del archivo.
  • Las pistas deben aparecer como listas de viñetas bajo encabezados.
  • Las pistas deben bastar para desbloquear a casi cualquier estudiante.
  • Las pistas no deben detallar la solución, sino señalar un recurso que describa la solución (p. ej., enlazar a la documentación de la función que hay que usar).
  • Las pistas pueden usar ejemplos de código para explicar conceptos, pero no para esbozar la solución. Por ejemplo, en un ejercicio de arrays podrían mostrar un fragmento de cómo funciona cierta función de array, pero no de una forma que se pueda copiar y pegar directamente en la solución.
  • Las pistas generales sobre el ejercicio pueden aparecer como una lista de Markdown bajo el encabezado ## General.
  • Las pistas específicas de una tarea deben aparecer como una lista de Markdown bajo encabezados que coincidan con el encabezado de su tarea en el instructions.md (p. ej., ## 2. Do Y).
  • Si no hay pistas generales ni pistas para una tarea concreta, los encabezados deben omitirse. Todo encabezado debe ir seguido de una lista de Markdown.
  • Prioriza las pistas específicas de una tarea sobre las generales, ya que es más probable que las primeras desbloqueen al estudiante que las segundas.
  • Los encabezados de las tareas deben describir el qué de la tarea, no el cómo.
  • Los encabezados de las tareas deben usar mayúsculas de oración normales (p. ej., ## 2. Check if a book can be borrowed).
  • Las tareas deben ser explícitas sobre qué método, función o tipo hay que implementar y su valor esperado (p. ej., 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 las pistas no será un camino «recomendado» y (suavemente) desaconsejaremos usarlas a menos que el estudiante no pueda avanzar sin ellas. Por ello, conviene tener en cuenta que el estudiante que las lea estará algo confundido o abrumado, y quizá frustrado.

Ejemplo

# 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

Archivo: .meta/design.md

Objetivo: Describir el diseño del ejercicio.

Presencia: Obligatorio

Este archivo contiene información sobre el diseño del ejercicio, lo que incluye cosas como su objetivo, sus metas didácticas, qué no enseñar y más. Esta información se puede extraer del issue de GitHub correspondiente al ejercicio.

Existe para informar a futuros mantenedores o colaboradores sobre el alcance y las limitaciones de un ejercicio, y para evitar la tendencia natural a volver los ejercicios más complejos con el tiempo.

Ejemplo

# 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.

Archivo: .meta/config.json

Objetivo: Contener metainformación sobre el ejercicio.

Presencia: Obligatorio

Este archivo contiene metainformación sobre el ejercicio:

  • authors: El nombre o nombres de usuario de GitHub del autor o autores del ejercicio (obligatorio)
    • Incluye a los revisores si sus revisiones cambian sustancialmente el ejercicio (hasta el punto de que parezca que «llegasteis juntos»)
  • contributors: El nombre o nombres de usuario de GitHub del colaborador o colaboradores del ejercicio (opcional)
    • Incluye a los revisores si sus revisiones son significativas, procesables o se han aplicado.
  • forked_from: De qué ejercicio o ejercicios se bifurcó (obligatorio si el ejercicio es una bifurcación)
  • files: Las ubicaciones de los archivos usados en este ejercicio, relativas al directorio del ejercicio (obligatorio)
  • language_versions: Los requisitos de versión del lenguaje (opcional)
  • blurb: Una descripción breve de este ejercicio. Su longitud debe ser <= 350. Markdown no es compatible (obligatorio)
  • source: La fuente en la que se basa este ejercicio (opcional)
  • source_url: La URL de la fuente en la que se basa este ejercicio (opcional)
  • representer: Metainformación relacionada con cómo el representer procesa este archivo (opcional)
    • version: Un entero con la versión del representer que se usará para el ejercicio (obligatorio si la clave padre está presente)
  • icon: El slug del icono (consulta la lista completa de iconos). Si no se especifica, se usará el slug del ejercicio (opcional)
  • custom: Cualquier dato no estándar específico del ejercicio. Se puede usar para personalizar el comportamiento de las herramientas del track por ejercicio (opcional)

Si alguien es autor y colaborador a la vez, inclúyelo solo como autor.

Ejemplo 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"
}

Ejemplo completo

Supongamos que el usuario FSharpForever ha escrito un ejercicio llamado log-levels para el track de F#. PythonProfessor adapta el ejercicio para el track de Python. Más tarde, el usuario GladToHelp mejora el ejercicio.

{
  "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
  }
}

Ten en cuenta que:

  • El orden de los autores y colaboradores no es significativo y no tiene ningún sentido.
  • Si estás bifurcando un ejercicio, no hagas referencia a los autores o colaboradores originales. Solo asegúrate de que forked_from sea correcto.
  • Aunque no es habitual, sí es posible bifurcar desde varios ejercicios.
  • language_versions es un string de formato libre que los tracks pueden usar e interpretar como quieran.

Archivo: .approaches/introduction.md

Objetivo: Introducción a los enfoques más comunes para el ejercicio

Presencia: Opcional

Este archivo describe los enfoques más comunes para el ejercicio. Consulta la documentación para obtener más información sobre qué debe incluir este archivo.

Ejemplo

# 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.

Archivo: .approaches/config.json

Objetivo: Metadatos de los enfoques

Presencia: Opcional (obligatorio cuando existe una introducción de enfoque o un enfoque)

Este archivo contiene metainformación sobre los enfoques del ejercicio:

  • introduction: El nombre o nombres de usuario de GitHub del autor o autores de la introducción de los enfoques del ejercicio (opcional)

    • authors: El nombre o nombres de usuario de GitHub del autor o autores de la introducción de los enfoques del ejercicio (obligatorio)
      • Incluye a los revisores si sus revisiones cambian sustancialmente la introducción de los enfoques del ejercicio (hasta el punto de que parezca que «llegasteis juntos»)
    • contributors: El nombre o nombres de usuario de GitHub del colaborador o colaboradores de la introducción de los enfoques del ejercicio (opcional)
      • Incluye a los revisores si sus revisiones son significativas, procesables o se han aplicado.
  • approaches: Un array que lista los enfoques detallados (opcional)

    • uuid: un UUID V4 que identifica de forma única el enfoque. El UUID debe ser único tanto dentro del track como en todos los tracks, y nunca debe cambiar
    • slug: el slug del enfoque, que es un string en minúsculas con formato kebab-case. El slug debe ser único entre todos los slugs de enfoques del track. Su longitud debe ser <= 255.
    • title: el título del enfoque. Su longitud debe ser <= 255.
    • blurb: Una descripción breve de este enfoque. Su longitud debe ser <= 350. Markdown no es compatible (obligatorio)
    • authors: El nombre o nombres de usuario de GitHub del autor o autores del enfoque del ejercicio (obligatorio)
      • Incluye a los revisores si sus revisiones cambian sustancialmente el enfoque del ejercicio (hasta el punto de que parezca que «llegasteis juntos»)
    • contributors: El nombre o nombres de usuario de GitHub del colaborador o colaboradores del enfoque del ejercicio (opcional)
      • Incluye a los revisores si sus revisiones son significativas, procesables o se han aplicado.
    • tags: Especifica las condiciones para que un envío se vincule a un enfoque. (opcional)
      • all: Un array de tags que deben estar todos presentes en un envío (opcional, a menos que any no tenga elementos)
      • any: Un array de tags de los que al menos uno debe estar presente en un envío (opcional, a menos que all no tenga elementos)
      • not: ninguno de los tags debe estar presente en un envío (opcional)

Ejemplo

{
  "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"]
    }
  ]
}

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

Objetivo: Descripción detallada del enfoque

Presencia: Opcional (obligatorio para los enfoques)

Este archivo contiene una descripción detallada del enfoque. Consulta la documentación para obtener más información sobre qué debe incluir este archivo.

Ejemplo

# 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.

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

Objetivo: Fragmento que muestra el enfoque

Presencia: Opcional (obligatorio para los enfoques)

Este archivo contiene un pequeño fragmento que muestra el enfoque. El fragmento se muestra en la página Dig Deeper de un ejercicio.

Su número de líneas debe ser <= 8.

Consulta la documentación para obtener más información sobre qué debe incluir este archivo.

Ejemplo

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);

Archivo: .article/config.json

Objetivo: Metadatos de los artículos

Presencia: Opcional (obligatorio cuando existe un artículo)

Este archivo contiene metainformación sobre los artículos del ejercicio:

  • articles: Un array que lista los artículos detallados (opcional)
    • uuid: un UUID V4 que identifica de forma única el artículo. El UUID debe ser único tanto dentro del track como en todos los tracks, y nunca debe cambiar
    • slug: el slug del artículo, que es un string en minúsculas con formato kebab-case. El slug debe ser único entre todos los slugs de artículos del track. Su longitud debe ser <= 255.
    • title: el título del artículo. Su longitud debe ser <= 255.
    • blurb: Una descripción breve de este artículo. Su longitud debe ser <= 350. Markdown no es compatible (obligatorio)
    • authors: El nombre o nombres de usuario de GitHub del autor o autores del artículo del ejercicio (obligatorio)
      • Incluye a los revisores si sus revisiones cambian sustancialmente el artículo del ejercicio (hasta el punto de que parezca que «llegasteis juntos»)
    • contributors: El nombre o nombres de usuario de GitHub del colaborador o colaboradores del artículo del ejercicio (opcional)
      • Incluye a los revisores si sus revisiones son significativas, procesables o se han aplicado.

Ejemplo

{
  "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"]
    }
  ]
}

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

Objetivo: Descripción detallada del enfoque

Presencia: Opcional (obligatorio para los enfoques)

Este archivo contiene una descripción detallada del enfoque. Consulta la documentación para obtener más información sobre qué debe incluir este archivo.

Ejemplo

# 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 |         - |

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

Objetivo: Fragmento que muestra el enfoque

Presencia: Opcional (obligatorio para los artículos)

Este archivo contiene un pequeño fragmento que muestra el artículo. El fragmento se muestra en la página Dig Deeper de un ejercicio.

Su número de líneas debe ser <= 8.

Consulta la documentación para obtener más información sobre qué debe incluir este archivo.

Ejemplo

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

Archivo: implementación stub

Objetivo: Proporcionar un punto de partida para los estudiantes.

Presencia: Obligatorio

  • Diseña el stub de forma que el estudiante sepa dónde añadir código.
  • Define stubs para cualquier sintaxis que no se presente en el ejercicio. Para la mayoría de los ejercicios, esto significa definir funciones o métodos stub.
  • En los lenguajes compilados, considera la posibilidad de que el código sea compilable, ya que los mensajes del compilador a veces pueden ser difíciles de entender para los estudiantes que son nuevos en el lenguaje.
  • El código debe ser lo más simple posible.
  • Usa solo las características del lenguaje que presenten el ejercicio o sus prerrequisitos (y los prerrequisitos de estos, y así sucesivamente).
  • El archivo stub se muestra al estudiante cuando programa en el navegador y se descarga a su sistema de archivos cuando usa la CLI.
  • Las rutas relativas al archivo o archivos de implementación stub deben especificarse en la clave "files.solution" del archivo .meta/config.json.

Ejemplo

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

Archivo: tests

Objetivo: Verificar que una solución es correcta.

Presencia: Obligatorio

  • Los tests no deben usar los ejemplos del archivo instructions.md.
  • El código debe ser lo más simple posible.
  • Usa solo las características del lenguaje que presenten los prerrequisitos del ejercicio (y los prerrequisitos de estos, y así sucesivamente).
  • El archivo de tests no se muestra al estudiante cuando programa en el navegador, pero sí se descarga a su sistema de archivos cuando usa la CLI.
  • Las rutas relativas al archivo o archivos de test deben especificarse en la clave "files.test" del archivo .meta/config.json.

Ejemplo

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

Archivo: implementación ejemplar

Objetivo: Proporcionar la implementación objetivo a la que el estudiante debe aspirar.

Presencia: Obligatorio

  • Esta implementación es el código objetivo al que queremos que aspire el estudiante.
  • A los mentores se les mostrará este código como el «objetivo» al escribir sus comentarios
  • La implementación solo debe usar las características del lenguaje que presenten el ejercicio o sus prerrequisitos (y los prerrequisitos de estos, y así sucesivamente).
  • El archivo ejemplar no se muestra al estudiante cuando programa en el navegador y no se descarga a su sistema de archivos cuando usa la CLI.
  • El archivo ejemplar se mostrará a los mentores al comentar soluciones o representaciones.
  • Las rutas relativas al archivo o archivos de implementación ejemplar deben especificarse en la clave "files.exemplar" del archivo .meta/config.json.

Ejemplo

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

Archivo: archivos adicionales

Objetivo: Garantizar que los tests se puedan ejecutar.

Presencia: Obligatorio si los archivos predeterminados no bastan para ejecutar los tests

Algunos lenguajes requieren archivos adicionales para que los tests se ejecuten. Ejemplos de ello son los archivos de proyecto de C# y los archivos package.json de Node, sin los cuales no será posible ejecutar los tests.

Archivos compartidos

Algunos archivos no son específicos de ejercicios individuales, sino que se aplican a todos los ejercicios. Consulta la documentación para obtener más información.

Nomenclatura

Los ejercicios de concepto deben llevar el nombre de su historia o tema, no de su concepto o conceptos.

Buenos ejemplos de nombres:

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

Nombres no permitidos:

  • Booleans: usa un nombre de concepto, no un nombre de historia
  • Exercise #1: un ejercicio no es una historia ni un tema

Cuando bifurques un ejercicio sin cambios importantes, usa el nombre original siempre que sea posible.

Slugs

Cada ejercicio también tiene un slug, que es una versión normalizada del nombre del ejercicio según las siguientes reglas:

  1. Usa minúsculas.
  2. Usa kebab-case.
  3. Usa caracteres alfanuméricos latinos y guiones (expresión regular: [a-z0-9-]+)
  4. Prefiere los dígitos escritos con palabras antes que los numéricos, a menos que haya una razón concreta para preferir el dígito (p. ej., two-fer antes que 2-fer)

Buenos ejemplos de slugs:

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

Slugs no permitidos:

  • TIM-FROM-MARKETING: no usa minúsculas (es decir, tim-from-marketing)
  • TimFromMarketing: no usa kebab-case (es decir, tim-from-marketing)
  • floating-point-numbers: usa un nombre de concepto, no un nombre de historia

Presentación

Hay una diferencia en cómo se presenta la documentación de un ejercicio al estudiante cuando usa el editor del navegador frente a cuando usa la CLI. Consulta este documento para obtener más información.

Icono

Cada ejercicio tiene un icono asociado. Por defecto, el icono mostrado es el cuyo nombre coincide con el slug del ejercicio. Se puede sobrescribir especificando la propiedad icon en el archivo .meta/config.json del ejercicio.

Si estás bifurcando un ejercicio existente, probablemente ya haya un icono para ese ejercicio. Si no es así, abre un issue en el repositorio website-icons.