تمرین مفهومی


تمرین‌های مفهومی تمرین‌هایی هستند که برای آموزش مفاهیم مشخص (برنامه‌نویسی) طراحی شده‌اند. مفاهیمی که تمرین‌های مفهومی آموزش می‌دهند، یک سرفصل را شکل می‌دهند. برای اطلاعات بیشتر درباره‌ی چگونگی طراحی یک سرفصل، مستندات سرفصل را ببینید.

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 (exemplar implementation)
        ├── CarsAssemble.cs (stub implementation)
        └── CarsAssemblyTests.cs (tests)

حداقل مشخصات معتبر

ما برای تمرین‌های تازه، رویکرد «ادغام خوش‌بینانه» را ترجیح می‌دهیم؛ یعنی ترک‌ها می‌توانند تمرین‌ها را در وضعیت «کار در جریان» توسعه دهند. حداقل وضعیت معتبر، که configlet را پاس می‌کند و به شما اجازه‌ی ادغام می‌دهد، این است:

  • یک ورودی معتبر در config.json ترک، با status برابر با wip.
  • یک فایل معتبر .meta/config.json
  • وجود فایل‌های زیر، هرچند ممکن است خالی باشند:
    • .docs/introduction.md
    • .docs/instructions.md
    • .docs/hints.md
    • پیاده‌سازی استاب
    • فایل تست

فایل: .docs/introduction.md

هدف: معرفی مفهوم یا مفاهیمی که تمرین به دانشجو می‌آموزد.

وجود: الزامی

  • اطلاعات ارائه‌شده باید فقط به‌اندازه‌ای زمینه به دانشجو بدهد که خودش راه‌حل را کشف کند.
  • فقط اطلاعاتی ارائه شود که برای فهم مبانی مفهوم و حل تمرین لازم است. اطلاعات اضافی باید برای سند about.md آن مفهوم بماند.
  • لینک‌ها باید کم و فقط در صورت لزوم به کار روند. گرچه پیوندی که موضوعی پیچیده مانند بازگشت را توضیح می‌دهد می‌تواند مفید باشد، برای بیشتر مفاهیم این پیوندها اطلاعاتی بیش از نیاز می‌دهند؛ پس هدف باید توضیح کوتاه و درجای مطلب باشد.
  • از اصطلاحات فنی درست استفاده کنید تا دانشجو بتواند به‌راحتی اطلاعات بیشتری جست‌وجو کند.
  • از مثال‌های کد فقط باید برای معرفی نحوه‌ی نگارش تازه استفاده شود (دانشجو نباید لازم باشد برای دیدن نمونه‌هایی از نحوه‌ی نگارش در وب جست‌وجو کند). در دیگر موارد، به‌جای کد، توضیح یا پیوند بدهید.

برای نمونه، مقدمه‌ی یک تمرین «رشته‌ها» ممکن است رشته را فقط «دنباله‌ای از نویسه‌های یونیکد» یا «زنجیره‌ای از بایت‌ها» توصیف کند، به کاربران بگوید چطور یک رشته بسازند، و توضیح دهد که رشته متدهایی دارد که می‌توان با آن‌ها آن را دستکاری کرد. مگر آنکه دانشجو برای حل تمرین نیاز به فهم جزئیات دقیق‌تری داشته باشد، همین نوع توضیح کوتاه (به‌همراه نمونه‌ای از نحوه‌ی نگارش آن) باید برای حل تمرین کافی باشد.

مثال

# 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

هدف: توصیف طراحی تمرین.

وجود: الزامی

این فایل اطلاعاتی درباره‌ی طراحی تمرین دارد؛ مواردی مانند هدف آن، اهداف آموزشی‌اش، آنچه نباید آموزش داده شود و بیشتر. این اطلاعات را می‌توان از ایشوی 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: توصیف کوتاهی از این تمرین. طولش باید کمتر یا مساوی ۳۵۰ باشد. از Markdown پشتیبانی نمی‌شود (الزامی)
  • source: منبعی که این تمرین بر آن مبتنی است (اختیاری)
  • source_url: نشانی منبعی که این تمرین بر آن مبتنی است (اختیاری)
  • representer: فرادادهی مربوط به نحوه‌ی پردازش این فایل توسط representer (اختیاری)
    • version: عددی صحیح برای نسخه‌ی representer که در تمرین استفاده می‌شود (اگر کلید والد موجود باشد، الزامی است)
  • 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 نسخه‌ی ۴ که رویکرد را به‌طور یکتا مشخص می‌کند. این UUID باید هم درون ترک و هم در میان همه‌ی ترک‌ها یکتا باشد و هرگز تغییر نکند
    • slug: اسلاگ رویکرد، که رشته‌ای با حروف کوچک و به‌شکل kebab-case است. این اسلاگ باید میان همه‌ی اسلاگ‌های رویکرد در ترک یکتا باشد. طولش باید کمتر یا مساوی ۲۵۵ باشد.
    • title: عنوان رویکرد. طولش باید کمتر یا مساوی ۲۵۵ باشد.
    • blurb: توصیف کوتاهی از این رویکرد. طولش باید کمتر یا مساوی ۳۵۰ باشد. از 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» تمرین نمایش داده می‌شود.

تعداد خطوطش باید کمتر یا مساوی ۸ باشد.

برای اطلاعات بیشتر درباره‌ی آنچه باید در این فایل بیاید، مستندات را ببینید.

مثال

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 نسخه‌ی ۴ که مقاله را به‌طور یکتا مشخص می‌کند. این UUID باید هم درون ترک و هم در میان همه‌ی ترک‌ها یکتا باشد و هرگز تغییر نکند
    • slug: اسلاگ مقاله، که رشته‌ای با حروف کوچک و به‌شکل kebab-case است. این اسلاگ باید میان همه‌ی اسلاگ‌های مقاله در ترک یکتا باشد. طولش باید کمتر یا مساوی ۲۵۵ باشد.
    • title: عنوان مقاله. طولش باید کمتر یا مساوی ۲۵۵ باشد.
    • blurb: توصیف کوتاهی از این مقاله. طولش باید کمتر یا مساوی ۳۵۰ باشد. از 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» تمرین نمایش داده می‌شود.

تعداد خطوطش باید کمتر یا مساوی ۸ باشد.

برای اطلاعات بیشتر درباره‌ی آنچه باید در این فایل بیاید، مستندات را ببینید.

مثال

| 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 استفاده می‌کند به سیستم فایلی‌اش دانلود نمی‌شود.
  • فایل معیار هنگام نظر دادن روی راه‌حل‌ها یا representations به منتورها نشان داده می‌شود.
  • مسیرهای نسبی فایل(های) پیاده‌سازی معیار باید در کلید "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. از نویسه‌های الفبایی عددی لاتین و خط تیره استفاده کنید (الگوی regex: [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 تمرین تغییر داد.

اگر تمرین موجودی را فورک می‌کنید، احتمالاً از قبل آیکونی برای آن تمرین وجود دارد. اگر نه، لطفاً یک ایشو در مخزن website-icons باز کنید.