Module ১ · প্রথম program: console, let আর const, type, typeof
comment, নাম আর এমন code যা মানুষ পড়তে পারে
এই lesson-এ যা শিখবে
- দুই রকমের comment-ই লিখতে পারবে, আর এমন comment লিখতে পারবে, যেটা বলে code-টা কেন আছে, কী করে সেটা না।
- JavaScript-এর অভ্যাস মেনে value, বাঁধা setting আর function-এর নাম দিতে পারবে, আর দুই space দিয়ে indent করতে পারবে।
- Automatic semicolon insertion কী করে, বুঝিয়ে বলতে পারবে, আর semicolon ছাড়া যে লাইন ভেঙে পড়ে, সেটা ধরতে পারবে।
Amara আর Bob দোকানের একই বিশ লাইনের program লিখেছে। Amara-র program-এ comment দুইটা, আর পড়তে প্রায় একটা অনুচ্ছেদের মতো লাগে। Bob-এর program-এ প্রতিটা লাইনে একটা comment, আর প্রতিটা শুধু পাশের লাইনটাই আবার বলে: count = count + 1;-এর উপরে লেখা "add 1 to count"। দুইটা program-ই চলে। এক সপ্তাহ পরে নিরাপদে বদলানো যায় শুধু একটাকে, আর সেটা বেশি comment-ওয়ালাটা না। প্রতিটা program-এর একজন দ্বিতীয় পাঠক থাকে, একজন মানুষ; এই lesson তার জন্য লেখা নিয়ে।
দুই রকমের comment
Comment হলো program-এর ভেতরের এমন লেখা, যেটা engine এড়িয়ে যায়। ওটা থাকে মানুষের জন্য। JavaScript-এ comment দুই রকম।
Comment-এর দুই রূপ
// a line comment: from the two slashes to the end of the line
/* a block comment:
from slash-star to star-slash, across as many lines as you like */
//এমন comment শুরু করে, যেটা লাইনের সঙ্গেই শেষ হয়। প্রায় সব কাজে এটাই ব্যবহার করো।/*এমন comment শুরু করে, যেটা শেষ হয় পরের*/-এ, সেটা যত লাইন পরেই আসুক।- কোনোটাই program কী করে, তা বদলায় না। কোনো লাইন চালানোর আগেই engine comment ফেলে দেয়।
// Delivery fee for one order, in taka.
const fee = 60; // the same in every district this month
/* Free delivery above 1000 taka was tried in August
and stopped, so it is not in this program. */
console.log("Delivery:", fee);
Delivery: 60
চার লাইন comment, এক লাইন output: //-এর পরের সবকিছু, আর /* আর */-এর মাঝের সবকিছু engine বাদ দিয়েছে। String-এর ভেতরের // কোনো comment না, তাই "https://progsity.io" পুরোটাই ছাপা হয়। তাই comment হলো পাঠকের জন্য একটা নোট, দুই রূপের একটায়, আর সেটা কখনো চলে না।
ভালো comment বলে কেন
Code কী করে, সেটা code নিজেই বলে। যে comment সেটা আবার বলে, সে পাঠকের সময় খায়, আর code বদলালে পুরোনো হয়ে যায়। এই হলো Bob-এর comment-গুলো।
let count = 0; // set count to 0
count = count + 1; // add 1 to count
console.log(count); // print count
1
তিনটা comment-ই মুছে দাও, কিছুই হারাবে না। কাজের comment এমন প্রশ্নের উত্তর দেয়, যেটা code দিতে পারে না। কাজটা এভাবে কেন করা? অন্যভাবে করলে কী গোলমাল হতো? এই সংখ্যাটা এল কোথা থেকে?
// Prices are kept in paisa, so sums stay exact (lesson 03).
const pencil = 299;
const eraser = 199;
// Divide by 100 only when printing, never before adding.
console.log((pencil + eraser) / 100);
4.98
দুইটা comment-ই একটা সিদ্ধান্ত বুঝিয়ে বলে। এগুলো না থাকলে পরের মানুষটা হয়তো দামগুলোকে 2.99 আর 1.99 বানিয়ে "সহজ" করে ফেলবে, আর lesson 03-এর rounding ফিরিয়ে আনবে। তাই comment লেখো "কেন"-র জন্য, আর "কী"-র ভার ছেড়ে দাও নাম আর সাজানোর উপর।
যে নামের comment লাগে না
Comment সরানোর সবচেয়ে ভালো উপায় একটা ভালো নাম। const d = 7;-এর comment লাগে; const deliveryDays = 7;-এর লাগে না। JavaScript code তিনটা অভ্যাস মেনে চলে, আর বড় বড় style guide তিনটাতেই একমত।
| কীসের নাম | অভ্যাস | উদাহরণ |
|---|---|---|
একটা value: একটা let, বা সাধারণ একটা const | camelCase, একটা বিশেষ্য (noun) | totalPrice, itemCount, isMember |
| একটা বাঁধা setting, program চলার আগেই জানা | UPPER_SNAKE_CASE | MAX_ITEMS, VAT_RATE, DELIVERY_FEE |
| একটা function (Module 5) | camelCase, শুরু একটা ক্রিয়া (verb) দিয়ে | printReceipt, calculateTotal |
হ্যাঁ-না value-র নাম সবচেয়ে ভালো পড়া যায় সামনে is বা has থাকলে, তাতে if (isMember) পড়তে লাগে ইংরেজি বাক্যের মতো। UPPER_SNAKE_CASE সব const-এর জন্য না, শুধু সেই অল্প কয়টা setting-এর জন্য, যেগুলোকে ঘিরে program-টা বানানো। const total = a + b; একটা const ঠিকই, কিন্তু এর হিসাব হয় program চলার সময়, তাই এটা camelCase-ই থাকে।
নামটা program-এর কতটা জুড়ে ব্যবহার হবে, নামের দৈর্ঘ্যও হবে সেই মাপে। তিন লাইন টিকে থাকা একটা counter-এর জন্য i ঠিক আছে; গোটা program জুড়ে ব্যবহার হওয়া value-র নাম হওয়া উচিত পুরো শব্দে। তাই এমন নাম বাছো, যাতে comment লাগেই না: camelCase-এ, আর program-এর বাঁধা setting-গুলোর জন্য UPPER_SNAKE_CASE।
Indentation আর spacing
{ }-এর ভেতরের code দুই space ভেতরে ঢোকানো থাকে, প্রতিটা স্তরে আরও এক ধাপ। Engine এটার দিকে একদমই তাকায় না; কোনটা কার অংশ, মানুষ সেটা বোঝে এর উপর ভর করেই।
const n = 3;
for (let i = 1; i <= n; i++) {
if (i === 2) {
console.log(i, "is the middle one");
} else {
console.log(i);
}
}
1
2 is the middle one
3
এই track দুই space দিয়ে indent করে, যেটা Prettier-এর default; Prettier হলো সেই code formatter, যেটা বেশিরভাগ JavaScript team চালায়। Prettier-এর default operator-এর দুই পাশে space দেয়, double quote ব্যবহার করে, আর statement শেষ করে semicolon দিয়ে। তাই এই track-এর code দেখতে Prettier যা ছাপত তেমনই, আর পরে spacing-এর কাজটা তুমি ওর হাতেই ছেড়ে দিতে পারো।
Semicolon, আর সেই একটা case যেটা ভোগায়
Semicolon ছাড়াও program চলতে দেখেছ। ওটা automatic semicolon insertion, সংক্ষেপে ASI। যেখানে statement আর এগোতে পারে না, সেখানে line break এলে engine তোমার হয়ে একটা semicolon বসিয়ে দেয়। নিয়মটা হলো, পরের লাইন statement-টাকে চালিয়ে নিতে পারে কি না। পারলে কোনো semicolon বসে না। উল্টো দিকের একটা নিয়মও আছে, যেটা কাজে লাগবে function লেখা শুরু করলে (Module 5): return-এর ঠিক পরে line break এলে statement সব সময় ওখানেই শেষ।
যে লাইন ( বা [ দিয়ে শুরু হয়, সেটা সব সময় আগের লাইনকে চালিয়ে নিতে পারে। তাই engine দুইটা লাইন জুড়ে দেয়, আর ফল দাঁড়ায় এমন কিছু, যা কেউ লেখেনি। এই হলো lesson 02-এর Amara-র অদলবদল, Module 8-এর একটা কায়দায় এক লাইনে করা, আর semicolon ছাড়া।
let left = "tea"
let right = "coffee"
[left, right] = [right, left]
console.log(left, right)
Program থেমে যায় ReferenceError: Cannot access 'right' before initialization দিয়ে, আর message দেখিয়ে দেয় লাইন 3। Engine লাইন 2 আর 3-কে পড়েছে একটা statement হিসেবে, নিচে যেমন দেখানো। প্রতিটা লাইনের শেষে semicolon দিলে একই program ছাপে coffee tea।
এজন্যই এই track প্রতিটা semicolon লেখে। খরচ লাইনপ্রতি একটা character, আর ঝামেলাটা পুরোপুরি উধাও। কিছু team জেনেবুঝে semicolon বাদ দেয়, যেমন যারা JavaScript Standard Style মানে। ওদের নিয়ম হলো, যে লাইন ( বা [ দিয়ে শুরু হয়, তার একদম শুরুতে একটা semicolon বসানো। দুইটা পথই কাজ করে; ভাঙে তখন, যখন অজান্তে দুইটা মিশে যায়। তাই ASI বাদ পড়া বেশিরভাগ semicolon ঠিকঠাক বসিয়ে দেয়, আর ভুল করে শুধু ( বা [ দিয়ে শুরু হওয়া লাইনে।
আগে আর পরে
এই হলো Bob-এর রসিদের program, প্রথমবার যেমন লিখেছিল। চলে, আর output-ও ঠিক।
let a=3,b=15,c=2,d=20
let x=a*b+c*d // total
x=x+x*0.15 // add
console.log("total",x)
total 97.75
আর এই হলো Amara-র version, যেটা একই লাইন ছাপে।
// One order: 3 cups of tea and 2 samosas.
const TEA_PRICE = 15;
const SAMOSA_PRICE = 20;
const VAT_RATE = 0.15;
const teaCups = 3;
const samosas = 2;
const subtotal = teaCups * TEA_PRICE + samosas * SAMOSA_PRICE;
// VAT is charged on the whole subtotal, not per item.
const total = subtotal + subtotal * VAT_RATE;
console.log("total", total);
total 97.75
Output একই, আর পাঠক যত প্রশ্ন করতে পারে, সবগুলোর উত্তর page-এই আছে: কোন সংখ্যাটা দাম, কোনটা গোনা, 0.15 কী, VAT কোথায় বসে। Bob-এর // add এমন কিছুই বলেনি, যা ওর code আগেই বলেনি। Amara-র comment code-এর বাইরের একটা নিয়ম লিখে রাখে। তাই পড়ার মতো code মূলত নাম আর সাজানোর ব্যাপার, আর যেখানে কোনো সিদ্ধান্ত বোঝানো দরকার, সেখানে একটা comment।
শুধু একটা সংখ্যা মানে একটা রহস্য। একটা comment সেটাকে একটা তথ্য বানিয়ে দেয়।
// 5 minutes of grace before a contest submission is marked late.
const GRACE_MINUTES = 5;
console.log("Grace:", GRACE_MINUTES, "minutes");
Grace: 5 minutes
নাম বলে সংখ্যাটা কী। Comment বলে সেটা কীসের জন্য, যেটা কোনো নাম বলতে পারত না।
Run in CompilerZara-র সন্দেহ, একটা লাইন ভুল। মুছে না ফেলে, একটা run-এর জন্য ও লাইনটাকে comment বানিয়ে দেয়।
let score = 40;
score = score + 25;
// score = score * 2;
console.log("Score:", score);
Score: 65
তৃতীয় লাইন comment out করা থাকলে score 65; লাইনটা ফিরিয়ে আনলে 130। একটা লাইন বন্ধ করতে তার সামনে // বসানোকে বলে comment out করা। Program জমা দেওয়ার আগে এমন লাইন সরিয়ে ফেলো, নইলে পরের পাঠক ভাববে, এগুলোর কোনো দরকার আছে কি না।
Kenji-র quiz program দুইটা সংখ্যাকে ঘিরে বানানো। ও সংখ্যা দুইটা রাখে সবার আগে, UPPER_SNAKE_CASE-এ, যাতে খুঁজে পাওয়া আর বদলানো সহজ হয়।
const QUESTIONS = 10;
const PASS_MARK = 7;
const correct = 8;
const passed = correct >= PASS_MARK;
console.log(correct, "of", QUESTIONS, "correct");
console.log("Passed:", passed);
8 of 10 correct
Passed: true
>= মানে "অন্তত", আর এটা দেয় true বা false। Pass mark বদলে 6 হলে edit করার লাইন একটাই, আর তার নামই বলে দেয় কোনটা।
ASI-এর অংশে যে program crash করেছিল, সেটাই, প্রতিটা লাইনে একটা করে semicolon দিয়ে।
let left = "tea";
let right = "coffee";
[left, right] = [right, left];
console.log(left, right);
coffee tea
লাইন 2-এর শেষের semicolon ওই statement শেষ করে দেয়, তাই লাইন 3 পড়া হয় আলাদাভাবে। এর square bracket value দুইটা অদলবদল করে; কীভাবে, বুঝিয়ে বলবে Module 8।
Run in Compilerএটা কোথায় কাজে লাগে
- Airbnb আর Google-এর style guide. দুইটাই camelCase নাম আর semicolon চায়। Google-এর guide সত্যিকারের constant-এর নাম লেখে CONSTANT_CASE-এ, UPPER_SNAKE_CASE-এর জন্য এটাই ওদের নাম।
- Prettier. Save করলেই এই formatter একটা file-এর সাজ নতুন করে লেখে: default হিসেবে দুই space-এর indent, double quote, semicolon আর 80 character-এর লাইন। React আর Next.js-এর repository ওদের code format করে এটা দিয়েই।
- ESLint. Linter হলো এমন tool, যেটা code না চালিয়েই পড়ে, আর সম্ভাব্য bug আর ভাঙা অভ্যাস জানায়, যেমন এমন একটা নাম, যেটা declare করা হয়েছে কিন্তু কখনো ব্যবহার হয়নি। এই track এটা শেখায় না, কিন্তু বেশিরভাগ team Prettier-এর পাশাপাশি এটাও চালায়।
যে ভুলগুলো সবাই করে
১. যে block comment কখনো বন্ধ হয় না।
/* the price list
const price = 450;
console.log(price);
Program শুরুই হয় না: SyntaxError: Invalid or unexpected token। /*-এর পরের সবকিছু comment, যতক্ষণ না একটা */ আসে, আর সেটা আসেইনি। */ দিয়ে বন্ধ করো, নয়তো প্রতিটা লাইনে // ব্যবহার করো। ভুলটা হয় তখন, যখন লম্বা একটা note লিখতে শুরু করো আর ভাবো পরে শেষ করবে।
২. Block comment-এর ভেতরে block comment।
/* outer note /* inner note */ still outer */
console.log("hi");
Program শুরুই হয় না: SyntaxError: Unexpected identifier 'outer'। প্রথম */-ই পুরো comment শেষ করে দেয়, আর engine still outer */-কে code হিসেবে পড়তে যায়। একটা block comment-এর ভেতরে আরেকটা বসানো যায় না। এই ফাঁদে তুমি পড়বে তখন, যখন এমন একটা অংশ comment out করবে, যাতে আগে থেকেই একটা comment আছে।
৩. মিথ্যা বলা comment।
// VAT is 10%.
const VAT_RATE = 0.15;
কোনো message নেই, কোনোদিনই আসবে না। Rate বদলেছে, comment বদলায়নি। পরের পাঠক comment-কে বিশ্বাস করে, আর হাতে করা প্রতিটা হিসাব ভুল করে। Code বদলালে পাশের comment-গুলোও পড়ো, আর যে comment সত্যি রাখবে না, সেটা মুছে দাও। এটা চোখ এড়িয়ে যায়, কারণ comment-এর জন্য কোনো run কখনো fail করে না, তাই কেউ মনেও করিয়ে দেয় না।
৪. Semicolon ছাড়া লাইনের পরে bracket দিয়ে শুরু হওয়া লাইন।
const label = "Total:"
(120 + 45)
TypeError: "Total:" is not a function। Engine লাইন দুইটা জুড়ে বানিয়েছে "Total:"(120 + 45), মানে একটা string-কে call করা। লাইন 1-এর শেষে একটা semicolon দাও। এটা তুমি দেখবে শুধু কোনো semicolon মুছে ফেলার পরে, আর এজন্যই এই track কখনো semicolon মোছে না।
David একটা বইয়ের stall-এর জন্য এই program লিখেছে। এটা কাজ করে, কিন্তু আর কেউ পড়তে পারে না। এটা নতুন করে লেখো: ভালো নাম, UPPER_SNAKE_CASE-এ বাঁধা setting, দুই space-এর indent, semicolon, আর বড়জোর দুইটা comment, যেগুলো "কেন" বলে। হুবহু একই দুইটা লাইন ছাপতে হবে।
Output. হুবহু এই দুই লাইন।
books 3 cost 540
after discount 486
let q=3,p=180
let t=q*p
console.log("books",q,"cost",t)
let t2=t-t*0.1 // minus
console.log("after discount",t2)
Grade হয় না: judge শুধু output দেখে, আর এখানে আসল কথা হলো code। তোমারটা "আগে আর পরে" অংশের Amara-র রসিদের সঙ্গে মিলিয়ে দেখো।
Run in CompilerMaria n-এর নামতা চায়, কলামগুলো সোজা লাইনে মেলানো। দশটা লাইনের প্রতিটা দেখতে n x i = p। i-এর বাঁ দিকে space বসিয়ে সেটাকে 2 character করা হয়, আর p-কে ততটা চওড়া করা হয়, n * 10-এ যতগুলো character। String(x).padStart(w) x-কে লেখা হিসেবে দেয়, বাঁ দিকে space যোগ করে করে, যতক্ষণ না সেটা w character লম্বা হয়; পুরোটা দেখাবে Module 3।
Input. একটা পূর্ণসংখ্যা n।
Output. দশ লাইন, i-এর 1 থেকে 10 পর্যন্ত।
Sample. Input 7 দিলে এই লাইনগুলো, 7 x 1 = 7 থেকে 7 x 10 = 70 পর্যন্ত।
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
// Work out the width of n * 10 once, before the loop.
// Then, for i from 1 to 10, push one padded line.
console.log(out.join("\n"));
Grade হয় times-table হিসেবে। লুকানো test-এ আছে n = 1, আর statement সবচেয়ে বড় যে n দিতে দেয়, সেটাও।
সচরাচর যে প্রশ্নগুলো আসে
Comment কি program ধীর করে দেয়?
না। Engine file পড়ার সময়েই এগুলো ফেলে দেয়, কিছু চলার আগেই। Website-গুলো তবু প্রায়ই এগুলো ছেঁটে ফেলে, minifier নামের একটা tool দিয়ে, যাতে browser-এ কম byte পাঠাতে হয়।
Tab, নাকি space?
Engine-এর কাছে দুইটাই চলে। এই track দুই space ব্যবহার করে, Prettier-এর default, আর জরুরি নিয়ম একটাই: file-এর বাকি অংশ যেমন, তুমিও তেমন লেখো।
ASI যদি থাকেই, তাহলে semicolon বাদ দিলে সমস্যা কী?
কিছু team বাদ দেয়ও,
(বা[দিয়ে শুরু হওয়া লাইনের জন্য একটা নিয়ম রেখে। এই track semicolon লেখে, যাতে ওই নিয়মটা তোমার কখনো লাগেই না। প্রতিটা project-এর জন্য একটা style বেছে নাও, আর সেটাই মেনে চলো।ঠিক কয়টা comment থাকা উচিত?
পাঠক code দেখে ধরতে পারবে না, এমন সিদ্ধান্ত যতগুলো, ততগুলো। ভালো নামওয়ালা ছোট একটা program-এ সংখ্যাটা প্রায়ই শূন্য, নয়তো উপরে একটা, যেটা বলে program-টা কীসের জন্য।
মূল কথা
//লাইনের শেষ পর্যন্ত comment;/* */কয়েক লাইন জুড়ে থাকে, আর একটার ভেতরে আরেকটা বসে না।- ভালো comment বলে "কেন"; "কী", সেটা code আর তার নামগুলোই বলে দেয়।
- Value-র জন্য camelCase, বাঁধা setting-এর জন্য UPPER_SNAKE_CASE, আর function-এর নাম শুরু হয় ক্রিয়া দিয়ে।
{ }-এর প্রতিটা স্তরে দুই space, Prettier-এর default, আর operator-এর দুই পাশে space।- ASI line break-এ semicolon বসায় সেখানে, যেখানে পরের লাইন statement-টা চালিয়ে নিতে পারে না, আর
return-এর পরে সব সময়। (বা[দিয়ে শুরু হওয়া লাইন আগের লাইনের সঙ্গে জুড়ে যায়, তাই এই track প্রতিটা semicolon লেখে।
এরপর আসছে problems page: lesson 05-এর starter নিয়ে দশটা problem, grade করবে এমন এক judge, যে শুধু তোমার output পড়ে।
lesson ৬ শেষ
শেষ হলে চিহ্ন দিন, অগ্রগতি আপনার সাথে থাকবে।
পরেরটা: Problem: প্রথম program