FORTRAN থেকে Rust পর্যন্ত—প্রতি যুগের হার্ডওয়্যার, সেফটি, ও ওয়েব কর্তব্য ভাষার নকশাকে আকার দেয়। দেখুন কীভাবে প্রতিটি ডিজাইন সিদ্ধান্ত বাস্তব সমস্যা মেটায়।

প্রোগ্রামিং ভাষা কেবল “একটি ভাষা অন্যটার থেকে উন্নত” নয়। এগুলো হলো সেই সমস্যাগুলোর প্রতিক্রিয়া যা একটি নির্দিষ্ট সময়ে সমাধান করার দরকার ছিল।
যখন আমরা ভাষা ডিজাইন বলি, আমরা কেবল কোডের চেহারা নয় আরও অনেক কিছু নিয়ে কথা বলি। একটি ভাষা হলো এক ধরনের সিদ্ধান্তসম্ভার, যেমন:
এই সিদ্ধান্তগুলো সাধারণত সেই প্রযুক্তিগত বা সামাজিক সীমাবদ্ধতার চারপাশে বিন্যস্ত হয়: সীমিত হার্ডওয়্যার, দামী কম্পিউট টাইম, অপারেটিং সিস্টেমের অভাব, বা (পরবর্তীতে) বৃহৎ দল, গ্লোবাল নেটওয়ার্ক, এবং সিকিউরিটি হুমকি।
ভাষা তাদের সময়কে প্রতিফলিত করে। প্রাথমিক ভাষাগুলো সীমিত মেশিন থেকে সর্বোচ্চ মান বের করতে গুরুত্ব দিয়েছিল। পরে ভাষাগুলো বহুত্ব এবং পোর্টেবিলিটি ইত্যাদিতে ঝুঁকলো। প্রকল্প বড় হতে শুরু করলে ভাষাগুলো স্ট্রাকচার, আবস্ট্রাকশন এবং টুলিং দিকেই ঝুঁকে পড়ল যাতে বড় কোডবেস বজায় রাখা যায়। সর্বশেষে, কনকারেন্সি, ক্লাউড ডিপ্লয়মেন্ট, এবং সিকিউরিটি চাপ নতুন ট্রেডঅফগুলোকে টেনে আনল।
এই আর্টিকেলটি প্রতিনিধিত্বমূলক উদাহরণ—পুরো বছরভিত্তিক টাইমলাইন নয়। এখানে আপনি দেখবেন কিভাবে কয়েকটি প্রভাবশালী ভাষা তাদের যুগের প্রয়োজনগুলোকে বহন করে এবং কিভাবে ধারনা রিসাইকেল ও পরিশোধিত হয়।
ভাষার “কেন” বোঝা হলে তার শক্তি ও সীমা বোঝা যায়। এটা পরিষ্কার করে দেয়: এই ভাষা কি টাইট পারফরম্যান্সের জন্য অপ্টিমাইজড, দ্রুত ইটারেশনের জন্য, বড় দলের রক্ষণাবেক্ষণের জন্য, নাকি নিরাপত্তার জন্য? আপনি কোনটা শিখবেন বা প্রকল্পে কোনটা ব্যবহার করবেন—এ ধরনের প্রাসঙ্গিকতা একটি ফিচার চেকলিস্টের মতই বাস্তব।
প্রারম্ভিক প্রোগ্রামিং ভাষাগুলো স্বাদ নয় বরং পদার্থবিদ্যা ও বাজেট দ্বারা গঠিত ছিল। মেশিনে খুব কম মেমরি ছিল, স্টোরেজ সিদ্ধহস্ত ছিল, এবং CPU আজকের তুলনায় অনেক ধীর। এতে অবিরত ট্রেডঅফ ছিল: প্রতিটি অতিরিক্ত ফিচার, প্রতিটি লম্বা নির্দেশ, প্রতিটি অ্যাবস্ট্রাকশন স্তর—এসবেরই প্রকৃত খরচ ছিল।
যদি আপনার কাছে ছোট প্রোগ্রাম ও ছোট ডেটাসেটের জায়গাই থাকে, তাহলে আপনি ভাষা ও টুল বানাবেন যা প্রোগ্রামগুলো কম্প্যাক্ট ও পূর্বাভাসযোগ্য রাখে। প্রাথমিক সিস্টেমগুলো প্রোগ্রামারদের সরল কন্ট্রোল ফ্লো ও ন্যূনতম রানটাইম সাপোর্টের দিকে প্রসারিত করেছিল। এমনকি “উপযোগী” ফিচারগুলো—সমৃদ্ধ স্ট্রিং, ডাইনামিক মেমরি ম্যানেজমেন্ট, বা হাই-লেভেল ডাটা স্ট্রাকচার—অনির্বাচ্যও হতে পারত কারণ এগুলো অতিরিক্ত কোড ও বুককিপিং দাবি করত।
প্রায়ই প্রাথমিক প্রোগ্রামগুলো ব্যাচে চালত। আপনি একটি কাজ প্রস্তুত করতেন (কমপক্ষে পাঞ্চ কার্ডের মাধ্যমে), জমা দিতেন, এবং অপেক্ষা করতেন। ভুল হলে কেন তা জানতে অনেকক্ষণ লাগত—কারণ কাজ শেষ না হওয়া পর্যন্ত বা ব্যর্থ না হওয়া পর্যন্ত আপনি জানতেন না।
যে দীর্ঘ ফিডব্যাক সাইকেলটি বদলে দিল তা হলো:
যখন মেশিন টাইম মূল্যবান এবং ইন্টারফেস সীমিত, ভাষাগুলো বন্ধুবৎসল ডায়াগনিস্টিক বা শিক্ষানবিশের জন্য উপযোগী করে তৈরি করা হয়নি। এরর মেসেজ প্রায়শই সংক্ষিপ্ত, কখনো কখনো রহস্যময়, এবং অপারেটরকে কার্ড ডেক বা ছাপানো আউটপুটে সমস্যার অবস্থান জানাতে মনোনিবেশ করত।
প্রাথমিক ক্যালকুলেশন ডিমান্ডের বড় অংশই বৈজ্ঞানিক ও ইঞ্জিনিয়ারিং কাজ থেকে এসেছে: ক্যালকুলেশন, সিমুলেশন, ও নিউমেরিকাল মেথড। এজন্য প্রাথমিক ভাষার ফিচারগুলো প্রায়শই দক্ষ আরিথমেটিক, অ্যারে ও সূত্র লেখার পদ্ধতির উপর কেন্দ্রীভূত ছিল—যা হার্ডওয়্যারের সাথে ভাল মানানসই ছিল এবং বিজ্ঞানীরা কাগজে কাজ করা পদ্ধতির সাথে মিলও রেখেছিল।
কিছু প্রারম্ভিক প্রোগ্রামিং ভাষা সার্বজনীন হতে চায়নি। তারা একটি সংকীর্ণ কাজ খুব ভালভাবে সমাধান করার জন্য তৈরি করা হয়েছিল—কারণ কম্পিউটার ছিল দামী, সময় সীমিত, এবং “সবকিছুর জন্য ঠিক আছে” মানে প্রায়ই “কোথাও দারুণ নয়।”
FORTRAN (FORmula TRANslation) উদ্দেশ্য ছিল প্রকৌশল ও বৈজ্ঞানিক গণনার জন্য। এর কেন্দ্রীয় প্রস্তাবনা ছিল বাস্তবসম্মত: বিজ্ঞানীদেরকে অ্যাসেম্বলি-তে হাত দিয়ে প্রতিটি বিবরণ লেখার চাইতে ম্যাথ-ভারী প্রোগ্রাম লেখা সহজ করে দেওয়া।
এই লক্ষ্যই এর ডিজাইনকে আকৃত করে। এটি সংখ্যাত্মক অপারেশন ও অ্যারে-স্টাইল গণনায় ঝুঁকেছিল এবং পারফরম্যান্সে গুরুত্ব দিয়েছিল। প্রকৃত উদ্ভাবন কেবল সিনট্যাক্স ছিল না—এটি এই ধারণা ছিল যে একটি কম্পাইলার এমন মেশিন কোড উৎপন্ন করতে পারে যা বিজ্ঞানীরা বিশ্বাস করবে। যখন আপনার প্রধান কাজ সিমুলেশন বা পদার্থবিজ্ঞানের টেবিল তৈরি করা, রানটাইমের সাশ্রয় বিলম্ব ঘটাতে পারে—এবং তাই পারফরম্যান্স জীবন-অর্থবহ।
COBOL একটি ভিন্ন জগতের লক্ষ্য করেছিল: সরকার, ব্যাঙ্ক, বীমা, পে-রোল, ও ইনভেন্টরি—সকলেই রেকর্ড ও রিপোর্টের সমস্যা।
COBOL ইংরেজি-সদৃশ, বিস্তৃত স্টাইলে ঝুঁকেছিল যাতে বড় সংস্থায় প্রোগ্রামগুলো রিভিউ ও মেইনটেন করা সহজ হয়। ডেটা ডেফিনিশনগুলো প্রথম শ্রেণীর উদ্বেগ ছিল, কারণ ব্যবসায়িক সফটওয়্যার ফর্ম, অ্যাকাউন্ট, এবং ট্রানজেকশনের মডেলিংয়ের উপর নির্ভর করে।
উভয় ভাষাই একটি ডিজাইন নীতি দেখায়: ভাষার ভোকাবুলারি কাজের সাথে অনুবাদযোগ্য হওয়া উচিত।
FORTRAN গণিত ও গণনায় কথা বলে। COBOL রেকর্ড ও প্রসিডিউরের ভাষায় বলে। তাদের জনপ্রিয়তা তাদের যুগের অগ্রাধিক্য প্রকাশ করে: বাস্তব ওয়ার্কলোড সমাধান করা—চাকুরটি ছিল দ্রুত সংখ্যাত্মক গণনা না ব্যবসায়িক ডেটা ও রিপোর্টিং—এটাই প্রধান লক্ষ্য।
৬০–৭০-এর দশকে কম্পিউটার সস্তা ও সাধারণ হয়ে উঠলেও—তারা এখনও পারস্পরিকভাবে ভিন্ন। এক মেশিনের জন্য লেখা সফটওয়্যার অন্য মেশিনে পৌঁছালে অনেক অংশ হাতে পুনঃলিখতে হত।
অনেক গুরুত্বপূর্ণ সফটওয়্যার অ্যাসেম্বলিতে লেখা হত — সর্বোচ্চ পারফরম্যান্স ও নিয়ন্ত্রণ দেয়—কিন্তু খরচও বেশি: প্রতিটি CPU-র নিজস্ব ইনস্ট্রাকশন সেট, কোড পড়া কঠিন, এবং সামান্য পরিবর্তনও দিনের পরিশ্রমে পরিণত হত। সেই কষ্ট একটি ভাষার চাহিদা তৈরি করল যেটা "মেটালের কাছে" লাগবে কিন্তু আপনাকে একটি প্রসেসরে আটকে রাখবে না।
C একটি বাস্তবসম্মত সমঝোতা হিসেবে আবির্ভূত হল। এটি অপারেটিং সিস্টেম ও টুল লেখার জন্য ডিজাইন করা হয়েছিল—বিশেষ করে Unix—তবে হার্ডওয়্যারের ক্রস-কম্পাইলযোগ্যতা বজায় রেখে। C প্রোগ্রামারদের নিম্নলিখিত সুবিধা দিল:
Unix কে C-এ পুনরায় লেখা হচ্ছে—এটি বিখ্যাত প্রমাণ পয়েন্ট: অপারেটিং সিস্টেম নতুন হার্ডওয়্যারে অনেক সহজে স্থানান্তর করা যায় অ্যাসেম্বলি-নির্ভর সিস্টেমের তুলনায়।
C আশা করেছিল আপনি নিজেই মেমরি ম্যানেজ করবেন (এলোকেট, ফ্রি, ভুলগুলি এড়াতে)। এখন এটা ঝুঁকিপূর্ণ শোনালেও, তা তখনকার অগ্রাধিকারগুলোকে মিলে যাচ্ছিল। মেশিনে সীমিত রিসোর্স, অপারেটিং সিস্টেমে প্রেডিক্টেবল পারফরম্যান্স, এবং প্রোগ্রামারদের হার্ডওয়্যারের কাছে বেশি কাছাকাছি কাজ করার অভ্যাস—এসব মিলিয়ে ম্যানুয়াল ম্যানেজমেন্ট গ্রহণযোগ্য ছিল।
C দ্রুততা ও নিয়ন্ত্রণকে অপ্টিমাইজ করেছিল এবং তা দিয়েছিল। মূল্য ছিল সেফটি ও সহজতা: বাফার ওভারফ্লো, ক্র্যাশ, এবং সূক্ষ্ম বাগগুলো সাধারণ ঝুঁকি হয়ে উঠল। সেই সময়ে, সেই ঝুঁকিগুলো প্রায়ই পোর্টেবিলিটি ও পারফরম্যান্সের বিনিময়ে গ্রহণযোগ্য মনে করা হত।
প্রোগ্রাম ছোট, একক-উদ্দেশ্য ইউটিলিটিগুলো থেকে ব্যবসা চালানো পণ্যগুলোতে পরিণত হওয়ার সাথে, নতুন সমস্যা প্রধান হয়ে উঠল: কেবল "এটা কাজ করে কি না" নয়, বরং "কিভাবে এটাকে বছরের পর বছর ধরে কাজ রাখব?" প্রাথমিক কোড প্রায়ই goto দিয়ে একদমই লাফিয়ে নির্দেশিত হয়ে জটিল স্প্যাগেটি কৌড তৈরি করত—যা পড়া, টেস্ট করা বা নিরাপদে পরিবর্তন করা কঠিন করত।
স্ট্রাকচার্ড প্রোগ্রামিং একটি সরল ধারণা এগিয়ে দিল: কোডের একটি পরিষ্কার আকৃতি থাকা উচিত। যান্ত্রিকভাবে নির্দিষ্ট নোডে লাফানো বন্ধ করে, ডেভেলপাররা ভাল-সংজ্ঞায়িত নির্মাণ ব্লক—if/else, while, for, এবং switch—ব্যবহার করল যাতে কন্ট্রোল ফ্লো পূর্বাভাসযোগ্য হয়।
এই পূর্বাভাসযোগ্যতা গুরুত্বপূর্ণ কারণ ডিবাগিং মূলত “এক্সিকিউশন কিভাবে এখানে পৌঁছেছে?” জিজ্ঞাসার উত্তর দেওয়ার ব্যাপার। যখন ফ্লোটি স্ট্রাকচারে দৃশ্যমান হয়, কম বাগ লুকায়।
একবার সফটওয়্যার দলভিত্তিক কাজ হয়ে উঠলে, রক্ষণযোগ্যতা প্রযুক্তিগত চেয়ে বেশি সামাজিক সমস্যা হয়ে উঠল। নতুন সহকর্মীরা এমন কোড বুঝতে চেয়েছিল যা তারা লিখেনি। ম্যানেজাররা পরিবর্তনের জন্য অনুমান চেয়েছিল। ব্যবসাগুলো নিশ্চিত হতে চেয়েছিল যে আপডেট সবকিছু ভেঙে দেবে না।
ভাষাগুলো এমন কনভেনশনকে উৎসাহ দিল যা এক ব্যক্তির মেমোরির বাইরেও স্কেল করে: সঙ্গতিপূর্ণ ফাংশন সীমানা, স্পষ্ট ভেরিয়েবল লাইফটাইম, এবং আলাদা ফাইল ও লাইব্রেরিতে কোড সংগঠনের উপায়।
টাইপগুলো বেশি গুরুত্বপূর্ণ হয়ে উঠল কারণ এগুলো “অভ্যন্তরীণ ডকুমেন্টেশন” ও প্রারম্ভিক ত্রুটি সনাক্তকরণ হিসেবে কাজ করে। যদি একটি ফাংশন সংখ্যাকে আশা করে কিন্তু টেক্সট পায়, শক্ত টাইপ সিস্টেম তা ব্যবহারকারীর সামনে আসার আগেই ধরতে পারে।
মডিউল ও স্কোপগুলো পরিবর্তনের বিস্তারের ক্ষেত্র সীমিত করতে সাহায্য করেছে। ডিটেইলগুলো প্রাইভেট রেখে স্থিতিশীল ইন্টারফেসExpose করলে দলগুলো ইন্টারনাল রিফ্যাক্টর করে সম্পূর্ণ প্রোগ্রাম পুনরায় লেখার ঝুঁকি ছাড়াই পরিবর্তন করতে পারে।
কমন ইমপ্রুভমেন্টগুলো অন্তর্ভুক্ত ছিল:
একসাথে, এই পরিবর্তনগুলো ভাষাগুলোকে এমন কোডের দিকে ঠেলে দিল যা পড়া, রিভিউ করা, এবং নিরাপদে বিকাশ করা সহজ।
অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং (OOP) “জিতেছে” না কারণ এটা একমাত্র ভালো ধারণা ছিল—এটা জিতেছিল কারণ এটা অনেক দলেই যে ধরণের সফটওয়্যার তারা বানাচ্ছিল তার সঙ্গে মানানসই ছিল: বহু মানুষের দ্বারা রক্ষণাবেক্ষণীয়, দীর্ঘজীবী ব্যবসায়িক সফটওয়্যার।
OOP জটিলতার জন্য একটি সুশৃঙ্খল গল্প দিয়েছিল: প্রোগ্রামকে অনুপযুক্ত দায়িত্বসহ “অবজেক্ট” হিসেবে উপস্থাপন করা।
এনকাপসুলেশন (অভ্যন্তরীণ ডিটেইল লুকানো) দুর্ঘটনাজনিত ভাঙা থেকে রক্ষা করার বাস্তব উপায় ছিল। ইনহেরিটেন্স ও পলিমরফিজম পুনঃব্যবহারের প্রতিশ্রুতি দিল: সাধারণ ভার্সন একবার লিখুন, পরে স্পেশালাইজ করুন, এবং একই ইন্টারফেসে বিভিন্ন ইমপ্লিমেন্টেশন প্লাগ করুন।
ডেস্কটপ সফটওয়্যার ও গ্রাফিক্যাল ইন্টারফেস বাড়ার সঙ্গে সঙ্গে, ডেভেলপারদের অনেক ইন্টারঅ্যাক্টিং কম্পোনেন্ট (উইন্ডো, বাটন, ডকুমেন্ট, মেনু, ইভেন্ট) পরিচালনা করতে হয়। অবজেক্ট ও মেসেজের ধারনা এই ইন্টারেকটিভ অংশগুলোর সাথে সুন্দরভাবে মানায়।
একই সময়ে, এন্টারপ্রাইজ সিস্টেম ব্যাংকিং, ইনসুরেন্স, ইনভেন্টরি, ও HR-এর মত ডোমেইন নিয়ে বেড়েছিল। এসব পরিবেশে কনসিস্টেন্সি, টিম-কলাবোরেশন, ও বছর বছর চলার উপযোগী কোডবেস মূল্যায়িত ছিল। OOP একটি সাংগঠনিক প্রয়োজন পূরণ করল: কাজকে মডিউল ভাগ করে আলাদা টিম থেকে মালিকানা কড়া রাখা, সীমানা প্রয়োগ করা, এবং ফিচার যোগ করার ধরণ মানক করা।
OOP কাজে লাগলে তা স্থিতশীল সীমানা ও পুনঃব্যবহারযোগ্য কম্পোনেন্ট সৃষ্টি করে। কিন্তু ডেভেলপাররা যখন সবকিছু ওভার-মডেল করে, গভীর ক্লাস হায়ারারকি, “গড অবজেক্ট”, বা ফ্যাশন হিসেবে প্যাটার্ন ব্যবহার করতে শুরু করে—তবে জটিলতা বেড়ে যায়। অনেক স্তর সাধারণ পরিবর্তনকেও কাগজপত্রের মতো করে দিতে পারে।
যদিও সকল ভাষাই “পিউর OOP” নয়, অনেকেই OOP-এর ডিফল্ট ধারণা গ্রহণ করেছে: ক্লাস-প্রতিচ্ছবিভূত স্ট্রাকচার, ইন্টারফেস, অ্যাক্সেস মডিফায়ার, ও ডিজাইন প্যাটার্ন। আধুনিক প্রচলিত সিনট্যাক্সের অনেক অংশ এখনো এই যুগের বড় দল ও বড় কোডবেস সংগঠনের গুরুত্ব প্রতিফলিত করে।
জাভা একটি নির্দিষ্ট ধরনের সফটওয়্যার বুমের সঙ্গে উঠেছিল: বড়, দীর্ঘজীবী ব্যবসায়িক সিস্টেম যেগুলো অনির্দিষ্টভাবে মিশ্র সার্ভার, অপারেটিং সিস্টেম, ও ভেন্ডর হার্ডওয়্যারে ছড়িয়ে ছিল। কোম্পানিগুলো স্থিতিশীল ডিপ্লয়মেন্ট, কম ক্র্যাশ, এবং বড় দল বেড়ে উঠুক তা চান—এবং বারবার সবকিছু পুনরায় না লিখলেই ভালো।
জাভা সরাসরি মেশিনের নির্দেশনায় কম্পাইল না করে, বাইটকোডে কম্পাইল করে যা Java Virtual Machine (JVM)-এ চলে। JVM হয়ে উঠল একটি “স্ট্যান্ডার্ড লেয়ার” যা এন্টারপ্রাইজরা নির্ভর করতে পারে: একই অ্যাপ এক্সিকিউটেবল বিভিন্ন OS-এ চালাতে পারা যায় সামান্য পরিবর্তনে।
এটাই “write once, run anywhere”-এর মুল—শূন্য প্ল্যাটফর্ম কুয়িরিকস নয়, বরং বহু পরিবেশ সমর্থন করার খরচ ও ঝুঁকি কমানো।
জাভা সেফটিকে একটি প্রাথমিক ফিচার হিসেবে গ্রহণ করল, একেবারেই ঐচ্ছিক হিসেবে নয়।
গারবেজ কালেকশন মেমরি বাগ (ড্যাংগলিং পয়েন্টার, ডাবল-ফ্রি) দূর করে। অ্যারে বাউন্ড চেকস আউট-অফ-রেঞ্জ পড়া/লেখা আটকায়। শক্ত টাইপ সিস্টেমের সাথে এসব একত্রে বিধ্বংসী ক্র্যাশকে পূর্বাভাসযোগ্য এক্সসেপশনে রূপান্তর করে—যা পুনরুৎপাদন করা, লগ করা, ও ফিক্স করা সহজ।
এন্টারপ্রাইজরা স্থিতিশীলতা, টুলিং, ও গভর্ন্যান্সকে মূল্য দেয়: মানক বিল্ড প্রসেস, শক্ত IDE সাপোর্ট, বিস্তৃত লাইব্রেরি, এবং মনিটরিং/ম্যানেজমেন্ট করা runtime। JVM সমৃদ্ধ সার্ভার ও ফ্রেমওয়ার্ক ইকোসিস্টেম তৈরি করল যা বড় দলের উন্নয়নকে আরও সঙ্গতিপূর্ণ করে তোলে।
জাভার সুবিধাগুলো বিনামূল্যের নয়। ম্যানেজড রuntime সাটআপ টাইম ও মেমরি ওভারহেড যোগ করে, এবং গারবেজ কালেকশন ঠিকমতো টিউন না করলে লেটেন্সি স্পাইক করতে পারে। সময়ের সাথে ইকোসিস্টেমে স্তরগুলো জমে—ফ্রেমওয়ার্ক, কনফিগারেশন, ডিপ্লয়মেন্ট মডেল—যা বিশেষজ্ঞ জ্ঞানের চাহিদা বাড়ায়।
তবুও অনেক প্রতিষ্ঠানের জন্য এই চুক্তি মূল্যবান ছিল: কম লো-লেভেল ব্যর্থতা, সহজ ক্রস-প্ল্যাটফর্ম ডিপ্লয়মেন্ট, এবং বড় ব্যবসা ও কোডবেসের সাথে স্কেল করা রানটাইম।
৯০-এর শেষ ভাগ ও ২০০০-এর দশকে অনেক দল অপারেটিং সিস্টেম লিখছিল না—তারা ডাটাবেস যুক্ত করছিল, ওয়েবসাইট বানাচ্ছিল, ও অটোমেশন করছিল। বটলনেক বদলে গেল: কাঁচা CPU দক্ষতা না, বরং ডেভেলপার টাইম। দ্রুত ফিডব্যাক ও ছোট রিলিজ সাইকেল “কত দ্রুত আমরা পরিবর্তন করতে পারি?”—এটি প্রথম শ্রেণীর চাহিদা হয়ে দাঁড়াল।
ওয়েব অ্যাপ দ্রুতই দিনে বানার গল্পে পরিণত হলো। ব্যবসাগুলো নতুন পেজ, রিপোর্ট, ইন্টিগ্রেশন দ্রুত চেয়েছে; পুরো কম্পাইল–লিংক–ডিপ্লয় পাইপলাইন ছাড়া দ্রুত ফিক্স প্রয়োজন। স্ক্রিপ্টিং ভাষাগুলো সেই রিদমে মেলে: ফাইল এডিট, চালান, ফলাফল দেখুন।
এটি কে সফটওয়্যার বানাতে পারে তার দায়িত্বও বদলে দিল—সিস্টেম অ্যাডমিন, অ্যানালিস্ট, ছোট দলরা কার্যকরী টুল চালু করতে পারল গভীর মেমরি ম্যানেজমেন্ট বা বিল্ড সিস্টেমের গভীর জ্ঞানের ছাড়াই।
Python ও Ruby ডাইনামিক টাইপিংকে কাজে লাগালো: কম ডিক্লারেশন, কম সিরিমনি। শক্তিশালী স্ট্যান্ডার্ড লাইব্রেরি সঙ্গে থাকায় সাধারণ কাজগুলো “একটি ইমপোর্ট”-এর দূরত্বে হয়ে উঠল:
এই “ব্যাটারিস-ইনক্লুডেড” দৃষ্টিভঙ্গি অনুসন্ধান-ভিত্তিক এক্সপেরিমেন্টেশনকে পুরস্কৃত করল এবং অটোমেশন স্ক্রিপ্টগুলো প্রাকৃতিকভাবে সত্যিকারের অ্যাপ্লিকেশনে বড় হতে পারে।
Python অটোমেশন ও জেনেরেল-প্রসপোজের জন্য একটি প্রিয় পছন্দ হয়ে উঠল, Ruby ওয়েব ডেভেলপমেন্টকে ত্বরান্বিত করল (বিশেষত ফ্রেমওয়ার্কের মাধ্যমে), এবং PHP প্রাথমিক সার্ভার-সাইড ওয়েবে দাপট দেখাল কারণ এটি পেজে সরাসরি এমবেড করা সহজ ও প্রায় সর্বত্র ডিপ্লয় করা যেত।
যেই ফিচারগুলো প্রোডাক্টিভিটি বাড়ায়, সেগুলোই খরচও বাড়ায়:
অর্থাৎ, স্ক্রিপ্টিং ভাষা পরিবর্তনের সুবিধার জন্য অপচয় ছিল; দলগুলো রিলায়েবিলিটি কিনে নিত টুলিং ও প্র্যাকটিস দিয়ে—এটি আধুনিক ইকোসিস্টেমের মাইলফলক যেখানে ডেভেলপার স্পিড ও সফটওয়্যার কোয়ালিটি দুটোই প্রত্যাশিত।
ওয়েব ব্রাউজার হঠাৎ করে মিলিয়ন মানুষের কাছে পৌঁছানো “কম্পিউটার” হয়ে উঠল। কিন্তু এটি খালি ক্যানভাস ছিল না: একটি স্যান্ডবক্স, অনিশ্চিত হার্ডওয়্যারে চলে, এবং ইন্টারঅ্যাকটিভ থাকার সময় প্রতিক্রিয়াশীল থাকতে হয়। এই পরিবেশই JavaScript-এর ভূমিকা নির্ধারণ করে—কোনও নিখুঁত ভাষার উপর নয়।
ব্রাউজারে কোড মুহূর্তেই সরবরাহ করতে হয়, অপ্রত্যাশিত কন্টেন্টের পাশে নিরাপদে চলতে হয়, এবং পেজ ইন্টারঅ্যাকটিভ রাখতে হয়। এই চাহিদা JavaScript-কে দ্রুত স্টার্টআপ, ডাইনামিক আচরণ, এবং পেজ-সংলগ্ন API-এর দিকে ঠেলে দিল: ক্লিক, ইনপুট, টাইমার, ও পরে নেটওয়ার্ক অনুরোধ।
JavaScript সফল হলো বড় কারণে: এটা ইতিমধ্যেই ব্রাউজারে ছিল। কোনও ব্রাউজারে আচরণ চাইলে, JavaScript ছিল ডিফল্ট—কোনো ইনস্টল ধাপ, কোনো পারমিশন, আলাদা রানটাইম নয়। প্রতিদ্বন্দ্বী ধারণা কাগজে ক্লিন দেখালেও, বিতরণের সুবিধা মেলানো কঠিন ছিল—“এটি প্রতিটি সাইটে চলে” এই সুবিধা বড়।
ব্রাউজার মৌলিকভাবে প্রতিক্রিয়াশীল: ইউজার ক্লিক করে, পেজ স্ক্রল করে, অনুরোধ যখন ফিরে আসে তখন কাজ করে। JavaScript-এর ইভেন্ট-চালিত স্টাইল (কলব্যাক, ইভেন্ট, প্রমিস) সেই বাস্তবতার ছাপ রাখে। সম্পূর্ণরূপে একবার চালানো প্রোগ্রাম নয়—ওয়েব কোড অনেকটাই “কিছু ঘটার জন্য অপেক্ষা করো, তারপর প্রতিক্রিয়া দেখাও” ধাঁচের।
সাফল্য একটি গ্র্যাভিটি ওয়েল তৈরি করে। ফ্রেমওয়ার্ক ও লাইব্রেরির বিশাল ইকোসিস্টেম গড়ে উঠল, এবং বিল্ড পাইপলাইন একটি নিজস্ব পণ্য বিভাগে পরিণত হলো: ট্রান্সপাইলার, বান্ডলার, মিনিফায়ার, প্যাকেজ ম্যানেজার। একই সাথে, ওয়েবের ব্যাকওয়ার্ড কম্প্যাটিবিলিটি-প্রতিশ্রুতি পুরোনো সিদ্ধান্তগুলো ধরে রেখে দিয়েছে—তাই আধুনিক JavaScript প্রায়ই পুরোনো সীমাবদ্ধতার উপর নতুন টুলদের স্তর লাগিয়ে গঠিত মনে হয়।
অনেক বছর ধরে দ্রুততর কম্পিউটার মানে ছিল: আপনার প্রোগ্রাম বাড়তি কোনো কোড ছাড়াই দ্রুত চলবে। সেই চুক্তি ভেঙে যায় যখন চিপগুলো ক্লক-স্পিড বাড়ানোর বদলে কোর বাড়াতে শুরু করে। হঠাৎ করে, অধিক পারফরম্যান্স পেতে হলে একে একাধিক কাজ একই সময়ে করাতে হত।
আধুনিক অ্যাপগুলো তুচ্ছ এক কাজ করে না। তারা প্রচুর অনুরোধ হ্যান্ডেল করে, ডাটাবেসে কথা বলে, UI রেন্ডার করে, ফাইল প্রসেস করে, এবং নেটওয়ার্কের অপেক্ষা করে—এবং ব্যবহারকারীরা তৎক্ষণাত প্রতিক্রিয়া চায়। মাল্টিকোর হার্ডওয়্যার প্যারালাল কাজ চালানো সম্ভব করেছে, কিন্তু যদি ভাষা বা রানটাইম "একটি মেইন থ্রেড, একটি ফ্লো" ধারণা ধরে তাহলে কষ্ট বাড়ে।
প্রারম্ভিক কনকারেন্সি OS থ্রেড ও লকগুলোর উপর নির্ভর করত। অনেক ভাষা এগুলো সরাসরি প্রকাশ করত—যা কাজ করলেও জটিলতা ডেভেলপারদের উপর চাপিয়ে দিত।
নতুন ডিজাইনগুলো সাধারণ প্যাটার্নগুলো সহজ করার চেষ্টা করে:
সফটওয়্যার সবসময়-চলমান সার্ভার হয়ে যাওয়ায়, “নর্মাল” প্রোগ্রাম করা হলো হাজার হাজার সমান্তরাল অনুরোধ হ্যান্ডেল করা। ভাষাগুলো I/O-ব্যাতিত ওয়ার্কলোড, ক্যানসেলেশন/টাইমআউট, এবং লোডে পূর্বানুমেয় পারফরম্যান্সের দিকে অপ্টিমাইজ করতে শুরু করল।
কনকারেন্সি ব্যর্থতাগুলো প্রায়ই বিরল ও রিপ্রোডিউস করা কঠিন। ভাষা ডিজাইন ক্রমশঃ প্রতিরোধ করতে চায়:
বড় পরিবর্তন: কনকারেন্সি আর এক্সট্রা বিষয় নয়—এটি একটি বেসলাইন প্রত্যাশা।
২০১০-এর দশকে অনেক দল কেবল এলগরিদম প্রকাশ করতে সংগ্রাম করছিল না—তারা সার্ভিসগুলোকে নিরাপদ, স্থিতিশীল, এবং ক্রমাগত ডিপ্লয় করার চাপের মধ্যে সহজে পরিবর্তনযোগ্য রাখতে সংগ্রাম করছিল। দুটি বড় সমস্যা মাথায় আসে: মেমরি ত্রুটির কারণে সিকিউরিটি বাগ, এবং জটিল স্ট্যাক/অসামঞ্জস্যপূর্ণ টুলিংয়ের কারণে ইঞ্জিনিয়ারিং ঘাটতি।
উচ্চ-মাত্রার ভলনারিবিলিটির বড় অংশ এখনো মেমরি সেফটি সমস্যা থেকে আসে: বাফার ওভারফ্লো, use-after-free, এবং সাবটিল আনডেফাইন্ড বিহেভিয়ার যা নির্দিষ্ট বিল্ড বা মেশিনে দেখা দেয়। আধুনিক ভাষা ডিজাইন এসবকে শুধুমাত্র প্রোগ্রামার ভুল নয়—অপশুট-ফাঁদ হিসেবে বিবেচনা করতে শুরু করেছে।
Rust সবচেয়ে স্পষ্ট প্রতিক্রিয়া। এর ownership ও borrowing নিয়মগুলো মূলত একটি চুক্তি: আপনি কড়া কম্পাইল-টাইম চেক পাস করবেন, বদলে পাবেন মেমরি সেফটির শক্তিশালী গ্যারান্টি বিনা গারবেজ কালেকশনের। তাই Rust আকর্ষণীয় সিস্টেম কোডের জন্য—যেগুলো ঐতিহাসিকভাবে C/C++-এ ছিল: নেটওয়ার্ক সার্ভিস, এমবেডেড অংশ, পারফরম্যান্স-সংবেদনশীল লাইব্রেরি—যেখানে সেফটি ও গতিবেগ দুটোই জরুরি।
Go প্রায় বিপরীত পথ নেয়: ভাষার ফিচার সীমিত করে কোডবেসকে পাঠযোগ্য ও পূর্বানুমেয় রাখা। এর ডিজাইন একটি দীর্ঘ-চলমান সার্ভিস, API, ও ক্লাউড অবকাঠামোর জগতকে প্রতিফলিত করে।
Go-এর স্ট্যান্ডার্ড লাইব্রেরি ও বিল্ট-ইন কনকারেন্সি প্রিমিটিভ (goroutines, channels) সরাসরি সার্ভিস ডেভেলপমেন্টকে সহায়তা করে, আর দ্রুত কম্পাইলার ও সরল ডিপেন্ডেন্সি গল্প দৈনন্দিন কাজের ঘর্ষণ কমায়।
টুলিং "ঐচ্ছিক অতিরিক্ত" নয়—এটি ভাষার প্রতিশ্রুতির অংশ হয়ে উঠল। Go gofmt দিয়ে এই মানসিকতা সাধারণীকরণ করল এবং একটি স্টাইল নিয়ম প্রতিষ্ঠা করল। Rust rustfmt, clippy, এবং একটি অত্যন্ত ইন্টিগ্রেটেড বিল্ড টুল (cargo) নিয়ে এলো।
আজকের "নিরন্তর শিপিং" পরিবেশে, এই টুলিং কাহিনী কম্পাইলার ও লিন্টারের বাইরে উচ্চ-স্তরের ওয়ার্কফ্লো—প্ল্যানিং, স্ক্যাফোল্ডিং, এবং দ্রুত ইটারেশন লুপ পর্যন্ত বিস্তৃত। এমন প্ল্যাটফর্ম যেমন Koder.ai এই পরিবর্তনকে উদাহরণ দেয়: দলগুলোকে চ্যাট-চালিত ইন্টারফেস দিয়ে ওয়েব, ব্যাকএন্ড, ও মোবাইল অ্যাপ তৈরি করতে দেয়—পরে সোর্স কোড এক্সপোর্ট করা, ডিপ্লয় করা, এবং স্ন্যাপশট দিয়ে রোলব্যাক করা যায় যখন দরকার। এটা একই ঐতিহাসিক প্যাটার্নের আরেকটি উদাহরণ: সবচেয়ে দ্রুত ছড়িয়ে পড়া টুলগুলো সেইগুলো যেগুলো যুগের সাধারণ কাজকে সস্তা ও কম ত্রুটিপূর্ণ করে।
যখন ফরম্যাটার, লিন্টার, ও বিল্ড সিস্টেম প্রথম-শ্রেণীর হয়, দলগুলো স্টাইল নিয়ে কম সময় নষ্ট করে ও অনিয়মিত পরিবেশে কম সময় লড়াই করে—আর বেশিবার নির্ভরযোগ্য সফটওয়্যার শিপ করতে পারে।
প্রোগ্রামিং ভাষা "জিতেন" না কারণ তারা নিখুঁত—তারা জিতেন যখন তারা সেই মুহূর্তের সাধারণ কাজটাকে সস্তা, নিরাপদ, বা দ্রুত করে দেয়—বিশেষত যখন সঠিক লাইব্রেরি ও ডিপ্লয়মেন্ট অভ্যাসের সাথে জোড়া পড়ে।
আজকের ভাষাপছন্দের বড় চালিকা হলো যেখানে কাজটি আছে: ডেটা পাইপলাইন, অ্যানালিটিক্স, মেশিন লার্নিং, ও অটোমেশন। এজন্য Python বাড়তেই থাকছে—শুধু সিনট্যাক্সের কারণে নয়, বরং ইকোসিস্টেমের কারণে: NumPy/Pandas ডেটার জন্য, PyTorch/TensorFlow ML-এর জন্য, নোটবুক এক্সপ্লোরেশনের জন্য, এবং বিশাল কমিউনিটি রিইউজেবল ব্লক বানায়।
SQL একটি চুপচাপ উদাহরণ—এটি ট্রেন্ডি নাও হতে পারে, কিন্তু বিজনেস ডেটার ডিফল্ট ইন্টারফেস হয়ে আছে কারণ এটি কাজের সাথে মানায়: ডিক্লারেটিভ কুয়েরি, পূর্বানুমেয় অপ্টিমাইজার, এবং টুল ও ভেন্ডরের মধ্যে ব্যাপক সামঞ্জস্য। নতুন ভাষাগুলো প্রায়শই SQL কে ইন্টিগ্রেট করে, বদলে দেয় না।
একই সময়ে, পারফরম্যান্স-ভিত্তিক AI GPU-অরিয়েন্টেড টুলিংকে এগিয়ে নিয়ে যাচ্ছে। আমরা আরও বেশি ভেক্টরাইজেশন, ব্যাচিং, ও হার্ডওয়্যার অ্যাক্সিলারেশন নিয়ে প্রথম-শ্রেণীর মনোযোগ দেখছি—চাই সেটা CUDA ইকোসিস্টেমের মাধ্যমে হোক, MLIR ও কম্পাইলার স্ট্যাকের মাধ্যমে, বা এমন ভাষা যেগুলো এই রানটাইমগুলোতে সহজে বাইন্ড করে।
কয়েকটি চাপ ভবিষ্যতের ভাষা ও বড় আপডেটগুলোকে প্রভাবিত করতে পারে:
ভাষা বেছে নেওয়ার সময়, এটাকে আপনার সীমাবদ্ধতার সাথে মিলিয়ে নিন: দলের অভিজ্ঞতা, হায়ারিং পুল, আপনি যে লাইব্রেরিগুলো নির্ভর করবেন, ডিপ্লয়মেন্ট টার্গেট, এবং নির্ভরযোগ্যতার চাহিদা। একটি “ভালো” ভাষা প্রায়ই সেই ভাষা যেটা আপনার সবচেয়ে ঘন ঘন কাজগুলোকে বিরক্তিকর করে তোলে—এবং আপনার ভুলগুলিকে সহজে প্রতিরোধ ও নির্ণয় করতে সাহায্য করে।
যদি ফ্রেমওয়ার্ক-ভিত্তিক ইকোসিস্টেম দরকার, ইকোসিস্টেমের জন্য বেছে নিন; যদি সঠিকতা ও নিয়ন্ত্রণ দরকার, নিরাপত্তা ও পারফরম্যান্স বিবেচনা করে বেছে নিন। অধিক সিদ্ধান্তনির্ভর চেকলিস্টের জন্য দেখুন /blog/how-to-choose-a-programming-language.