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

রুবি অন রেইলসে মিক্সিন এবং মডিউলে দক্ষতা: একটি বাস্তব গাইড

মডিউল এবং মিক্সিন, সন্দেহের বাইরে, রুবিকে এত আকর্ষণীয় 만드는 দুটি চমৎকার রিসোর্স। এগুলো অ্যাপ্লিকেশনকে সেই কোড শেয়ার করার ক্ষমতা দেয় যেটা অন্য জায়গায় সহজে ব্যবহার করা যায়। এছাড়া, এটি ফাংশনালিটি এবং কনসার্ন গ্রুপ করে আমাদের কোড অর্গানাইজ করতে সাহায্য করে, যা আমাদের কোডের রিডেবিলিটি এবং মেইনটেইনেবিলিটি উন্নত করে।

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

আশা করি আপনি যাত্রাটি উপভোগ করবেন!

মডিউল কী (What are Modules)

মডিউল রুবির সবচোয়ে চমৎকার রিসোর্সের একটি কারণ এগুলো দুটি চমৎকার বেনিফিট প্রদান করে: আমরা নেমস্পেস তৈরি করতে পারি নাম সংঘর্ষ রোধ করতে এবং আমরা সেগুলো মিক্সিন হিসেবে ব্যবহার করতে পারি অ্যাপ্লিকেশন জুড়ে কোড শেয়ার করতে।

স্ট্রাকচারালভাবে, একটি মডিউল যেকোনো রুবি ক্লাসের সাথে খুব সিমিলার। আসলে, রুবির জন্য, একটি Class একটি Module, নিচে irb কনসোলে দেখানো হলো:

> Class.is_a?(Module) => true

ক্লাসের মতো, মডিউলের সাথেও আমরা মেথড এবং কনস্ট্যান্ট গ্রুপ করি এবং কোড শেয়ার করি। যাক, একটি মডিউল এবং একটি প্লেইন রুবি ক্লাসের মাঝে কয়েকটি পার্থক্য রয়েছে:

  • আমরা ডেফিনিশন module কীওয়ার্ড দিয়ে শুরু করি class-এর বদলে;
  • আমরা মডিউল ইনস্ট্যানশিয়েট করতে পারি না, তাই এতে থেকে কোনো অবজেক্ট তৈরি করা যায় না;
  • আমরা মডিউল থেকে ইনহেরিট করতে পারি না, তাই আমরা সেগুলো মিক্সিন হিসেবে ব্যবহার করি;
  • মডিউলগুলো স্ট্যান্ডআলোন কোড, তাই মডিউলগুলোর কোনো ইনহেরিটেন্স হায়ারার্কি নেই;

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

এভাবে একটি মডিউল দেখতে হয়:

# lib/modules/invoice_creator.rb module InvoiceCreator TAX_FEE = 0.5 def self.generate puts "Don't worry! I'll generate the invoice for you at #{TAX_FEE}%" end def invoice_total puts "I'll return the invoice total" 1000 end end

এই উদাহরণে, আমরা লক্ষ্য করতে পারি একটি মডিউল দুটি ধরনের মেথড প্রদান করতে পারে: মডিউল মেথড এবং ইনস্ট্যান্স মেথড।

self.generate একটি মডিউল মেথড, যার মানে আমরা এটা যেকোনো অন্য অবজেক্টে ইনক্লুড (বা এক্সটেন্ড) না করেও ব্যবহার করতে পারি। এটি খুব কমন যখন আমরা সার্ভিস অবজেক্ট তৈরি করি, উদাহরণস্বরূপ। আমরা আমাদের মডিউল মেথড এভাবে কল করতে পারি:

2.5.3 :006 > InvoiceCreator.generate Don't worry! I'll generate the invoice for you => nil

invoice_total একটি ইনস্ট্যান্স মেথড এবং এটি ব্যবহার করতে পারতে, আমাদের মডিউলটি একটি ক্লাসে ইনক্লুড করতে হবে, যেন:

# app/models/invoice.rb class Invoice < ApplicationRecord include InvoiceCreator # এটি আমাদের মডিউলকে Invoice ক্লাসে ইনক্লুড করে def calculate_tax total = invoice_total # আমাদের মডিউল থেকে ইনক্লুড করা মেথড tax = total * InvoiceCreator::TAX_FEE puts "This is the invoice tax: #{tax}" end end

InvoiceCreator-এর সকল ইনস্ট্যান্স মেথড Invoice ইনস্ট্যান্সের জন্য উপলব্ধ হয়ে যায়, তাই আমরা calculate_tax মেথড খুব সহজে কল করতে পারি:

2.5.3 :008 > Invoice.new.calculate_tax "I'll return the invoice total" "This is the invoice tax: 500.0" => nil 2.5.3 :009 >

এছাড়া, calculate_tax-এর ভিতরে আপনি লক্ষ্য করেছেন যে আমরা আমাদের মডিউলে ডিফাইন করা একটি কনস্ট্যান্ট ব্যবহার করছি। যেমন আমি আগে বললাম, মডিউলগুলো কনস্ট্যান্ট রাখার চমৎকার জায়গা!

এখন একটি সিনেরিও কল্পনা করুন যেখানে আমাদের দুটি ধরনের InvoiceCreator দরকার সাপ্লায়ার এবং কাস্টমারের জন্য সম্পূর্ণ ভিন্ন ইনভয়েস জেনারেট করতে। আমরা একটি নাম ক্ল্যাশে পড়ব, এবং এটা এড়াতে, আমরা মডিউলের অন্য চমৎকার বেনিফিট ব্যবহার করব: নেমস্পেস। পরবর্তী সেকশনে এটা দেখি।

সর্বত্র নেমস্পেস (Namespaces Everywhere)

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

আমাদের কোডে ফিরে যাই। আমাদের দুটি আলাদা মডিউল তৈরি করতে হবে:

# lib/modules/customer/invoice_creator.rb module Customer module InvoiceCreator def self.generate puts "Don't worry! I'll generate the customer invoice for you" end end end # lib/modules/supplier/invoice_creator.rb module Supplier module InvoiceCreator def self.generate puts "Don't worry! I'll generate the supplier invoice for you" end end end

তারপর আমরা Customer::InvoiceCreator বা Supplier::InvoiceCreator ব্যবহার করতে পারি যেখানে দরকার:

2.5.3 :014 > Customer::InvoiceCreator.generate Don't worry! I'll generate the customer invoice for you => nil 2.5.3 :015 > Supplier::InvoiceCreator.generate Don't worry! I'll generate the supplier invoice for you => nil 2.5.3 :016 >

এভাবে প্রতিটি স্পেসিফিক কোড তার নিজস্ব মডিউলের ভিতরে র‍্যাপ্ড থাকবে, সেপারেশন অফ কনসার্নস প্রিন্সিপল রেসপেক্ট করে। এর পাশাপাশি, সর্বত্র নেমস্পেসিং আমাদের কোড ভালোভাবে অর্গানাইজড রাখার একটি চমৎকার উপায়।

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

মিক্সিন ব্যবহারের জাদু (The Magic of Using Mixins)

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

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

উদাহরণস্বরূপ, কল্পনা করুন আমাদের InvoiceCreator মডিউল একটি সার্ভিস যা অন্যান্য সেক্টের মডিউল দ্বারা প্রদত্ত ফাংশনালিটি ব্যবহার করতে হবে, যেমন InvoiceCalculator, InvoiceRenderer এবং InvoiceSender, সেগুলো ইনভয়েস ক্রিয়েশন প্রসেস পূরণ করতে প্রয়োজনীয়।

আমরা এটা অর্জন করতে পারি মডিউলদের একটি চেইন মিক্সিন হিসেবে আমাদের কোডে ইনক্লুড করে, যাতে আমরা মেথডগুলো সরাসরি ব্যবহার করতে পারি, নিচের উদাহরণের মত:

# lib/modules/invoice_calculator.rb module InvoiceCalculator def calculate_items_total puts "imagine some math here" end end # lib/modules/invoice_renderer.rb module InvoiceRenderer def generate_invoice_pdf puts "imagine that we are using some PDF generation magic here" end end # lib/modules/invoice_sender.rb module InvoiceSender def send_invoice puts "imagine your favorite mail service being used here" end end

যেহেতু আমরা InvoiceCreator-কে অন্য তিনটি মডিউল থেকে ইনহেরিট করতে পারি না, আমরা সেগুলো ইনক্লুড করছি। এইভাবে InvoiceCreator অন্যান্য ইনভয়েস মডিউলগুলো থেকে সকল মেথড ইনক্লুড করে, এবং আমরা এই মেথডগুলো যেকোনো ক্লাস/মডিউলে কল করতে পারি যেখানে InvoiceCreator মডিউল ইনক্লুড করা হয়েছে। সতর্ক থাকুন! যদি কোনো মডিউলগুলোর মেথডে সেম নাম থাকে, তবে সেগুলো একে অপরের ওপর ওভাররাইট করবে।

# lib/modules/customer/invoice_creator.rb module Customer module InvoiceCreator include InvoiceCalculator include InvoiceRenderer include InvoiceSender def generate_invoice calculate_items_total # from InvoiceCalculator generate_invoice_pdf # from InvoiceRenderer send_invoice # from InvoiceSender end end end

এখন আমরা আমাদের সার্ভিস মেথডগুলো যেকোনো জায়গা থেকে কল করতে পারি যেখানে এটা ইনক্লুড করা আছে, এভাবে করলেই:

# app/models/invoice.rb class Invoice < ApplicationRecord include Customer::InvoiceCreator def send_invoice_to_customer puts "Don't worry! I'll generate the customer invoice for you" generate_invoice end end

এটি রেজাল্ট হবে, InvoiceCreator মডিউলের মাধ্যমে ইনক্লুড করা ইনভয়েস মডিউলগুলোর মেথড কল করলেই:

2.5.3 :051 > Invoice.new.generate_invoice Don't worry! I'll generate the supplier invoice for you imagine some math here imagine that we are using some PDF generation magic here imagine your favorite mail service being used here => nil

লক্ষ্য করুন এটি কীভাবে কমপোজিশন ওভার ইনহেরিটেন্স প্রিন্সিপল ব্যবহার করছি। এই প্রিন্সিপল দাবি করে: আপনি কমপোজিশন প্রেফার করবেন যতক্ষণ পারেন। কমপোজিশনে, আমরা এমন ক্লাস তৈরি করি যেগুলো অন্যদের স্পেসিফিক ফাংশনালিটি প্রদান করার জন্য রেসপন্সিবল, যা ঠিক আমরা করছি।

এতটুকুই সব ফোকস (That's all Folks!)

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

রুবি এবং রেইলসের চমৎকার রিসোর্সগুলো সম্পর্কে এখানে কথা বলতে থাকব, তাই টিউন্ড থাকুন!

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

  1. রেলসে ফ্ল্যাশ মেসেজ মাস্টার করুন: একটি সম্পূর্ণ গাইড

  2. রুবি ম্যাট্রিক্স বুঝতে: ডেফিনিশন, অ্যাপ্লিকেশন এবং কীভাবে তৈরি করবেন

  3. রুবি Struct ও OpenStruct: দক্ষ ভ্যালু অবজেক্টস

  4. রেইলসে OmniAuth-Twitter দিয়ে টুইটার লগইন ইন্টিগ্রেট করুন: ধাপে ধাপে গাইড