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

Awesome Print দিয়ে কোড আউটপুট মাস্টার করুন: ক্লিন, রিডেবল লগিং-এর জন্য একটি রুবি জেম

Awesome print হলো একটি সুন্দর জেম যা irb এবং pry-এ আপনার আউটপুট ফরম্যাট করে इसे আরও পঠনযোগ্য করে। উদাহরণস্বরূপ… awesome_print দিয়ে একটি হ্যাশ ডিসপ্লে করলে এরা এমন দেখে:

Awesome Print দিয়ে কোড আউটপুট মাস্টার করুন: ক্লিন, রিডেবল লগিং-এর জন্য একটি রুবি জেম

কিন্তু এটি কীভাবে কাজ করে?

“সত্য শুধু একটি জায়গায় পাওয়া যায়: কোডে।” ― রবার্ট সি. মার্টিন

আসুন সোর্স কোডে এক নজর দিয়ে বের করি!

অ্যAwsome প্রিন্টিং

আমি একটি কোড রিডিং সেশন একটি কুইক ওভারভিউ দিয়ে শুরু করি প্রজেক্ট স্ট্রাকচারের (ফাইল ও ফোল্ডার), তারপর আমি একটি প্রশ্ন করি আমার এক্সপ্লোরেশন ফোকাস করার জন্য। প্রথম প্রশ্ন যা আমার মনে পড়ল: awesome_print pry-এর আউটপুট কীভাবে পরিবর্তন করে? এখন আমি আমার ডিটেক্টিভ হ্যাট পরে এবং একটি হাইপোথিসিস বানাই: "এই জেমটি $stdout-কে রিপ্লেস করতে পারে যাতে এটি pry-এর আউটপুট ক্যাপচার করে এবং তারপর এটাকে প্রিটি বানাতে পারে।" কিন্তু এই ইমপ্লিমেন্টেশন আপনাকে আউটপুট কাস্টোমাইজ করতে দিবে না, যেমন pretty_print (রুবির স্ট্যান্ডার্ড লাইব্রেরি থেকে) করে। בנוסף, আমাদের কোড পার্স বা এভাল করতে হতো, ভালো আইডিয়া নয়! পরবর্তী: আমি দেখলাম এই জেমটি কীভাবে লোড হয়। এটি আমাদের কোডে একটি এন্ট্রি পয়েন্ট দেবে।

Awesome Print লোড করা

awesome_print pry-এ লোড করতে আপনাকে করতে হবে:

require 'awesome_print' 
AwesomePrint.pry!

এখন আমরা খুঁজতে চাই pry! কোথায় ডিফাইন করা হয়েছে। আমি Atom-এ "search in directory" ফিচারটি ব্যবহার করলাম এটি খুঁজে বের করতে। কোডটি এখানে:

def pry! 
  Pry.print = proc { |output, value| output.puts value.ai } 
  if defined?(Pry) 
end

লাগছে Pry আপনাকে এর আউটপুট মডিফাই করতে দেয় print-এর ভ্যালু সেট করে। তাই এটা আমাদের "কোথায় থেকে শুরু করব" প্রশ্নের উত্তর দিয়েছে 🙂

এই "proc" জিনিস সম্পর্কে আরও জানতে চান? "The Ultimate Guide to Blocks, Procs & Lambdas" পড়ুন। এটি আমার Ruby Deep Dive বইর একটি স্যামপল চ্যাপ্টার।

এই proc দুটি আর্গুমেন্ট নেয়:

  • output
  • value

এবং সেগুলোর ওপর দুটি মেথড কল করে। পরবর্তী প্রশ্ন: এই ai মেথডটি কী? এটি Kernel মডিউলে ডিফাইন করা একটি মেথড:

def ai(options = {}) 
  ap = AwesomePrint::Inspector.new(options) 
  awesome = ap.awesome(self) 
  if options[:html] 
    awesome = "</pre>#{awesome}</pre>" 
  end 
  awesome = awesome.html_safe if defined? ActiveSupport 
  end 
  awesome 
end 
alias :awesome_inspect :ai

কারণ সব অবজেক্ট ডিফল্টভাবে Kernel ইনক্লুড করে, সেগুলোতে এই ai মেথডটি উপলব্ধ থাকবে। এখন আসুন একটু গভীরে যাই এবং দেখি এই Inspector ক্লাস কীভাবে কাজ করে।

Inspector ক্লাস

inspector.rb খোলার সাথে সাথে আমরা initialize মেথডের ভেতরে একটি বিশাল অপশন হ্যাশ পাই। এখানে এর কিছু অংশ:

@options = { 
  indent: 4, # Number of spaces for indenting. 
  index: true, # Display array indices. 
  html: false, # Use ANSI color codes rather than HTML. 
  multiline: true, # Display in multiple lines. 
  # ... 
}

এর পর আমরা এই কোডটি পাই:

@formatter = AwesomePrint::Formatter.new(self) 
@indentator = AwesomePrint::Indentator.new(@options[:indent].abs) 
Thread.current[AP] ||= []

তবে এটা ফরম্যাটিং এবং কোডের ইন্ডেন্টেশন হ্যান্ডেল করার জন্য দুটি অবজেক্ট সেটআপ করছে। কিন্তু এই Thread.current জিনিসটি কী? এটি আপনাকে করেন্ট থ্রেডের অ্যাক্সেস দেয়। আপনি আপনার অ্যাপ্লিকেশনে থ্রেড ব্যবহার না করলেও আপনার একটি থ্রেড থাকবে, "মেইন" থ্রেড। এই AP কনস্ট্যান্টটি শুধু একটি কনস্ট্যান্ট যা inspector.rb-র টপে ডিফাইন করা আছে:

AP = :__awesome_print__
তাহলে এখানে কী হচ্ছে? Awesome print Thread.current এবং __awesome_print__ কী ব্যবহার করে কিছু ডেটা সংরক্ষণ করছে যা শুধু করেন্ট থ্রেডে উপলব্ধ। এটি মাল্টি-থ্রেডিং-এ সমস্যা এড়াতে ব্যবহৃত হয়।

অ্যAwsome ফরম্যাটিং

আসুন আউটপুট ফরম্যাটিং কোডটি দেখি, যা AwesomePrint::Formatter ক্লাসের ভেতরে হয়। এই পদ্ধতিতে ইনস্পেক্টর (ai মেথড দিয়ে তৈরি অবজেক্ট) format মেথড কল করবে।

def unnested(object) 
  @formatter.format(object, printable(object)) 
end
তারপর Formatter ক্লাসের এই format মেথডটি এই টাইপের অবজেক্টের সাথে নিবটা করার সেরা পদ্ধতি খুঁজে বের করবে এবং মেটা-প্রোগ্রামিং ব্যবহার করে আরেকটি মেথড কল করবে। মেথডটি এখানে:

def format(object, type = nil) 
  core_class = cast(object, type) 
  awesome = if core_class != :self 
    send(:"awesome_#{core_class}", object) # Core formatters. 
  else 
    awesome_self(object, type) # Catch all that falls back to object.inspect. 
  end 
  awesome 
end

এই Formatter ক্লাস বুঝতে আমাদের cast মেথডটিও দেখতে হবে:

def cast(object, type) 
  CORE.grep(type)[0] || :self 
end
CORE কনস্ট্যান্টটি একটি সিম্বল অ্যারে যা কোর রুবি ক্লাসগুলোকে প্রতীক করে এবং :self হলো একটি সিম্বল যা এখানে "নট ফাউন্ড" বোঝায় (শুধু এই উদাহরণে, রুবি সাধারণত নয়)।
CORE = [:array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod]
হতে যাচ্ছে এটা: ফরম্যাট করা হচ্ছে অবজেক্টটি যদি "কোর ক্লাস" লিস্টে থাকে তবে এটি একটি স্পেশালাইজড ফরম্যাট পাবে। অন্যথায়, এটি একটি জেনেরিক ফরম্যাট পাবে। স্পেশালাইজড ফরম্যাটারগুলো lib/awesome_print/formatters/ ডিরেক্টরিতে ডিফাইন করা থাকে এবং এতে Array, Hash এবং Class এর মত জিনিসগুলো থাকে। উদাহরণস্বরূপ, ক্লাসের জন্য ফরম্যাটার মেথডটি এখানে:
def format 
  superclass = klass.superclass 
  if superclass 
    colorize("#{klass.inspect} < #{superclass}", :class) 
  else 
    colorize(klass.inspect, :class) 
  end 
end
আপনি চাইলে আপনার নিজস্ব ফরম্যাটারও লিখতে পারেন।

সারসংক্ষেপ

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

  1. Pry মাস্টার করুন: প্রতিটি জুনিয়র Rubyist-এর জন্য অপরিহার্য ডিবাগিং টুল

  2. টু-ফ্যাক্টর অথেন্টিকেশন পরিচিতি: আপনার একাউন্ট সিকিউরিটি শক্তিশালী করুন

  3. রুবিতে VCR মাস্টার করুন: টেস্ট পারফরম্যান্স ও নির্ভরযোগ্যতা বাড়ান

  4. Awesome Print দিয়ে কোড আউটপুট মাস্টার করুন: ক্লিন, রিডেবল লগিং-এর জন্য একটি রুবি জেম