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

রেলস কনসার্নস দক্ষতা: কার্যকর মডিউল ব্যবহারের স্পষ্ট গাইড

আপনি যদি কখনো রুবি অন রেলস ব্যবহার করে থাকেন, তবে আপনি কনসার্নস কনসেপ্টের সাথে 마주 হয়ে থাকেন নিশ্চিত। যখনই আপনি একটি নতুন রেলস প্রজেক্ট শুরু করেন, আপনি একটি ডিরেক্টরি পান app/controllers/concerns এবং app/models/concerns। কিন্তু কনসার্নস কী? এবং রেলস কমিউনিটি के লোকরা কেন কখনো কখনো এদের খারাপভাবে কথা বলে?

দ্রুত ওভারভিউ

একটি রেলস কনসার্ন হল যেকোনো মডিউল যা ActiveSupport::Concern মডিউল এক্সটেন্ড করে। আপনি জিজ্ঞাসা করতে পারেন — কনসার্নস মডিউল থেকে কীভাবে আলাদা? মূল পার্থক্য হল রেলস কনসার্নস আপনাকে কিছু ম্যাজিক করার অনুমতি দেয়, এইভাবে:

# app/models/concerns/trashable.rb module Trashable extend ActiveSupport::Concern included do scope :existing, -> { where(trashed: false) } scope :trashed, -> { where(trashed: true) } end def trash update_attribute :trashed, true end end

আপনি included শব্দটি দেখছেন। এটি একটি রেলস কার্বোহাইড্রেট যা একটি রুবি মডিউলের ওপর ছড়ানো হয়েছে। ActiveSupport::Concern আপনার জন্য যা করে সেটি হল আপনাকে কোড রাখতে দেয় যা আপনি included ব্লকের ভিতরে ইভ্যালুয়েট করা চান। উদাহরণস্বরূপ, আপনি আপনার মডেল থেকে ট্র্যাশিং লজিক বের করতে চান। included আপনাকে সেটি করতে দেয় যা আমরা করেছি এবং পরে আপনার মডেলের কনসার্ন ইনক্লুড করতে পারেন এইভাবে:

class Song < ApplicationRecord include Trashable has_many :authors # ... end

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

একটি ক্লাসিক মিক্সিন উদাহরণ

কনসার্নসের গভীরে যাওয়ার আগে, আসুন এদের সম্পর্কে আরেকটি ব্যাখ্যা যোগ করি। যখন আপনি include SomeModule বা extend AnotherModule দেখেন, এগুলোকে মিক্সিন বলা হয়। একটি মিক্সিন হল কোডের একটি সেট যা অন্য ক্লাসগুলোর সাথে যোগ করা যায়। এবং, যেমন আমরা সবাই রুবি ডকুমেন্টেশন থেকে জানি, একটি মডিউল হল মেথড এবং কনস্ট্যান্টের একটি সংগ্রহ। তো আমরা এখানে যা করছি সেটি হল মেথড এবং কনস্ট্যান্ট ধারণকারী মডিউলগুলো বিভিন্ন ক্লাসে ইনক্লুড করা যাতে সেগুলো সেগুলো ব্যবহার করতে পারে।

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

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

আমার কাছে সব কিছু আছে

যখন আপনি কিছু এক্সট্র্যাক্ট করার সিদ্ধান্ত নেন একটি কনসার্নে, যেমন Trashable কনসার্ন, তখন আপনার অ্যাক্সেস থাকে সেটির সকল ফাংশনালিটিতে যেখানে Trashable ইনক্লুড করা হয়েছে। এটা বড় শক্তি আনে, কিন্তু রিচার্ড শ্নেম্যান তাঁর ব্লগ পোস্টে এই বিষয়ে বলেছিলেন — "মহান শক্তির সাথে আসে জটিল কোড তৈরি করার মহান ক্ষমতা"। তিনি বোঝাতে চেয়েছিলেন কোড জটিল করা যা আপনি भरোसा করতে পারেন, কিছু যেটি আপনার কনসার্নসে থাকার উচিত।

আমরা একবার আর Trashable-এ নজর দেই:

module Trashable extend ActiveSupport::Concern included do scope :existing, -> { where(trashed: false) } scope :trashed, -> { where(trashed: true) } end def trash update_attribute :trashed, true end end

কনসার্নের লজিক এই ফ্যাক্টের ওপর নির্ভর করে যে trashed ফিল্ডটি বিদ্যমান থাকে যেখানে কনসার্নটি ইনক্লুড করা হয়েছে। ঠিক? কোন বড় ব্যাপার নয়, এটি আমরা চাইছি। কিন্তু, আমি যা দেখি হয় সেটি হল লোকরা প্রলোভন হন মডেল থেকে অন্যান্য জিনিস কনসার্নে টানাতে। কীভাবে এটি হতে পারে সেটি চিত্রিত করতে, আসুন কল্পনা করি Song মডেলে আরেকটি মেথড আছে featured_authors:

class Song < ApplicationRecord include Trashable has_many :authors def featured_authors authors.where(featured: true) end # ... end class Album < ApplicationRecord include Trashable has_many :authors def featured_authors authors.where(featured: true) end # ... end

বेहतरভাবে বোঝাতে, আমি একটি Album মডেল যোগ করেছি যেটিও Trashable ইনক্লুড করে। চলুন ধরি আমরা ফিচারড অথরদের নোটিফাই করতে চাই গান এবং অ্যালবাম ট্র্যাশ হলে। লোকরা প্রলোভন হবে এই লজিক Trashable কনসার্নে রাখতে এইভাবে:

module Trashable extend ActiveSupport::Concern included do scope :existing, -> { where(trashed: false) } scope :trashed, -> { where(trashed: true) } end def trash update_attribute :trashed, true notify(featured_authors) end def notify(authors) # ... end end

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

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

class Song < ApplicationRecord include Trashable has_many :authors def featured_authors authors.where(featured: true).where(region: 'Europe') end # ... end class Album < ApplicationRecord include Trashable has_many :authors # ... end

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

এখানে যেটি রিস্কি সেটি হল কনসার্ন (মিক্সিন) খুব কিছু জানে যে মডেলে এটি ইনক্লুড হয়েছে। এটিকে বলা হয় সার্কুলার ডিপেন্ডেন্সি। Song এবং Album Trashable-র ওপর নির্ভর করে ট্র্যাশিং-এর জন্য, Trashable উভয়ের ওপর নির্ভর করে featured_authors ডেফিনিশনের জন্য। একই কথা বলা যায় trashed ফিল্ডটির অস্তিত্বের জন্য যেটি দুই মডেলই থাকতে হবে Trashable কনসার্ন কাজ করার জন্য।

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

তোমরা কোথা থেকে এসেছ

আমাদের নোটিফাইসহ Trashable-র দিকে ফিরে দিয়ে, আমাদের এর সম্পর্কে কিছু করতে হবে। কনসার্নস ব্যবহার করার সময় আরেকটি জিনিস হয় সেটি হল আমরা জিনিসগুলো ওভার-ড্রাই (over-DRY) করার প্রবণতা রাখি। আসুন সেটি করার চেষ্টা করি, প্রদর্শনের উদ্দেশ্যে, আমাদের বিদ্যমান মডেলগুলোতে অন্য একটি কনসার্ন তৈরি করে (সহন করুন এইটায়):

module Authorable has_many :authors def featured_authors authors.where(featured: true) end end

তখন, আমাদের Song এবং Album এর রূপ হবে এইভাবে:

class Song < ApplicationRecord include Trashable include Authorable # ... end class Album < ApplicationRecord include Trashable include Authorable # ... end

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

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

 # Concerns module Trashable extend ActiveSupport::Concern included do scope :existing, -> { where(trashed: false) } scope :trashed, -> { where(trashed: true) } end def trash update_attribute :trashed, true end end module Authorable has_many :authors # অন্যান্য ইউজফুল মেথড যা অথর সংক্রান্ত মডেলগুলোর জুড়ে। # যদি কোই নেই, তবে কনসার্নটি ডিচ করুন। end # Models class Song < ApplicationRecord include Trashable include Authorable def featured_authors authors.where(featured: true).where(region: 'Europe') end # ... end class Album < ApplicationRecord include Trashable include Authorable def featured_authors authors.where(featured: true) end # ... end

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

চূড়ান্ত বস

বেসক্যাম্পের জন্য, রেলস ক্রিয়েটররা, কনসার্নস অন্যান্য কনসার্ন রেফারেন্স করা একদম ঠিক মনে হয় যেমন DHH একটা টুইটে কিছুকাল আগে ইলাস্ট্রেট করেছিলেন:

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

 # ... include Subscribable # Depends on Readable include Eventable # Depends on Recordables # ...

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

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

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

উপসংহার

যেমন আমরা দেখেছি, কনসার্নস কিছু নয় বরং মডিউল যা কিছু উপযোগী সিনট্যাক্স 슈গার প্রদান করে আপনার কোড এক্সট্র্যাক্ট এবং ড্রাই আপ করার জন্য। আপনার বেল্টের নিচে আপনার আরও উপযোগী টুল থাকলে, হয়তো আপনাকে কনসার্নস तरफ তাত্ক্ষণিক হাত বাড়াতে হবে না। ফাইল আটাচমেন্ট হ্যান্ডলিং এবং আমরা উদাহরণে দেখানো ট্র্যাশিং লজিক এর মতো বিহেভিয়র মডিউল (কনসার্নস) এ এক্সট্র্যাক্ট করার ভালো প্রার্থী হতে পারে।

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

কোনো সমাধান পেরফেক্ট নয়, এবং আশা করি আপনি ব্লগ পোস্টে রেলস কনসার্নস পদ্ধতি বুঝতে পেরেছেন। সবসময় আপনার জাজমেন্ট ব্যবহার করুন এবং সুবিধা-অসুবিধা সম্পর্কে সচেতন থাকুন।

পরবর্তীটি পর্যন্ত, চেয়ার্স!

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


  1. রুবি অন রেইলস AWS Lambda-তে ডিপ্লয়: ধাপে ধাপে গাইড

  2. রেইলস প্রজেক্টের জন্য দক্ষ ডকুমেন্টেশন ওয়ার্কফ্লো ডিজাইন

  3. আপনার রেইলস অ্যাপস রক্ষা করুন: ইনজেকশন আক্রমণ বুঝা এবং প্রতিরোধ

  4. Angular এবং Rails 5 ইন্টিগ্রেশন: একটি স্মুথ ফুল-স্ট্যাক পদ্ধতি