Konzeptübungen


Konzept-Übungen sind Übungen, die darauf ausgelegt sind, bestimmte (Programmier-)Konzepte zu vermitteln. Die Konzepte, die in den Konzept-Übungen vermittelt werden, bilden einen Syllabus. Weitere Informationen dazu, wie du einen Syllabus entwirfst, findest du in der Syllabus-Dokumentation.

Note

Du kannst schnell eine neue Konzept-Übung anlegen, indem du die folgenden Befehle aus dem Stammverzeichnis des Tracks ausführst:

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

Weitere Informationen findest du in der configlet create-Dokumentation

Metadaten

Die Metadaten einer Konzept-Übung werden im Schlüssel exercises.concept in der config.json-Datei definiert. Die Metadaten definieren die UUID, den Slug und mehr für die Übung.

Beispiel

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

Dateien

Jede Konzept-Übung hat ihr eigenes Verzeichnis innerhalb des Verzeichnisses exercises/concept des Tracks. Der Name des Verzeichnisses der Konzept-Übung muss mit der Eigenschaft slug der Konzept-Übung übereinstimmen, wie sie in der config.json-Datei definiert ist.

Eine Konzept-Übung hat vier Arten von Dateien:

Dokumentationsdateien

Diese Dateien werden den Lernenden gezeigt, um die Übung zu erklären.

  • .docs/introduction.md: stellt die Konzepte vor, die die Übung den Lernenden vermittelt (erforderlich)
  • .docs/instructions.md: enthält die Anweisungen für die Übung (erforderlich)
  • .docs/hints.md: gibt den Lernenden Hinweise, damit sie bei einer Übung wieder weiterkommen (erforderlich)

Metadatendateien

Diese Dateien werden den Lernenden nicht gezeigt, sondern dienen dazu, die Metadaten der Übung zu definieren.

  • .meta/config.json: enthält Meta-Informationen zur Übung (erforderlich)
  • .meta/design.md: beschreibt das Design der Übung (erforderlich)

Ansatz-Dateien

Diese Dateien beschreiben Ansätze für die Übung.

  • .approaches/introduction.md: Einführung in die gebräuchlichsten Ansätze für die Übung (optional)
  • .approaches/config.json: Metadaten für die Ansätze (optional)
  • .approaches/<approach-slug>/content.md: Beschreibung des Ansatzes (optional)
  • .approaches/<approach-slug>/snippet.txt: Snippet, das den Ansatz vorstellt (optional)

Artikel-Dateien

Diese Dateien beschreiben Artikel für die Übung.

  • .articles/config.json: Metadaten für die Artikel (optional)
  • .articles/<article-slug>/content.md: Beschreibung des Artikels (optional)
  • .articles/<article-slug>/snippet.md: Snippet, das den Artikel vorstellt (optional)

Übungsdateien

Die sprachspezifischen Dateien, wie die Implementierungs- und Testdateien. Die Namen dieser Dateien sind trackspezifisch.

  • Testsuite: überprüft die Korrektheit einer Lösung (erforderlich)
  • Stub-Implementierung: bietet den Lernenden einen Ausgangspunkt (erforderlich)
  • Exemplar-Implementierung: bietet eine idiomatische Implementierung, die alle Tests besteht (erforderlich)
  • Zusätzliche Dateien: stellen sicher, dass die Tests ausgeführt werden können (optional)

Beispiel

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-Implementierung)
        ├── CarsAssemble.cs (Stub-Implementierung)
        └── CarsAssemblyTests.cs (Tests)

Minimale gültige Spezifikation

Wir setzen bei neuen Übungen auf einen „optimistischen Merge"-Ansatz, bei dem Tracks Übungen in einem „Work in Progress"-Zustand entwickeln können. Der minimale gültige Zustand, der configlet besteht und das Mergen erlaubt, ist:

  • Ein gültiger Eintrag in der config.json des Tracks, bei dem status auf wip gesetzt ist.
  • Eine gültige .meta/config.json-Datei
  • Die folgenden Dateien müssen vorhanden sein, auch wenn sie leer sein dürfen:
    • .docs/introduction.md
    • .docs/instructions.md
    • .docs/hints.md
    • Stub-Implementierung
    • Testdatei

Datei: .docs/introduction.md

Zweck: Die Konzepte vorstellen, die die Übung den Lernenden vermittelt.

Vorhandensein: Erforderlich

  • Die bereitgestellten Informationen sollten den Lernenden gerade genug Kontext geben, um die Lösung selbst herauszufinden.
  • Es sollten nur Informationen bereitgestellt werden, die nötig sind, um die Grundlagen des Konzepts zu verstehen und die Übung zu lösen. Zusätzliche Informationen gehören in das about.md-Dokument des Konzepts.
  • Links sollten sparsam eingesetzt werden, wenn überhaupt. Ein Link, der ein komplexes Thema wie Rekursion erklärt, mag nützlich sein, doch bei den meisten Konzepten liefern Links mehr Informationen als nötig, daher sollte das Ziel sein, die Dinge knapp direkt im Text zu erklären.
  • Es sollten die richtigen Fachbegriffe verwendet werden, damit die Lernenden leicht nach weiteren Informationen suchen können.
  • Codebeispiele sollten nur verwendet werden, um neue Syntax einzuführen (die Lernenden sollten nicht im Web nach Syntaxbeispielen suchen müssen). In anderen Fällen gib statt Code lieber Beschreibungen oder Links an.

Ein Beispiel: Die Einführung zu einer „Strings"-Übung könnte einen String einfach als „Folge von Unicode-Zeichen" oder als „Reihe von Bytes" beschreiben, den Nutzenden zeigen, wie man einen String erstellt, und erklären, dass ein String Methoden hat, mit denen man ihn bearbeiten kann. Sofern die Lernenden nicht noch detaillierteres Wissen brauchen, um die Übung zu lösen, sollten diese kurze Erklärung (zusammen mit einem Beispiel für die Syntax) ausreichen, damit sie die Übung lösen können.

Beispiel

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

Datei: .docs/introduction.md.tpl

Zweck: Vorlage, aus der eine introduction.md-Datei erzeugt wird.

Vorhandensein: Optional

Das Dokument introduction.md führt die Lernenden in die Konzepte der Übung ein. Jedes Konzept hat außerdem sein eigenes introduction.md-Dokument, das außerhalb des Kontexts einer Übung nicht angezeigt wird.

Wenn die Einführung des Konzepts wortwörtlich in die Einführung der Übung übernommen werden soll, kann eine introduction.md.tpl-Datei verwendet werden. Diese Datei erlaubt es, über Platzhalter auf die Konzept-Einführungen zu verweisen: %{concept:<concept-slug>}.

configlet kann eine introduction.md-Datei aus einer Vorlagendatei erzeugen. In der erzeugten Datei werden die Konzept-Platzhalter durch den Inhalt von introduction des Konzepts ersetzt.

Die Exercism-Website kennt nur das Dokument introduction.md. Es liegt in der Verantwortung des Tracks, die introduction.md zu erzeugen, wenn eine Vorlagendatei verwendet wird.

Tracks können für jede Übung entscheiden, ob sie eine Vorlage verwenden oder nicht. In manchen Fällen ist es vielleicht nicht optimal, die Einführung des Konzepts wortwörtlich zu übernehmen. Entscheide dich immer für das, was den Lernenden die beste Lernerfahrung bietet.

Beispiel

# Introduction

%{concept:variables}

Datei: .docs/instructions.md

Zweck: Die Anweisungen für die Übung bereitstellen.

Vorhandensein: Erforderlich

Diese Datei ist in zwei Teile aufgeteilt.

  1. Der erste Teil erklärt die „Geschichte" oder das „Thema" der Übung. Er sollte in der Regel keine Codebeispiele enthalten.
  2. Der zweite Teil enthält klare Anweisungen, was die Lernenden tun müssen, in Form einer oder mehrerer Aufgaben.

Jede Aufgabe muss folgendem Standard entsprechen:

  • Beginne mit einer Überschrift der zweiten Ebene, die mit einer Zahl beginnt (z. B. ## 1. Do X, ## 2. Do Y).
  • Die Überschrift sollte beschreiben, was umgesetzt werden soll, nicht wie (z. B. ## 1. Check if an appointment has already passed).
  • Beschreibe, welche Funktion/Methode die Lernenden definieren/implementieren müssen (z. B. Implement method X(...) that takes an A and returns a Z),
  • Gib ein Beispiel für die Verwendung dieser Funktion im Code an. Diese Beispiele sollten sich von denen in den Tests unterscheiden.

Wir legen großen Wert darauf, dass die Inhalte von Exercism für alle sicher sind, und entscheiden deshalb bei der Frage, ob eine Geschichte angemessen ist oder nicht, lieber vorsichtig. Wir sind sorgfältig damit, was wir mergen, aber uns ist klar, dass es schwer ist, zu erkennen, was als problematisch aufgefasst werden könnte. Deshalb gehen wir immer davon aus, dass du in guter Absicht handelst, und tun in der Überprüfung unser Bestes, um Probleme auf nicht konfrontative Weise zu erkennen. Wenn du eine Geschichte mit uns abklären möchtest, erwähne bitte @exercism/leadership, und wir schauen sie uns gemeinsam an. Hier sind einige Richtlinien:

  • Achte darauf, dass die Geschichte einladend ist und von allen verstanden werden kann. Wenn die Geschichte Insiderwitze oder regionalen Slang enthält, denk über alternative Formulierungen nach.
  • Versuche, Beispiele zu schreiben, die alle einschließen. Ziehe zum Beispiel in Betracht, Namen aus anderen Kulturen und gemischte Geschlechter zu verwenden.
  • Frag dich, ob du persönlich jemanden kennst, der sich durch die Geschichte angegriffen fühlen würde. Wenn ja, denk darüber nach, sie zu ändern, um das zu vermeiden.

Beispiel

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

Datei: .docs/hints.md

Zweck: Den Lernenden Hinweise geben, damit sie bei einer Übung wieder weiterkommen.

Vorhandensein: Erforderlich

  • Wenn die Lernenden nicht weiterkommen, können sie auf einen Button klicken, um einen Hinweis anzufordern, der den relevanten Teil der Datei anzeigt.
  • Hinweise sollten als Aufzählungspunkte unter Überschriften stehen.
  • Die Hinweise sollten ausreichen, um fast alle Lernenden wieder weiterzubringen.
  • Die Hinweise sollten die Lösung nicht ausbuchstabieren, sondern auf eine Ressource verweisen, die die Lösung beschreibt (z. B. ein Link zur Dokumentation der zu verwendenden Funktion).
  • Die Hinweise dürfen Codebeispiele verwenden, um Konzepte zu erklären, aber nicht, um die Lösung zu umreißen. In einer Listen-Übung könnten sie zum Beispiel einen Ausschnitt zeigen, wie eine bestimmte Listenfunktion funktioniert, aber nicht so, dass er sich direkt in die Lösung kopieren lässt.
  • Allgemeine Hinweise zur Übung können als Markdown-Liste unter der Überschrift ## General stehen.
  • Aufgabenspezifische Hinweise sollten als Markdown-Liste unter Überschriften stehen, die ihrer Aufgabenüberschrift in der instructions.md entsprechen (z. B. ## 2. Do Y).
  • Wenn es keine allgemeinen Hinweise oder keine Hinweise zu einer bestimmten Aufgabe gibt, sollten die Überschriften weggelassen werden. Auf jede Überschrift muss eine Markdown-Liste folgen.
  • Gib aufgabenspezifischen Hinweisen den Vorrang vor allgemeinen Hinweisen, da aufgabenspezifische Hinweise die Lernenden eher weiterbringen als allgemeine.
  • Aufgabenüberschriften sollten das Was der Aufgabe beschreiben, nicht das Wie.
  • Aufgabenüberschriften sollten normale Satzschreibung verwenden (z. B. ## 2. Check if a book can be borrowed).
  • Aufgaben sollten ausdrücklich angeben, welche Methode/Funktion/welchen Typ man implementieren soll und welchen erwarteten Wert sie hat (z. B. 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`).

Die Hinweise anzusehen ist kein „empfohlener" Weg, und wir raten (sanft) davon ab, sie zu nutzen, es sei denn, die Lernenden kommen ohne sie nicht weiter. Insofern lohnt es sich zu bedenken, dass die Lernenden beim Lesen ein wenig verwirrt oder überfordert und vielleicht frustriert sein werden.

Beispiel

# 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

Datei: .meta/design.md

Zweck: Das Design der Übung beschreiben.

Vorhandensein: Erforderlich

Diese Datei enthält Informationen zum Design der Übung, darunter etwa ihr Ziel, ihre Lernziele, was nicht vermittelt werden soll und mehr. Diese Informationen lassen sich dem zugehörigen GitHub-Issue der Übung entnehmen.

Sie existiert, um künftige Maintainer oder Mitwirkende über den Umfang und die Grenzen einer Übung zu informieren und so dem natürlichen Trend entgegenzuwirken, Übungen mit der Zeit immer komplexer zu machen.

Beispiel

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

Datei: .meta/config.json

Zweck: Enthält Meta-Informationen zur Übung.

Vorhandensein: Erforderlich

Diese Datei enthält Meta-Informationen zur Übung:

  • authors: Die GitHub-Benutzernamen des Autors bzw. der Autoren der Übung (erforderlich)
    • Einschließlich Reviewern, wenn ihre Reviews die Übung wesentlich verändern (so sehr, dass es sich anfühlt wie „ihr habt es gemeinsam geschafft")
  • contributors: Die GitHub-Benutzernamen der Mitwirkenden an der Übung (optional)
    • Einschließlich Reviewern, wenn ihre Reviews sinnvoll, umsetzbar oder bereits umgesetzt sind.
  • forked_from: Von welcher Übung bzw. welchen Übungen sie geforkt wurde (erforderlich, wenn die Übung geforkt ist)
  • files: Die Speicherorte der in dieser Übung verwendeten Dateien, relativ zum Verzeichnis der Übung (erforderlich)
  • language_versions: Anforderungen an die Sprachversion (optional)
  • blurb: Eine kurze Beschreibung dieser Übung. Die Länge muss <= 350 sein. Markdown wird nicht unterstützt (erforderlich)
  • source: Die Quelle, auf der diese Übung basiert (optional)
  • source_url: Die URL der Quelle, auf der diese Übung basiert (optional)
  • representer: Meta-Informationen dazu, wie der Representer diese Datei verarbeitet (optional)
    • version: Eine Ganzzahl für die Version des Representers, die für die Übung verwendet werden soll (erforderlich, wenn der übergeordnete Schlüssel vorhanden ist)
  • icon: Der Slug des Icons (siehe die vollständige Liste der Icons). Wenn nicht angegeben, wird der Slug der Übung verwendet (optional)
  • custom: Beliebige übungsspezifische, nicht standardisierte Daten. Kann verwendet werden, um das Verhalten der Track-Tools pro Übung anzupassen (optional)

Wenn jemand sowohl Autor als auch Mitwirkender ist, führe diese Person nur als Autor auf.

Minimales Beispiel

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

Vollständiges Beispiel

Angenommen, der Nutzer FSharpForever hat eine Übung namens log-levels für den F#-Track geschrieben. PythonProfessor passt die Übung für den Python-Track an. Später verbessert der Nutzer GladToHelp die Übung.

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

Beachte:

  • Die Reihenfolge von Autoren und Mitwirkenden spielt keine Rolle und hat keine Bedeutung.
  • Wenn du eine Übung forkst, verweise nicht auf die ursprünglichen Autoren oder Mitwirkenden. Stelle nur sicher, dass forked_from korrekt ist.
  • Auch wenn es nicht üblich ist, ist es möglich, von mehreren Übungen zu forken.
  • language_versions ist ein freier String, den Tracks nach Belieben verwenden und interpretieren können.

Datei: .approaches/introduction.md

Zweck: Einführung in die gebräuchlichsten Ansätze für die Übung

Vorhandensein: Optional

Diese Datei beschreibt die gebräuchlichsten Ansätze für die Übung. Weitere Informationen dazu, was in diese Datei gehört, findest du in der Dokumentation.

Beispiel

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

Datei: .approaches/config.json

Zweck: Metadaten für die Ansätze

Vorhandensein: Optional (erforderlich, wenn eine Ansatz-Einführung oder ein Ansatz existiert)

Diese Datei enthält Meta-Informationen zu den Ansätzen der Übung:

  • introduction: Die GitHub-Benutzernamen der Autoren der Ansatz-Einführung der Übung (optional)

    • authors: Die GitHub-Benutzernamen der Autoren der Ansatz-Einführung der Übung (erforderlich)
      • Einschließlich Reviewern, wenn ihre Reviews die Ansatz-Einführung der Übung wesentlich verändern (so sehr, dass es sich anfühlt wie „ihr habt es gemeinsam geschafft")
    • contributors: Die GitHub-Benutzernamen der Mitwirkenden an der Ansatz-Einführung der Übung (optional)
      • Einschließlich Reviewern, wenn ihre Reviews sinnvoll, umsetzbar oder bereits umgesetzt sind.
  • approaches: Ein Array, das die ausführlichen Ansätze auflistet (optional)

    • uuid: eine V4-UUID, die den Ansatz eindeutig identifiziert. Die UUID muss sowohl innerhalb des Tracks als auch über alle Tracks hinweg eindeutig sein und darf sich nie ändern
    • slug: der Slug des Ansatzes, ein String in Kleinbuchstaben im Kebab-Case. Der Slug muss über alle Ansatz-Slugs innerhalb des Tracks hinweg eindeutig sein. Die Länge muss <= 255 sein.
    • title: der Titel des Ansatzes. Die Länge muss <= 255 sein.
    • blurb: Eine kurze Beschreibung dieses Ansatzes. Die Länge muss <= 350 sein. Markdown wird nicht unterstützt (erforderlich)
    • authors: Die GitHub-Benutzernamen der Autoren des Ansatzes der Übung (erforderlich)
      • Einschließlich Reviewern, wenn ihre Reviews den Ansatz der Übung wesentlich verändern (so sehr, dass es sich anfühlt wie „ihr habt es gemeinsam geschafft")
    • contributors: Die GitHub-Benutzernamen der Mitwirkenden am Ansatz der Übung (optional)
      • Einschließlich Reviewern, wenn ihre Reviews sinnvoll, umsetzbar oder bereits umgesetzt sind.
    • tags: Gib die Bedingungen an, unter denen eine Einsendung mit einem Ansatz verknüpft wird. (optional)
      • all: Ein Array von Tags, die alle in einer Einsendung vorhanden sein müssen (optional, es sei denn, any hat keine Elemente)
      • any: Ein Array von Tags, von denen mindestens einer in einer Einsendung vorhanden sein muss (optional, es sei denn, all hat keine Elemente)
      • not: keiner der Tags darf in einer Einsendung vorhanden sein (optional)

Beispiel

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

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

Zweck: Ausführliche Beschreibung des Ansatzes

Vorhandensein: Optional (erforderlich für Ansätze)

Diese Datei enthält eine ausführliche Beschreibung des Ansatzes. Weitere Informationen dazu, was in diese Datei gehört, findest du in der Dokumentation.

Beispiel

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

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

Zweck: Snippet, das den Ansatz vorstellt

Vorhandensein: Optional (erforderlich für Ansätze)

Diese Datei enthält ein kleines Snippet, das den Ansatz vorstellt. Das Snippet wird auf der Seite „Dig Deeper" einer Übung angezeigt.

Die Anzahl der Zeilen muss <= 8 sein.

Weitere Informationen dazu, was in diese Datei gehört, findest du in der Dokumentation.

Beispiel

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

Datei: .article/config.json

Zweck: Metadaten für die Artikel

Vorhandensein: Optional (erforderlich, wenn ein Artikel existiert)

Diese Datei enthält Meta-Informationen zu den Artikeln der Übung:

  • articles: Ein Array, das die ausführlichen Artikel auflistet (optional)
    • uuid: eine V4-UUID, die den Artikel eindeutig identifiziert. Die UUID muss sowohl innerhalb des Tracks als auch über alle Tracks hinweg eindeutig sein und darf sich nie ändern
    • slug: der Slug des Artikels, ein String in Kleinbuchstaben im Kebab-Case. Der Slug muss über alle Artikel-Slugs innerhalb des Tracks hinweg eindeutig sein. Die Länge muss <= 255 sein.
    • title: der Titel des Artikels. Die Länge muss <= 255 sein.
    • blurb: Eine kurze Beschreibung dieses Artikels. Die Länge muss <= 350 sein. Markdown wird nicht unterstützt (erforderlich)
    • authors: Die GitHub-Benutzernamen der Autoren des Artikels der Übung (erforderlich)
      • Einschließlich Reviewern, wenn ihre Reviews den Artikel der Übung wesentlich verändern (so sehr, dass es sich anfühlt wie „ihr habt es gemeinsam geschafft")
    • contributors: Die GitHub-Benutzernamen der Mitwirkenden am Artikel der Übung (optional)
      • Einschließlich Reviewern, wenn ihre Reviews sinnvoll, umsetzbar oder bereits umgesetzt sind.

Beispiel

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

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

Zweck: Ausführliche Beschreibung des Ansatzes

Vorhandensein: Optional (erforderlich für Ansätze)

Diese Datei enthält eine ausführliche Beschreibung des Ansatzes. Weitere Informationen dazu, was in diese Datei gehört, findest du in der Dokumentation.

Beispiel

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

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

Zweck: Snippet, das den Ansatz vorstellt

Vorhandensein: Optional (erforderlich für Artikel)

Diese Datei enthält ein kleines Snippet, das den Artikel vorstellt. Das Snippet wird auf der Seite „Dig Deeper" einer Übung angezeigt.

Die Anzahl der Zeilen muss <= 8 sein.

Weitere Informationen dazu, was in diese Datei gehört, findest du in der Dokumentation.

Beispiel

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

Datei: Stub-Implementierung

Zweck: Den Lernenden einen Ausgangspunkt bieten.

Vorhandensein: Erforderlich

  • Gestalte den Stub so, dass die Lernenden wissen, wo sie Code hinzufügen müssen.
  • Definiere Stubs für jede Syntax, die in der Übung nicht eingeführt wird. Bei den meisten Übungen bedeutet das, Stub-Funktionen bzw. -Methoden zu definieren.
  • Bei kompilierten Sprachen solltest du kompilierbaren Code in Betracht ziehen, da Compiler-Meldungen für Lernende, die mit der Sprache neu sind, manchmal schwer zu verstehen sind.
  • Der Code sollte so einfach wie möglich sein.
  • Verwende nur Sprachfunktionen, die durch die Übung oder ihre Voraussetzungen (und deren Voraussetzungen und so weiter) eingeführt werden.
  • Die Stub-Datei wird den Lernenden beim Codieren im Browser angezeigt und bei Verwendung der Kommandozeile auf das Dateisystem der Lernenden heruntergeladen.
  • Die relativen Pfade zu den Stub-Implementierungsdatei(en) müssen im Schlüssel "files.solution" der .meta/config.json-Datei angegeben werden.

Beispiel

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

Datei: Tests

Zweck: Die Korrektheit einer Lösung überprüfen.

Vorhandensein: Erforderlich

  • Die Tests sollten nicht die Beispiele aus der instructions.md-Datei verwenden.
  • Der Code sollte so einfach wie möglich sein.
  • Verwende nur Sprachfunktionen, die durch die Voraussetzungen der Übung (und deren Voraussetzungen und so weiter) eingeführt werden.
  • Die Testdatei wird den Lernenden beim Codieren im Browser nicht angezeigt, aber bei Verwendung der Kommandozeile doch auf ihr Dateisystem heruntergeladen.
  • Die relativen Pfade zu den Testdatei(en) müssen im Schlüssel "files.test" der .meta/config.json-Datei angegeben werden.

Beispiel

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

Datei: Exemplar-Implementierung

Zweck: Die Ziel-Implementierung bereitstellen, auf die die Lernenden hinarbeiten sollen.

Vorhandensein: Erforderlich

  • Diese Implementierung ist der Zielcode, auf den die Lernenden hinarbeiten sollen.
  • Mentoren wird dieser Code beim Schreiben von Feedback als „Ziel" angezeigt
  • Die Implementierung sollte nur Sprachfunktionen verwenden, die durch die Übung oder ihre Voraussetzungen (und deren Voraussetzungen und so weiter) eingeführt werden.
  • Die Exemplar-Datei wird den Lernenden beim Codieren im Browser nicht angezeigt und bei Verwendung der Kommandozeile nicht auf ihr Dateisystem heruntergeladen.
  • Die Exemplar-Datei wird Mentoren angezeigt, wenn sie Lösungen oder Repräsentationen kommentieren.
  • Die relativen Pfade zu den Beispiel-Implementierungsdatei(en) müssen im Schlüssel "files.exemplar" der .meta/config.json-Datei angegeben werden.

Beispiel

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

Datei: Zusätzliche Dateien

Zweck: Sicherstellen, dass die Tests ausgeführt werden können.

Vorhandensein: Erforderlich, wenn die Standarddateien nicht ausreichen, um die Tests auszuführen

Manche Sprachen benötigen zusätzliche Dateien, damit die Tests laufen. Beispiele dafür sind die Projektdateien von C# und die package.json-Dateien von Node, ohne die es nicht möglich ist, die Tests auszuführen.

Gemeinsam genutzte Dateien

Manche Dateien sind nicht spezifisch für einzelne Übungen, sondern gelten für alle Übungen. Weitere Informationen findest du in der Dokumentation.

Benennung

Konzept-Übungen sollten nach ihrer Geschichte bzw. ihrem Thema benannt werden, nicht nach ihren Konzepten.

Gute Beispiele für Namen:

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

Unzulässige Namen:

  • Booleans: verwendet einen Konzeptnamen statt eines Namens einer Geschichte
  • Exercise #1: eine Übung ist keine Geschichte bzw. kein Thema

Wenn du eine Übung ohne größere Änderungen forkst, verwende nach Möglichkeit den ursprünglichen Namen.

Slugs

Jede Übung hat außerdem einen Slug, eine normalisierte Version des Übungsnamens nach den folgenden Regeln:

  1. Verwende Kleinbuchstaben.
  2. Verwende Kebab-Case.
  3. Verwende lateinische alphanumerische Zeichen und Bindestriche (Regexp: [a-z0-9-]+)
  4. Bevorzuge ausgeschriebene Zahlen gegenüber Ziffern, außer es gibt einen konkreten Grund, die Ziffer zu bevorzugen (z. B. two-fer statt 2-fer)

Gute Beispiele für Slugs:

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

Unzulässige Slugs:

  • TIM-FROM-MARKETING: verwendet keine Kleinbuchstaben (d. h. tim-from-marketing)
  • TimFromMarketing: verwendet kein Kebab-Case (d. h. tim-from-marketing)
  • floating-point-numbers: verwendet einen Konzeptnamen statt eines Namens einer Geschichte

Präsentation

Es gibt einen Unterschied darin, wie die Übungsdokumentation den Lernenden angezeigt wird, wenn sie den Editor im Browser statt der Kommandozeile verwenden. Weitere Informationen findest du in diesem Dokument.

Icon

Jede Übung hat ein zugehöriges Icon. Standardmäßig ist das angezeigte Icon dasjenige, dessen Name mit dem Slug der Übung übereinstimmt. Du kannst das überschreiben, indem du die Eigenschaft icon in der .meta/config.json-Datei der Übung angibst.

Wenn du eine bestehende Übung forkst, gibt es für diese Übung wahrscheinlich schon ein Icon. Falls nicht, eröffne bitte ein Issue im Repository website-icons.