কম্পিউটার টিউটোরিয়াল

রুবিতে স্টেট মেশিন দক্ষতা অর্জন: একটি প্র্যাক্টিক্যাল গাইড

একটি স্টেট মেশিন কোনো কিছুর সমস্ত সম্ভাব্য স্টেট এবং সেই স্টেটগুলোর মাঝে অনুমোদিত ট্রানজিশন ধারণ করে। উদাহরণস্বরূপ, একটি দরজার স্টেট মেশিনে মাত্র দুটি স্টেট থাকবে (open এবং closed) এবং দুটি ট্রানজিশন (opening এবং closing)।

অন্যদিকে, জটিল স্টেট মেশিনে শত শত ট্রানজিশন সহ একাধিক ভিন্ন স্টেট থাকতে পারে। চারপাশে তাকালে ফাইনাইট স্টেট মেশিন পাবেন—ওয়েবসাইট থেকে কেনাকাটা, ভেন্ডিং মেশিন থেকে চিপস কেনা, বা এটিএম থেকে টাকা উত্তোলন।

এই পোস্টে রুবিতে স্টেট মেশিন সেট আপ করা এবং state_machines জেম ব্যবহার করা দেখানো হয়েছে।

ডেভেলপমেন্টে স্টেট মেশিনের প্রয়োজনীয়তা

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

পণ্য অনলাইনে বিক্রির একটি সাধারণ অ্যাপ্লিকেশনে, একটি Order নিচের অনেকগুলো স্টেটে যেতে পারে:

  • created
  • processing
  • ready
  • shipped
  • delivered
  • void

অনুমোদিত ট্রানজিশনগুলো নিচের ডায়াগ্রামে দেখানো হয়েছে।

রুবিতে স্টেট মেশিন দক্ষতা অর্জন: একটি প্র্যাক্টিক্যাল গাইড

অর্ডারকে স্টেট মেশিন হিসেবে ভিজুয়ালাইজ করলে পণ্য অর্ডার থেকে ডেলিভারি পর্যন্ত পুরো ফ্লো স্পষ্ট বোঝা যায়। এবং আমরা ডেভেলপাররা সেই ফ্লোর নির্দিষ্ট পয়েন্টে কী করা যায় আর কী করা যায় না সেটি স্পষ্টভাবে বুঝতে পারি।

そう言うと, খুব ব্যাপক সমস্যার জন্য এটি ব্যবহার করলে সैकড়ের স্টেট তৈরি হতে পারে যা রিজনিং করা কঠিন। তাই ইমপ্লিমেন্ট করার আগে আপনার প্রস্তাবিত স্টেট মেশিনের জন্য টপ-লেভেল আইডিয়া এবং স্টেট চার্ট রাখুন।

রুবিতে আমাদের প্রথম স্টেট মেশিন

চলুন রুবিতে আমাদের OrderStateMachine ইমপ্লিমেন্ট করি।


এটি একটি সহজ ইমপ্লিমেন্টেশন। স্টেট মেশিনের প্রতিটি সম্ভাব্য ট্রানজিশনের জন্য একটি মেথড ডিফাইন করা হয়েছে যা স্যানিটি চেক করে এবং ট্রানজিশন পারফর্ম করে।

উপরোক্ত ইমপ্লিমেন্টেশনের ভালো দিক হচ্ছে সব কিছু এক্সপ্লিসিট: নতুন ডেভেলপারও খুব দ্রুত স্টেট মেশিনের পুরো স্কোপ বুঝতে পারে।

চলুন ট্রানজিশনে কিছু সাইড-ইফেক্ট যোগ করি। প্যাক করা ও ডেলিভারেবল অর্ডারগুলো স্বয়ংক্রিয়ভাবে শিপ করব:


নাইভ ইমপ্লিমেন্টেশন ভালো কাজ করে, কিন্তু অনেক ট্রানজিশন ও কন্ডিশন থাকলে এটি অত্যধিক ভার্বোজ হয়ে যায়।

Ruby Toolbox-এ চেক করলে স্টেট মেশিনের বেশ কিছু জেম পাওয়া যাবে। state_machines এবং aasm সবচেয়ে জনপ্রিয়, এবং উভয়েই রেইলস ব্যবহার করার জন্য ActiveRecord অ্যাডাপ্টার রয়েছে। উভয়ই ভালোভাবে টেস্ট করা ও প্রোডাকশন-রেডি। স্টেট মেশিন ইমপ্লিমেন্ট করতে হলে সেগুলো চেক করুন।

রুবিতে State Machines জেম ব্যবহার করা

এই পোস্টে আমরা state_machines জেম দিয়ে আমাদের Order এর স্টেট মেশিন কীভাবে মডেল করব সেটি বর্ণনা করব।


উপরোক্ত ক্লাস আমাদের সিম্পল স্টেট মেশিন এবং এর সব সম্ভাব্য ট্রানজিশন ডিফাইন করে। এর পাশাপাশি এটি অর্ডারের ওপর অনেক ইউটিলিটি মেথড অটোমেটিক্যালি এক্সপোজ করে:


রুবিতে State Machines জেম দিয়ে সাইড-ইফেক্ট এক্সিকিউট করা

রিয়েল-ওয়ার্ল্ড সিস্টেমের মতো, স্টেট মেশিনের অনেক ট্রানজিশনে সাইড-ইফেক্ট থাকে। state_machines জেম সেগুলো ডিফাইন ও এক্সিকিউট করা সহজ করে দেয়। দুটি সাইড-ইফেক্ট যোগ করি:

  1. ready স্টেটে সব ট্রানজিশনে, অর্ডার deliverable হলে ডেলিভারি কনসাইনমেন্ট তৈরি করা।
  2. সব fail_delivery ইভেন্টে, ইউজারকে ইমেইল পাঠিয়ে ইভেন্টটি নোটিফাই করা।

অর্ডারে সাধারণভাবে ট্রানজিশন পারফর্ম করতে পারি:


state_machines জেমের গিটহাব পেজ দেখে জেমের সব সম্ভাব্য অপশন জানতে পারেন।

রুবি অন রেইলসে ActiveRecord সহ State Machines জেম ব্যবহার করা

আলোচনা করা হয়েছে, state_machines এবং aasm উভয়ই ActiveRecord সাপোর্ট করে। ActiveRecord-এর সাথে state_machines জেম ব্যবহার করলে ইমপ্লিমেন্টেশনে খুব কিছু পরিবর্তন হয় না। আগের সেকশনগুলোতে যা আলোচনা করা হয়েছে সেগুলো ব্যবহার করতে পারবেন।

কিছু অডিশনাল ফিচার আপনি পাবেন:

  1. সাইড-ইফেক্ট ট্রানজ্যাকশনের ভেতরে হয়। ডাটাবেস অপারেশন ফেইল হলে স্টেট চেঞ্জ কমিট হয় না। use_transactions দিয়ে এই বিহেভিয়ার ডিজেবল করা যায়।
  2. অন্য ActiveRecord কলব্যাকের মতো, করেন্ট মডেলের অ্যাট্রিবিউট ট্রানজিশন থেকে আপডেট করতে হলে before_transition কলব্যাকের ভেতরে করতে হবে। after_transition-এ আপডেট করতে মডেল আবার সেভ করতে হবে। উদাহরণ দেখুন:

  1. জেম অটোমেটিক্যালি স্কোপস প্রদান করে মডেলগুলো স্টেট দিয়ে ফিল্টার করতে। উদাহরণ: Order.with_state(:processing) দিয়ে সব প্রসেসিং অর্ডার বা Order.without_state(:processing) দিয়ে প্রসেসিং না হওয়া সব অর্ডার বের করা যায়।
  2. ম্যাচিং ট্রানজিশন ছাড়া স্টেট চেঞ্জ অ্যাটেমপ্ট করলে (যেমন processing থেকে delivered), রেকর্ড সেভ হবে না এবং ভ্যালিডেশন এররে রর যোগ হবে। এরর মেসেজ ইন্টারন্যাশনালাইজ করতে কনফিগ ফাইলে (যেমন en.yml) স্টেট ও ইভেন্টের ট্রান্সলেশন কী যোগ করুন:

সাইড নোট: ActiveRecord পারফরম্যান্স ইস্যু ট্রাবলশুট করার পোস্টটি দেখুন।

রাপ আপ: রুবিতে স্টেট মেশিন বিল্ড করা

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

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

পরবর্তী পোস্ট পর্যন্ত, স্টেট মেশিন বিল্ড করতে শুভকামনা!

P.S. Ruby Magic পোস্টগুলো প্রকাশ होते ही পেতে চাইলে আমাদের Ruby Magic নিউজলেটার সাবস্ক্রাইব করুন এবং কোনো পোস্ট মিস করবেন না!

রুবিতে স্টেট মেশিন দক্ষতা অর্জন: একটি প্র্যাক্টিক্যাল গাইড

পুলকিত গোয়াল

আমাদের অতিথি লেখক পুলকিত একজন সিনিয়র ফুল-স্ট্যাক ইঞ্জিনিয়ার এবং কনসাল্ট্যান্ট। ফুরসতে তিনি ব্লগে নিজের অভিজ্ঞতা লিখেন।

পুলকিত গোয়ালের সব আর্টিকেল

  1. অ্যান্ড্রয়েডে ফ্র্যাগমেন্ট間 ডেটা পাস করার পদ্ধতি

  2. HTML Paragraphs

  3. Tkinter-এ বাটন ক্লিক ইভেন্ট হ্যান্ডল করা

  4. পাইথনে সিবর্নের লাইনপ্লট ব্যবহার করে একাধিক কলামসহ টাইম সিরিজ প্লট