Ejercicios de conceptos


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

Note

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

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

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

Metadatos

Los metadatos de un ejercicio de conceptos se definen en la clave exercises.concept del archivo config.json. Los metadatos definen el UUID, el slug y más cosas 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 conceptos tiene su propio directorio dentro del directorio exercises/concept del track. El nombre del directorio del ejercicio de conceptos debe coincidir con la propiedad slug del ejercicio de conceptos, tal como se define en el archivo config.json.

Un ejercicio de conceptos tiene cuatro tipos de archivos:

Archivos de documentación

Estos archivos se le presentan 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 desatascarse en un ejercicio (obligatorio)

Archivos de metadatos

Estos archivos no se le presentan 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 enfoques

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ículos

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 pruebas. Los nombres de estos archivos son específicos de cada track.

  • Conjunto de pruebas: verifica la corrección de una solución (obligatorio)
  • Implementación stub: proporciona un punto de partida para los estudiantes (obligatorio)
  • Implementación ejemplar: proporciona una implementación idiomática que pasa todas las pruebas (obligatorio)
  • Archivos adicionales: garantizan que las pruebas puedan ejecutarse (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 (exemplar implementation)
        ├── CarsAssemble.cs (stub implementation)
        └── 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 un estado de «trabajo en curso». El estado mínimo válido, que pasará configlet y te permitirá 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
  • Que estén presentes los siguientes archivos, aunque pueden estar vacíos:
    • .docs/introduction.md
    • .docs/instructions.md
    • .docs/hints.md
    • Implementación stub
    • Archivo de pruebas

Archivo: .docs/introduction.md

Propósito: Presentar al estudiante el concepto o los conceptos que enseña el ejercicio.

Presencia: Obligatorio

  • La información proporcionada debe darle al estudiante el contexto justo para que pueda encontrar la solución por sí mismo.
  • Solo debe proporcionarse 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, si es que se usan. Aunque un enlace que explique un tema complejo como la recursión podría ser útil, para la mayoría de los conceptos los enlaces proporcionarán más información de la necesaria, así que el objetivo debería ser explicar las cosas de forma concisa en el propio texto.
  • Deben usarse términos técnicos correctos 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.

A modo de ejemplo, la introducción de un ejercicio de «strings» podría describir un string como solo una «secuencia de caracteres Unicode» o una «serie de bytes», decirle a quien lo lee cómo crear un string y explicar que un string tiene métodos que pueden usarse 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

Propósito: 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, puede usarse un archivo introduction.md.tpl. Este archivo permite referirse 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 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 podría no ser lo óptimo. Elige siempre lo que ofrezca la mejor experiencia de aprendizaje al estudiante.

Ejemplo

# Introduction

%{concept:variables}

Archivo: .docs/instructions.md

Propósito: 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 muestras 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 con un número (por ejemplo, ## 1. Do X, ## 2. Do Y).
  • El encabezado debe describir qué implementar, no cómo implementarlo (por ejemplo, ## 1. Check if an appointment has already passed).
  • Describir qué función/método debe definir/implementar el estudiante (por ejemplo, Implement method X(...) that takes an A and returns a Z),
  • Proporcionar un ejemplo de uso de esa función en código. Estos ejemplos deben ser distintos de los que se dan en las pruebas.

Valoramos mucho hacer que el contenido de Exercism sea seguro para todos y, por eso, a menudo pecamos de precavidos al decidir si una historia es apropiada o no. Aunque somos cuidadosos con lo que fusionamos, entendemos que es difícil ser consciente de lo que puede percibirse como problemático, así que siempre asumiremos que actúas de buena fe y haremos 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 revisaremos juntos. Aquí tienes algunos puntos orientativos:

  • Intenta asegurarte de que la historia sea acogedora y que todos puedan entenderla. Si la historia contiene chistes internos o jerga regional, intenta pensar en frases alternativas.
  • Intenta escribir ejemplos que sean inclusivos para todos. Por ejemplo, considera usar nombres de otras culturas y géneros variados.
  • 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

Propósito: Proporcionar pistas al estudiante para ayudarle a desatascarse en un ejercicio.

Presencia: Obligatorio

  • Si el estudiante se atasca, le permitiremos hacer clic en un botón para solicitar una pista, que mostrará la parte correspondiente del archivo.
  • Las pistas deben ir como viñetas bajo encabezados.
  • Las pistas deben ser suficientes para desbloquear a casi cualquier estudiante.
  • Las pistas no deben revelar la solución, sino señalar un recurso que describa la solución (por ejemplo, enlazar a la documentación de la función que se debe usar).
  • Las pistas pueden usar muestras de código para explicar conceptos, pero no para esbozar la solución. Por ejemplo, en un ejercicio de listas podrían mostrar un fragmento de cómo funciona cierta función de listas, 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 instructions.md (por ejemplo, ## 2. Do Y).
  • Si no hay pistas generales ni pistas para una tarea específica, los encabezados deben omitirse. Cada encabezado debe ir seguido de una lista de Markdown.
  • Prioriza las pistas específicas de cada tarea por encima de las generales, ya que es más probable que desbloqueen al estudiante que las generales.
  • Los encabezados de las tareas deben describir el qué de la tarea, no el cómo.
  • Los encabezados de las tareas deben usar el uso normal de mayúsculas de oración (por ejemplo, ## 2. Check if a book can be borrowed).
  • Las tareas deben ser explícitas sobre qué método/función/tipo implementar y su valor esperado (por ejemplo, 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 desaconsejaremos (sutilmente) su uso a menos que el estudiante no pueda avanzar sin ellas. Por eso conviene tener en cuenta que el estudiante que las lea estará un poco 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

Propósito: Describir el diseño del ejercicio.

Presencia: Obligatorio

Este archivo contiene información sobre el diseño del ejercicio, que incluye cosas como su objetivo, sus metas de enseñanza, qué no enseñar y más. Esta información puede extraerse 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 así evitar la tendencia natural a que los ejercicios se vuelvan cada vez 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

Propósito: Contiene metainformación sobre el ejercicio.

Presencia: Obligatorio

Este archivo contiene metainformación sobre el ejercicio:

  • authors: El nombre o los nombres de usuario de GitHub del autor o los autores del ejercicio (obligatorio)
    • Incluye a los revisores si sus revisiones cambian sustancialmente el ejercicio (hasta el punto de que parezca que «llegaron ahí juntos»)
  • contributors: El nombre o los nombres de usuario de GitHub del colaborador o los colaboradores del ejercicio (opcional)
    • Incluye a los revisores si sus revisiones son significativas, accionables 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: Requisitos de versión del lenguaje (opcional)
  • blurb: Una descripción breve de este ejercicio. Su longitud debe ser <= 350. No se admite Markdown (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 para 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 específico del ejercicio que no sea estándar. Puede usarse para personalizar el comportamiento de las herramientas del track por ejercicio (opcional)

Si alguien es tanto autor como colaborador, lístalo 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 adelante, 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 los colaboradores no es significativo y no tiene ningún significado.
  • Si bifurcas un ejercicio, no hagas referencia a los autores o colaboradores originales. Solo asegúrate de que forked_from sea correcto.
  • Aunque no es común, sí es posible bifurcar a partir de varios ejercicios.
  • language_versions es una cadena de formato libre que los tracks pueden usar e interpretar como quieran.

Archivo: .approaches/introduction.md

Propósito: 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 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

Propósito: Metadatos de los enfoques

Presencia: Opcional (obligatorio cuando existe una introducción a los enfoques o un enfoque)

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

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

    • authors: El nombre o los nombres de usuario de GitHub del autor o los autores de la introducción a los enfoques del ejercicio (obligatorio)
      • Incluye a los revisores si sus revisiones cambian sustancialmente la introducción a los enfoques del ejercicio (hasta el punto de que parezca que «llegaron ahí juntos»)
    • contributors: El nombre o los nombres de usuario de GitHub del colaborador o los colaboradores de la introducción a los enfoques del ejercicio (opcional)
      • Incluye a los revisores si sus revisiones son significativas, accionables 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 una cadena en minúsculas y kebab-case. El slug debe ser único entre todos los slugs de enfoque 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. No se admite Markdown (obligatorio)
    • authors: El nombre o los nombres de usuario de GitHub del autor o los 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 «llegaron ahí juntos»)
    • contributors: El nombre o los nombres de usuario de GitHub del colaborador o los colaboradores del enfoque del ejercicio (opcional)
      • Incluye a los revisores si sus revisiones son significativas, accionables o se han aplicado.
    • tags: Especifica las condiciones para cuándo una solución enviada se vincula a un enfoque. (opcional)
      • all: Un array de etiquetas que deben estar todas presentes en una solución enviada (opcional, a menos que any no tenga elementos)
      • any: Un array de etiquetas de las cuales al menos una debe estar presente en una solución enviada (opcional, a menos que all no tenga elementos)
      • not: ninguna de las etiquetas debe estar presente en una solución enviada (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

Propósito: 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 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

Propósito: 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 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

Propósito: 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 una cadena en minúsculas y kebab-case. El slug debe ser único entre todos los slugs de artículo 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. No se admite Markdown (obligatorio)
    • authors: El nombre o los nombres de usuario de GitHub del autor o los 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 «llegaron ahí juntos»)
    • contributors: El nombre o los nombres de usuario de GitHub del colaborador o los colaboradores del artículo del ejercicio (opcional)
      • Incluye a los revisores si sus revisiones son significativas, accionables 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

Propósito: 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 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

Propósito: 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 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

Propósito: Proporcionar un punto de partida para los estudiantes.

Presencia: Obligatorio

  • Diseña el stub de modo que el estudiante sepa dónde agregar 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/métodos stub.
  • Para los lenguajes compilados, considera tener código que compile, ya que los mensajes del compilador a veces pueden ser difíciles de entender para estudiantes nuevos en el lenguaje.
  • El código debe ser lo más simple posible.
  • Usa solo características del lenguaje presentadas por el ejercicio o sus prerrequisitos (y los prerrequisitos de estos, y así sucesivamente).
  • El archivo stub se le muestra al estudiante cuando programa en el navegador y se descarga a su sistema de archivos cuando usa la CLI.
  • Las rutas relativas al o a los 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: Pruebas

Propósito: Verificar la corrección de una solución.

Presencia: Obligatorio

  • Las pruebas no deben usar los ejemplos del archivo instructions.md.
  • El código debe ser lo más simple posible.
  • Usa solo características del lenguaje presentadas por los prerrequisitos del ejercicio (y los prerrequisitos de estos, y así sucesivamente).
  • El archivo de pruebas no se le 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 o a los archivos de prueba 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

Propósito: 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 un estudiante.
  • A los mentores se les mostrará este código como el «objetivo» al escribir retroalimentación
  • La implementación solo debe usar características del lenguaje presentadas por el ejercicio o sus prerrequisitos (y los prerrequisitos de estos, y así sucesivamente).
  • El archivo ejemplar no se le 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 les mostrará a los mentores al comentar soluciones o representaciones.
  • Las rutas relativas al o a los archivos de implementación de ejemplo 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

Propósito: Garantizar que las pruebas puedan ejecutarse.

Presencia: Obligatorio si los archivos predeterminados no bastan para ejecutar las pruebas

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

Archivos compartidos

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

Nombres

Los ejercicios de conceptos deben nombrarse según su historia/tema, no según 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/tema

Al bifurcar un ejercicio sin cambios importantes, usa el nombre original cuando 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 en lugar de las cifras, a menos que haya una razón específica para preferir la cifra (por ejemplo, two-fer en lugar de 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 del ejercicio al estudiante cuando se usa el editor en el navegador frente a cuando se usa la CLI. Consulta este documento para más información.

Icono

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

Si estás bifurcando un ejercicio existente, probablemente ya exista un icono para ese ejercicio. Si no, por favor abre un issue en el repositorio website-icons.