Концептуальні вправи


Концепт-вправи - це вправи, покликані навчати конкретних концепцій (програмування). Концепції, яких навчають концепт-вправи, формують силабус. Щоб дізнатися більше про те, як проєктувати силабус, перегляньте документацію про силабус.

Note

Можна швидко створити каркас нової концепт-вправи, виконавши такі команди з кореневого каталогу треку:

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

Докладніше див. у документації про configlet create

Метадані

Метадані концепт-вправи визначаються в ключі exercises.concept у файлі config.json. Метадані визначають UUID, слаг вправи та інше.

Приклад

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

Файли

Кожна концепт-вправа має власний каталог у каталозі exercises/concept треку. Назва каталогу концепт-вправи має збігатися з властивістю slug концепт-вправи, визначеною у файлі config.json.

Концепт-вправа має чотири типи файлів:

Файли документації

Ці файли подаються учневі, щоб допомогти пояснити вправу.

  • .docs/introduction.md: знайомить учня з концепціями, яких навчає вправа (обовʼязковий)
  • .docs/instructions.md: містить інструкції до вправи (обовʼязковий)
  • .docs/hints.md: містить підказки, що допомагають учневі, коли той застряг у вправі (обовʼязковий)

Файли метаданих

Ці файли не подаються учневі, а використовуються для визначення метаданих вправи.

  • .meta/config.json: містить метаінформацію про вправу (обовʼязковий)
  • .meta/design.md: описує дизайн вправи (обовʼязковий)

Файли підходів

Ці файли описують підходи до вправи.

  • .approaches/introduction.md: вступ до найпоширеніших підходів до вправи (необовʼязковий)
  • .approaches/config.json: метадані підходів (необовʼязковий)
  • .approaches/<approach-slug>/content.md: опис підходу (необовʼязковий)
  • .approaches/<approach-slug>/snippet.txt: фрагмент, що демонструє підхід (необовʼязковий)

Файли статей

Ці файли описують статті до вправи.

  • .articles/config.json: метадані статей (необовʼязковий)
  • .articles/<article-slug>/content.md: опис статті (необовʼязковий)
  • .articles/<article-slug>/snippet.md: фрагмент, що демонструє статтю (необовʼязковий)

Файли вправи

Файли, специфічні для мови, як-от файли реалізації та тестів. Назви цих файлів залежать від треку.

  • Набір тестів: перевіряє правильність рішення (обовʼязковий)
  • Заглушка: дає учням відправну точку (обовʼязковий)
  • Еталонна реалізація: надає ідіоматичну реалізацію, яка проходить усі тести (обовʼязковий)
  • Додаткові файли: забезпечують можливість запуску тестів (необовʼязковий)

Приклад

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 (еталонна реалізація)
        ├── CarsAssemble.cs (заглушка)
        └── CarsAssemblyTests.cs (тести)

Мінімальна припустима специфікація

Ми надаємо перевагу підходу «оптимістичного злиття» для нових вправ, за якого треки можуть розробляти вправи у стані «робота в процесі». Мінімальний припустимий стан, який пройде перевірку configlet і дозволить злити зміни, такий:

  • Дійсний запис у config.json треку з status, установленим у wip.
  • Дійсний файл .meta/config.json
  • Наявність таких файлів, навіть якщо вони можуть бути порожніми:
    • .docs/introduction.md
    • .docs/instructions.md
    • .docs/hints.md
    • Заглушка
    • Файл тестів

Файл: .docs/introduction.md

Призначення: Познайомити учня з концепціями, яких навчає вправа.

Наявність: Обовʼязковий

  • Надана інформація має дати учневі рівно стільки контексту, скільки потрібно, щоб самостійно дійти до рішення.
  • Варто надавати лише інформацію, потрібну для розуміння основ концепції та розвʼязання вправи. Зайву інформацію слід залишити для документа about.md цієї концепції.
  • Посилання варто використовувати ощадливо, якщо взагалі використовувати. Хоча посилання, що пояснює складну тему на кшталт рекурсії, може бути корисним, для більшості концепцій посилання дадуть більше інформації, ніж потрібно, тож метою має бути стисле пояснення просто в тексті.
  • Слід використовувати належні технічні терміни, щоб учень легко міг знайти більше інформації.
  • Приклади коду варто використовувати лише для представлення нового синтаксису (учням не потрібно шукати в інтернеті приклади синтаксису). В інших випадках замість коду варто наводити описи або посилання.

Наприклад, вступ до вправи «рядки» міг би описувати рядок тексту (англ. string) просто як «послідовність символів Unicode» або «низку байтів», розповідати користувачам, як створити рядок тексту, і пояснювати, що рядок тексту має методи, які можна використовувати для роботи з ним. Якщо учневі не потрібно розуміти тонших деталей, щоб розвʼязати вправу, такого короткого пояснення (разом із прикладом його синтаксису) має бути достатньо для розвʼязання.

Приклад

# 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

Призначення: Шаблон, з якого генерується файл introduction.md.

Наявність: Необовʼязковий

Документ introduction.md знайомить учня з концепціями вправи. Кожна концепція також має власний документ introduction.md, який не показують поза контекстом вправи.

Якщо вступ концепції має бути дослівно включений у вступ вправи, можна використати файл introduction.md.tpl. Цей файл дозволяє посилатися на вступи концепцій через заповнювачі: %{concept:<concept-slug>}.

configlet може згенерувати файл introduction.md із файлу-шаблону. У згенерованому файлі заповнювачі концепцій буде замінено вмістом introduction цієї концепції.

Сайт Exercism знає лише про документ introduction.md. Відповідальність за генерацію introduction.md, коли використовується файл-шаблон, лежить на треку.

Треки можуть вирішувати для кожної вправи окремо, використовувати шаблон чи ні. У деяких випадках дослівне використання вступу концепції може бути не найкращим. Завжди варто обирати те, що дає учневі найкращий досвід навчання.

Приклад

# Introduction

%{concept:variables}

Файл: .docs/instructions.md

Призначення: Надати інструкції до вправи.

Наявність: Обовʼязковий

Цей файл поділено на дві частини.

  1. Перша частина пояснює «історію» чи «тему» вправи. Зазвичай вона не повинна містити прикладів коду.
  2. Друга частина містить чіткі інструкції про те, що учневі потрібно зробити, у вигляді одного або кількох завдань.

Кожне завдання має відповідати таким вимогам:

  • Починатися із заголовка другого рівня, що починається з числа (наприклад, ## 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),
  • Наводити приклад використання цієї функції в коді. Ці приклади мають відрізнятися від тих, що наведені в тестах.

Ми дуже цінуємо безпечність контенту Exercism для всіх, тож часто схиляємося до обережності, вирішуючи, чи доречна та чи інша історія. Ми уважно ставимося до того, що зливаємо, але розуміємо, що важко усвідомлювати, що може здатися проблематичним, тож ми завжди припускаємо добрі наміри й робимо все можливе, щоб помітити будь-які проблеми під час рецензування, не створюючи конфронтації. Якщо є бажання перевірити історію разом із нами, згадайте @exercism/leadership, і ми розглянемо її разом. Ось кілька орієнтирів:

  • Намагаймося, щоб історія була привітною та зрозумілою для всіх. Якщо історія містить жарти для своїх або регіональний сленг, варто подумати про інші формулювання.
  • Намагаймося писати приклади, інклюзивні для всіх. Наприклад, варто використовувати імена з різних культур і різної статі.
  • Запитаймо себе, чи знаємо ми особисто когось, кого ця історія могла б образити. Якщо так, варто її змінити, щоб цього уникнути.

Приклад

# 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

Призначення: Надати учневі підказки, які допомагають подолати труднощі у вправі.

Наявність: Обовʼязковий

  • Якщо учень застрягне, ми дозволимо йому натиснути кнопку, щоб запросити підказку, яка покаже відповідну частину файлу.
  • Підказки мають бути у вигляді списку під заголовками.
  • Підказок має вистачати, щоб розблокувати майже будь-якого учня.
  • Підказки не мають викладати рішення, а натомість мають вказувати на ресурс, який його описує (наприклад, посилання на документацію функції, яку слід використати).
  • Підказки можуть використовувати зразки коду, щоб пояснити концепції, але не для окреслення рішення. Наприклад, у вправі про масиви вони можуть показати фрагмент того, як працює певна функція масиву, але не так, щоб його можна було безпосередньо скопіювати в рішення.
  • Загальні підказки про вправу можуть бути у вигляді списку Markdown під заголовком ## General.
  • Підказки до конкретного завдання мають бути у вигляді списку Markdown під заголовками, що збігаються із заголовком відповідного завдання в instructions.md (наприклад, ## 2. Do Y).
  • Якщо немає загальних підказок або підказок до конкретного завдання, заголовки слід опустити. Після кожного заголовка має йти список Markdown.
  • Надаваймо перевагу підказкам до конкретного завдання над загальними, адже перші частіше розблоковують учня.
  • Заголовки завдань мають описувати що робить завдання, а не як.
  • У заголовках завдань має бути звичайний регістр речення (наприклад, ## 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`).

Перегляд підказок не вважатиметься «рекомендованим» шляхом, і ми (мʼяко) відраджуватимемо його використання, якщо учень не може просунутися без них. Тож варто зважати, що учень, який їх читає, буде трохи спантеличеним, перевантаженим і, можливо, розчарованим.

Приклад

# 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

Файл: .meta/design.md

Призначення: Описати дизайн вправи.

Наявність: Обовʼязковий

Цей файл містить інформацію про дизайн вправи, зокрема її мету, навчальні цілі, те, чого не слід навчати, тощо. Цю інформацію можна взяти з відповідного issue на GitHub.

Він існує, щоб поінформувати майбутніх супровідників чи контрибʼюторів про обсяг і обмеження вправи, аби уникнути природної тенденції до ускладнення вправ із часом.

Приклад

# 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

Призначення: Містить метаінформацію про вправу.

Наявність: Обовʼязковий

Цей файл містить метаінформацію про вправу:

  • authors: імʼя користувача GitHub автора (авторів) вправи (обовʼязково)
    • Включаючи рецензентів, якщо їхні рецензії суттєво змінили вправу (настільки, що здається, ніби «дійшли до цього разом»)
  • contributors: імʼя користувача GitHub контрибʼютора (контрибʼюторів) вправи (необовʼязково)
    • Включаючи рецензентів, якщо їхні рецензії змістовні, дієві або враховані.
  • forked_from: з якої вправи (вправ) зроблено форк (обовʼязково, якщо вправу форкнуто)
  • files: розташування файлів, використаних у цій вправі, відносно каталогу вправи (обовʼязково)
  • language_versions: вимоги до версії мови (необовʼязково)
  • blurb: короткий опис цієї вправи. Його довжина має бути <= 350. Markdown не підтримується (обовʼязково)
  • source: джерело, на якому ґрунтується ця вправа (необовʼязково)
  • source_url: URL джерела, на якому ґрунтується ця вправа (необовʼязково)
  • representer: метаінформація про те, як репрезентер обробляє цей файл (необовʼязково)
    • version: ціле число, версія репрезентера, яку слід використати для вправи (обовʼязково, якщо наявний батьківський ключ)
  • icon: слаг іконки (див. повний список іконок). Якщо не вказано, буде використано слаг вправи (необовʼязково)
  • custom: будь-які нестандартні дані, специфічні для вправи. Можна використовувати для налаштування поведінки інструментарію треку для окремої вправи (необовʼязково)

Якщо хтось є одночасно і автором, і контрибʼютором, його слід зазначати лише як автора.

Мінімальний приклад

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

Повний приклад

Припустімо, що користувач FSharpForever написав вправу log-levels для треку F#. PythonProfessor адаптує цю вправу для треку Python. Згодом користувач GladToHelp покращує вправу.

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

Зауваження:

  • Порядок авторів і контрибʼюторів не має значення й ні про що не свідчить.
  • Якщо робимо форк вправи, не слід посилатися на початкових авторів чи контрибʼюторів. Головне, щоб forked_from був правильний.
  • Хоча це й не поширено, форк можна зробити з кількох вправ одночасно.
  • language_versions - це рядок тексту довільної форми, який треки можуть використовувати й тлумачити як завгодно.

Файл: .approaches/introduction.md

Призначення: Вступ до найпоширеніших підходів до вправи

Наявність: Необовʼязковий

Цей файл описує найпоширеніші підходи до вправи. Докладніше про те, що має бути в цьому файлі, див. у документації.

Приклад

# 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

Призначення: Метадані підходів

Наявність: Необовʼязковий (обовʼязковий, коли існує вступ до підходів або підхід)

Цей файл містить метаінформацію про підходи до вправи:

  • introduction: імʼя користувача GitHub автора (авторів) вступу до підходів вправи (необовʼязково)

    • authors: імʼя користувача GitHub автора (авторів) вступу до підходів вправи (обовʼязково)
      • Включаючи рецензентів, якщо їхні рецензії суттєво змінили вступ до підходів вправи (настільки, що здається, ніби «дійшли до цього разом»)
    • contributors: імʼя користувача GitHub контрибʼютора (контрибʼюторів) вступу до підходів вправи (необовʼязково)
      • Включаючи рецензентів, якщо їхні рецензії змістовні, дієві або враховані.
  • approaches: масив, що перелічує докладні підходи (необовʼязково)

    • uuid: UUID версії 4, який унікально ідентифікує підхід. UUID має бути унікальним як у межах треку, так і серед усіх треків, і ніколи не повинен змінюватися
    • slug: слаг підходу, рядок тексту в нижньому регістрі у форматі kebab-case. Слаг має бути унікальним серед усіх слагів підходів у межах треку. Його довжина має бути <= 255.
    • title: назва підходу. Її довжина має бути <= 255.
    • blurb: короткий опис цього підходу. Його довжина має бути <= 350. Markdown не підтримується (обовʼязково)
    • authors: імʼя користувача GitHub автора (авторів) підходу до вправи (обовʼязково)
      • Включаючи рецензентів, якщо їхні рецензії суттєво змінили підхід до вправи (настільки, що здається, ніби «дійшли до цього разом»)
    • contributors: імʼя користувача GitHub контрибʼютора (контрибʼюторів) підходу до вправи (необовʼязково)
      • Включаючи рецензентів, якщо їхні рецензії змістовні, дієві або враховані.
    • tags: визначає умови, за яких подання повʼязують із підходом (необовʼязково)
      • all: масив тегів, які всі мають бути присутні в поданні (необовʼязково, окрім випадку, коли any не має елементів)
      • any: масив тегів, принаймні один з яких має бути присутній у поданні (необовʼязково, окрім випадку, коли all не має елементів)
      • not: жоден із тегів не має бути присутній у поданні (необовʼязково)

Приклад

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

Призначення: Докладний опис підходу

Наявність: Необовʼязковий (обовʼязковий для підходів)

Цей файл містить докладний опис підходу. Докладніше про те, що має бути в цьому файлі, див. у документації.

Приклад

# 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

Призначення: Фрагмент, що демонструє підхід

Наявність: Необовʼязковий (обовʼязковий для підходів)

Цей файл містить невеликий фрагмент, що демонструє підхід. Фрагмент показується на сторінці «Dig Deeper» вправи.

Кількість його рядків має бути <= 8.

Докладніше про те, що має бути в цьому файлі, див. у документації.

Приклад

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

Призначення: Метадані статей

Наявність: Необовʼязковий (обовʼязковий, коли існує стаття)

Цей файл містить метаінформацію про статті до вправи:

  • articles: масив, що перелічує докладні статті (необовʼязково)
    • uuid: UUID версії 4, який унікально ідентифікує статтю. UUID має бути унікальним як у межах треку, так і серед усіх треків, і ніколи не повинен змінюватися
    • slug: слаг статті, рядок тексту в нижньому регістрі у форматі kebab-case. Слаг має бути унікальним серед усіх слагів статей у межах треку. Його довжина має бути <= 255.
    • title: назва статті. Її довжина має бути <= 255.
    • blurb: короткий опис цієї статті. Його довжина має бути <= 350. Markdown не підтримується (обовʼязково)
    • authors: імʼя користувача GitHub автора (авторів) статті до вправи (обовʼязково)
      • Включаючи рецензентів, якщо їхні рецензії суттєво змінили статтю до вправи (настільки, що здається, ніби «дійшли до цього разом»)
    • contributors: імʼя користувача GitHub контрибʼютора (контрибʼюторів) статті до вправи (необовʼязково)
      • Включаючи рецензентів, якщо їхні рецензії змістовні, дієві або враховані.

Приклад

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

Призначення: Докладний опис підходу

Наявність: Необовʼязковий (обовʼязковий для підходів)

Цей файл містить докладний опис підходу. Докладніше про те, що має бути в цьому файлі, див. у документації.

Приклад

# 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

Призначення: Фрагмент, що демонструє підхід

Наявність: Необовʼязковий (обовʼязковий для статей)

Цей файл містить невеликий фрагмент, що демонструє статтю. Фрагмент показується на сторінці «Dig Deeper» вправи.

Кількість його рядків має бути <= 8.

Докладніше про те, що має бути в цьому файлі, див. у документації.

Приклад

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

Файл: Заглушка

Призначення: Надати учням відправну точку.

Наявність: Обовʼязковий

  • Проєктуймо заглушку так, щоб учень знав, де додати код.
  • Визначаймо заглушки для будь-якого синтаксису, не представленого у вправі. Для більшості вправ це означає визначення функцій і методів-заглушок.
  • Для компільованих мов варто подбати про код, який компілюється, адже повідомлення компілятора іноді буває важко зрозуміти учням, для яких мова нова.
  • Код має бути якомога простішим.
  • Використовуймо лише ті можливості мови, які представлені у вправі або її передумовах (та їхніх передумовах, і так далі).
  • Файл заглушки показують учневі під час кодування в браузері та завантажують до файлової системи учня під час використання CLI.
  • Відносні шляхи до файлу (файлів) заглушки мають бути вказані в ключі "files.solution" файлу .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

Файл: Тести

Призначення: Перевірити правильність рішення.

Наявність: Обовʼязковий

  • Тести не мають використовувати приклади з файлу instructions.md.
  • Код має бути якомога простішим.
  • Використовуймо лише ті можливості мови, які представлені в передумовах вправи (та їхніх передумовах, і так далі).
  • Файл тестів не показують учневі під час кодування в браузері, але так завантажують до файлової системи учня під час використання CLI.
  • Відносні шляхи до файлу (файлів) тестів мають бути вказані в ключі "files.test" файлу .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

Файл: Еталонна реалізація

Призначення: Надати цільову реалізацію, до якої має прагнути учень.

Наявність: Обовʼязковий

  • Ця реалізація є цільовим кодом, до якого ми хочемо, щоб прагнув учень.
  • Наставникам показують цей код як «цільовий» під час написання відгуків
  • Реалізація має використовувати лише ті можливості мови, які представлені у вправі або її передумовах (та їхніх передумовах, і так далі).
  • Файл еталонної реалізації не показують учневі під час кодування в браузері та не завантажують до файлової системи учня під час використання CLI.
  • Файл еталонної реалізації показують наставникам під час коментування рішень або репрезентацій.
  • Відносні шляхи до файлу (файлів) еталонної реалізації мають бути вказані в ключі "files.exemplar" файлу .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

Файл: Додаткові файли

Призначення: Забезпечити можливість запуску тестів.

Наявність: Обовʼязкові, якщо типових файлів недостатньо для запуску тестів

Деякі мови вимагають додаткових файлів для запуску тестів. Прикладом таких файлів є файли проєктів C# і файли package.json Node, без яких запустити тести неможливо.

Спільні файли

Деякі файли не є специфічними для окремих вправ, а стосуються натомість всіх вправ. Докладніше див. у документації.

Найменування

Концепт-вправи слід називати за їхньою історією чи темою, а не за їхніми концепціями.

Хороші приклади назв:

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

Неприпустимі назви:

  • Booleans: використовує назву концепції, а не назву історії
  • Exercise #1: вправа не є історією чи темою

Коли робимо форк вправи без суттєвих змін, за можливості використовуймо оригінальну назву.

Слаги

Кожна вправа також має слаг: нормалізовану версію назви вправи, отриману за такими правилами:

  1. Використовувати нижній регістр.
  2. Використовувати kebab-case.
  3. Використовувати латинські алфавітно-цифрові символи та дефіси (регулярний вираз: [a-z0-9-]+)
  4. Надавати перевагу числам, записаним словами, а не символами цифр, якщо немає конкретної причини віддати перевагу цифрі (наприклад, two-fer, а не 2-fer)

Хороші приклади слагів:

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

Неприпустимі слаги:

  • TIM-FROM-MARKETING: не використовує нижній регістр (тобто tim-from-marketing)
  • TimFromMarketing: не використовує kebab-case (тобто tim-from-marketing)
  • floating-point-numbers: використовує назву концепції, а не назву історії

Подача

Є різниця в тому, як документація вправи подається учневі під час використання редактора в браузері та CLI. Докладніше див. у цьому документі.

Іконка

Кожна вправа має супровідну іконку. Типово показується іконка, назва якої збігається зі слагом вправи. Це можна змінити, указавши властивість icon у файлі .meta/config.json вправи.

Якщо робимо форк наявної вправи, для неї, ймовірно, вже є іконка. Якщо ні, відкрийте issue в репозиторії website-icons.