আজকাল #freeze
দেখা খুবই সাধারণ রুবি কোডে ব্যবহৃত হয়। তবে কেন ফ্রিজ ব্যবহার করা হচ্ছে তা প্রায়শই সম্পূর্ণরূপে পরিষ্কার হয় না। এই পোস্টে আমরা সবচেয়ে সাধারণ কারণগুলি দেখব যেগুলি একজন বিকাশকারী ভেরিয়েবলগুলিকে ফ্রিজ করতে পারে৷ প্রতিটি কারণ ব্যাখ্যা করার জন্য, আমি রেল কোডবেস এবং অন্যান্য জনপ্রিয় ওপেন সোর্স প্রকল্প থেকে উদাহরণ কোড উদ্ধৃত করেছি৷
অপরিবর্তনীয় ধ্রুবক তৈরি করা
রুবিতে, ধ্রুবকগুলি পরিবর্তনযোগ্য। এটা একটু বিভ্রান্তিকর, কিন্তু কোড বুঝতে যথেষ্ট সহজ। এখানে, আমি একটি স্ট্রিং ধ্রুবক তৈরি করেছি এবং এটিতে আরেকটি স্ট্রিং যুক্ত করছি।
MY_CONSTANT = "foo"
MY_CONSTANT << "bar"
puts MY_CONSTANT.inspect # => "foobar"
#freeze ব্যবহার করে, আমি একটি ধ্রুবক তৈরি করতে সক্ষম হয়েছি যা আসলে ধ্রুবক। এইবার, যখন আমি স্ট্রিংটি পরিবর্তন করার চেষ্টা করি, আমি একটি রানটাইম ত্রুটি পাই৷
MY_CONSTANT = "foo".freeze
MY_CONSTANT << "bar" # => RuntimeError: can't modify frozen string
অ্যাকশনডিসপ্যাচ কোডবেসে এর একটি বাস্তব-বিশ্বের উদাহরণ এখানে। রেলগুলি লগগুলিতে সংবেদনশীল ডেটা লুকিয়ে রাখে "[ফিল্টারড]" পাঠ্য দিয়ে প্রতিস্থাপন করে৷ এই টেক্সট একটি হিমায়িত ধ্রুবক সংরক্ষণ করা হয়.
module ActionDispatch
module Http
class ParameterFilter
FILTERED = '[FILTERED]'.freeze
...
বস্তু বরাদ্দ কমানো
আপনার রুবি অ্যাপের গতি বাড়ানোর জন্য আপনি যা করতে পারেন তার মধ্যে একটি হল তৈরি করা বস্তুর সংখ্যা হ্রাস করা। অবজেক্ট বরাদ্দের একটি বিরক্তিকর উৎস স্ট্রিং লিটারেল থেকে আসে যা বেশিরভাগ অ্যাপ জুড়ে ছিটিয়ে দেওয়া হয়।
প্রতিবার আপনি লগ ("foobar") এর মতো একটি পদ্ধতি কল করেন, আপনি একটি নতুন স্ট্রিং অবজেক্ট তৈরি করেন। যদি আপনার কোড প্রতি সেকেন্ডে হাজার হাজার বার এই ধরনের একটি পদ্ধতি কল করে, তার মানে আপনি প্রতি সেকেন্ডে হাজার হাজার স্ট্রিং তৈরি করছেন (এবং আবর্জনা সংগ্রহ করছেন)। এটা অনেক বেশি মাথা ঘোরা!
সৌভাগ্যবশত, রুবি আমাদের একটি উপায় দেয়। যদি আমরা স্ট্রিং লিটারেল ফ্রিজ করি, রুবি ইন্টারপ্রেটার শুধুমাত্র একটি স্ট্রিং অবজেক্ট তৈরি করবে এবং ভবিষ্যতে ব্যবহারের জন্য এটি ক্যাশে করবে। আমি হিমায়িত বনাম নন-ফ্রোজেন স্ট্রিং আর্গুমেন্টের পারফরম্যান্স দেখানো একটি দ্রুত বেঞ্চমার্ক একসাথে রেখেছি। এটি প্রায় 50% কর্মক্ষমতা বৃদ্ধি দেখায়।
require 'benchmark/ips'
def noop(arg)
end
Benchmark.ips do |x|
x.report("normal") { noop("foo") }
x.report("frozen") { noop("foo".freeze) }
end
# Results with MRI 2.2.2:
# Calculating -------------------------------------
# normal 152.123k i/100ms
# frozen 167.474k i/100ms
# -------------------------------------------------
# normal 6.158M (± 3.3%) i/s - 30.881M
# frozen 9.312M (± 3.5%) i/s - 46.558M
আপনি যদি রেল রাউটারটি দেখেন তবে আপনি এটি কার্যত দেখতে পাবেন। যেহেতু প্রতিটি ওয়েব পৃষ্ঠার অনুরোধের জন্য রাউটার ব্যবহার করা হয়, এটি দ্রুত হওয়া প্রয়োজন। এর মানে অনেক হিমায়িত স্ট্রিং লিটারাল।
# excerpted from https://github.com/rails/rails/blob/f91439d848b305a9d8f83c10905e5012180ffa28/actionpack/lib/action_dispatch/journey/router/utils.rb#L15
def self.normalize_path(path)
path = "/#{path}"
path.squeeze!('/'.freeze)
path.sub!(%r{/+\Z}, ''.freeze)
path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase }
path = '/' if path == ''.freeze
path
end
রুবিতে অন্তর্নির্মিত অপ্টিমাইজেশান>=2.2
রুবি 2.2 এবং পরবর্তী (MRI) স্বয়ংক্রিয়ভাবে স্ট্রিং লিটারেলগুলিকে হিমায়িত করবে যা হ্যাশ কী হিসাবে ব্যবহৃত হয়৷
user = {"name" => "george"}
# In Ruby >= 2.2
user["name"]
# ...is equivalent to this, in Ruby <= 2.1
user["name".freeze]
এবং ম্যাটজের মতে, রুবি 3-এ সমস্ত স্ট্রিং লিটারেল স্বয়ংক্রিয়ভাবে হিমায়িত হয়ে যাবে।
লিঙ্ক:DevelopersMeeting20150820Japan - স্ট্রিং লিটারালগুলি রুবি 3.0-এ ডিফল্টরূপে হিমায়িত (অপরিবর্তনীয়) হয় https://t.co/4XcelftmSa
— Yukihiro Matsumoto (@yukihiro_matz) আগস্ট 20, 2015
মূল্য বস্তু এবং কার্যকরী প্রোগ্রামিং
যদিও রুবি একটি কার্যকরী প্রোগ্রামিং ভাষা নয়, অনেক রুবিবাদী একটি কার্যকরী শৈলীতে কাজ করার মূল্য দেখতে শুরু করেছে। এই শৈলীর প্রধান নীতিগুলির মধ্যে একটি হল আপনার পার্শ্ব প্রতিক্রিয়া এড়ানো উচিত। শুরু হওয়ার পর অবজেক্টের পরিবর্তন করা উচিত নয়।
কনস্ট্রাক্টরের অভ্যন্তরে ফ্রিজ পদ্ধতিতে কল করার মাধ্যমে, এটি নিশ্চিত করা সম্ভব যে একটি বস্তু কখনই পরিবর্তন হবে না। কোনো অনিচ্ছাকৃত পার্শ্বপ্রতিক্রিয়ার ফলে একটি ব্যতিক্রম উত্থাপিত হবে।
class Point
attr_accessor :x, :y
def initialize(x, y)
@x = x
@y = y
freeze
end
def change
@x = 3
end
end
point = Point.new(1,2)
point.change # RuntimeError: can't modify frozen Point