মার্গারেট হ্যামিলটনঃ অ্যাপোলো-১১ এর নেপথ্য বীর

margaret_hamilton_in_action

মার্গারেট হ্যামিলটন

সম্প্রতি নাসার অ্যাপোলো চন্দ্রাভিজানের কোড ডেভেলপার মার্গারেট হ্যামিলটন, আমেরিকার সর্বোচ্চ বেসামরিক পুরষ্কার “প্রেসিডেন্টশিয়াল মেডেল অফ ফ্রিডম” লাভ করেছেন। মার্গারেট হিয়েফিল্ড হ্যামিলটন এই বছর ২২ নভেম্বর, অ্যাপোলো চন্দ্রাভিজানের “অন-বোর্ড ফ্লাইট ডেভেলপমেন্ট”-এর কাজের জন্য বারাক ওবামা কর্তৃক এই পুরষ্কার লাভ করেন।

হ্যামিলটন, নিজের সফটওয়্যার কোম্পানী “হ্যামিলটন টেকনোলজিস ইনকর্পোরেট” প্রতিষ্ঠা করার আগে MIT-এর লিঙ্কন ল্যাবরেটরিতে কম্পিউটার বিজ্ঞানী হিসেবে দীর্ঘদিন কাজ করেন। লিঙ্কন ল্যাবরেটরিতে কাজ করার সময় তিনি asynchronous সফটওয়্যার, priority scheduling, priority displays এবং “human-in-the-loop decision capability” উপর যে মতবাদ প্রদান করেন, তা বর্তমান আধুনিক এবং নির্ভরযোগ্য সফটওয়্যার ডিজাইন এবং ইঞ্জিনিয়ারিং এর মূল ভিত্তি হিসেবে বিবেচিত হয়।

“প্রেসিডেন্টশিয়াল মেডেল অফ ফ্রিডম” যুক্তরাষ্ট্রের সর্বোচ্চ বেসামরিক পুরষ্কার, যেটি ক্ষমতাসীন প্রেসিডেন্টের মাধ্যমে প্রদান করা হয়ে থাকে। যুক্তরাষ্ট্রের জাতীয় স্বার্থে প্রশংসনীয় অবদানের জন্য শিল্পকলা, ব্যবসা ও অর্থনীতি, কম্পিউটিং, মানবতামূলক কার্যক্রম, চিকিৎসা এবং অন্যান্য আরো কিছু সরকারী ও বেসরকারী খাতে এই পুরষ্কার প্রদান করা হয়ে থাকে।

MIT এর অ্যারোনটিক্স ও অ্যাস্ট্রোনটিক্স বিভাগের প্রধান, প্রফেসর জাইমি পিয়ারে, হ্যামিলটনের এর পুরষ্কার পাওয়া সম্পর্কে বলেন, “এটি মার্গারেট হ্যামিলটনের জন্য একটি অসাধারণ প্রাপ্তি”। তিনি আরো বলেন, “সে একজন সত্যিকার সফটওয়্যার অগ্রদূত এবং একইসাথে বলতে সংকোচ নেই যে, তাঁর নেতৃত্বে পরিচালিত MIT-এর ইন্সট্রুমেন্টেশন ল্যাবের সফটওয়্যার ডিভিশনই আমাদের চাঁদে নিয়ে গিয়েছিল।”

বস্তুত, MIT ইন্সট্রুমেন্টেশন ল্যাবের অ্যাপোলো পরিচালনা ও নিয়ন্ত্রণ ছিল অ্যাপোলো প্রোগ্রামের প্রথম চুক্তি, যা ১৯৬১ সালের ৯ আগস্ট ঘোষণা করা হয়। এই ঘোষণার ১০ সপ্তাহ পর তৎকালীন প্রেসিডেন্ট জন এফ ক্যানেডি বিংশ শতাব্দীর অন্যতম লক্ষ্য হিসেবে মানুষের চাঁদে অবতরণের কথা ঘোষণা করেন।

মার্গারেট হ্যামিলটন যুক্তরাষ্ট্রের ইরহাম কলেজ থেকে গণিতে স্নাতক ডিগ্রী অর্জন করেন এবং MIT থেকে আবহাওয়াবিদ্যা (meteorology) তে স্নাতকোত্তর ডিগ্রী অর্জন করেন। পরবর্তীতে তিনি MIT এর লিঙ্কন ল্যাবে “ Semi-Automatic Ground Environment Air Defense System” বা SAGE প্রকল্পে যোগ দেন। SAGE ছিল যুক্তরাষ্ট্রের প্রথম বিমান প্রতিরক্ষামূলক প্রকল্প, যা কিনা ছিল পারমানবিক বোমার প্রকল্প “ম্যানহাটন প্রজেক্ট”-এর চেয়ে বেশি ব্যয়বহুল এবং পঞ্চাশ-ষাট দশকের ডিজিটাল কম্পিউটিং-এর উন্নয়নের যুগান্তকারী পদক্ষেপ। SAGE এবং Apollo প্রজেক্টে কাজ করার পর, হ্যামিলটন নাসার স্পেস শাটল এবং স্কাইল্যাব প্রোগ্রামের সাথে যুক্ত হন।

অ্যাপোলো-১১ কোডের প্রিন্ট কপির সাথে মার্গারেট হ্যামিলটন
অ্যাপোলো-১১ কোডের প্রিন্ট কপির সাথে মার্গারেট হ্যামিলটন

মার্গারেট হ্যামিলটন বিজ্ঞান ও প্রযুক্তিতে “আইকন লেডি” হিসেবে পরিচিতি পান অ্যাপোলো কোডের প্রিন্ট আউটের সাথে তাঁর একটি ছবি সামাজিক যোগাযোগ মাধ্যমে ছড়িয়ে পরার পর। গত বছর (২০১৫ সালে), মার্গারেট হ্যামিলটনের ডেভেলপ করা সম্পূর্ণ অ্যাপোলো কোডটি, কোড শেয়ারিং সাইট গিটহাবে যুক্ত করা হয়ঃ সেখানে কোডের প্রথম লাইনে লেখা হয়ঃ
“SUBMITTED: MARGARET H. HAMILTON DATE: 28 MAR 69 / M.H.HAMILTON, COLOSSUS PROGRAMMING LEADER / APOLLO GUIDANCE AND NAVIGATION”

"প্রেসিডেন্টশিয়াল মেডেল অফ ফ্রিডম" পুরষ্কার বিতরণী অনুষ্ঠানে মার্গারেট হ্যামিলটন
“প্রেসিডেন্টশিয়াল মেডেল অফ ফ্রিডম” পুরষ্কার বিতরণী অনুষ্ঠানে মার্গারেট হ্যামিলটন

এই বছর (২০১৬) ১৬ নভেম্বর প্রেসিডেন্ট বারাক ওবামা “প্রেসিডেন্টশিয়াল মেডেল অফ ফ্রিডম” প্রাপ্ত ২১ জনের নাম ঘোষণা করেন। এই ২১ জনের তালিকায় আরো অনেকের সাথে কম্পিউটার বিজ্ঞানের আরেকজন পথিকৃৎ প্রয়াত গ্রেস হোপার, MIT-এর “রে অ্যান্ড মারিয়া স্টাটা সেন্টার ফর কম্পিউটার, ইনফরমেশন অ্যাণ্ড ইন্টিলিজেন্স” -এর ডিজাইনার ফ্র্যাঙ্ক গেরি, বিল গেটস্‌, মেলিন্ডা গেটসের নাম রয়েছে। ২২ নভেম্বর ওয়াশিংটনে এই পুরষ্কার বিতরণী অনুষ্ঠান মঞ্চায়িত হয়।

লেখকঃ তামান্না নিশাত রিনি।

Facebook Comments

হ্যাশ ফাংশন – ২

লেখকঃ বজলুর রহমান রোকন
লেখকঃ বজলুর রহমান রোকন

আগের পোস্টের সমস্যাটি হলো- দুটি ভিন্ন ভিন্ন স্ট্রিং হ্যাশ ফাংশনে দিলে যদি একই ভ্যালু পাওয়া যায় তাহলে কী হবে? উত্তরটির জন্য পুরো আর্টিক্যাল পড়তে হবে।

এখন শুরুতে আমি একটি প্রশ্ন করি, দুটি ভিন্ন স্ট্রিংয়ের জন্য হ্যাশ ফাংশন কি একই ভ্যালু রিটার্ন করতে পারে? উত্তরটি নির্ভর করে তোমার হ্যাশ ফাংশনের উপর। তুমি কীভাবে সেটি ইমপ্লিমেন্ট করছো তার ওপর। তবে বাস্তবে কোনো হ্যাশ ফাংশনই শতভাগ এই নিশ্চয়তা দেয় না যে, সে সবসময়ই ভিন্ন ভিন্ন স্ট্রিংয়ের জন্য ভিন্ন ভিন্ন ভ্যালু রিটার্ন করবে।

আরো গভীরে যাওয়ার আগে সমস্যাটা নিয়ে আরো একটু আলোচনা করি। মনে করো, তোমার হ্যাশ ফাংশনটি খুবই সাধারণ। এটি অ্যারেতে উপাদানগুলো বর্ণানুক্রমে স্থান দেয়। তোমার পণ্যগুলো যথাক্রমে আদা, রসুন, পেঁপে, কলা ইত্যাদি হয় এবং তোমার অ্যারের সাইজ যদি 10।

h1

h2

উপরের ছবি দুটি থেকে দেখতে পাচ্ছো, আদা, কলা, পেঁপে, রসুন এবং মরিচ এগুলোর হ্যাশ ভ্যালু যথাক্রমে ১,২,৩ ও ৭, ৮। সুতরাং এগুলো অ্যারের ০,১,২ ও ৬,৭ নম্বর ইন্ডেক্সে বসনো হয়েছে। কিন্তু জীবন তো আর পুষ্পশয্যা নয়। একটু পরেই এসেছে আম। আর তোমার হ্যাশ ফাংশন এর জন্যে ভ্যালু রিটার্ন করেছে ১।

সমস্যাটি নিশ্চয় বুঝতে পারছো। এই সমস্যাকে বলা হয় কলিশন (collision)। এখন তুমি যদি অ্যারের ১ নম্বর ইনডেক্সে আমের দাম রাখো, তাহলে আগের আদার দামের সাথে এটি রিপ্লেস হয়ে যাবে। এতে করে তুমি যদি পরবর্তীতে আদার দাম দাও, তোমার হ্যাশটেবিল আমের দাম দিয়ে দিবে যা হওয়া উচিৎ নয়।

কলিশন সমাধানের উপায় কী হতে পারে? এ সমস্যা সমাধানের আসলে অনেকগুলো উপায় হতে পারে। তবে সবচেয়ে সহজ উপায় হলো, যে সব পণ্যের হ্যাশ ভ্যালু একই সেগুলোকে একই স্লটে রাখা এবং এজন্যে লিংকডলিস্ট ব্যবহার করা।

লিংকডলিস্টের নাম নিশ্চয় শুনেছো এবং আমার ধারণা প্রত্যেকেই ইমপ্লিমেন্ট করেছো। লিংকডলিস্ট হচ্ছে ট্রেনের মতো। একটির পেছনে আরেকটি বগি জোড়া লাগিয়ে তাতে ভ্যালু রাখা।

তবে এতেও একটি সমস্যা আছে। তোমার মুদির দোকানের সবগুলো পণ্য যদি একটি নির্দিষ্ট বর্ণ দিয়ে শুরু হয় তাহলে প্রথম স্লটে একটি বিশাল চেইন হবে। এক্ষেত্রে হ্যাশ টেবিল থেকে কোন পণ্যের দাম খুঁজে আনার সময় আর O(1) থাকবে না বরং সেটি হয়ে যাবে O(n)। কারণ তখন তোমাকে লিংকডলিস্ট থেকে উপাদানটি খুঁজতে হবে। লিংকডলিস্ট থেকে কোন উপাদান খুঁজে বের করতে সময় লাগে O(n)।

h3

উপরের ছবি থেকে নিশ্চয় দেখতে পাচ্ছো সমস্যাটি কোথায়? তোমার অ্যারের বাকি স্লটগুলো প্রায় খালি রয়ে গেছে।
তাহলে এখান থেকে দুটি বিষয় জানা গেলো –
১. হ্যাশ ফাংশন অনেক গুরুত্বপুর্ণ। এটি খুব সিম্পল হলে সমস্যা।
২. প্রত্যেকটি স্লটেই যদি অনেক বড় লিংকলিস্ট থাকে, তাহলে কনস্ট্যান্ট টাইম অর্থাৎ O(‌1) সময়ে তুমি উপাদান খুঁজে বের করতে পারছো না।
এখন যদি তুমি একটি ভালো হ্যাশ ফাংশন লিখতে পারো, এবং প্রত্যেক স্লটেই যাতে বিশাল লিংকডলিস্টের চেইন না হয় তা নিশ্চিত করতে পারো তাহলেই O(‌1) সময়ে হ্যাশ টেবিল থেকে ভ্যালু পড়তে পারবে।

এবার Load Factor বলে একটা টার্ম আছে, এটি নিয়ে একটু বলি তোমাদের। একটি হ্যাশটেবিলের লোড ফ্যাক্টর খুব সহজেই বের করা যায়।

Load Factor = Number of items in the hash table / Total slot in the array
তাহলে তোমার অ্যারেতে যদি স্লট হয় 10 এবং উপাদানের সংখ্যা যদি হয় ৭ তাহলে লোড ফ্যাক্টর হবে- 0.7। এটি দিয়ে একটি হ্যাশটেবলি কতগুলো স্লট ফাকা আছে তা বের করা যায়। একটি হ্যাশটেবিলের লোড ফ্যাক্টর যদি 1 হয় তাহলে এর বোঝায়, এর প্রত্যেকটি স্লটে একটি করে উপাদান রয়েছে। লোড ফ্যাক্টর একের অধিক থাকার অর্থ হলো, টেবিলের কোন স্লটে একাধিক উপাদান রয়েছে।

কনস্ট্যান্ট টাইম অর্থাৎ O(1) সময়ে কোন উপাদান খুঁজে পাওয়া নিশ্চিত করতে চাইলে লোড ফ্যাক্টর সবসময় একের নিচে রাখতে হবে। এটি করার জন্যে যখনই লোড ফ্যাক্টর ১ এর বেশি হবে তখনই টেবিলকে রিসাইজ করে আবার প্রত্যেকটি উপাদানের হ্যাশ ক্যালকুলেট করে বিভিন্ন স্লটে বসাতে হবে। এই অপারেশনটি মোটামুটি এক্সপেনসিভ। তবে তুমি কনস্ট্যান্ট টাইম উপাদানগুলো খুঁজে পাচ্ছো টেবিলের সাইজ যতোই হোক না কেনো।

তাহলে উপরের আলোচনা থেকে নিশ্চয় বুঝতে পারছো যে, যদিও কনস্ট্যান্ট টাইমে আমরা উপাদান খুঁজে বের করতে চাচ্ছি, কিন্তু সবসময় তা সম্ভব নয়। তবে best case এটি অবশ্যই O(1) হবে এবং worst case-এ এটি O(n) হতে পারে।

Facebook Comments

হ্যাশ ফাংশন ১

bazlur_pic
লেখকঃ বজলুর রহমান রোকন।

মনে করো, তুমি একটি মুদি দোকান দিয়েছো। তোমার দোকানে হরেকরকম পণ্যদ্রব্য রয়েছে। এই পণ্যগুলোর নাম ও দাম আলাদা আলাদা। এগুলো মনে রাখতে গিয়ে তুমি হিমশিম খাচ্ছো। তুমি সবগুলো খাতায় লিখে রেখেছো। যখনই তুমি একটি পণ্য বিক্রি করো, তোমাকে সেই খাতা দেখতে হয়। খাতা থেকে খুঁজে বের করতে হয়।

খাতাতে যদি নামগুলো বর্ণানুক্রমে রাখা না থাকে, তাহলে তোমার প্রতিবার খুঁজে বের করতে অনেক সময় লাগে। অ্যালগরিমদ ক্লাসে নিশ্চয় শিখেছো যে এক্ষেত্রে খুঁজে বের করার সময় O(n) । তবে নামগুলো যদি বর্ণানুক্রমে রাখা থাকে তাহলে বাইনারি সার্চ ব্যবহার করা যায় আর তখন সময় লাগবে O(log n)। তুমি নিশ্চয় জানো যে O(n) চেয়ে O(log n) কম সময় লাগে।

img1

যদিও O(log n) কম সময় লাগছে, তবুও কিছুটা সময় লাগছে। সবচেয়ে ভাল হতো যদি কোন সময়ই না লাগতো। তুমি সবগুলো পণ্যের নাম এবং দাম মুখস্থ করে ফেলতে পারতে এবং ক্রেতা কোন পণ্যের নাম বলার সঙ্গে সঙ্গেই তুমি দাম বলে দিতে পারতে।

চলো, তাহলে কিভাবে এই সমস্যার সমাধান করা যায়, তার একটা উপায় বের করে ফেলি। এর জন্যে একটি বিশেষ উপায় আছে যার নাম হ্যাশ ফাংশন। হ্যাশ ফাংশন এমন একটি ফাংশন যাতে একটি স্ট্রিং ইনপুট হিসেবে দিলে তা একটি ইন্টিজার রিটার্ন করে। এই ফাংশন একই স্ট্রিং এর জন্যে সবসময় একই সংখ্যা রিটার্ন করে।

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

মনে করো, তোমার ১০ সাইজের একটি অ্যারে রয়েছে। এখন, ধরো, পেঁপের দাম ২০ টাকা। পেঁপে নামটি যদি হ্যাশ ফাংশনে দাও, তাহলে এটি যদি ৪ রিটার্ন করে, তাহলে অ্যারের চতুর্থ নম্বর ইনডেক্সে পেঁপের দামর রেখে দেবে। এভাবে আদার নাম হ্যাশ ফাংশনে দিলে যদি ৩ রিটার্ন করে, তাহলে তাকে তিন নম্বর ইনডেক্সে রেখে দিলে। এভাবে কলা, মরিচ ইত্যাদি রেখে দিলে। এখন যখন তোমার এগুলো দাম জানার দরকার হয়, তাহলে চট করে হ্যাশ ফাংশনে নামটি দিয়ে তার ইনডেক্সটি বের করে নিলে। অ্যারতে ইনডেক্স জানলে ভ্যালু পড়ে আনা খুব সহজ। অ্যারে থেকে ভ্যালু পরে আনার সময় আসলে O(1) ।
img2

img3
হ্যাশ টেবিল

এখন তুমি নিজে নিজে তোমার প্ছন্দের কোন পোগ্রামিং ল্যাংগুয়েজে এটি ইমপ্লিমেন্ট করে দেখতে পারো। সাধারণত সবগুলো আধুনিক প্রোগ্রামিং ল্যাংগুয়েজে এই ডেটা স্ট্রাকচার তৈরি করে দেওয়া থাকে, তবে এটি সম্পর্কে জানাটা জরুরী। এতে করে তুমি নিশ্চিত করে কোথায় কোথায় ব্যবহার করা যায় বুঝতে পারবে।

উপরের যে উদাহরণটি দিয়েছি তাতে একটি সমস্যা রয়েছে। সেটি নিয়ে পরবর্তীতে আলোচনা করবো। তবে সমস্যাটি তুমি চিন্তা করে যদি খুঁজে বের করতে পারো তাহলে নিচে কমেন্ট করে জানাও।

পরের পর্বঃ হ্যাশ ফাংশন ২।

পাদটিকা: বাইনারি সার্চের টাইম কমপ্লেক্সিটি কিভাবে O(log n) হলো, সেটা না বুঝলে দ্বিমিকের ডিসক্রিট ম্যাথমেটিক্স কোর্সের তৃতীয় ইউনিটের লেকচার দেখে নাও।

Facebook Comments

ফ্লো চার্ট (Flow Chart)

ফ্লো চার্ট (বাংলায় প্রবাহ চিত্র)-এর নাম আমরা সবাই কমে বেশি শুনে থাকি। এখন ফ্লো চার্ট জিনিসটা কী, এমন প্রশ্ন অনেকের মনেই আসে। ফ্লো চার্ট হচ্ছে এক ধরণের ডায়াগ্রাম বা চিত্র যা কোনো অ্যালগোরিদম, কাজের ধারা বা প্রসেস-কে চিত্রের মাধ্যমে বিভিন্ন জ্যামিতিক চিহ্ন বা symbol দ্বারা প্রকাশ করে এবং সেই জ্যামিতিক চিহ্ন বা symbol গুলো তীরচিহ্ন দ্বারা একে অপরের সাথে যুক্ত থাকে।

ফ্লো চার্টের মাধ্যমে একটি প্রোগ্রামের খুঁটিনাটি অংশগুলো খুব সহজেই বুঝানো যায়। যেমনঃ বাড়ি তৈরি করার সময় একজন আর্কিটেক্ট বাড়ির ডিজাইন করে আমাদের খুব সহজেই দেখাতে পারেন যে বাড়িটির কোথায় কী কী জিনিস থাকবে। ফ্লো চার্টের মাধ্যেমেই এই একই কাজই করা হয়। অর্থাৎ, একটি ফ্লো চার্ট বানানোর উদ্দেশ্য হলো একটি প্রোগ্রাম কীভাবে সমাধান করা হয়েছে, সেটি বিভিন্ন ডায়াগ্রাম বা চিহ্নের সাহায্যে অন্যকে বুঝানো।

ফ্লো চার্টের দুইটি প্রকারভেদ আছেঃ

  • ডাটা ফ্লো চার্ট ।
  • প্রসেস ফ্লো চার্ট।

প্রোগ্রামাররা ডাটা ফ্লো চার্ট ব্যবহার করে থাকে। কোন জায়গা থেকে ডাটা আসছে, ডাটা কিভাবে পরিবর্ধন হচ্ছে এবং কোথায় জমা হচ্ছে এসব চিহ্নিত করার জন্য প্রোগ্রামাররা ডাটা ফ্লো চার্ট ব্যবহার করে।

প্রসেস ফ্লো চার্ট কোন প্রসেস বা কাজকে ডকুমেন্ট আকারে দেখানোর জন্য, একটি কাজের কার্যকারিতা বা efficiency বুঝানোর জন্য, কোন প্রশিক্ষণ বা ট্রেনিং এর জন্য ব্যবহার করা হয়।

ফ্লো চার্ট ছোটখাট প্রসেস বা প্রোগ্রামের জন্য ব্যবহার করা হয়ে থাকে। ফ্লো চার্টে সাধারণত দুই ধরণের বাক্স ব্যবহার করা হয়ঃ

  • প্রসেসিং স্টেপঃ এই ধাপকে এ্যাকটিভিটি বা কার্যক্রম ধাপও বলা হয়ে থাকে। একে আয়তাকার বাক্স দ্বারা প্রকাশ করা হয়।
  • ডিসিশন স্টেপ বা সিদ্ধান্ত ধাপঃ এই ধাপকে ডায়মন্ড বা হীরক আকৃতি দ্বারা প্রকাশ করা হয়।

নিচের ছবিতে আমি একটি ফ্লো চার্টের বিভিন্ন আকৃতির পরিচয় দিয়েছিঃ

table

আমরা একটা ছোট্ট উদাহরণের মাধ্যমে ফ্লো চার্টের ব্যাপারটা বোঝার চেষ্টা করি। ধরা যাক, তুমি একজন সৌখিন মানুষ। তোমার শখ গলফ খেলা। তুমি মনে করলে শুক্রবার গলফ খেলতে বের হবে, যদি আবহাওয়া ভাল থাকে। বাংলাদেশে আজকাল আবার হুটহাট বৃষ্টি চলে আসে। তাই বের হওয়ার আগে তুমি আবহাওয়ার সর্বশেষ খোঁজ খবর নিয়ে বের হবে। এর জন্য তোমাকে প্রথমেই যে কাজটি করতে হবে সেটি হলো আবহাওয়ার চ্যানেলে গিয়ে বা মোবাইলের অ্যাপস থেকে weather forecast দেখতে হবে। তারপর সিদ্ধান্ত নিতে হবে, যদি বৃষ্টি হওয়ার সম্ভাবনা থাকে তাহলে তুমি কী করবে আর না থাকলেই বা কী করবে। বৃষ্টি থাকলে তুমি ঘর থেকে বের হবে না আর বৃষ্টি না থাকলে বের হবে। এখন এই পুরো বিষয়টা যদি আমরা ফ্লো চার্টের মাধ্যমে দেখি তাহলে চিত্রটা হবে এমনঃ

sampfc

এই ফ্লো চার্টটিতে প্রথমেই আমরা ফ্লো চার্টের নিয়মানুযায়ী start দিয়ে শুরু করেছি , ওভাল বাক্স দিয়ে সেটিকে চিহ্নিত করেছি। তারপর আমরা ওয়েদার চ্যানেল দেখার কাজটি করেছি। এখানে আমরা প্রসেসিং এর জন্য আয়তাকার চিহ্ন ব্যবহার করেছি, কারণ এখান থেকেই আমরা আমাদের সিদ্ধান্ত বা ডিসিশন নেয়ার ধাপের দিকে যাবো। পরের ধাপে আছে ডিসিশন বা সিদ্ধান্ত ধাপ। সেখানে লেখা আছে “Rain Predicted?”, এখানে লক্ষ্য করে দেখো, ডিসিশন বা সিদ্ধান্ত ধাপে আমাদের অ্যারো বা তীর চিহ্ন আছে দুইটি; যা yes/no দিয়ে চিহ্নিত করা। যদি yes হয় তাহলে আমরা বলছি “Stay Home” এবং সেখান থেকে আরেকটি অ্যারো দিয়ে ফ্লো চার্টটি Stop করে দিচ্ছি। আবার যদি “Rain Predicted”-এ ডিসিশন হয় no, তাহলে আমরা “Play Golf” এর কাজ প্রসেসিং করে Stop ধাপে চলে যাচ্ছি। এখানে মনে রাখার বিষয় যে, ফ্লো চার্চের ডিসিশন সবসময় হয় ডান-বাম অথবা নিচের দিকে যাবে। কখনো উপরের দিকে যাবে না। কারণ, কোন কিছুর Flow সবসময় উপর থেকে নিচের দিকে আসে।

একটি সহজ প্রোগ্রামিং সমস্যার মাধ্যমে আমরা একটি ফ্লো চার্ট তৈরি করার চেষ্টা করি । ধরা যাক, আমরা দুইটি সংখ্যা যোগ করার জন্য একটি প্রোগ্রাম লিখবো। প্রোগ্রামটি হবে এমনঃ

#include<stdio.h>
int main()
{
    int a,b,total;
    scanf("%d %d", &a, &b);
    total = a + b;
    printf("%d\n",total);
    return 0;
}

প্রোগ্রামটির জন্য আমরা যদি ফ্লো চার্ট লিখি তাহলে হবে এমনঃ

enflowchartm_clip_image004

অন্যান্য ফ্লো চার্টের মতই এটা start দিয়ে শুরু হয়েছে। যেহেতু দুইটি নাম্বার ইনপুট নেয়ার দরকার আছে আমাদের, তাই আমরা এখানে Input A, Input B নিয়েছি এবং সেটিকে সামান্তরিক চিহ্নের মাধ্যমে দেখিয়েছি। তবে, আলাদা আলাদা ভাবে এভাবে ইনপুট না নিয়েও পাশাপাশি Input A,B অথবা Read A,B এভাবেও ফ্লো চার্টে ইনপুট নেয়ার কাজটি দেখানো যায়। তারপর আমরা a,b দুইটি যোগ করে একটি Total ভ্যারিয়েবলে রেখেছি এবং এর পরের ধাপে Total প্রিন্ট করেছি। সবশেষে আমরা stop দিয়ে ফ্লো চার্টটি শেষ করেছি।

এবার যদি আমরা লুপ সংক্রান্ত একটি কোডের কথা চিন্তা করি, যেখানে ১ থেকে ১০০ পর্যন্ত বিজোড় সংখ্যা বের করার প্রোগ্রাম লিখতে হবে। প্রোগ্রামটি হবে এমনঃ

#include<stdio.h>
int main()
{
    int i=0;
    while(i<=100)
    {
        if(i%2 != 0)
        {
            printf("%d\n",i);
        }
        i++;
    }
    return 0;
}

এই প্রোগ্রামটিতে আমরা while লুপের সাহায্যে 100 পর্যন্ত লুপটি চালিয়েছি এবং লুপের ভিতরে বিজোড় সংখ্যা বের করার কন্ডিশন দিয়েছি। বিজোড় সংখ্যা বা odd numbers বের করার জন্য if কন্ডিশনটিতে i এর যেসকল মানকে 2 দ্বারা ভাগ করলে ভাগশেষ শূন্য হবে না সেই সংখ্যাগুলোকে আমরা প্রিন্ট করেছি। এই প্রোগ্রামটির ফ্লো চার্টে আমাদের ডিসিশন স্টেপ আসবে দুইটিঃ একটি while এর জন্য এবং একটি if এর জন্য। ফ্লো চার্টটি নিম্নরূপঃ
odd-numsএখানে প্রথমেই আমরা i এর মান 0 এ্যাসাইন করে দিয়েছি, যেহেতু পরবর্তীতে আমরা i এর মান এক করে ইনক্রিমেন্ট করবো। তারপর আমরা while (i<=100) reached ডিসিশন ধাপে গিয়েছি। খেয়াল করে দেখো, এই ডিসিশন থেকে yes/no দিয়ে দুইটি তীর চিহ্ন বের হয়েছে। আমাদের প্রোগ্রামের লজিক আমাদের বলছে যতক্ষণ না i এর মান ১০০ এর সমান বা এর থেকে ছোট থাকছে , ততক্ষণ আমাদের if(i%2 !=0) কন্ডিশন তার কাজ করে যাচ্ছে এবং odd নাম্বার বা বিজোড় সংখ্যাগুলো প্রিন্ট করে যাচ্ছে। একই সাথে লুপটি সামনে এগিয়ে যাচ্ছে, i এর মান compute i= i+1 এ যেয়ে এক এক করে বৃদ্ধি পাচ্ছে। যখন i এর মান 100 এর বড় হয়ে যাবে, তখন ফ্লো চার্ট stop হয়ে যাবে।

প্রশ্ন আসতে পারে, ফ্লো চার্ট ব্যবহার করার সুবিধা কী? প্রবলেম সল্ভিং এর সময় ফ্লো চার্ট ব্যবহার করে আমরা একটি প্রবলেমকে ছোট ছোট অনেকগুলো সুস্পষ্ট ভাগে ভাগ করতে পারি। অনেক সময় দেখা যায়, প্রোগ্রামিং সমস্যা সমাধান করার সময় আমরা খুব গুরুত্বপূর্ণ কোন কিছু বাদ দিয়ে যাচ্ছি। কিন্তু যদি ফ্লো চার্টের মাধ্যমে আমরা আগে প্রবলেমটি analysis করি তাহলে আমাদের খুঁটিনাটি জিনিস বাদ যাওয়ার সম্ভাবনা কমে। সেইসাথে অতিরিক্ত জিনিস, যা আমাদের প্রোগ্রামের requirements এ নেই, সেগুলো বাদ দেয়ার মাধ্যমে একটি প্রোগ্রামকে আরো বেশি efficient করা যায়।

লেখকঃ তামান্না নিশাত রিনি।

Facebook Comments

ভার্টিক্যাল ও হরাইজনটাল স্কেলিং

একটি ওয়েব অ্যাপ্লিকেশন যখন কোনো সার্ভারে রান করে, তখন সেটি মূলতঃ চারটি জিনিসের ওপর নির্ভর করে :

  1. সিপিইউ (CPU) বা প্রসেসিং পাওয়ার
  2. মেমোরি
  3. হার্ড ডিস্ক
  4. নেটওয়ার্ক

screen-shot-2016-11-04-at-12-22-51-pm

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

  1. ভার্টিক্যাল স্কেলিং (Vertical Scaling)
  2. হরাইজনটাল স্কেলিং (Horizontal Scaling)

ভার্টিক্যাল শব্দের বাংলা অর্থ উল্লম্ব বা খাড়া। এখন আমরা একটি বিল্ডিংয়ের কথা চিন্তা করতে পারি। আমরা ১০০ তলা ফাউন্ডেশন দিয়ে একটি বিল্ডিং তৈরি করলাম, কিন্তু শুরুতে মাত্র দশ তলা তৈরি করা হলো। তারপরে আস্তে আস্তে যখন চাহিদা বাড়তে লাগল, তখন সেই বিল্ডিংকে আমরা আরো ওপরের দিকে বাড়াতে পারবো। এটিই হচ্ছে ভার্টিক্যাল স্কেলিং। সার্ভারে ভার্টিক্যাল স্কেলিংয়ের ক্ষেত্রে আমরা আরো উন্নত কনফিগারেশনের সার্ভার ব্যবহার করবো। আমরা যদি অ্যামাজন ওয়েব সার্ভিসের ইসি২ (ec2) ইনস্ট্যান্স টাইপের কথা বিবেচনা করি, সেখানে সর্বনিম্ন কনফিগারেশনের সার্ভার হচ্ছে টি২ ন্যানো (T2 nano) যেখানে মাত্র একটি ভার্চুয়াল সিপিইউ ও মাত্র ৫১২ মেগাবাইট মেমোরি রয়েছে। আবার x1.32xlarge টাইপের সার্ভারে ১২৮টি ভার্চুয়াল সিপিইউ, ১৯৫২ গিগাবাইট মেমোরি রয়েছে। https://aws.amazon.com/ec2/instance-types/ লিঙ্কে গেলে বিস্তারিত জানা যাবে এবং আমরা আমাদের প্রয়োজনমতো কনফিগারেশনের সার্ভার ব্যবহার করতে পারবো, যখন খুশি তখন! তো এই ধরনের স্কেলিংয়ের সুবিধা হচ্ছে, স্কেলিং করা খুব সহজ, অতিরিক্ত কোনো ডিজাইন বা কাজের তেমন প্রয়োজন পড়ে না। আর সীমাবদ্ধতা হচ্ছে সেই ১০০ তালা বিল্ডিংয়ের মতো। যেখানে আমরা স্কেল করতে পারবো ১০০ তলা পর্যন্ত।

আর হরাইজনটাল মানে আনুভূমিক (সহজ বাংলায় বললে সরলরৈখিক বা বরাবর)। ধরা যাক, আমার বিশাল জায়গা রয়েছে। সেখানে একটি দশ তলা বিল্ডিং তৈরি করলাম। এখন আমাকে আরো মানুষের জায়গা দিতে হবে। আমি তখন আরেকটি দশ তলা বিল্ডিং তৈরি করলাম। এভাবে চাহিদা যত বাড়তে থাকবে, আমি ততগুলো বিল্ডিং তৈরি করতে পারবো। অ্যামাজনের ওয়েব সার্ভিস (AWS) ব্যবহার করে এই কাজটি করা যায়। সেখানে আমি লোড ব্যালেন্সার (ELB -> Elastic Load Balancer) ব্যবহার করে বলে দিতে পারি যে সর্বনিম্ন কয়টি ও সর্বোচ্চ কয়টি ইনস্ট্যান্স (সার্ভার) চলবে, এবং তারপরে কিছু নিয়মকানুন বলে দিতে হবে। নিয়মকানুনগুলো এরকম হতে পারে যে, সিপিইউ লোড ৭০% এর চেয়ে বেশি হলে আরো একটি ইনস্ট্যান্স চালু হবে। কিংবা মেমোরি ৮০% এর চেয়ে বেশি হলে আরো একটি ইনস্ট্যান্স চালু হবে। একে বলে স্কেল আপ (scale up)। আবার সিপিইউ লোড ৪০% এর চেয়ে কম হলে এবং মেমোরির ব্যবহার ৫০% এর চেয়ে কম হলে একটি ইনস্ট্যান্স বা সার্ভার বন্ধ করে দেওয়া হবে। একে বলে স্কেল ডাউন (scale down)। এই রুলসগুলো সেট করে দিলে কাজগুলো স্বয়ংক্রিয়ভাবেই হবে। হরাইজনটাল স্কেলিংয়ের সুবিধা হচ্ছে এক্ষেত্রে অনেক বেশি লোড সামাল দেওয়া যায়, এবং যেহেতু স্কেল আপ ও ডাউনের সুবিধা আছে, তাই যখন লোড বেশি তখন বেশি ইনস্ট্যান্স ব্যবহৃত হবে, লোড কম থাকলে কম সংখ্যক ইনস্ট্যান্স ব্যবহৃত হবে। তাই খরচও কম পড়বে অনেক। আর অসুবিধা হচ্ছে এখানে কিছু কনফিগারেশনের ব্যাপার আছে আর আর্কিটেকচারও অন্যভাবে ডিজাইন করতে হবে। অর্থাৎ এক্ষেত্রে একটু লেখাপড়া, জ্ঞানার্জন ও অভিজ্ঞতার প্রয়োজন।

পাদটীকা :

  • ক্লাউডভিত্তিক ওয়েব আর্কিটেকচার সম্পর্কে আরো জানতে হলে গুগলে সার্চ করে বিভিন্ন ব্লগ ও আর্টিকেল পড়তে হবে, ভিডিও দেখতে হবে।
  • অ্যামাজন ছাড়া গুগল, আলিবাবা ও মাইক্রোসফটেরও ক্লাউড সার্ভিস রয়েছে।
  • ওয়েব সম্পর্কে বেসিক ধারণা পাকাপোক্ত করার জন্য রয়েছে দ্বিমিক কম্পিউটিংয়ের ফ্রি অনলাইন কোর্স – ওয়েব কনসেপ্টস্
Facebook Comments

ডাটাবেজ ট্রানজেকশন ও এসিড

রিলেশনাল ডাটাবেজের খুব মৌলিক একটি বিষয় হচ্ছে ডাটাবেজ ট্রানজেকশন। আর ডাটাবেজ ট্রানজেকশনের একটি গুরুত্বপূর্ণ বিষয় হচ্ছে এসিড প্রোপার্টি। আজকের লেখায় এই বিষয়ে আলোচনা করবো।

মনে করি জনি, রবিন, জামাল আর কামাল নামে চার বন্ধুর একই ব্যাংকে একাউন্ট আছে। ওই ব্যাংকের ডাটাবেজে Account নামে একটি টেবিল আছে এবং নিচে আমরা সেই Account টেবিলের ডাটা দেখতে পাচ্ছি –

Account No Account Name Balance
100-01 Jony 15000
100-02 Robin 5000
100-03 Kamal 10000
100-04 Jamal 1200

এবার আমরা নিচের ঘটনাগুলি লক্ষ করি –

  • জনি তার একাউন্ট থেকে ১০০০ টাকা তুলে নিল (Cash Withdraw)
  • একজন রবিনের একাউন্টে ৫০০ টাকা জমা দিল (Cash Deposit)
  • কামাল তার একাউন্ট থেকে ২০০০ টাকা জামালের একাউন্টে পাঠাল (Fund Transfer)
  • জামাল তার একাউন্টে কত টাকা আছে তা জানতে চাইল (Balance Enquiry)

উপরের প্রথম তিনটি ঘটনা Account টেবিলের Balance কলামের ডাটা পরিবর্তন করবে এবং শেষের ঘটনাটি Balance কলামের ডাটা পড়বে। আর রিলেশনাল ডাটাবেজ ম্যানেজমেন্ট সিস্টেমের (RDBMS) পরিপ্রেক্ষিতে এ ধরনের ঘটনাগুলিকে আমরা ডাটাবেজ ট্রানজেকশন (Database Transaction or Transaction) বা ট্রানজেকশন বলি। একটি ডাটাবেজ ট্রানজেকশনে এক বা একাধিক কাজ/ধাপ থাকতে পারে। যেমন, যখন কামাল তার একাউন্ট থেকে ২০০০ টাকা জামালের একাউন্টে পাঠাল তখন দুটি কাজ হবে প্রথমে কামালের একাউন্ট থেকে ২০০০ টাকা কমাতে হবে এবং তারপরে জামালের একাউন্টে ২০০০ টাকা বাড়াতে হবে। প্রতিটি ট্রানজেকশন হয় সফল ভাবে সম্পূর্ণ বা কমিট (Commit) হবে নয়তো রোলব্যাক (Rollback) বা ট্রানজেকশনের পূর্বের অবস্থায় ফেরত যাবে। একটি ট্রানজেকশন ডাটাতে যে পরিবর্তন করে সেই পরিবর্তিত ডাটা ডাটাবেজে স্থায়ী ভাবে রেখে দেয়াকে কমিট (Commit) বলে। আর রোলব্যাক (Rollback) হল ট্রানজেকশনের ফলে ডাটাতে যে পরিবর্তন হয়েছে সেগুলোকে বাদ দিয়ে ডাটাকে ট্রানজেকশন শুরুর পূর্বের অবস্থায় ফিরিয়ে নেয়া। উদাহরণস্বরূপ, আমরা আবার কামালের একাউন্ট থেকে ২০০০ টাকা জামালের একাউন্টে পাঠানর ট্রানজেকশনটি বিশ্লেষণ করি। আমরা জানি এই ট্রানজেকশনে দুটি কাজ করতে হবে। মনে করি প্রথম কাজটি সফল হল অর্থাৎ কামালের একাউন্ট থেকে ২০০০ টাকা কমানো হল, তাহলে কামালের একাউন্টে থাকবে ৮০০০ টাকা (ট্রানজেকশন শুরুর আগে কামালের একাউন্টে ১০০০০ টাকা ছিল)। কিন্তু কোনো কারণে দ্বিতীয় কাজটি মানে জামালের একাউন্টে ২০০০ টাকা বাড়ানো গেল না। সুতরাং এই ট্রানজেকশনটিকে রোলব্যাক করতে হবে এবং রোলব্যাক করার পরে কামালের একাউন্টে আবার ১০০০০ টাকা হয়ে যাবে।

ডাটাবেজ ট্রানজেকশন বা ট্রানজেকশনের নিম্নোক্ত চারটি বৈশিষ্ট্য/ধর্ম আছে –

  • Atomicity (এটমিসিটি)
  • Consistency (কন্সিসটেনসি)
  • Isolation (আইসোলেশন)
  • Durability (ডিউরাবিলিটি)

আর এই চারটি বৈশিষ্ট্যের প্রথম অক্ষর গুলো দিয়ে অর্থাৎ A, C, I এবং D নিয়ে আমরা বলি এসিড (ACID)। ডাটাবেজ ম্যানেজমেন্ট সিস্টেম নিজেই ট্রানজেকশনের এই বৈশিষ্ট্যগুলি পরিচালনা করে এবং অ্যাপ্লিকেশন ডেভেলপারদের আশ্বস্ত করে যে প্রতিটি ট্রানজেকশন সেগুলো মেনে চলবে।

আমারা এই চারটি বৈশিষ্ট্য উদাহরনের মাধ্যমে বোঝার চেষ্টা করি –

Atomicity – ডাটাবেজ ট্রানজেকশনের এই গুনটি নিশ্চিত করে যে, হয় একটি ট্রানজেকশনের সবগুলি ধাপ সফল হবে অথবা কোনটিই হবে না। যেমন, মনে করি, জনি তার বন্ধু রবিনকে ১,০০০ টাকা দিতে চায়। এখন জনির ব্যাংক একাউন্টে ১০,০০০ টাকা আছে আর রবিনের একাউন্টে ৪,০০০ টাকা আছে। তাহলে আমাদেরকে একটি ডাটাবেজ ট্রানজেকশন করতে হবে এবং এই ট্রানজেকশনে আমাদের দুটি কাজ/ধাপ সম্পন্ন করেতে হবে। প্রথমে জনির একাউন্ট থেকে ১,০০০ টাকা কেটে নিতে হবে এবং তারপরে রবিনের একাউন্টে সেই ১,০০০ টাকা যোগ করতে হবে। আমারা এই ট্রানজেকশনটিকে সফল বলব যদি দুটি কাজই সম্পূর্ণ হয়। আর ট্রানজেকশনটি সফল/কমিট (Commit) হলে জনির একাউন্টে থাকবে ৯,০০০ টাকা এবং রবিনের একাউন্টে হবে ৫,০০০ টাকা। এখন যদি কোনও কারণে জনির একাউন্ট থেকে টাকা কেটে নেওয়ার পরে তা রবিনের একাউন্টে যোগ করতে না পারি তাহলে আমাদের ট্রানজেকশনটি সফল/কমিট হবে না। আর ট্রানজেকশনটি সফল না হলে জনির ব্যাংক একাউন্টে ১০,০০০ টাকা এবং রবিনের একাউন্টে ৪,০০০ টাকাই থাকবে অর্থাৎ ট্রানজেকশনটি রোলব্যাক (Rollback) হবে। ডাটাবেজ ট্রানজেকশনের এটমিসিটি বৈশিষ্ট্যটি এই বিষয়টির নিশ্চয়তা দান করে।

Consistency – কন্সিসটেনসি এর বাংলা অর্থ সামঞ্জস্য বা সঙ্গতি অথবা মিল। রিলেশনাল ডাটাবেজ ম্যানেজমেন্ট সিস্টেমে কন্সিসটেনসি দ্বারা আমরা বুঝি যে প্রতিটি ডাটাবেজ ট্রানজেকশনকে ডাটাবেজে নির্ধারিত নিয়মের (Database Constraint) সাথে সামঞ্জস্য রেখে ডাটা পরিবর্তন বা নতুন ডাটা যোগ করতে হবে। আমারা নানাবিধ উপায়ে ডাটাবেজ ট্রানজেকশনের উপরে বাধ্যবাধকতা বা নিয়ম (Database Constraint) নির্ধারণ করতে পারি। যেমন, প্রাইমারি কি (primary key), ফরেন কি (foreign key), ট্রিগার (trigger), ইত্যাদি দ্বারা আমরা ট্রানজেকশনের উপরে বাধ্যবাধকতা বা নিয়ম আরোপ করতে পারি। মনে করি আমাদের একটি Student টেবিল আছে এবং studentId হল এই টেবিলের প্রাইমারি কি। আমরা যখন নতুন একজন স্টুডেন্টের ডাটা যোগ (data insert) করতে যাব তখন ডাটাবেজ পরীক্ষা করে দেখবে যে প্রাইমারি কি নিয়মটি মানা হচ্ছে কিনা। নিচের ছবিতে বিষয়টি দেখানো হল –

studentId name
101 John এই ডাটাটি সফল ভাবে যোগ হবে কারন ডাটাবেজ পরীক্ষা করে দেখবে যে 101 দিয়ে আর কোনও স্টুডেন্ট নেই।
102 Simon এই ডাটাটিও সফল ভাবে যোগ হবে কারন ডাটাবেজ পরীক্ষা করে দেখবে যে 102 দিয়ে আর কোনও স্টুডেন্ট নেই।
101 Jack এই ডাটা আমরা যোগ করতে পারবনা কারন ডাটাবেজ পরীক্ষা করে দেখবে যে 101 দিয়ে আগে থেকেই একজন স্টুডেন্ট আছে। অর্থাৎ এই ডাটাবেজ ট্রানজেকশনটি ডাটাবেজে নির্ধারিত প্রাইমারি কি এর নিয়ম অনুযায়ী সফল হবে না।

এভাবেই ডাটাবেজে নির্ধারিত নিয়মগুলো (Database Constraint) প্রতিটি ট্রানজেকশনের সময় পরীক্ষা করে দেখে যেন ট্রানজেকশনটি নিয়মের ব্যত্তয় না ঘটিয়ে সম্পূর্ণ হয়।

Isolation – আইসোলেশনের আভিধানিক অর্থ হল বিচ্ছিন্নতা। আর এই বৈশিষ্ট্যটি নিশ্চিত করে যে একাধিক ট্রানজেকশন নিরাপদে এবং স্বাধীনভাবে কোনরূপ সংঘর্ষ ছাড়া একই সময়ে সম্পূর্ণ হতে পারে, কিন্তু এটা কোন ট্রানজেকশনটি আগে হবে আর কোনটি পরে হবে অর্থাৎ ক্রম (order) নিশ্চিত করে না। উদাহরণস্বরূপ, মনে করি রনির একাউন্টে ১৫,০০০ টাকা আছে। রনি তার দুই বন্ধু কামাল এবং জামাল কে যথাক্রমে ৩,০০০ ও ২,০০০ টাকার দুটি চেক দিল। কামাল এবং জামাল একসাথে ব্যাংকে গেল টাকা তোলার জন্য। তারা দুজন ব্যাংকের দুজন অপারেটরের কাছে একই সময়ে চেক দুটি জমা দিল। এখানে একই সাথে দুটি ট্রানজেকশন হবে, কিন্তু যেহেতু একই একাউন্ট থেকে টাকা তোলা হবে তাই যে কোনও একটি ট্রানজেকশন আগে হবে এবং অন্যটিকে অপেক্ষা করতে হবে। ধরে নেই জামালের ট্রানজেকশনটি আগে শুরু হল তাই কামালের ট্রানজেকশনটি অপেক্ষা করবে। জামালের ট্রানজেকশনটি সম্পূর্ণ হলে কামালের ট্রানজেকশনটি শুরু হবে। অর্থাৎ জামালের ট্রানজেকশনটি যখন শুরু হবে তখন রনির একাউন্টে আছে ১৫,০০০ টাকা আর ট্রানজেকশনটি শেষ হবার পরে রনির একাউন্টে ১৩,০০০ টাকা থাকবে। আর কামালের ট্রানজেকশনটি যখন শুরু হবে তখন রনির একাউন্টে আছে ১৩,০০০ টাকা আর ট্রানজেকশনটি শেষ হবার পরে রনির একাউন্টে ১০,০০০ টাকা থাকবে। যেহেতু দুটি ট্রানজেকশনই একই ডাটার (রনির একাউন্ট) উপর নির্ভরশীল তাই একটিকে অন্যটি শেষ হবার জন্য অপেক্ষা করতে হচ্ছে। যদি এভাবে না হত তাহলে যে ডাটার উপর ট্রানজেকশনগুলি নির্ভরশীল সেই ডাটা একটা সামঞ্জস্যহীন (inconsistent) অবস্থায় চলে যাবে। আর ডাটা যেন কোনও ভাবেই সামঞ্জস্যহীন না হয় সে জন্যই ট্রানজেকশন আইসোলেশন প্রয়োজন।

ডাটাবেজে চারটি আইসোলেশন লেভেল আছে –

  1. Read Uncommitted
  2. Read Committed
  3. Repeatable Read
  4. Serializable

Read Uncommitted হল আইসোলেশনের সর্বনিম্ন লেভেল আর Serializable হচ্ছে সর্বোচ্চ লেভেল। এই আইসোলেশন লেভেলগুলির কিছু সমস্যা আছে যথা, Dirty Reads, Non Repeatable Reads এবং Phantom। নিচে এগুলোর বর্ণনা দেয়া হল –

Dirty Read – একটি ট্রানজেকশন অন্য ট্রানজেকশনের দ্বারা পরিবর্তিত ডাটা যা কমিট (commit) হয়নি সেগুলো পড়তে পারাকেই ডারটি রিড বলে। উদাহরণ স্বরূপ, মনে করি একজন ক্রেতা একটি কেনাকাটার সাইট থেকে কোনও একটি পণ্য ২৮০ টি কিনতে চাইল, এখন তার জন্য ট্রানজেকশন A শুরু হল। ট্রানজেকশন A প্রথমে দেখবে যে ঐ পণ্যের ২৮০ টি স্টকে আছে কিনা। ধরে নেই সাইটের ডাটাবেজে Product_Inventory নামে একটি টেবিল আছে যাতে পণ্যের পরিমান আছে। তো ট্রানজেকশন A সেই Product_Inventory টেবিল থেকে পেল যে তার ইউজার যে পণ্যটি কিনতে চায় তা ৫০০ টি আছে। সুতরাং ট্রানজেকশন A এই অর্ডারটিকে কনফার্ম করল এবং Product_Inventory টেবিলে ঐ পণ্যটির পরিমান ৫০০ থেকে কমিয়ে ২২০ করে দিল। কিন্তু ট্রানজেকশন A এখনও কমিট হয়নি। একই সময়ে আরও একজন ঐ একই সাইট থেকে ঠিক ঐ পণ্যটি ৪০০ টি কিনতে চাইল। ধরে নেই পরের ক্রেতার জন্য ট্রানজেকশন B শুরু হল। ট্রানজেকশন B দেখল যে ঐ পণ্যটি মাত্র ২২০ টি আছে, তাই সে ক্রেতাকে জানাল যে তার অর্ডারটি নেয়া যাচ্ছে না। এরই মধ্যে আবার ট্রানজেকশন A এর যে ক্রেতা সে অর্ডারটি বাতিল করে দিল, তার ফলে ট্রানজেকশন A রোলব্যাক হয়ে গেল। অর্থাৎ Product_Inventory টেবিলে ঐ পণ্যটির পরিমান আবার ৫০০ হয়ে গেল। তার মানে এখানে ট্রানজেকশন B এমন একটি ডাটা পেয়েছিল যা আসলে কমিট হয়নি আর এটাকেই Dirty Read বলে।

Non Repeatable Read – একটি ট্রানজেকশন যদি একই ডাটা দুবার পড়ে আর দুবার দুটি আলাদা ভ্যালু পায় তাকে Non Repeatable Read বলে। যেমন, মনে করি রবিন একটি কেনাকাটার সাইট থেকে কোনও একটি পণ্য ৩০০ টি কিনতে চাইল, এখন তার জন্য ট্রানজেকশন A শুরু হল। ট্রানজেকশন A প্রথমে দেখবে যে ঐ পণ্যের ৩০০ টি স্টকে আছে কিনা। ধরে নেই সাইটের ডাটাবেজে Product_Inventory নামে একটি টেবিল আছে যাতে পণ্যের পরিমান আছে। তো ট্রানজেকশন A সেই Product_Inventory টেবিল থেকে পেল যে রবিন যে পণ্যটি কিনতে চায় তা ৫০০ টি আছে। একই সময়ে জামাল ঐ একই সাইট থেকে ঠিক ঐ পণ্যটি ২৫০ টি কিনতে চাইল। ধরে নেই জামালের জন্য ট্রানজেকশন B শুরু হল এবং এই ট্রানজেকশনটি Product_Inventory টেবিল থেকে পেল যে ঐ পণ্যের ৫০০ টি স্টকে আছে। এদিকে রবিন তার অর্ডারটিকে কনফার্ম করল তার ফলে ট্রানজেকশন A পণ্যটির পরিমান ৫০০ থাকে কমিয়ে ২০০ করে দিল এবং ট্রানজেকশন A কমিট হয়ে গেল। ওদিকে জামাল তার অর্ডারে একটু পরিবর্তন করল, সে ঐ পণ্যটি বাদ দিয়ে অন্য একটি পণ্য ২৫০ টি কিনতে চাইল। ফলে ট্রানজেকশন B আবার Product_Inventory টেবিল থেকে খুঁজে পেল যে এই পরে অর্ডার দেয়া পণ্যটি মাত্র ১০০ টি রয়েছে। তাই ট্রানজেকশন B জামালকে জানাল যে পরে অর্ডার দেয়া পণ্যটি স্টকে ২৫০ টি নেই, জামাল আবার প্রথমে অর্ডার দেয়া পণ্যটি নিতে চাইল। এবার ট্রানজেকশন B Product_Inventory টেবিল থেকে দেখল যে এই পণ্যের আর ২০০ টি অবশিষ্ট আছে এবং অর্ডারটি নেয়া যাচ্ছে না। অর্থাৎ ট্রানজেকশন B একই ডাটা দুবার পড়ে দুটি ভিন্ন ভ্যালু (পণ্যের দুটি ভিন্ন পরিমান) পেল। ট্রানজেকশন B যে সমস্যাটির মুখে পড়েছে তাকে Non Repeatable Read বলে।

Phantom – মনে করি কেনাকাটার সাইটের ডাটাবেজে Order নামে একটি টেবিল আছে এবং এই টেবিলে সব অর্ডারের ডাটা আছে। এখন একজন জানতে চাইল মোট কতগুলো অর্ডার হয়েছে। তো একটি ট্রানজেকশন A শুরু হল যা কিনা Order টেবিল থেকে মোট কতটি অর্ডার হয়েছে তা বের করবে। এদিকে একই সময়ে অন্য একটি ট্রানজেকশন B নতুন একটি ডাটা Order টেবিলে যোগ করল। এখন যদি ট্রানজেকশন A আবার Order টেবিল থেকে মোট কতটি অর্ডার হয়েছে তা বের করে তাহলে ভিন্ন ভ্যালু পাবে। এই ধরনের ঘটনাকে Phantom বলে। Non Repeatable Read এর সাথে Phantom এর পার্থক্য হচ্ছে এখানে ডাটা ভিন্ন হচ্ছে নতুন ডাটা যোগ করার ফলে বা ডাটা মুছে ফেলার কারণে (insert or delete)।

নিচের টেবিলে কোন আইসোলেশন লেভেলে কোন অসুবিধা গুলো হয় বা হয় না তা দেখানো হল –

Isolation Level Dirty Read Non Repeatable Read Phantom
Read Uncommitted হয় হয় হয়
Read Committed হয় না হয় হয়
Repeatable Read হয় না হয় না হয়
Serializable হয় না হয় না হয় না

Durability – ডিউরাবিলিটি শব্দের মানে স্থায়িত্ব। ডাটাবেজ ট্রানজেকশনের এই ধর্মটি নিশ্চিত করে যে, যখন একটি ট্রানজেকশন সফল হয় তখন তার ফলে যে ডাটা পরিবর্তন হয় তা যেন স্থায়ীভাবে ডাটাবেজে থেকে যায়। এর অর্থ হল, সব ধরনের অঘটন/দুর্ঘটনা সত্ত্বেও (System Failure/System Crash) বা সিস্টেম রিস্টার্ট (System Restart) হলেও সফল ট্রানজেকশনের দ্বারা ডাটাতে যে পরিবর্তন হয়ছে তা স্থায়ী ভাবে ডাটাবেজে সংরক্ষিত থাকবে। যেমন, মনে করি আমাদের একটি বাসের টিকেট বুকিং সিস্টেম আছে। এই বুকিং সিস্টেমে রবিন একটি টিকেট বুকিং দিল এবং তার বুকিংটি সফল হল, আর এরপরেই এই বুকিং সিস্টেমটি বৈদ্যুতিক গোলযোগের (Power Failure) কারণে (System Crash) ক্র্যাশ করল। কিন্তু যেহেতু রবিনের বুকিংটি সফল হয়েছিল তাই বুকিং সিস্টেমটি পুনরায় চালু হবার পরে তার করা বুকিংটি ডাটাবেজে পাওয়া যাবে।

আশা করি লেখাটি ডাটাবেজ ট্রানজেকশন ও এসিড সম্বন্ধে বুঝতে সাহায্য করবে।

লেখকঃ মোঃ শফিউজ্জামান রাজিব, ডাটাবেজ ও বিগ ডাটা প্রফেশনাল।

Facebook Comments

টিডিডি – টেস্ট ড্রিভেন ডেভেলাপমেন্ট

Test Driven Development (TDD)-এর বাংলা অর্থ হচ্ছে টেস্ট চালিত ডেভেলাপমেন্ট। এখানে টেস্ট বলতে সাধারণত সফটওয়্যার টেস্ট (ইউনিট টেস্ট এবং/অথবা ইন্টিগ্রেশন টেস্ট) এবং ডেভেলাপমেন্ট বলতে সফটওয়্যার ডেভেলাপমেন্ট বোঝানো হয়। এটা হচ্ছে সফটওয়্যার ডেভেলাপমেন্ট করার একটি পদ্ধতি। কিছু কিছু বিষয় আছে, যেগুলো নিয়ে সবাই কথা বলতে ভালোবাসে, সবাই হু-হু করে মাথা নাড়ায় যে এটি খুবই ভালো, কিন্তু কেউ আসলে বাস্তব জীবনে বা নিজের জীবনে সেটা অনুসরণ করে না, টিডিডি এমনই এক জিনিস। সারা পৃথিবীতে অনেক সফটওয়্যার ডেভেলাপার এটি নিয়ে কথা বলে, বিভিন্ন কনফারেন্সে আলোচনা হয়, ব্লগ পোস্ট হয়, কিন্তু খুবই কম সংখ্যক সফটওয়্যার ডেভেলাপার এই পদ্ধতি অনুসরণ করে। তাহলে এই বিষয় নিয়ে লিখছি কেন? কারণ দেশে-বিদেশে ইন্টারভিউতে এটি খুবই কমন একটি প্রশ্ন এবং তাই এই বিষয়ে সবার বেসিক ধারণা থাকা উচিত। তারপরে কেউ ব্যক্তিগতভাবে আগ্রহী হলে সে ইন্টারনেট ঘেঁটে টিডিডি সম্পর্কে আরো জেনে নিবে।

টিডিডি পদ্ধতিতে, যখন কোনো রিকোয়ারমেন্ট দেওয়া হয়, তখন সেটি বিশ্লেষণ করে টেস্ট কেইসগুলো আগে বের করা হয়। তারপরে মূল কোড লেখা হয়। একটি উদাহরণের সাহায্যে বিষয়টি ব্যাখ্যা করি।

ধরা যাক, আমাকে কেউ রিকোয়ারমেন্ট দিলো যে, একটি প্রোগ্রাম লিখতে হবে, যেখানে শিক্ষার্থীদের নম্বর ইনপুট দিলে লেটার গ্রেড আউটপুট দেখাবে। তো একটু আলাপ-সালাপ করে আমি রিকোয়ারমেন্ট বুঝে নিলাম এরকম :

  • ৫০ নম্বরের নিচে পেলে ফেইল, অর্থাৎ F গ্রেড।
  • ৫০ থেকে ৫৯ এর মধ্যে নাম্বার পেলে B গ্রেড।
  • ৬০ থেকে ৬৯ এর মধ্যে নাম্বার পেলে B+ গ্রেড।
  • ৭০ থেকে ৭৯ এর মধ্যে নাম্বার পেলে A- গ্রেড।
  • ৮০ থেকে ৮৯ এর মধ্যে নাম্বার পেলে A গ্রেড।
  • ৯০ কিংবা তার বেশি পেলে A+ গ্রেড।

কেউ ল্যাঙ্গুয়েজ ঠিক না করে দিলে আমি পাইথন ব্যবহার করতেই পছন্দ করি, তাই আমার প্রিয় ল্যাঙ্গুয়েজ পাইথনে আমি শুরুতেই একটি ফাংশন লিখে ফেললাম।

def calculate_grade(marks):
    """ Takes marks as input and returns grade as output """
    return "F"

এখন আমি ফাংশনের জন্য টেস্ট কোড লিখে ফেললাম এরকম :

def test_calculate_grade():
    assert calculate_grade(0) == "F"
    assert calculate_grade(30) == "F"
    assert calculate_grade(49) == "F"

তারপরে টেস্ট রান করবো : pytest grade.py। আউটপুট আসবে সব টেস্ট পাশ।

1 passed in 0.01 seconds

কিন্তু সমস্যা হচ্ছে এভাবে কাজ করলে টিডিডি হবে না। টিডিডির ক্ষেত্রে প্রথমে আমার টেস্ট কোড লিখতে হবে, অর্থাৎ test_calculate_grade() ফাংশনটি লিখতে হবে, সেখানে এক বা একাধিক টেস্ট কেইস থাকতে হবে আর তারপরে calculate_grade() ফাংশনটি লেখা হবে। যেই ব্যাপারটি খুবই গুরুত্বপূর্ণ, সেটি হচ্ছে টেস্ট কেস পাশ করানোর জন্য নূন্যতম যতটুকু কোড লেখা দরকার, আমরা ততটুকু কোডই লিখবো। তাহলে আমি প্রথমে ওপরের test_calculate_grade() ফাংশনটি লিখবো, তারপরে নিচের কোড লিখবো।

def calculate_grade(marks):
    """ Takes marks as input and returns grade as output """
    pass

এবারে টেস্ট রান করাবো (সেই আগের কমান্ড pytest grade.py)। আউটপুট আসবে এমন :

>       assert calculate_grade(0) == "F"
E       assert None == 'F'
E        +  where None = calculate_grade(0)
grade.py:9: AssertionError

তাহলে দেখা যাচ্ছে, প্রথমে আমার কোডে কিছু নেই, তাই 0 নম্বর পাওয়ার পরেও F রিটার্ন না করে None রিটার্ন করছে। তাহলে এই কেস পাশ করানোর জন্য এখন আমি ফাংশনটি আপডেট করবো :

def calculate_grade(marks):
    """ Takes marks as input and returns grade as output """
    return "F"

এবারে টেস্ট রান করলে তিনটি টেস্ট কেইসই পাশ করবে। এখন আমি B গ্রেডের জন্য দুইটি টেস্ট কেইস যুক্ত করবো।

def test_calculate_grade():
    assert calculate_grade(0) == "F"
    assert calculate_grade(30) == "F"
    assert calculate_grade(49) == "F"
    assert calculate_grade(50) == "B"
    assert calculate_grade(59) == "B"

এখন টেস্ট রান করলে আউটপুট আসবে এরকম :

>       assert calculate_grade(50) == "B"
E       assert 'F' == 'B'
E         - F
E         + B

grade.py:12: AssertionError

এখন এই টেস্ট কেস পাশ করাতে হবে। এজন্য আমরা এভাবে প্রোগ্রাম লিখবো :

 def calculate_grade(marks):
    """ Takes marks as input and returns grade as output """
    if marks < 50:
        return "F"
    else:
        return "B"

এখন টেস্ট রান করলে সবগুলো কেস পাশ করবে। এখন বাকী সব কেস যোগ করে ফেলবো।

 def test_calculate_grade():
    assert calculate_grade(0) == "F"
    assert calculate_grade(30) == "F"
    assert calculate_grade(49) == "F"
    assert calculate_grade(50) == "B"
    assert calculate_grade(59) == "B"
    assert calculate_grade(60) == "B+"
    assert calculate_grade(69) == "B+"
    assert calculate_grade(70) == "A-"
    assert calculate_grade(79) == "A-"
    assert calculate_grade(80) == "A"
    assert calculate_grade(89) == "A"
    assert calculate_grade(90) == "A+"
    assert calculate_grade(100) == "A+"

এখন একটা একটা করে টেস্টকেস পাশ করানোর জন্য আমি কোড লিখতে থাকবো, এবং প্রতিটি টেস্ট কেস পাশ করে কি না, সেটি দেখার জন্য প্রতিবার টেস্ট রান করাবো। একসময় আমার কোড সব টেস্ট কেস পাশ করবে এবং তখন সেটি দেখতে নিচের মতো হবে :

 def calculate_grade(marks):
    """ Takes marks as input and returns grade as output """
    if marks < 50:
        return "F"
    elif marks < 60:
        return "B"
    elif marks < 70:
        return "B+"
    elif marks < 80:
        return "A-"
    elif marks < 90:
        return "A"
    else:
        return "A+"

এভাবে দেখতে দেখতে আমার কোডটি সম্পূর্ণ তৈরি হয়ে গেল। টেস্ট ড্রিভেন ডেভেলাপমেন্টকে অনেক সময় টেস্ট ফার্স্ট ডেভেলাপমেন্টও বলা হয়, কারণ এখানে প্রথমে টেস্ট কেস লিখতে হয়। টিডিডি-এর মূল ধারণা নিচের সহজ ছবিটির মাধ্যমেও মনে রাখা যায়:

image_thumb3
Test Driven Development (collected from the Internet)

আশা করি টেস্ট ড্রিভেন ডেভেলামপেন্টের ধারণা অনেকেরই কাজে লাগবে চাকরির ইন্টারভিউতে এবং কেউ কেউ হয়ত তার প্রজেক্টে এর প্রয়োগ শুরু করে দিবে। এখন একটি বিষয়। কেউ যদি ৫৯.৫ বা এরকম নাম্বার পায়, তখন তার গ্রেড কী হবে? এটি রিকোয়ারমেন্টে বলা নাই। কিন্তু পরে জানা গেল যে ভগ্নাংশ হলে সেটিকে সিলিং (ceiling) করতে হবে, মানে ৫৯ এর চেয়ে বড় কিন্তু ৬০-এর চেয়ে ছোট সব সংখ্যাকে ৬০ ধরতে হবে। তাহলে এখন আমরা যদি নিচের টেস্টকেস যোগ করি, তাহলে টেস্ট ফেইল করবে:

assert calculate_grade(59.3) == "B"

এই টেস্ট কেসের মতো আরো টেস্ট কেস তৈরি করা এবং সেগুলো পাশ করানোর কাজটুকু পাঠককে দেওয়া হলো।

Facebook Comments

লোড টেস্টিং

একটি সফটওয়্যারের লোড টেস্টিং (load testing) বলতে বোঝায়, সফটওয়্যারটি কতটুকু লোড নিতে পারে। লোড টেস্টিংকে আধুনিক বাংলায় অনুবাদ করলে দাঁড়ায় চাপ সামলাও, কিন্তু যেহেতু এটি একটি পরিচিত টার্ম, তাই আমরা লোড টেস্টিংই বলবো। লোড টেস্টিং যে কেবল সফটওয়্যারের হয় এমন নয়, লিফট, গাড়ি, রড ইত্যাদি অনেক কিছুরই লোড টেস্টিং করা হয়। সফটওয়্যার ক্ষেত্রে আবার বিভিন্ন রকম সফটওয়্যারের জন্য লোড টেস্টিং ভিন্ন অর্থ বহন করে। আমি যদি একটি ফাইল প্রসেসিং সফটওয়্যার নিয়ে কাজ করি, তাহলে সেটির জন্য খুব বড় ফাইলে কাজ করতে দিয়ে লোড টেস্টিং করা যায়। একটি ভিডিও প্রসেসিং সফটওয়্যার কত বড় ভিডিও নিয়ে কাজ করতে পারে, সেটিও একটি লোড টেস্ট হতে পারে ওই সফটওয়্যারের জন্য। কিন্তু আমি আলোচনা করবো ওয়েব সার্ভিস বা ওয়েব এপিআই-এর লোড টেস্টিং নিয়ে। এক্ষেত্রে লোড বলতে বোঝাবে, একসাথে কয়টি ক্লায়েন্ট-এর লোড ওই ওয়েব সার্ভিস সামলাতে পারে।

[এই লেখাটি যারা ওয়েব প্রোগ্রামিংয়ের সঙ্গে পরিচিত, তাদের জন্য। যাদের ওয়েব সম্পর্কে একেবারেই ধারণা নেই, তারা দ্বিমিকের ওয়েব কনসেপ্টস্ নামক ফ্রি অনলাইন কোর্সটি করে ফেলতে পারে।]

একসাথে কয়টি ক্লায়েন্ট আমার ওয়েব সার্ভিস ব্যবহার করতে পারে, এই তথ্য বের করে আমি কী করব? ক্লায়েন্ট মানে হচ্ছে ইউজার। তো আমি যদি এমন কিছু তৈরি করি, যেটি হাজার হাজার ইউজার একই সময়ে ব্যবহার করবে, তাহলে আমার আগে থেকে জানা থাকতে হবে যে আমার ওয়েব সার্ভিস একসাথে কতজন ব্যবহার করতে পারবে এবং আমি যদি জানি যে কতজন ক্লায়েন্ট বা ব্যবহারকারী ওয়েব সার্ভিসটি ব্যবহার করবে, আমি সেই অনুযায়ী ব্যবস্থা নিতে পারবো। যেমন আমি যদি আমার স্কুলের পরীক্ষার ফলাফল দেখার করার জন্য একটি সিস্টেম তৈরি করি যেখানে ওয়েব বা মোবাইল অ্যাপ ব্যবহার করে শিক্ষার্থীরা তাদের পরীক্ষার ফলাফল দেখতে পাবে, তাহলে আমার জানতে হবে স্কুলে মোট কতজন শিক্ষার্থী আছে। আর ফলাফল যেহেতু একই সময়ে প্রকাশ করা হবে, তাই সবাই সম্ভবত একই সময়ে অ্যাপ বা ওয়েবসাইট দিয়ে ফলাফল দেখতে চাইবে। স্কুলের শিক্ষার্থীর সংখ্যা যদি ৩০০০ হয়, তাহলে আমার এই অ্যাপ ও ওয়েবসাইটের পেছনে যে ওয়েবসার্ভিসটি আছে, সেটি ওই ৩০০০ ব্যবহারকারীর লোড সামলাতে পারতে হবে। আবার আমি যদি এসএসসি পরীক্ষার ফলাফলের ওয়েবসাইট ও অ্যাপ তৈরি করি, তাহলে সেই সিস্টেমের যে ওয়েব সার্ভিস থাকবে, তাকে একসাথে পনের লক্ষ ব্যবহারকারীর চাপ সামলানোর জন্য প্রস্তুতি নিতে হবে। তাই লোড টেস্ট করাটা খুবই গুরুত্বপূর্ণ।

ধরা যাক, আমার একটা এপিআই আছে, যেখানে শিক্ষার্থীর রোল নাম্বার ইনপুট দিলে পুরো রেজাল্ট আউটপুট দিবে। সেই এপিআইটা আমি লোড টেস্ট করতে চাই। কীভাবে করব?

প্রথম পদ্ধতি হচ্ছে, আমি আমার কম্পিউটার থেকে বিভিন্ন রোলনাম্বার দিয়ে ওই এপিআই কল করতে পারি। একই সময়ে অনেকবার কল করবো কীভাবে? মাল্টিথ্রেডিং ব্যবহার করে আমরা এমন একটি প্রোগ্রাম লিখতে পারি। তবে সেটি আসলে করার দরকার হবে না, কারণ ইতিমধ্যে এরকম অনেক টুলস পাওয়া যায়। আমি যেমন কয়েকমাস আগে Vegeta নামক একটি টুল ব্যবহার করেছি। এটি ওপেন সোর্স তাই সোর্সকোড দেখলে ধারণা করা যাবে যে লোড টেস্টিং টুলস কিভাবে তৈরি করতে হয়। আরেকটি টুল আছে, jMeter নাম (এটিও ওপেন সোর্স), যেটি আরো ৫ বছর আগে জাতীয় বিশ্ববিদ্যালয়ের ফল প্রকাশের কাজের সময় ব্যবহার করেছিলাম। সেই অভিজ্ঞতা জানা যাবে এই লেখায় : ওয়েবসাইট বিপর্যয় ও মুক্তি উপায়

এখন আমি আমার কম্পিউটারে কোনো একটা টুলস ব্যবহার করে লোড টেস্টিং করে ফেললাম। কিন্তু এখানে দুটি সমস্যা আছে:

  1. প্রতিটি কম্পিউটারেরই একসাথে ওয়েব রিকোয়েস্ট করার (বা ওয়েব সার্ভিসকে কল করার) একটি সীমাবদ্ধতা থাকে, একটি নির্দিষ্ট সংখ্যার বেশি রিকোয়েস্ট একসাথে পাঠানো যায় না।
  2. দ্বিতীয় সমস্যা হচ্ছে নেটওয়ার্কের গতির সীমাবদ্ধতা। ঢাকায় আমার বাসার কিংবা অফিসের ইন্টারনেট যথেষ্ট গতিসম্পন্ন নয়।

তাই, আমাকে যেটি করতে হবে, একসাথে অনেকগুলো কম্পিউটার যোগাড় করে একসাথে লোড টেস্টিং শুরু করতে হবে। তাহলে আমি যদি ১০টি কম্পিউটার ব্যবহার করি, তাহলে ১০ গুণ লোড তৈরি করতে পারার কথা। কিন্তু সবাই যদি একই নেটওয়ার্কে থাকে, তাহলে এক্ষেত্রেও আমি নেটওয়ার্কের সীমাবদ্ধতার কারণে আটকে যাবো। তাহলে করণীয় কী?

আমরা ভিপিএস ব্যবহার করে এই লোড টেস্টিংয়ের কাজ করতে পারি। কারণ ভিপিএসগুলো খুবই দ্রুতগতির নেটওয়ার্কে থাকে এবং আমরা আমাদের প্রয়োজনীয়সংখ্যক (১০০টা দরকার হলে ১০০টা) ভিপিএস চালু করতে পারি। জেমিটার (jMeter) সফটওয়্যারটি একসাথে অনেক কম্পিউটারে বা সার্ভারে ইনস্টল করে কনফিগার করা যায় যেন একই সময়েে অনেকগুলো সার্ভার থেকে রিকোয়েস্ট পাঠানো যায়।

ওপরের কাজগুলো বেশ ঝামেলাসাপেক্ষ। তাই আজকাল অনেক সার্ভিস চালু হয়েছে যারা আমার হয়ে লোড টেস্ট করে দিবে। যেমন : loader.io (এরকম আরো আছে, গুগল সার্চ করলেই পাওয়া যাবে)। এসব সার্ভিস তাদের প্রয়োজনমতো কম্পিউটার ব্যবহার করবে, আমার কেবল সার্ভিসটি ব্যবহার করতে জানতে হবে।

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

Facebook Comments

ইউনিট টেস্টিং

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

ইউনিট টেস্ট কিভাবে করে? ফাংশন লেখার পরে ওই ফাংশনের জন্য আলাদা একটি ফাইলে আরেকটি ফাংশন লিখতে হবে যেটি বিভিন্ন ইনপুট প্যারামিটারের মাধ্যমে ওই ফাংশনকে কল করবে। তারপরে আউটপুট মিলিয়ে দেখতে হবে যে আমরা যেই আউটপুট আশা করছি আর ফাংশনটি যেই আউটপুট দিচ্ছে – দুটি সমান কী না। ব্যাস, আমাদের ইউনিট টেস্ট হয়ে গেল। ইন্ডাস্ট্রিতে প্রচলিত সব প্রোগ্রামিং ল্যাঙ্গুয়েজেই ইউনিট টেস্ট সহজ করার জন্য বিভিন্ন প্যাকেজ তৈরি করা থাকে। যদিও এসব প্যাকেজ ব্যবহার না করেও ইউনিট টেস্ট করা যায়, যেহেতু প্যাকেজ তৈরি করে দেওয়া আছে, তাই প্যাকেজ ব্যবহার না করার কোনো কারণ নেই। আমরা এখন পাইথনে একটি সহজ উদাহরণ দেখবো।

পাইথনে unittest নামে একটি বিল্ট-ইন মডিউল রয়েছে যেটি ব্যবহার করে ইউনিট টেস্ট করা যায়। কিন্তু আমরা ব্যবহার করবো pytest কারণ এটি ব্যবহার করা অনেক বেশি সহজ। তবে এটি আলাদাভাবে ইনস্টল করতে হয়। কীভাবে ইনস্টল করতে হয়, সেটি ওদের অফিশিয়াল ডকুমেন্টশন থেকে দেখে নিতে হবে, এই লেখা পড়ার জন্য পাইটেস্ট ইনস্টল করার দরকার নেই, পরে করলেও হবে (কারণ এই লেখার উদ্দেশ্য হচ্ছে ইউনিট টেস্টিং সম্পর্কে প্রাথমিক ধারণা দেওয়া)। আরেকটি জিনিস জানতে হবে, সেটি হচ্ছে assert স্টেটম্যান্ট। assert এর পরে কোনো কিছু লিখলে পাইথন সেটা চালিয়ে দেখে এবং ফলাফল হয় True না হয় False হয়। ফলাফল False হলে পাইথন AssertionError এক্সেপশন দেয়।

ধরা যাক, আমাকে একটি প্রোগ্রাম লিখতে বলা হলো, যেটি ইনপুট হিসেবে একটি বছর নেবে এবং বছরটি লিপ ইয়ার কী না, সেটি বলে দেবে। লিপ ইয়ার হলে True আর লিপ ইয়ার না হলে False রিটার্ণ করবে। আমি জানি যে, কোনো সালকে যদি 4 দিয়ে ভাগ করলে ভাগশেষ শূণ্য হয়, তাহলে সেটি লিপ ইয়ার। তো আমি ঝটপট পাইথনে সেটি লিখে ফেললাম :

def is_leap_year(year):
        """This functon returns True if year is a leap year, returns False otherwise"""
        if year % 4 == 0:
                return True
        return False

এখন এই ফাংশনের জন্য ইউনিট টেস্ট লিখব :

def test_is_leap_year():
        assert is_leap_year(2016) == True
        assert is_leap_year(2015) == False

আমি আমার প্রোগ্রাম leapyear.py নামে সেভ করলাম। এখন pytest রান করাবো।

 tamimshahriar$ pytest leapyear.py 

======= test session starts========

platform darwin -- Python 3.5.1, pytest-3.0.3, py-1.4.31, pluggy-0.4.0

rootdir: /Users/tamimshahriar/work/practice/pypractice, inifile: 

collected 1 items 

leapyear.py .

======= 1 passed in 0.01 seconds =====

ওপরে দেখতে পাচ্ছি যে আমার টেস্ট ঠিকঠাকভাবে পাশ করেছে, কোনো সমস্যা নেই। এখন আমি খোঁজখবর নিয়ে জানলাম যে 2100 সাল নাকি আসলে লিপইয়ার না, কারণ সালটা যদি 100 দিয়ে বিভাজ্য হয়, সেটা 400 দিয়েও বিভাজ্য হতে হবে। তাহলে আমি এই টেস্ট কেইসটি আমার টেস্টে যোগ করে আবার টেস্ট রান করবো। এখন আমার টেস্ট ফাংশনটি হবে এরকম :

def test_is_leap_year():
        assert is_leap_year(2016) == True
        assert is_leap_year(2015) == False
        assert is_leap_year(2100) == False

এখন আবার টেস্ট রান করি : pytest leapyear.py, আউটপুট আসবে এরকম :

========= FAILURES ===========
_______ test_is_leap_year __________

    def test_is_leap_year():
        assert is_leap_year(2016) == True
        assert is_leap_year(2015) == False
>       assert is_leap_year(2100) == False
E     assert True == False
E     +  where True = is_leap_year(2100)

leapyear.py:10: AssertionError

===== 1 failed in 0.03 seconds =====

কোন টেস্ট কেইস ফেইল করেছে সেটা একটা তীরচিহ্ন দিয়ে দেখানো হয়েছে। এখন আমি আমার অরিজিনাল ফাংশনের কোড ঠিক করলে টেস্ট কেস পাশ করবে (পাঠকদের সেটি করার পরামর্শ দেওয়া হলো)।

ইউনিট টেস্ট করার সময় বিভিন্ন ধরনের কেস টেস্ট করা উচিত। ইউনিট টেস্টের সুবিধা হচ্ছে :

  • যে কেউ কোড দেখার আগেই ইউনিট টেস্ট দেখে ধারণা করতে পারবে যে ফাংশনটা আসলে কিভাবে ব্যবহার করতে হয়।
  • ইউনিট টেস্টের কেসগুলো দেখলে বোঝা যায় যে কোনো বিশেষ কেস মিস হয়ে গেল কী না আর তখন সেই কেস যোগ করে টেস্ট রান করলে বোঝা যাবে সেই কেসের জন্য ফাংশনটি ঠিকভাবে আউটপুট দিচ্ছে কী না।
  • অন্যকেউ যদি ফাংশনে কোনো পরিবর্তন করে তাহলে অনেক সময় ফাংশনে অনাকাঙ্ক্ষিত বাগ চলে আসতে পারে। সেক্ষেত্রে যদি ফাংশনের ইউনিট টেস্ট ঠিকঠাক লেখা থাকে, তাহলে বাগ ঢুকে যাওয়ার সম্ভাবনা অনেক কমে যায়। কারণ বাগ ঢুকলে ইউনিট টেস্ট ফেইল করবে (যদি ওই কেসটি আগে থেকে ইউনিট টেস্টে লেখা থাকে)।

এই লেখায় ইউনিট টেস্টের একেবারে প্রাথমিক বিষয়গুলো লেখলাম। ইউনিট টেস্ট ঠিকভাবে লেখা শিখতে অনেক সময়, ধৈর্য্য ও পরিবেশের প্রয়োজন। আমি এখন এটি ভালোভাবে শেখার চেষ্টা করছি। ভবিষ্যতে এই বিষয়ে আরো লিখার ইচ্ছা রইল। আরেকটা শেষ কথা বলা প্রয়োজন যে, ইউনিট টেস্ট লেখা কিন্তু ডেভেলাপারের কাজ ও দায়িত্ব, সফটওয়্যার টেস্টিং কিংবা কোয়ালিটি অ্যাশিউরেন্স টিমের কারো নয়।

Facebook Comments

ডাটাবেজ নরমালাইজেশন

ডাটাবেজ নরমালাইজেশন (normalization) কী জিনিস? এক কথায় আসলে উত্তর দেওয়া সম্ভব নয়। তাই বরং আসুন, আমরা বিষয়টি নিয়ে একটু বিস্তারিত আলচনা করি। কোনো কিছুকে নরমালাইজ (normalize) করার অর্থ হচ্ছে সেটিকে স্বাভাবিক (normal) অবস্থায় নিয়ে আসা। তো ডাটাবেজের ক্ষেত্রে এই নরমালাইজেশনের অর্থ হচ্ছে ডাটাবেজকে এমন অবস্থায় নিয়ে আসা যেন ডাটা রিডানডেন্সি (data redundancy) না থাকে এবং ডাটা ইন্টিগ্রিটি (data integrity) বজায় থাকে। এই যে এখন আবার নতুন দুটো জিনিস চলে এল, ডাটা রিডানডেন্সি ও ডাটা ইন্টিগ্রিটি। এগুলো আবার কী জিনিস?

ডাটা রিডানডেন্সি – ইংরেজিতে redundant শব্দের অর্থ হচ্ছে প্রয়োজনের অতিরিক্ত। আমাদের ডাটাবেজ ডিজাইনের সময় একটি ব্যাপারে লক্ষ রাখতে হবে যেন আমরা প্রয়োজনের অতিরিক্ত ডাটা না রাখি। অনেক সময়ই একই ডাটা বারবার বিভিন্ন টেবিলে এমনভাবে আসে, যেখানে টেবিলগুলো একটু অন্যভাবে ডিজাইন করলেই অনেক ডাটা বেঁচে যেত। ডাটাবেজ নরমালাইজ করার মাধ্যমে আমরা নিশ্চিত করি যে ডাটাবেজে রিডানডেন্ট ডাটা থাকছে না।

ডাটা ইনটিগ্রিটি – Integrity শব্দের অর্থ হচ্ছে শুদ্ধতা। অনেক সময় ডাটাবেজে বিভিন্ন কারণে (হার্ডওয়্যারের ত্রুটি কিংবা সফটওয়্যারের সমস্যা বা ডাটাবেজ ডিজাইনের সমস্যা) ডাটায় ভেজাল ঢুকে যায়। এই ভেজাল আবার কী জিনিস? ধরা যাক কোনো একভাবে হিসেব করলে একজন শিক্ষার্থীর মোট নাম্বার হয় ৫৪৬, আবার আরেকভাবে (যেমন অন্য কোনো টেবিল থেকে ডাটা নিয়ে) হিসেব করলে মোট নাম্বার হয় ৫৫৫। তার মানে ডাটাতে ভেজাল ঢুকে গিয়েছে বা ডাটা তার শুদ্ধতা হারিয়ে ফেলেছে। নরমালাইজেশন করলে ডাটার শুদ্ধতা বজায় থাকার সম্ভাবনা বেড়ে যায় অনেক।

এখন, নিচের উদাহরণগুলো দিয়ে নরমালাইজেশন বিষয়টি বোঝার চেষ্টা করি –

fig1

উপরের টেবিলটিতে কোনো নরমালাইজেশন নেই। এই টেবিলে নতুন ডাটা যোগ করতে (data insert), পুরনো ডাটা পরিবর্তন (data update) করতে এবং ডাটা মুছে ফেলতে (data delete) আমাদের কিছু অসুবিধা হবে (সেগুলোকে নরমালাইজেশন দ্বারা দূর করা যায়)। যেমন, আমরা যদি নতুন একজন স্টুডেন্ট এই টেবিলে যোগ করতে চাই যে কোনো সাবজেক্টই নেয় নি, তাহলে subject কলামে NULL ভ্যালু যাবে। আবার আমারা যদি একজন স্টুডেন্ট এর সাবজেক্ট বাড়াতে বা কমাতে চাই তাহলে আমরা খুব সহজে তা করতে পারব না, কারণ subject কলামে ডাটা কমা দিয়ে আলাদা করা আছে।

এখন আমরা Student টেবিলটিকে First normal form (1NF) নিতে চাই। First normal form (1NF) এর শর্ত হচ্ছে টেবিলের সব কলামের ভ্যালু একক (atomic) হতে হবে। আমারা দেখতে পাচ্ছি যে subject কলামের ডাটা একক (atomic) নয়। নিচে দেখানো উপায়ে আমরা Student টেবিলটিকে পরিবর্তন করে First normal form (1NF) এ নিলাম –

fig2

এখন Student টেবিলের সব কলামের ভ্যালু একক (atomic) হয়েছে। এবার আমারা দেখতে পাচ্ছি যে, একই ডাটা বার বার আসছে। শুধুমাত্র subject কলামের ডাটা পরিবর্তন হচ্ছে।

আমারা এবার Second normal form (2NF) এ আমদের Student টেবিলটিকে নিয়ে যাব। এর জন্য নিচের শর্ত দুটি পূরণ করতে হবে –
১) টেবিলটি First normal form (1NF) এ থাকতে হবে
২) কোনও non-prime অথবা non-key attribute, candidate key এর subset এর উপর নির্ভরশীল হতে পারবে না।

[candidate key মানে এমন কলাম বা কলামের সমষ্টি যা একটি টেবিলের প্রতিটি রেকর্ড কে আলাদা ভাবে চিহ্নিত করতে পারে। একটি টেবিলের এক বা একাধিক candidate key থাকতে পারে। এর মধ্যে একটি বিশেষ candidate key কে আমরা primary key বলি। যে attribute/column কোনও candidate key এর অংশ নয় তাকে non-prime attribute অথবা non-key attribute বলে।]।

আমদের Student টেবিলটি First normal form (1NF) এ আছে। আমাদের দ্বিতীয় শর্তটি পূরণ করতে হবে। Student টেবিল থেকে আমরা লক্ষ করি যে, {studentId, subject} কলাম দুটি মিলে হচ্ছে একটা candidate key এবং name, age, postCode, city কলামগুলো হচ্ছে non-prime attribute।

এখন name, age, postCode, city কলামগুলি শুধুমাত্র studentId কলামের উপর নির্ভরশীল এবং studentId হল candidate key: {studentId, subject} এর একটি subset।

আমরা Student টেবিলটিকে নিচের মত করে Second normal form (2NF) এ নিতে পারি। আমারা একটি নতুন টেবিল Student_Subject তৈরি করলাম স্টুডেন্ট এবং সাবজেক্ট এর মধ্যে সম্পর্ক ঠিক রাখার জন্য।

fig3

তাহলে আমাদের ডাটাবেজ এখন Second normal form (2NF)-এ চলে আসল। এবারে আমরা শেষ ধাপে যাব এবং একে Third normal form (3NF)-এ নেব। যার মাধ্যমে আমাদের নরমালাইজেশন করার প্রক্রিয়াটি সম্পন্ন হবে।

Third normal form (3NF) এ নেওয়ার জন্য আমদের নিচের দুটি শর্ত পূরণ করতে হবে –
১) টেবিল Second normal form (2NF) এ থাকতে হবে
২) কোনো Transitive functional dependency থাকতে পারবে না

[Transitive functional dependency – মনে করি একটি টেবিলের প্রাইমার‍ি কি (primary key) হচ্ছে A এবং এই টেবিলের দুটি নন-প্রাইম (non-prime) কলাম হচ্ছে B এবং C, যেখানে C কলামের ভ্যালু যতটা A কলামের ভ্যালুর উপরে নির্ভরশীল তার চাইতে B কলামের ভ্যালুর উপর বেশি নির্ভরশীল, আবার B কলামের ভ্যালু A কলামের ভ্যালুর উপরে সরাসরি নির্ভরশীল, তাহলে আমরা বলতে পারি যে C কলাম transitively কলাম A এর উপর নির্ভরশীল। ওই যে, ছাগল ঘাস খায়, মানুষ ছাগল খায়, তার মানে মানুষ ঘাস খায় – এরকম লজিক আর কী।]

আমাদের Student টেবিলটিতে studentId হচ্ছে প্রাইমার‍ি কি (primary key) এবং postCode আর city হচ্ছে দুটি নন-প্রাইম (non-prime) কলাম। আমরা লক্ষ করি যে, city কলামটি যতটা studentId কলামের উপরে নির্ভরশীল তার চাইতে বেশি নির্ভরশীল postCode কলামটির উপরে এবং postCode কলামটি আবার studentId কলামের উপরে সরাসরি নির্ভরশীল। সুতরাং আমরা বলতে পারি যে city কলামটি transitively কলাম studentId এর উপর নির্ভরশীল।

তাই Student টেবিলটিকে Third normal form (3NF)-এ নিতে নিচের মতো পরিবর্তন করতে পারি এবং PostCode_City নামে একটি নতুন টেবিল তৈরি করতে পারি –

fig4

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

লেখক – মোঃ শফিউজ্জামান রাজিব, বিগডাটা প্রফেশনাল।

Facebook Comments