মেটাপ্রোগ্রামিং শোনা খুব ফ্যান্সি শব্দের মতো লাগে, কিন্তু এটা কী ভালো?
এটি উপযোগী হতে পারে, কিন্তু অনেক লোক মেটাপ্রোগ্রামিং ব্যবহারের কিছু খরচ আছে সেটি বুঝে না।
সেটি স্পষ্ট করার জন্য…
মেটাপ্রোগ্রামিং আসলেই কী?
আমি মেটাপ্রোগ্রামিংকে এইভাবে ডিফাইন করি: যেকোনো মেথড ব্যবহার করা যা-
- আপনার কোডের কাঠামো পরিবর্তন করে (যেমন
define_method) - একটি স্ট্রিংকে রান করে যেন সেটি আপনার আসল রুবি কোডের অংশ (যেমন
instance_eval) - কোনো ইভেন্টের প্রতিক্রিয়া হিসেবে কিছু করে (যেমন
method_missing)
তাহলে মেটাপ্রোগ্রামিংয়ের খরচগুলো কী? আমি সেগুলো ৩ গ্রুপে ভাগ করেছি:
- গতি (Speed)
- পাঠযোগ্যতা (Readability)
- সার্চযোগ্যতা (Searchability)
নোট: আপনি চতুর্থ গ্রুপও বলতে পারেন: সিকিউরিটি। এর কারণ হলো
evalমেথডগুলো, যেগুলো কোনো সিকিউরিটি চেক করে না যা পাস করা হচ্ছে। আপনাকে নিজে সেটি করতে হবে।
প্রতিটিটি বিস্তারিতভাবে অন্বেষণ করি!
গতি (Speed)
প্রথম খরচ হলো গতি কারণ অধিকাংশ মেটাপ্রোগ্রামিং মেথড সাধারণ মেথডের চেয়ে ধীর।
এখানে কিছু বেঞ্চমার্কিং কোড:
require 'benchmark/ips' class Thing def method_missing(name, *args) end def normal_method end define_method(:speak) {} end t = Thing.new Benchmark.ips do |x| x.report("normal method") { t.normal_method } x.report("missing method") { t.abc } x.report("defined method") { t.speak } x.compare! end ফলাফল (Ruby 2.2.4):
normal method: 7344529.4 i/s defined method: 5766584.9 i/s - 1.34x slower missing method: 4777911.7 i/s - 1.54x slower
দেখতে পাচ্ছেন উভয় মেটাপ্রোগ্রামিং মেথড (define_method এবং method_missing) সাধারণ মেথডের চেয়ে যথেষ্ট ধীর।
এখানে একটা আকর্ষণীয় জিনিস আমি খুঁজে পেলাম…
উপরের ফলাফলগুলো Ruby 2.2.4- থেকে, কিন্তু আপনি যদি এই বেঞ্চমার্কগুলো Ruby 2.3 বা Ruby 2.4-এ রান করেন তবে মনে হবে এই মেথডগুলো আরও ধীর হচ্ছে!
Ruby 2.4 বেঞ্চমার্ক ফলাফল:
normal method: 8252851.6 i/s defined method: 6153202.9 i/s - 1.39x slower missing method: 4557376.3 i/s - 1.87x slower
আমি এই বেঞ্চমার্কটি একাধিকবার চালিয়েছি যেন কনফার্ম হয় এটি ফ্লুক নয়।
কিন্তু আপনি যদি খেয়াল করেন এবং ইটারেশন পার সেকেন্ড (i/s) তে নজর দেন তবে মনে হবে রেগুলার মেথডগুলো রুবি ২.৩ থেকে দ্রুত হয়েছে। সেটাই কারণ method_missing অনেক ধীর মনে হচ্ছে 🙂
পাঠযোগ্যতা (Readability)
instance_eval / class_eval মেথড ব্যবহার করলে এরর মেসেজ কমই সহায়ক হয়।
নিচের কোডটি দেখুন:
class Thing class_eval("def self.foo; raise 'something went wrong'; end") end Thing.foo এটি নিচের এরর দেবে:
(eval):1:in 'foo': 'something went wrong...' (RuntimeError)
লক্ষ্য করুন ফাইল নামটি অনুপস্থিত ( eval বলছে) এবং সঠিক লাইন নম্বরও নেই। ভালো খবর হলো এর সমাধান আছে, এই eval মেথডগুলো দুটি অতিরিক্ত প্যারামিটার নেয়:
- একটি ফাইল নাম
- একটি লাইন নম্বর
বিল্ট-ইন কনস্ট্যান্ট __FILE__ এবং __LINE__ কে class_eval-এর প্যারামিটার হিসেবে ব্যবহার করলে আপনি সঠিক তথ্য পাবেন এরর মেসেজে।
উদাহরণ:
class Thing class_eval( "def foo; raise 'something went right'; end", __FILE__, __LINE__ ) end
এটি ডিফল্ট কেন নয়? আমি জানি না, কিন্তু এটি মনে রাখা ভালো যদি আপনি এই মেথডগুলো ব্যবহার করতে চান 🙂
সার্চযোগ্যতা (Searchability)
মেটাপ্রোগ্রামিং মেথডগুলো আপনার কোডকে কম সার্চযোগ্য, কম অ্যাক্সেসযোগ্য (খারাপ ডকুমেন্টেশনfaces) এবং ডিবাগ করা কঠিন করে দেয়।
আপনি যদি একটি মেথড সংজ্ঞা খুঁজেন তবে আপনি CTRL+F (বা আপনি যে শর্টকাট ব্যবহার করেন) দিয়ে মেটাপ্রোগ্রামিং দিয়ে সংজ্ঞায়িত একটি মেথড খুঁজে পাবেন না, বিশেষ করে যদি মেথডের নাম রান-টাইমে তৈরি হয়।
নিচের উদাহরণটি মেটাপ্রোগ্রামিং ব্যবহার করে ৩টি মেথড সংজ্ঞায়িত করে:
class RubyBlog def create_post_tags types = ['computer_science', 'tools', 'advanced_ruby'] types.each do |type| define_singleton_method(type + "_tag") { puts "This post is about #{type}" } end end end rb = RubyBlog.new rb.create_post_tags rb.computer_science_tag ডকুমেন্টেশন জেনারেট করার টুলগুলো (যেমন Yard বা RDoc) এই মেথডগুলো খুঁজে পায় না এবং লিস্ট করতে পারে না।
এই টুলগুলো "স্ট্যাটিক অ্যানালিসিস" নামে একটি টেকনিক ব্যবহার করে ক্লাস ও মেথড খুঁজে বের করতে। এই টেকনিক শুধু সরাসরি সংজ্ঞায়িত মেথডগুলো ( def সিনট্যাক্স ব্যবহার করে) খুঁজে পেতে পারে।
yard doc শেষ উদাহরণটিই রান করে দেখুন, আপনি দেখবেন শুধু create_post_tags মেথডটি পাওয়া গেলো।
এটি এরকম দেখায়:

yard-কে এক্সট্রা মেথড ডকুমেন্ট করার জন্য বলার একটি উপায় আছে, @method ট্যাগ ব্যবহার করে, কিন্তু সেটি সবসময় ব্যাবহারিক নয়।
উদাহরণ:
class Thing # @method build_report define_method(:build_report) end
এছাড়াও আপনি যদি grep, ack, বা আপনার এডিটর ব্যবহার করে মেথড সংজ্ঞা খুঁজেন, মেটাপ্রোগ্রামিং মেথডগুলো খুঁজে পাওয়া রেগুলার মেথডের চেয়ে কঠিন হবে।
"আমি মনে করি সাইডকিউ কোনো মেটাপ্রোগ্রামিং ব্যবহার করে না কারণ আমি মনে করি এটি ৯৫% সময় কোডকে আরও অস্পষ্ট করে সাহায্য করার চেয়ে।" — মাইক পারহাম, সাইডকিউয়ের স্রষ্টা
উপসংহার
মেটাপ্রোগ্রামিং সম্পর্কে সবকিছু খারাপ নয়। সঠিক পরিস্থিতিতে এটি আপনার কোডকে আরও নমনীয় করতে উপযোগী হতে পারে।
শুধু অতিরিক্ত খরচগুলো সম্পর্কে সচেতন থাকুন যাতে আপনি ভালো সিদ্ধান্ত নিতে পারেন।
যদি এটি উপযোগী লাগে তবে এই পোস্ট শেয়ার করা না ভুলেন 🙂