কনসেপ্ট অনুশীলনী


কনসেপ্ট অনুশীলনী হলো এমন অনুশীলনী, যা নির্দিষ্ট (প্রোগ্রামিং) কনসেপ্ট শেখানোর জন্য তৈরি করা হয়েছে। কনসেপ্ট অনুশীলনীগুলো যে কনসেপ্টগুলো শেখায়, সেগুলো মিলে একটি সিলেবাস তৈরি করে। সিলেবাস কীভাবে ডিজাইন করতে হয় সে সম্পর্কে আরও জানতে সিলেবাস ডকুমেন্টেশন দেখুন।

Note

আপনি ট্র্যাকের রুট ডিরেক্টরি থেকে নিচের কমান্ডগুলো চালিয়ে দ্রুত একটি নতুন কনসেপ্ট অনুশীলনীর কাঠামো তৈরি করতে পারেন:

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

আরও জানতে configlet create ডকুমেন্টেশন দেখুন

মেটাডেটা

কনসেপ্ট অনুশীলনীর মেটাডেটা config.json ফাইলটির exercises.concept কী (key)-তে নির্ধারণ করা হয়। মেটাডেটায় অনুশীলনীর UUID, স্ল্যাগ এবং আরও অনেক কিছু নির্ধারিত হয়।

উদাহরণ

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

ফাইল

প্রতিটি কনসেপ্ট অনুশীলনীর জন্য ট্র্যাকের exercises/concept ডিরেক্টরির ভেতরে নিজস্ব একটি ডিরেক্টরি থাকে। কনসেপ্ট অনুশীলনীর ডিরেক্টরির নাম config.json ফাইলটিতে নির্ধারিত কনসেপ্ট অনুশীলনীর slug প্রোপার্টির সাথে মিলতে হবে।

একটি কনসেপ্ট অনুশীলনীতে চার ধরনের ফাইল থাকে:

ডকুমেন্টেশন ফাইল

এই ফাইলগুলো অনুশীলনীটি ব্যাখ্যা করতে সাহায্য করার জন্য শিক্ষার্থীর কাছে উপস্থাপন করা হয়।

  • .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 ডকুমেন্টের জন্য রেখে দেওয়া উচিত।
  • লিংক খুব কম ব্যবহার করা উচিত, একেবারে না করলেও চলে। রিকার্সনের মতো জটিল বিষয় ব্যাখ্যা করা একটি লিংক হয়তো কাজে লাগতে পারে, কিন্তু বেশিরভাগ কনসেপ্টের ক্ষেত্রে লিংকগুলো প্রয়োজনের চেয়ে বেশি তথ্য দেবে; তাই সংক্ষেপে লেখার ভেতরেই বিষয়গুলো ব্যাখ্যা করাই লক্ষ্য হওয়া উচিত।
  • যথাযথ টেকনিক্যাল শব্দ ব্যবহার করা উচিত, যাতে শিক্ষার্থী সহজে আরও তথ্য খুঁজে পায়।
  • কোড উদাহরণ শুধু নতুন সিনট্যাক্স পরিচয় করিয়ে দিতে ব্যবহার করা উচিত (সিনট্যাক্সের উদাহরণ খুঁজতে শিক্ষার্থীদের ওয়েবে যেতে হবে না)। অন্য ক্ষেত্রে কোডের বদলে বর্ণনা বা লিংক দিন।

উদাহরণ হিসেবে, একটি "স্ট্রিং" অনুশীলনীর পরিচিতিতে স্ট্রিংকে শুধু "ইউনিকোড ক্যারেক্টারের একটি ক্রম" বা "বাইটের একটি সিরিজ" হিসেবে বর্ণনা করা হতে পারে, ব্যবহারকারীদের স্ট্রিং কীভাবে তৈরি করতে হয় তা বলা হতে পারে, এবং ব্যাখ্যা করা হতে পারে যে স্ট্রিংয়ের এমন মেথড থাকে যা দিয়ে এটি নাড়াচাড়া করা যায়। অনুশীলনীটি সমাধান করার জন্য শিক্ষার্থীর আরও সূক্ষ্ম বিবরণ বোঝার দরকার না থাকলে, এই ধরনের সংক্ষিপ্ত ব্যাখ্যাই (সাথে এর সিনট্যাক্সের একটি উদাহরণ) শিক্ষার্থীর অনুশীলনী সমাধান করার জন্য যথেষ্ট হওয়া উচিত।

উদাহরণ

# 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

উদ্দেশ্য: অনুশীলনীতে আটকে গেলে সেখান থেকে বেরোতে সাহায্য করার জন্য শিক্ষার্থীকে হিন্ট দেওয়া।

উপস্থিতি: আবশ্যক

  • শিক্ষার্থী আটকে গেলে আমরা তাকে একটি বাটনে ক্লিক করে হিন্ট চাইতে দেব, যেটি ফাইলের প্রাসঙ্গিক অংশ দেখাবে।
  • হিন্টগুলো হেডিংয়ের নিচে বুলেট আকারে থাকা উচিত।
  • হিন্টগুলো প্রায় যেকোনো শিক্ষার্থীর আটকে থাকা কাটিয়ে উঠতে যথেষ্ট হওয়া উচিত।
  • হিন্টে সরাসরি সলিউশন বলে দেওয়া উচিত নয়; বরং সলিউশন বর্ণনা করে এমন কোনো রিসোর্সের দিকে ইশারা করা উচিত (যেমন ব্যবহারযোগ্য ফাংশনের ডকুমেন্টেশনের লিংক দেওয়া)।
  • হিন্টে কনসেপ্ট ব্যাখ্যা করতে কোড স্যাম্পল ব্যবহার করা যেতে পারে, তবে সলিউশনের রূপরেখা দিতে নয়। যেমন একটি লিস্ট অনুশীলনীতে নির্দিষ্ট কোনো লিস্ট ফাংশন কীভাবে কাজ করে তার স্নিপেট দেখানো হতে পারে, কিন্তু এমনভাবে নয় যে সেটি সরাসরি সলিউশনে কপি/পেস্ট করা যায়।
  • অনুশীলনী সম্পর্কে সাধারণ হিন্ট ## General হেডিংয়ের নিচে মার্কডাউন লিস্ট আকারে থাকতে পারে।
  • টাস্ক-নির্দিষ্ট হিন্ট এমন হেডিংয়ের নিচে মার্কডাউন লিস্ট আকারে থাকা উচিত, যা instructions.md-এ সেই টাস্কের হেডিংয়ের সাথে মেলে (যেমন ## 2. Do Y)।
  • কোনো সাধারণ হিন্ট না থাকলে বা নির্দিষ্ট কোনো টাস্কের জন্য হিন্ট না থাকলে হেডিংগুলো বাদ দিতে হবে। প্রতিটি হেডিংয়ের নিচে একটি মার্কডাউন লিস্ট থাকতে হবে।
  • সাধারণ হিন্টের চেয়ে টাস্ক-নির্দিষ্ট হিন্টকে প্রাধান্য দিন, কারণ টাস্ক-নির্দিষ্ট হিন্ট সাধারণ হিন্টের চেয়ে শিক্ষার্থীর আটকে থাকা কাটানোর সম্ভাবনা বেশি।
  • টাস্কের হেডিংয়ে টাস্কের কী বর্ণনা করা উচিত, কীভাবে নয়।
  • টাস্কের হেডিংয়ে স্বাভাবিক বাক্য-লেখার নিয়ম মেনে চলা উচিত (যেমন ## 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: এই অনুশীলনীর একটি সংক্ষিপ্ত বিবরণ। এর দৈর্ঘ্য <= 350 হতে হবে। মার্কডাউন সমর্থিত নয় (আবশ্যক)
  • source: এই অনুশীলনীটি যে সূত্রের উপর ভিত্তি করে তৈরি (ঐচ্ছিক)
  • source_url: এই অনুশীলনীটি যে সূত্রের উপর ভিত্তি করে তৈরি, তার 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 নামের ব্যবহারকারী F# ট্র্যাকের জন্য log-levels নামে একটি অনুশীলনী লিখেছেন। 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: অ্যাপ্রোচটিকে অনন্যভাবে চিহ্নিত করা একটি V4 UUID। UUID ট্র্যাকের ভেতরে এবং সব ট্র্যাক মিলিয়ে অনন্য হতে হবে, এবং কখনো বদলানো যাবে না
    • slug: অ্যাপ্রোচের স্ল্যাগ, যা ছোট হাতের অক্ষরের কেবাব-কেস স্ট্রিং। স্ল্যাগটি ট্র্যাকের ভেতরে সব অ্যাপ্রোচ স্ল্যাগের মধ্যে অনন্য হতে হবে। এর দৈর্ঘ্য <= 255 হতে হবে।
    • title: অ্যাপ্রোচের শিরোনাম। এর দৈর্ঘ্য <= 255 হতে হবে।
    • blurb: এই অ্যাপ্রোচের একটি সংক্ষিপ্ত বিবরণ। এর দৈর্ঘ্য <= 350 হতে হবে। মার্কডাউন সমর্থিত নয় (আবশ্যক)
    • 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: আর্টিকেলটিকে অনন্যভাবে চিহ্নিত করা একটি V4 UUID। UUID ট্র্যাকের ভেতরে এবং সব ট্র্যাক মিলিয়ে অনন্য হতে হবে, এবং কখনো বদলানো যাবে না
    • slug: আর্টিকেলের স্ল্যাগ, যা ছোট হাতের অক্ষরের কেবাব-কেস স্ট্রিং। স্ল্যাগটি ট্র্যাকের ভেতরে সব আর্টিকেল স্ল্যাগের মধ্যে অনন্য হতে হবে। এর দৈর্ঘ্য <= 255 হতে হবে।
    • title: আর্টিকেলের শিরোনাম। এর দৈর্ঘ্য <= 255 হতে হবে।
    • blurb: এই আর্টিকেলের একটি সংক্ষিপ্ত বিবরণ। এর দৈর্ঘ্য <= 350 হতে হবে। মার্কডাউন সমর্থিত নয় (আবশ্যক)
    • 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 ব্যবহার করলে তা শিক্ষার্থীর ফাইল সিস্টেমে ডাউনলোড হয়।
  • স্টাব ইমপ্লিমেন্টেশন ফাইলের আপেক্ষিক পাথ .meta/config.json ফাইলের "files.solution" কী (key)-তে উল্লেখ করতে হবে।

উদাহরণ

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 ব্যবহার করলে তা শিক্ষার্থীর ফাইল সিস্টেমে ডাউনলোড হয়।
  • টেস্ট ফাইলের আপেক্ষিক পাথ .meta/config.json ফাইলের "files.test" কী (key)-তে উল্লেখ করতে হবে।

উদাহরণ

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 ব্যবহার করলে তা শিক্ষার্থীর ফাইল সিস্টেমে ডাউনলোডও হয় না।
  • সলিউশন বা রিপ্রেজেন্টেশন নিয়ে মন্তব্য করার সময় মেন্টরদের এক্সেম্পলার ফাইলটি দেখানো হবে।
  • এক্সেম্পল ইমপ্লিমেন্টেশন ফাইলের আপেক্ষিক পাথ .meta/config.json ফাইলের "files.exemplar" কী (key)-তে উল্লেখ করতে হবে।

উদাহরণ

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#-এর প্রজেক্ট ফাইল এবং Node-এর package.json ফাইল; এগুলো ছাড়া টেস্ট চালানো সম্ভব হবে না।

শেয়ার করা ফাইল

কিছু ফাইল আলাদা আলাদা অনুশীলনীর জন্য নির্দিষ্ট নয়, বরং সব অনুশীলনীর ক্ষেত্রেই প্রযোজ্য। আরও জানতে ডকুমেন্টেশন দেখুন।

নামকরণ

কনসেপ্ট অনুশীলনীর নাম রাখা উচিত তার গল্প/থিম অনুসারে, তার কনসেপ্ট অনুসারে নয়।

নামের ভালো উদাহরণ:

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

অননুমোদিত নাম:

  • Booleans: কনসেপ্টের নাম ব্যবহার করেছে, গল্পের নাম নয়
  • Exercise #1: অনুশীলনী কোনো গল্প/থিম নয়

বড় কোনো পরিবর্তন ছাড়া অনুশীলনী ফর্ক করলে সম্ভব হলে মূল নামটিই ব্যবহার করুন।

স্ল্যাগ

প্রতিটি অনুশীলনীর একটি স্ল্যাগ থাকে, যা নিচের নিয়মে অনুশীলনীর নামের একটি নরমালাইজড রূপ:

  1. ছোট হাতের অক্ষর ব্যবহার করুন।
  2. kebab-case ব্যবহার করুন।
  3. ল্যাটিন আলফানিউমেরিক অক্ষর ও ড্যাশ ব্যবহার করুন (Regexp: [a-z0-9-]+)
  4. সংখ্যা লেখার সময় অঙ্কের বদলে শব্দে লেখা সংখ্যাকে প্রাধান্য দিন, তবে অঙ্কটিকে প্রাধান্য দেওয়ার নির্দিষ্ট কারণ থাকলে নয় (যেমন 2-fer-এর বদলে two-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 ব্যবহার করার সময় শিক্ষার্থীর কাছে অনুশীলনীর ডকুমেন্টেশন উপস্থাপনের ধরনে পার্থক্য থাকে। আরও জানতে এই ডকুমেন্টটি দেখুন।

আইকন

প্রতিটি অনুশীলনীর একটি সংশ্লিষ্ট আইকন থাকে। ডিফল্টভাবে যে আইকনটি দেখানো হয়, তার নাম অনুশীলনীর স্ল্যাগের সাথে মেলে। অনুশীলনীর .meta/config.json ফাইলে icon প্রোপার্টি উল্লেখ করে এটি ওভাররাইড করা যায়।

আপনি যদি বিদ্যমান কোনো অনুশীলনী ফর্ক করেন, তাহলে সম্ভবত ইতিমধ্যেই ওই অনুশীলনীর একটি আইকন আছে। না থাকলে অনুগ্রহ করে website-icons রিপোজিটরিতে একটি ইস্যু খুলুন।