ত্রুটি পরিচালনা প্রতিটি প্রোগ্রামের একটি গুরুত্বপূর্ণ অংশ। কোডের একটি অংশ বাস্তবায়নের সময় কী কী ত্রুটি হতে পারে সে সম্পর্কে সক্রিয় হওয়া গুরুত্বপূর্ণ। এই ত্রুটিগুলি এমনভাবে পরিচালনা করা উচিত যা নিশ্চিত করে যে আউটপুট উত্পাদিত হয়েছে যা প্রতিটি ত্রুটি এবং অ্যাপ্লিকেশনটির পর্যায়টি সঠিকভাবে বর্ণনা করে। তবুও, এটি এমনভাবে অর্জন করাও গুরুত্বপূর্ণ যেটি নিশ্চিত করে যে আপনার কোডটি কার্যকরী এবং পাঠযোগ্য থাকবে। চলুন শুরু করা যাক এমন একটি প্রশ্নের উত্তর দিয়ে যা আপনার কাছে ইতিমধ্যেই থাকতে পারে:রেলওয়ে ওরিয়েন্টেড প্রোগ্রামিং কি?
রেলওয়ে ওরিয়েন্টেড প্রোগ্রামিং
একটি ফাংশন যা একটি নির্দিষ্ট উদ্দেশ্য অর্জন করে ছোট ফাংশনগুলির একটি রচনা হতে পারে। এই ফাংশনগুলি বিভিন্ন পদক্ষেপগুলি সম্পাদন করে যা শেষ পর্যন্ত চূড়ান্ত লক্ষ্য অর্জনের দিকে নিয়ে যায়। উদাহরণস্বরূপ, একটি ফাংশন যা ডাটাবেসে একজন ব্যবহারকারীর ঠিকানা আপডেট করে এবং পরবর্তীতে ব্যবহারকারীকে এই পরিবর্তন সম্পর্কে অবহিত করে তার নিম্নলিখিত পদক্ষেপগুলি থাকতে পারে:
validate user -> update address -> send mail upon successful update
এই পদক্ষেপগুলির প্রতিটি ব্যর্থ হতে পারে বা সফল হতে পারে, এবং যে কোনও পদক্ষেপের ব্যর্থতা সমগ্র প্রক্রিয়ার ব্যর্থতার দিকে নিয়ে যায়, কারণ ফাংশনের উদ্দেশ্য অর্জিত হয় না৷
রেলওয়ে ওরিয়েন্টেড প্রোগ্রামিং (ROP) হল Scott Wlaschin দ্বারা উদ্ভাবিত একটি শব্দ যেটি এই ধরনের ফাংশনে ত্রুটি পরিচালনার ক্ষেত্রে রেলওয়ে সুইচ সাদৃশ্য প্রয়োগ করে। রেলওয়ে সুইচ করে (যাকে যুক্তরাজ্যে "পয়েন্ট" বলা হয়) এক ট্র্যাক থেকে অন্য ট্র্যাকে ট্রেন গাইড করে। স্কট এই সাদৃশ্যটিকে এই অর্থে ব্যবহার করে যে প্রতিটি পদক্ষেপের সাফল্য/ব্যর্থতা আউটপুট রেলওয়ের সুইচের মতো কাজ করে, কারণ এটি আপনাকে সাফল্যের ট্র্যাক বা ব্যর্থতার ট্র্যাকে নিয়ে যেতে পারে৷
একটি রেলওয়ে সুইচ হিসাবে কাজ করে সাফল্য/ব্যর্থতার আউটপুট
যখন কোনো ধাপে কোনো ত্রুটি থাকে, তখন আমরা ব্যর্থতার আউটপুট দ্বারা ব্যর্থতার ট্র্যাকে চলে যাই, যার ফলে বাকি ধাপগুলিকে বাই-পাস করা হয়। যাইহোক, যখন একটি সফল আউটপুট হয়, এটি আমাদের চূড়ান্ত গন্তব্যে নিয়ে যেতে সাহায্য করার জন্য পরবর্তী ধাপের ইনপুটের সাথে সংযুক্ত থাকে, যেমনটি নীচের ছবিতে দেখানো হয়েছে৷
একসাথে শৃঙ্খলিত বেশ কয়েকটি ধাপের সাফল্য/ব্যর্থতার ফলাফল
রেলওয়ে ওরিয়েন্টেড প্রোগ্রামিং এর পিছনে এই দুই-ট্র্যাক সাদৃশ্য। এটি প্রতিটি ধাপে এই সাফল্য/ব্যর্থতার আউটপুটগুলি ফেরত দেওয়ার চেষ্টা করে (অর্থাৎ, প্রতিটি পদ্ধতি যা একটি প্রক্রিয়ার অংশ) নিশ্চিত করতে যে এক ধাপে ব্যর্থতা সমগ্র প্রক্রিয়ার ব্যর্থতা। শুধুমাত্র প্রতিটি ধাপের সফল সমাপ্তিই সামগ্রিক সাফল্যের দিকে নিয়ে যায়।
একটি দৈনন্দিন জীবনের উদাহরণ
কল্পনা করুন যে দ্য মিল্ক শেকারস নামে একটি দোকান থেকে ব্যক্তিগতভাবে দুধের একটি কার্টন কেনার লক্ষ্য আপনার আছে . জড়িত সম্ভাব্য পদক্ষেপগুলি নিম্নরূপ হবে:
Leave your house -> Arrive at The Milk Shakers -> Pick up a carton of milk -> Pay for the carton of milk
আপনি যদি আপনার বাড়ি থেকে বের হতে না পারেন, তাহলে পুরো প্রক্রিয়াটিই ব্যর্থতা কারণ প্রথম ধাপটিই ব্যর্থতা। আপনি যদি বাড়ি থেকে বের হয়ে ওয়ালমার্টে যান? প্রক্রিয়াটি এখনও একটি ব্যর্থতা কারণ আপনি মনোনীত দোকানে যাননি। আপনি যে Walmart থেকে দুধ পেতে পারেন তার মানে এই নয় যে প্রক্রিয়াটি চলতে থাকবে। ROP Walmart-এ প্রক্রিয়াটি বন্ধ করে দেয় এবং একটি ব্যর্থতার আউটপুট ফেরত দেয় যা আপনাকে জানায় যে প্রক্রিয়াটি ব্যর্থ হয়েছে কারণ দোকানটি The Milk Shakers ছিল না। যাইহোক, আপনি যদি সঠিক দোকানে যেতেন, প্রক্রিয়াটি অব্যাহত থাকত, আউটপুটগুলি পরীক্ষা করে এবং হয় প্রক্রিয়াটি শেষ করে বা পরবর্তী ধাপে এগিয়ে যেতে। এটি আরও পঠনযোগ্য এবং মার্জিত ত্রুটি পরিচালনা নিশ্চিত করে এবং if/else
ছাড়াই এটি দক্ষতার সাথে অর্জন করে এবং return
পৃথক পদক্ষেপের সাথে যুক্ত বিবৃতি।
রেলে, আমরা ড্রাই মোনাডস নামে একটি রত্ন ব্যবহার করে এই দুই-ট্র্যাক রেলওয়ে আউটপুট অর্জন করতে পারি .
শুকনো মোনাদের ভূমিকা এবং তারা কীভাবে কাজ করে
Monads মূলত একটি গাণিতিক ধারণা ছিল। মূলত, এগুলি বেশ কয়েকটি বিশেষ ফাংশনের একটি রচনা বা বিমূর্ততা যা একটি কোডে ব্যবহৃত হলে, রাষ্ট্রীয় মানগুলির সুস্পষ্ট পরিচালনাকে বাদ দিতে পারে। এগুলি প্রোগ্রাম লজিকের জন্য প্রয়োজনীয় কম্পিউটেশনাল বয়লারপ্লেট কোডের একটি বিমূর্ততাও হতে পারে। স্টেটফুল মান একটি নির্দিষ্ট ফাংশনের জন্য স্থানীয় নয়, কয়েকটি উদাহরণের মধ্যে রয়েছে:ইনপুট, গ্লোবাল ভেরিয়েবল এবং আউটপুট। Monads একটি বাইন্ড ফাংশন ধারণ করে যা এই মানগুলিকে এক মোনাড থেকে অন্য মোনাডে প্রেরণ করা সম্ভব করে; অতএব, তারা স্পষ্টভাবে পরিচালনা করা হয় না. এগুলি ব্যতিক্রম, রোলব্যাক কমিট, লজিক পুনরায় চেষ্টা ইত্যাদি পরিচালনা করার জন্য তৈরি করা যেতে পারে। আপনি এখানে মোনাড সম্পর্কে আরও তথ্য পেতে পারেন।
যেমন এর ডকুমেন্টেশনে বলা হয়েছে, যা আমি আপনাকে পর্যালোচনা করার পরামর্শ দিচ্ছি, শুষ্ক মোনাড হল রুবির জন্য সাধারণ মোনাদের একটি সেট। মোনাডগুলি ত্রুটি, ব্যতিক্রম এবং চেইনিং ফাংশনগুলি পরিচালনা করার জন্য একটি মার্জিত উপায় প্রদান করে যাতে কোডটি আরও বোধগম্য হয় এবং সমস্ত ifs and elses
ছাড়াই সমস্ত পছন্দসই ত্রুটি পরিচালনা করা যায়। . আমরা ফলাফল মোনাড-এ ফোকাস করব কারণ আমাদের সাফল্য/ব্যর্থতার আউটপুটগুলি অর্জনের জন্য এটি ঠিক যা আমরা আগে বলেছি।
আসুন নিম্নলিখিত কমান্ডটি ব্যবহার করে রেলওয়ে-অ্যাপ শিরোনামের একটি নতুন রেল অ্যাপ শুরু করি:
rails new railway-app -T
কমান্ডে -T এর অর্থ হল যে আমরা পরীক্ষার জন্য RSpec ব্যবহার করতে চাই বলে আমরা পরীক্ষার ফোল্ডারটি এড়িয়ে যাব৷
এরপর, আমরা আমাদের জেমফাইলে প্রয়োজনীয় রত্ন যোগ করি:gem dry-monads
সাফল্য/ব্যর্থতার ফলাফল এবং gem rspec-rails
এর জন্য আমাদের টেস্টিং ফ্রেমওয়ার্ক হিসাবে পরীক্ষা এবং উন্নয়ন গ্রুপে। এখন, আমরা bundle install
চালাতে পারি যোগ করা রত্নগুলি ইনস্টল করতে আমাদের অ্যাপে। আমাদের পরীক্ষার ফাইল এবং সাহায্যকারী তৈরি করতে, যদিও, আমাদের নিম্নলিখিত কমান্ডটি চালাতে হবে:
rails generate rspec:install
একটি ফাংশনকে কয়েকটি ধাপে ভাগ করুন
আপনার চূড়ান্ত লক্ষ্য অর্জনের জন্য একসাথে কাজ করে এমন ছোট পদ্ধতিতে আপনার ফাংশনকে ভাগ করার পরামর্শ দেওয়া হয়। এই পদ্ধতিগুলির ত্রুটিগুলি, যদি থাকে, আমাদের প্রক্রিয়াটি ঠিক কোথায় ব্যর্থ হয়েছে তা শনাক্ত করতে এবং আমাদের কোডকে পরিষ্কার এবং পাঠযোগ্য রাখতে সাহায্য করে৷ এটিকে যতটা সম্ভব সহজ করার জন্য, আমরা একটি টয়োটা গাড়ি ডিলারশিপের একটি শ্রেণী তৈরি করব যা একজন ব্যবহারকারীকে একটি গাড়ি সরবরাহ করে৷ যদি চাহিদাকৃত মডেল এবং রঙ পাওয়া যায়, যদি উৎপাদনের বছর 2000 সালের আগে না হয়, এবং যে শহরটি ডেলিভারি করা হবে তা কাছাকাছি শহরের তালিকায় থাকে। এই আকর্ষণীয় হওয়া উচিত. :)
ডেলিভারি প্রক্রিয়াটিকে কয়েকটি ধাপে ভাগ করে শুরু করা যাক:
- যাচাই করুন যে উৎপাদনের বছর 2000 সালের আগে নয়।
- মডেল উপলব্ধ আছে কিনা যাচাই করুন।
- রঙ উপলব্ধ আছে কিনা যাচাই করুন।
- যাচাই করুন যে শহরে ডেলিভারি করা হবে সেটি একটি কাছাকাছি শহর৷ ৷
- গাড়ি বিতরণ করা হবে জানিয়ে একটি বার্তা পাঠান।
এখন যেহেতু আমরা বিভিন্ন ধাপ স্থির করেছি, আসুন কোডের মধ্যে ডুব দেওয়া যাক।
সফল/ব্যর্থতার আউটপুট ফলাফল ইনপুট করা
আমাদের অ্যাপ/মডেল ফোল্ডারে, আসুন car_dealership.rb
নামে একটি ফাইল তৈরি করি এবং গুরুত্বপূর্ণ বিবরণ সহ এই ক্লাসটি শুরু করুন। ফাইলের শীর্ষে, আমাদের dry/monads
প্রয়োজন , এবং ক্লাসের নামের ঠিক পরে, আমাদের অন্তর্ভুক্ত করতে হবে DryMonads[:result, :do]
. এটি ফলাফল মোনাড এবং ডোনেশন (যা ফলন শব্দ ব্যবহার করে বেশ কয়েকটি মোনাডিক অপারেশনের সমন্বয় সম্ভব করে) আমাদের কাছে উপলব্ধ করে তোলে৷
require 'dry/monads'
class CarDealership
include Dry::Monads[:result, :do]
def initialize
@available_models = %w[Avalon Camry Corolla Venza]
@available_colors = %w[red black blue white]
@nearby_cities = %w[Austin Chicago Seattle]
end
end
এরপর, আমরা আমাদের deliver_car
যোগ করি পদ্ধতি, যা জড়িত অন্যান্য সমস্ত পদক্ষেপ নিয়ে গঠিত এবং সমস্ত পদক্ষেপ সফল হলে একটি সফল বার্তা প্রদান করবে। এই ধাপগুলিকে একে অপরের সাথে একত্রিত করতে বা আবদ্ধ করতে আমরা ফলন শব্দটি যোগ করি। এর মানে হল যে এই ধাপগুলির যেকোনো একটি ব্যর্থতার বার্তা deliver_car
-এর ব্যর্থতার বার্তা হয়ে ওঠে পদ্ধতি, এবং তাদের যেকোনো একটিতে সফল আউটপুট তালিকার পরবর্তী ধাপের কলে ফল দেয়।
def deliver_car(year,model,color,city)
yield check_year(year)
yield check_model(model)
yield check_city(city)
yield check_color(color)
Success("A #{color} #{year} Toyota #{model} will be delivered to #{city}")
end
এখন, অন্য সব পদ্ধতি যোগ করা যাক এবং তাদের চেকের ফলাফলের উপর ভিত্তি করে সাফল্য/ব্যর্থতার ফলাফল সংযুক্ত করি।
def check_year(year)
year < 2000 ? Failure("We have no cars manufactured in year #{year}") : Success('Cars of this year are available')
end
def check_model(model)
@available_models.include?(model) ? Success('Model available') : Failure('The model requested is unavailable')
end
def check_color(color)
@available_colors.include?(color) ? Success('This color is available') : Failure("Color #{color} is unavailable")
end
def check_city(city)
@nearby_cities.include?(city) ? Success("Car deliverable to #{city}") : Failure('Apologies, we cannot deliver to this city')
end
আমাদের বর্তমানে আমাদের ক্লাস এবং আমাদের প্রয়োজনীয় সমস্ত পদ্ধতি রয়েছে। কিভাবে এই খেলা হবে? আসুন এই ক্লাসের একটি নতুন উদাহরণ তৈরি করে এবং deliver_car
-এ কল করে খুঁজে বের করি বিভিন্ন আর্গুমেন্ট সহ পদ্ধতি।
good_dealer = CarDealership.new
good_dealer.deliver_car(1990, 'Venza', 'red', 'Austin')
#Failure("We have no cars manufactured in year 1990")
good_dealer.deliver_car(2005, 'Rav4', 'red', 'Austin')
#Failure("The model requested is unavailable")
good_dealer.deliver_car(2005, 'Venza', 'yellow', 'Austin')
#Failure("Color yellow is unavailable")
good_dealer.deliver_car(2000, 'Venza', 'red', 'Surrey')
#Failure("Apologies, we cannot deliver to this city")
good_dealer.deliver_car(2000, 'Avalon', 'blue', 'Austin')
#Success("A blue 2000 Toyota Avalon will be delivered to Austin")
উপরে দেখানো হিসাবে, ডিলিভার_কার পদ্ধতির ব্যর্থতার ফলাফল এটি যে পদ্ধতিতে ব্যর্থ হয় তার উপর নির্ভর করে পরিবর্তিত হয়। সেই পদ্ধতির ব্যর্থতা তার ব্যর্থতায় পরিণত হয় এবং সমস্ত পদ্ধতির সাফল্যের উপর, এটি তার নিজের সাফল্যের ফলাফল ফিরিয়ে দেয়। এছাড়াও, আসুন ভুলে গেলে চলবে না যে এই ধাপগুলি হল স্বতন্ত্র পদ্ধতি যাকে স্বাধীনভাবে deliver_car
বলা যেতে পারে পদ্ধতি একটি উদাহরণ নীচে দেখানো হয়েছে:
good_dealer.check_color('wine')
#Failure("Color wine is unavailable")
good_dealer.check_model('Camry')
#Success('Model available')
RSpec দিয়ে পরীক্ষা করা হচ্ছে
উপরের কোডটি পরীক্ষা করতে, আমরা আমাদের নির্দিষ্ট ফোল্ডারে যাই এবং একটি ফাইল তৈরি করি car_dealership_spec.rb
spec/models
পথে . প্রথম লাইনে, আমাদের 'rails_helper' প্রয়োজন। আমরা প্রথমে ব্যর্থতার প্রেক্ষাপট এবং তারপর সাফল্যের জন্য পরীক্ষা লিখব।
require 'rails_helper'
describe CarDealership do
describe "#deliver_car" don
let(:toyota_dealer) { CarDealership.new }
context "failure" do
it "does not deliver a car with the year less than 2000" do
delivery = toyota_dealer.deliver_car(1990, 'Venza', 'red', 'Austin')
expect(delivery.success).to eq nil
expect(delivery.failure).to eq 'We have no cars manufactured in year 1990'
end
it "does not deliver a car with the year less than 2000" do
delivery = toyota_dealer.deliver_car(2005, 'Venza', 'yellow', 'Austin')
expect(delivery.success).to eq nil
expect(delivery.failure).to eq 'Color yellow is unavailable'
end
end
end
end
উপরে দেখানো হিসাবে, আমরা result.failure
ব্যবহার করে ব্যর্থতা বা সাফল্যের ফলাফলগুলি অ্যাক্সেস করতে পারি অথবা result.success
. সাফল্যের প্রেক্ষাপটের জন্য, পরীক্ষাগুলি এইরকম কিছু দেখাবে:
context "success" do
it "delivers a car when all conditions are met" do
delivery = toyota_dealer.deliver_car(2000, 'Avalon', 'blue', 'Austin')
expect(delivery.success).to eq 'A blue 2000 Toyota Avalon will be delivered to Austin'
expect(delivery.failure).to eq nil
end
end
এখন, আপনি deliver_car
-এ সরবরাহকৃত আর্গুমেন্ট টুইক করে ব্যর্থতার প্রসঙ্গে অন্যান্য পরীক্ষা যোগ করতে পারেন পদ্ধতি আপনি এমন পরিস্থিতিতে আপনার কোডে অন্যান্য চেক যোগ করতে পারেন যেখানে একটি অবৈধ যুক্তি প্রদান করা হয় (যেমন, বছরের ভেরিয়েবলের মান হিসাবে একটি স্ট্রিং প্রদান করা হয় এবং এটির মতো অন্যান্য)। bundle exec rspec
চলছে আপনার টার্মিনালে পরীক্ষা চালায় এবং দেখায় যে সমস্ত পরীক্ষা পাস। আপনাকে মূলত একই সময়ে ব্যর্থতা এবং সাফল্যের ফলাফলের জন্য আপনার পরীক্ষায় চেক যোগ করতে হবে না, কারণ আমরা একটি পদ্ধতির আউটপুট হিসাবে উভয়ই থাকতে পারি না। আমি শুধুমাত্র এটি যোগ করেছি যখন আমাদের ব্যর্থতার ফলাফল এবং এর বিপরীতে সাফল্যের ফলাফল কেমন হয় তা বোঝার জন্য সহায়তা করার জন্য।
উপসংহার
এটি শুধুমাত্র ড্রাই-মোনাডগুলির একটি ভূমিকা এবং রেলওয়ে ওরিয়েন্টেড প্রোগ্রামিং অর্জনের জন্য এটি কীভাবে আপনার অ্যাপে ব্যবহার করা যেতে পারে। এটির একটি প্রাথমিক ধারণা আরও জটিল ক্রিয়াকলাপ এবং লেনদেনের ক্ষেত্রে প্রয়োগ করা যেতে পারে। যেমনটি আমরা দেখেছি, একটি ক্লিনার এবং আরও পঠনযোগ্য কোড শুধুমাত্র ROP ব্যবহার করে অর্জনযোগ্য নয়, তবে ত্রুটি হ্যান্ডলিং বিস্তারিত এবং কম চাপযুক্ত। সর্বদা আপনার প্রক্রিয়া তৈরি করে এমন বিভিন্ন পদ্ধতিতে সংক্ষিপ্ত ব্যর্থতা/সফলতার বার্তা সংযুক্ত করতে মনে রাখবেন, কারণ এই পদ্ধতিটি কোথায় এবং কেন একটি ত্রুটি ঘটেছে তা সনাক্ত করতে সহায়তা করে। আপনি যদি ROP সম্পর্কে আরও তথ্য পেতে চান, আমরা স্কট ব্লাসচিনের এই উপস্থাপনাটি দেখার পরামর্শ দিই৷