2.20 ত্রুটি সামলানো ও স্থিতিস্থাপকতার প্যাটার্ন
পরিচিতি ও প্রেরণা
আপনার লেখা প্রতিটি প্রোগ্রাম ব্যর্থ হবে। একটি ডিস্ক ভরে যায়, একটি নেটওয়ার্ক পড়ে যায়, একটি সার্ভিস টাইমআউট করে, কোনো কলার আবর্জনা পাঠায়, কোনো নির্ভরতা এমন কিছু ফেরত দেয় যা ডকুমেন্টেশন কখনো উল্লেখ করেনি। প্রশ্ন কখনো ব্যর্থতা ঘটবে কি না নয়; প্রশ্ন হলো আপনার কোড সেই ব্যর্থতার মুখোমুখি হয় একটি পরিকল্পনা নিয়ে নাকি একটি বিস্ময় নিয়ে। ত্রুটি সামলানো হলো লাইনে লাইনে এবং ফাংশনে ফাংশনে সিদ্ধান্ত নেওয়ার কারুকাজ যে জগৎ সহযোগিতা না করলে আপনার কোড কী করবে। এটি নির্মাণের সবচেয়ে অনাকর্ষণীয় অংশ এবং সেই অংশ যা, যেকোনো ফিচারের চেয়ে বেশি, ঠিক করে মানুষ আপনার সিস্টেমকে বিশ্বাস করে কি না।
এই অধ্যায় কোড ও উপাদান স্তরে স্থিতিস্থাপকতা নিয়ে: একটি ফাংশন, মডিউল বা API-র ভেতরের পছন্দ। এটি অধ্যায় 3.5-এর পরিপূরক, যা সিস্টেম স্তরে স্থিতিস্থাপকতা কভার করে (লোড ব্যালান্সিং, প্রতিলিপি, সার্ভিস জুড়ে ফেইলওভার)। একটি অঞ্চল অন্ধকার হলে অধ্যায় 3.5 পুরো প্ল্যাটফর্ম দাঁড় করিয়ে রাখে; এই অধ্যায় একটি একক অনুরোধকে আপনার ডেটা নষ্ট করা বা চিহ্ন না রেখে উধাও হওয়া থেকে ঠেকায়। দুটি পরস্পরকে শক্তিশালী করে। আপনার স্থাপত্যে একটি সার্কিট ব্রেকারের তেমন মানে নেই যদি তার পেছনের কোড এক্সেপশন গিলে ফেলে, আর একটি রক্ষণাত্মক ফাংশন আপনাকে বাঁচাতে পারে না যদি চারপাশের সিস্টেমে বাড়তি ব্যবস্থা না থাকে। এই অধ্যায় অধ্যায় 2.9-এর (সফটওয়্যার নির্মাণ) ওপরও দাঁড়ায়, যেখানে ত্রুটি সামলানো অনেক শৃঙ্খলার একটি ছিল; এখানে তা পুরো বিষয় হয়।
বড় দলের জন্য পুরস্কার সামঞ্জস্য। শত শত ইঞ্জিনিয়ার শত শত ভিন্ন উপায়ে ত্রুটি সামলালে প্রতিটি সার্ভিস একটি ধাঁধা এবং প্রতিটি ঘটনা একটি খননকাজ হয়ে ওঠে। এন্টারপ্রাইজ পরিবেশে সেই অসামঞ্জস্য প্রতিটি নিরীক্ষা ও প্রতিটি ইন্টিগ্রেশনের খরচ বাড়ায়। সরকার ও অন্যান্য উচ্চ-ঝুঁকির সিস্টেমে ঝুঁকি আরও তীক্ষ্ণ: সঠিকতা, নিরাপদ ব্যর্থতা এবং স্পষ্ট নিরীক্ষা ট্রেইল এমন বৈশিষ্ট্য নয় যা আপনি পরে যোগ করেন, বরং প্রথম কমিট থেকেই সিস্টেমের থাকা দরকার এমন গুণ। যে সুবিধা সিস্টেম নিঃশব্দে ভুল হিসাব করে, বা যে নথি সিস্টেম ব্যর্থতা লগ না করে হারায়, তা কেবল ত্রুটিপূর্ণ নয়। তা এমনভাবে অবিশ্বাসযোগ্য, যা তার পেছনের প্রতিষ্ঠানকে ক্ষয় করে।
মূল নীতিসমূহ
- ভুল, ত্রুটির উৎস ও ব্যর্থতা আলাদা করুন, এবং প্রতিটি সঠিক স্তরে সামলান।
- ফেইল-ফাস্ট নাকি ফেইল-সেফ তা প্রসঙ্গ ধরে ইচ্ছাকৃতভাবে বাছুন, কখনো দুর্ঘটনায় নয়।
- প্রতিটি ফাংশন ও API-র ত্রুটি-সামলানোর চুক্তি সুস্পষ্ট ও সৎ করুন।
- সীমানায় যাচাই করুন; ভেতরে বিশ্বাস করুন; প্যারানয়া ছাড়াই রক্ষা করুন।
- কখনো নিঃশব্দে ত্রুটি গিলবেন না; তা প্রকাশ করুন, মুড়ে দিন, বা উদ্দেশ্য নিয়ে সামলান।
- আইডেমপোটেন্স, টাইমআউট, ব্যাকঅফ ও জিটার দিয়ে রিট্রাই নিরাপদ করুন।
- সুখী পথ যে নকশা-মনোযোগ পায়, ত্রুটির পথকেও তা দিন।
সুপারিশ
ভুল, ত্রুটির উৎস ও ব্যর্থতা আলাদা করুন
এলোমেলো শব্দভাণ্ডার এলোমেলো সামলানো তৈরি করে, তাই স্পষ্ট পরিভাষা দিয়ে শুরু করুন। ত্রুটির উৎস (fault) হলো সিস্টেমের একটি খুঁত: একটি বাগ, একটি খারাপ কনফিগারেশন, একটি নির্ভরতা যা বন্ধ। ভুল (error) হলো সেই অশুদ্ধ অভ্যন্তরীণ অবস্থা, যা ত্রুটির উৎস তৈরি করে: যেখানে মান থাকার কথা সেখানে একটি null, একটি ব্যালেন্স যা আর মেলে না। ব্যর্থতা (failure) হলো বাইরের পর্যবেক্ষক যা দেখেন: অনুরোধ ভুল উত্তর বা কোনো উত্তরই ফেরত দেয় না। একটি ত্রুটির উৎস অনেক ভুল ঘটাতে পারে, এবং অনেক ভুল কোনোটি দৃশ্যমান ব্যর্থতা হওয়ার আগেই ধরা পড়তে পারে। ত্রুটি সামলানোর পুরো উদ্দেশ্য হলো সেই শৃঙ্খল ভাঙা, ভুলটি ব্যবহারকারী বা নিরীক্ষক যে ব্যর্থতা অনুভব করেন তা হওয়ার আগে ধরা।
এই শব্দভাণ্ডার আপনাকে বলে কোথায় কাজ করবেন। ত্রুটির উৎস সম্বোধিত হয় পর্যালোচনা, টেস্টিং ও কনফিগারেশনে। ভুল সম্বোধিত হয় রানটাইমে এই অধ্যায়ের প্যাটার্ন দিয়ে। ব্যর্থতা সম্বোধিত হয় অবজার্ভেবিলিটি (অধ্যায় 9.2) এবং অধ্যায় 3.5-এর সিস্টেম-স্তরের স্থিতিস্থাপকতা দিয়ে। আপনার দল এই শব্দগুলো ভাগ করলে ঘটনা পর্যালোচনা ধারালো হয়: “বাগ” কী ছিল তা নিয়ে তর্কের বদলে আপনি ঠিক বলতে পারেন শৃঙ্খল কোথায় ভাঙা উচিত ছিল এবং ভাঙেনি।
প্রসঙ্গ ধরে ফেইল-ফাস্ট বা ফেইল-সেফ বাছুন
ফেইল-ফাস্ট মানে কিছু ভুল হওয়ার মুহূর্তেই থামা, খারাপ অবস্থায় এগোতে অস্বীকার করা যাতে সমস্যা জোরে এবং তার কারণের কাছেই প্রকাশ পায়। ফেইল-সেফ মানে একটি পরিচিত, নিরীহ অবস্থায় নেমে আসা এবং যা নিরাপদে পারেন তা সেবা দিয়ে চলা। কোনোটিই সর্বজনীনভাবে সঠিক নয়, এবং দক্ষতা হলো প্রসঙ্গ ধরে বাছা। উন্নয়নের সময় এবং অভ্যন্তরীণ সীমানায় ফেইল-ফাস্ট আপনার বন্ধু: লঙ্ঘিত ইনভ্যারিয়ান্টে থেমে যাওয়া প্রোগ্রাম আপনাকে দীর্ঘ রহস্যের বদলে একটি ছোট স্ট্যাক ট্রেস দেয়। প্রোডাকশনে, ব্যবহারকারী-মুখী সিস্টেমের প্রান্তে, ফেইল-সেফ প্রায়ই জেতে: কিছুই ফেরত না দেওয়া সুপারিশ প্যানেল এমন চেকআউট পাতার চেয়ে ভালো, যা লোডই হয় না।
প্রতিটি সীমানার জন্য এটি ইচ্ছাকৃতভাবে ঠিক করুন এবং সিদ্ধান্ত লিখে রাখুন। একটি ফ্লাইট-কন্ট্রোল বা চিকিৎসা-যন্ত্রের উপাদান একটি সংজ্ঞায়িত অবস্থায় নিরাপদে ব্যর্থ হয় কারণ নষ্ট ডেটায় চালিয়ে যাওয়া কাউকে আঘাত করতে পারে। একটি খতিয়ান পোস্টিং দ্রুত ব্যর্থ হয় কারণ ভুল এন্ট্রি পোস্ট করা কোনোটাই না করার চেয়ে খারাপ। ভুল জোড়া দুই দিকেই বিপজ্জনক: যেখানে ফেইল-ফাস্ট দরকার ছিল সেখানে ফেইল-সেফ বিকৃতি লুকায়, আর যেখানে ফেইল-সেফ দরকার ছিল সেখানে ফেইল-ফাস্ট একটি প্রসাধনী হোঁচটকে বিভ্রাটে পরিণত করে।
আপনার ত্রুটি-সংকেত প্রক্রিয়া বাছুন এবং তা সামঞ্জস্যপূর্ণভাবে ব্যবহার করুন
কিছু ভুল হয়েছে সংকেত দিতে ভাষাগুলো আপনাকে দুটি বিস্তৃত উপায় দেয়। এক্সেপশন সামলানো একটি অবজেক্ট কল স্ট্যাকে ওপরে ছুড়ে দেয় যতক্ষণ না কোনো হ্যান্ডলার তা ধরে, ত্রুটির পথকে মূল যুক্তি থেকে আলাদা করে। বিকল্প হলো সুস্পষ্ট ত্রুটি-মান: ফাংশন একটি ফলাফল ও একটি ত্রুটি দুটিই ফেরত দেয়, এবং কলারকে দুটিই পরীক্ষা করতে হয়। অনেক আধুনিক ভাষা শেষটিকে একটি Result টাইপ দিয়ে আনুষ্ঠানিক করে, প্রায়ই Result বা Either নামে, যা কলারকে মান ব্যবহারের আগে সাফল্য বা ব্যর্থতা খুলতে বাধ্য করে। প্রতিটি পদ্ধতির খরচ আছে। এক্সেপশন সুখী পথ পরিচ্ছন্ন রাখে কিন্তু নিয়ন্ত্রণ প্রবাহ লুকাতে পারে এবং ডেভেলপারদের তথ্য মুছে ফেলা ক্যাচ-অল ব্লকে প্রলুব্ধ করে। সুস্পষ্ট ফলাফল প্রতিটি ব্যর্থতাকে টাইপ স্বাক্ষরে দৃশ্যমান করে কিন্তু আনুষ্ঠানিকতা যোগ করে এবং ভাষা পরীক্ষা বাধ্য না করলে উপেক্ষা করা যায়।
সঠিক উত্তর কোন প্রক্রিয়া তার চেয়ে সামঞ্জস্য ও সততা নিয়ে বেশি। আপনার ভাষা ও ইকোসিস্টেমের পছন্দের রীতি বাছুন এবং আপনার সার্ভিস জুড়ে একরকম প্রয়োগ করুন যাতে পাঠক সবসময় জানেন ব্যর্থতা কীভাবে চলাচল করে। এক্সেপশন সংরক্ষণ করুন সত্যিকারের ব্যতিক্রমী অবস্থার জন্য, “ব্যবহারকারী পাওয়া যায়নি”-র মতো সাধারণ নিয়ন্ত্রণ প্রবাহের জন্য নয়, যা স্বাভাবিক ফলাফল হিসেবে মডেল করা ভালো। যা-ই বাছুন, কখনো ব্যর্থতাকে অদৃশ্য হতে দেবেন না: অযাচাইকৃত ত্রুটি-মান একটি ফাঁকা catch ব্লকের মতোই বিপজ্জনক। একটি বড় কোডবেসে একটি লিখিত রীতি আর উপেক্ষা-করা ত্রুটি চিহ্নিতকারী একটি লিন্টার যেকোনো ব্যক্তির পছন্দকে হারায়।
ত্রুটি-সামলানোর চুক্তি সুস্পষ্ট করুন
প্রতিটি ফাংশন ও প্রতিটি API-র একটি ত্রুটি-সামলানোর চুক্তি আছে, কেউ তা লিখুক বা না লিখুক। তা উত্তর দেয়: এখানে কী ভুল হতে পারে, আপনি তা কীভাবে জানবেন, এবং তা হলে অবস্থা সম্পর্কে কী নিশ্চিত? সেই চুক্তি সুস্পষ্ট করুন। একটি ফাংশন কোন ত্রুটি ফেরত দিতে বা ছুড়তে পারে তা নথিবদ্ধ করুন, পুনরুদ্ধারযোগ্য ত্রুটি (কলার যুক্তিসঙ্গতভাবে রিট্রাই বা ফলব্যাক করতে পারে) এবং অপুনরুদ্ধারযোগ্য ত্রুটি (কলার এটি সারাতে পারে না এবং প্রচার বা বাতিল করা উচিত) আলাদা করুন, এবং ব্যর্থতায় ফাংশন অবস্থা অপরিবর্তিত রাখে কি না তা বলুন। এই শেষ বৈশিষ্ট্য, কখনো শক্তিশালী এক্সেপশন নিশ্চয়তা বলা হয়, মানে ব্যর্থ কল এমন যেন কখনো হয়নি, যা ঠিক কলারকে নিরাপদে রিট্রাই করতে দেয়।
একটি পাবলিক বা দল-জোড়া API-র জন্য এই চুক্তি ইন্টারফেসের অংশ, প্যারামিটার টাইপের মতোই বাস্তব। একটি ছোট, স্থিতিশীল ত্রুটি শ্রেণিবিন্যাস নকশা করুন: যাচাইকরণ ত্রুটি, পাওয়া যায়নি, দ্বন্দ্ব, অননুমোদিত, নির্ভরতা-অনুপলব্ধ এবং অভ্যন্তরীণ ত্রুটির মতো সীমিত বিভাগ। কলাররা তখন স্ট্রিং পার্স না করেই বিভাগ ধরে শাখা করতে পারে। একটি স্পষ্ট শ্রেণিবিন্যাস অনেক সার্ভিস জুড়ে ত্রুটি সামলানো সংমিশ্রণযোগ্য করে, এবং ব্যর্থতা নিরীক্ষণযোগ্য করে, কারণ প্রতিটি ব্যর্থতা একটি পরিচিত, নামকরা ধরনে মেলে।
সীমানায় যাচাই করুন এবং প্যারানয়া ছাড়াই রক্ষা করুন
আস্থা সীমানা পেরোনো ডেটা (একটি নেটওয়ার্ক অনুরোধ, একটি ফাইল, ব্যবহারকারীর ইনপুট, অন্য সার্ভিসের বার্তা) যাচাই না হওয়া পর্যন্ত বৈরী গণ্য করুন, এবং সীমানায় একবার, পুঙ্খানুপুঙ্খভাবে যাচাই করুন। এটি বিচক্ষণতার সঙ্গে প্রয়োগ করা রক্ষণাত্মক প্রোগ্রামিং। যে মডিউলের ইনপুট আপনি ইতিমধ্যে যাচাই করেছেন, তার ভেতরে প্রতিটি লাইনে অপ্রয়োজনীয় পরীক্ষা যুক্তি লুকায় এবং ঠিক সেই ব্যর্থতাগুলো চাপা দেয়, যা আপনি দেখতে চাইতেন। শৃঙ্খলা হলো: প্রান্তে কঠোরভাবে রক্ষা করুন, ভেতরে বিশ্বাস করুন। ডেটা যেখানে ঢোকে সেখানে কাঠামো, পরিসর ও ইনভ্যারিয়ান্ট যাচাই করুন, তা এমন টাইপে রূপান্তর করুন যা অবৈধ অবস্থাকে অপ্রকাশযোগ্য করে, এবং ভেতরের কোডকে ধরে নিতে দিন যে সে পরিষ্কার ডেটা নিয়ে কাজ করছে।
প্যারানয়ার প্রকৃত খরচ আছে। null পরীক্ষা ও রক্ষণাত্মক শাখায় ঢাকা কোড পড়া কঠিন, এবং আরও খারাপ, তা প্রায়ই একটি স্পষ্ট ব্যর্থতাকে নীরব কাঁধ ঝাঁকুনিতে পরিণত করে, যেখানে অ্যালার্ম তোলা উচিত ছিল সেখানে একটি ডিফল্ট ফেরত দিয়ে। যে রক্ষণশীলতা বাগ ঢাকে তা নিরাপত্তা নয়; তা স্থগিতকরণ।
রিট্রাই নিরাপদ, সীমিত ও ভদ্র করুন
অনেক ত্রুটির উৎস সাময়িক: ক্ষণিক নেটওয়ার্ক ঝলক, একটি সার্ভিস পুনরায় চালু হওয়া, সংক্ষিপ্ত লক কনটেনশন। যেকোনো বিতরিত সিস্টেমে (অধ্যায় 3.3) এই আংশিক ব্যর্থতা ব্যতিক্রমের বদলে স্বাভাবিক ঘটনা। রিট্রাই স্বাভাবিক সাড়া, কিন্তু একটি সরল রিট্রাই লুপ ভরা বন্দুক। প্রথমত, আপনি যে অপারেশন রিট্রাই করেন তা আইডেমপোটেন্ট করুন, মানে দুবার সম্পাদন একবার সম্পাদনের মতোই প্রভাব ফেলে। আইডেমপোটেন্স ছাড়া টাইমআউটের পরের রিট্রাই একটি কার্ডে দুবার চার্জ করতে বা দুটি রেকর্ড তৈরি করতে পারে, কারণ আপনি বলতে পারেন না প্রথম প্রচেষ্টা ব্যর্থ হয়েছিল নাকি কেবল তার স্বীকৃতি হারিয়েছে। প্রাপক যাতে পুনরাবৃত্তি চিনে ডিডুপ করতে পারে সেজন্য রাইটের জন্য আইডেমপোটেন্সি কী ব্যবহার করুন।
দ্বিতীয়ত, প্রতিটি দূরবর্তী কলে টাইমআউট দিন যাতে আটকে যাওয়া নির্ভরতা আপনাকে আটকাতে না পারে। তৃতীয়ত, সূচকীয় ব্যাকঅফ দিয়ে রিট্রাই ব্যবধান রাখুন, প্রতি প্রচেষ্টার পরে অপেক্ষা দ্বিগুণ করে, এবং জিটার (সামান্য এলোমেলো বিলম্ব) যোগ করুন যাতে একসঙ্গে সেরে ওঠা হাজার ক্লায়েন্ট একটি ভিড়ে সমলয় না হয়ে সেরে-ওঠা সার্ভিসকে আবার ফেলে না দেয়। চতুর্থত, রিট্রাইয়ের সংখ্যা ও মোট সময় সীমিত করুন, তারপর মার্জিতভাবে হাল ছাড়ুন। সীমা, ব্যাকঅফ, জিটার ও আইডেমপোটেন্স ছাড়া রিট্রাই একটি ছোট ঝলককে নিজে-ডেকে-আনা বিভ্রাটে পরিণত করার সবচেয়ে সাধারণ উপায়ের একটি।
কোডে সার্কিট ব্রেকার, বাল্কহেড ও মার্জিত অবনমন যোগ করুন
একটি নির্ভরতা সত্যিই বন্ধ থাকলে তাকে রিট্রাই করা কেবল পরিশ্রম অপচয় করে এবং গর্ত গভীর করে। একটি সার্কিট ব্রেকার একটি নির্ভরতায় কলের ব্যর্থতার হার দেখে এবং ব্যর্থতা সীমা পেরোলে ধ্বংসপ্রাপ্ত কলের অপেক্ষার বদলে কুলডাউন সময়ের জন্য তাৎক্ষণিক ব্যর্থ হতে “খুলে” যায়। কুলডাউনের পরে সে একটি পরীক্ষামূলক কল যেতে দেয় এবং নির্ভরতা সেরে উঠলে আবার বন্ধ হয়। এটি আপনার কলার (জমে-থাকা টাইমআউটের বদলে দ্রুত, পূর্বানুমেয় ব্যর্থতা) ও সংগ্রামরত নির্ভরতা (সেরে ওঠার শ্বাস নেওয়ার জায়গা) দুটিকেই রক্ষা করে। জাহাজের জলরোধী কুঠুরির নামে নামকরা বাল্কহেড প্যাটার্ন সম্পদ আলাদা করে যাতে একটি সম্পৃক্ত নির্ভরতা প্রতিটি থ্রেড বা সংযোগ খেয়ে পুরো প্রসেস ডুবিয়ে না দেয়; আপনি প্রতিটি নির্ভরতাকে নিজস্ব সীমিত পুল দেন।
এই প্যাটার্ন কোড স্তরে মার্জিত অবনমনের সঙ্গে জোড় বাঁধে: অপরিহার্য নয় এমন নির্ভরতা অনুপলব্ধ হলে ত্রুটির বদলে হ্রাসপ্রাপ্ত কিন্তু কার্যকর ফলাফল ফেরত দিন। বাসি তথ্যের নোটসহ ক্যাশ করা ডেটা দেখান, ব্যক্তিগতকরণ প্যানেল লুকান, রাইট পরের জন্য কিউ করুন। এটি অধ্যায় 3.5-এর সিস্টেম-স্তরের স্থিতিস্থাপকতার স্থানীয় পরিপূরক: স্থাপত্য মেশিন জুড়ে বাড়তি ব্যবস্থা দেয়, আর আপনার কোড একটি অংশ অনুপস্থিত থাকলে সুস্থ আচরণ দেয়।
প্রসঙ্গসহ ত্রুটি মুড়ুন এবং কখনো গিলবেন না
যেখানে ঘটেছে সেখান থেকে দশ স্তর ওপরে “connection refused” পড়া ত্রুটি প্রায় অকেজো। ত্রুটি ছড়ানোর সময় প্রসঙ্গসহ মুড়ুন: আপনি কী করার চেষ্টা করছিলেন, কোন এন্টিটি বা অনুরোধ, কোন নির্ভরতা, এবং মূল কারণ সংরক্ষণ করে যাতে শিকড় হারিয়ে না যায়। ভালো ভাষা ও লাইব্রেরি এই ত্রুটি-শৃঙ্খল সরাসরি সমর্থন করে। লক্ষ্য হলো একটিমাত্র লগ লাইন অন-কল ইঞ্জিনিয়ারকে বলে কী ব্যর্থ হয়েছে, কোন অপারেশনে, কোন ইনপুটের জন্য। এটি অধ্যায় 9.2-এর অবজার্ভেবিলিটি ও অধ্যায় 2.15-এর ডিবাগিংয়ের কাঁচামাল।
প্রধান পাপ হলো ত্রুটি গিলে ফেলা: একটি ফাঁকা catch ব্লক, একটি উপেক্ষা-করা রিটার্ন মান, একটি catch যা ডিবাগ স্তরে লগ করে কিছুই না ঘটার মতো চালিয়ে যায়। গিলে-ফেলা ত্রুটি অদৃশ্য হয় না; সে পরে নষ্ট ডেটা বা ব্যাখ্যাহীন ত্রুটি হিসেবে ফিরে আসে, এখন তার কারণ থেকে বিচ্ছিন্ন। প্রতিটি ত্রুটির তিনটি নিয়তির একটি পেতে হবে: সামলান (পুনরুদ্ধার বা অবনমন), মুড়ে ছড়িয়ে দিন, বা স্ট্যাকের শীর্ষে পূর্ণ প্রসঙ্গসহ লগ করে ব্যর্থ হন। ত্রুটি ধরে এর কোনোটিই না করলে আপনি আপনার ভবিষ্যৎ আত্মার কাছ থেকে একটি ভবিষ্যৎ ঘটনা লুকাতে বেছে নিয়েছেন।
ট্রেড-অফ: সুবিধা ও অসুবিধা
| পদ্ধতি | সুবিধা | অসুবিধা |
|---|---|---|
| এক্সেপশন | পরিচ্ছন্ন সুখী পথ; অযাচাইকৃত হলে উপেক্ষা করা কঠিন | লুকানো নিয়ন্ত্রণ প্রবাহ; ক্যাচ-অল মুছে ফেলায় প্রলুব্ধ করে |
| সুস্পষ্ট ত্রুটি-মান / Result টাইপ | স্বাক্ষরে ব্যর্থতা দৃশ্যমান; সামলানো বাধ্য করে | বেশি আনুষ্ঠানিকতা; প্রয়োগ ছাড়া উপেক্ষা করা যায় |
| ফেইল-ফাস্ট | বাগ জোরে ও কারণের কাছে প্রকাশ করে | প্রান্তে ব্যবহার করলে দুর্বল ব্যবহারকারী অভিজ্ঞতা |
| ফেইল-সেফ | সেবা চালু রাখে; ব্যবহারকারী ও ডেটা রক্ষা করে | যেখানে ফেইল-ফাস্ট দরকার ছিল সেখানে ব্যবহার করলে বিকৃতি ঢাকতে পারে |
| ব্যাকঅফসহ রিট্রাই | সাময়িক ত্রুটি স্বয়ংক্রিয়ভাবে পার করে | আইডেমপোটেন্স ছাড়া লোড বাড়ায় ও ডাবল-রাইট ঘটায় |
| সার্কিট ব্রেকার | দ্রুত ব্যর্থতা; নির্ভরতাকে সেরে উঠতে দেয় | বাড়তি অবস্থা ও টিউনিং; স্থায়ী সমস্যা ঢাকতে পারে |
| সীমানায় রক্ষণাত্মক যাচাইকরণ | খারাপ ডেটা আগে, একবার, জোরে ধরে | বাড়াবাড়ি হলে যুক্তি এলোমেলো করে এবং প্রকৃত ব্যর্থতা লুকায় |
কেন্দ্রীয় টানাপোড়েন দৃশ্যমানতা ও গোলমালের মধ্যে। খুব নীরবে ত্রুটি সামলালে আপনি সমস্যা লুকান যতক্ষণ না তা ব্যয়বহুল হয়; খুব জোরে ও সর্বত্র সামলালে আপনি আনুষ্ঠানিকতায় সংকেত ডুবিয়ে দেন এবং গুরুত্বপূর্ণ ব্যর্থতা ঢাকেন। অবস্থান ও উদ্দেশ্য দিয়ে এর সমাধান করুন। সীমানায় জোরালো ও কঠোর হোন, যেখানে খারাপ ডেটা ও নির্ভরতা ব্যর্থতা ঢোকে। ভেতরে নীরব ও বিশ্বাসী হোন, যেখানে ইনপুট ইতিমধ্যে পরিষ্কার। ফেইল-ফাস্ট বনাম ফেইল-সেফ প্রতি সীমানায় ঠিক করুন এবং লিখে রাখুন। লক্ষ্য এমন কোড, যেখানে প্রতিটি ব্যর্থতার ঠিক একজন স্পষ্ট মালিক ও একটি স্পষ্ট নিয়তি আছে, এবং কিছু ফাটলের মধ্যে নিঃশব্দে পড়ে না।
আপনার দলের সঙ্গে আলোচনার প্রশ্ন
আমাদের সার্ভিস জুড়ে কি একটি ভাগ করা ত্রুটি শ্রেণিবিন্যাস ও ত্রুটি-সামলানোর রীতি আছে, নাকি প্রতিটি দল নিজের মতো করে? বড় দলে এটি সংমিশ্রিত হওয়া ব্যর্থতা ও বিভ্রান্তিকর ব্যর্থতার পার্থক্য। একটি সার্ভিস যখন যাচাইকরণ সমস্যায় HTTP 500 ফেরত দেয়, আরেকটি টাইপ করা এক্সেপশন ছোড়ে, তৃতীয়টি null ফেরত দেয়, তখন প্রতিটি ইন্টিগ্রেশন একটি দর-কষাকষি এবং প্রতিটি ঘটনা একটি অনুবাদ অনুশীলন। আপনার তিনটি সার্ভিস জুড়ে একই যৌক্তিক ব্যর্থতার, ধরুন “রেকর্ড পাওয়া যায়নি”-র, উদাহরণ আনুন এবং দেখুন তারা কতটা ভিন্নভাবে তা সংকেত দেয়। উত্তর একটি লিখিত মানে পরিণত হওয়া উচিত: ত্রুটি বিভাগের একটি সীমিত সেট, তা সংকেত দেওয়ার একটি সামঞ্জস্যপূর্ণ উপায়, এবং তা প্রয়োগ করা একটি লিন্টার বা পর্যালোচনা চেকলিস্ট। এখানে সামঞ্জস্য প্রতিটি ভবিষ্যৎ ইন্টিগ্রেশন, নিরীক্ষা ও অন-কল শিফটে ফল দেয়।
প্রতিটি গুরুত্বপূর্ণ সীমানার জন্য আমরা কি ইচ্ছাকৃতভাবে ফেইল-ফাস্ট বা ফেইল-সেফ বেছেছি, এবং কোড কি সেই পছন্দের সঙ্গে মেলে? বেশিরভাগ দল কখনো এই সিদ্ধান্ত সুস্পষ্টভাবে নেয়নি, মানে যিনি প্রথম কোড লিখেছেন তিনিই তা নিয়েছেন, অসঙ্গতভাবে। প্রতিদ্বন্দ্বী বিবেচনা প্রকৃত: ফেইল-সেফ ব্যবহারকারীদের সেবা দিয়ে চলে কিন্তু বিকৃতি ছড়াতে দিতে পারে, আর ফেইল-ফাস্ট ডেটা রক্ষা করে কিন্তু একটি ছোট নির্ভরতা বিভ্রাটকে দৃশ্যমান ব্যর্থতায় পরিণত করতে পারে। আপনার ঘটনা ইতিহাস আনুন এবং সবচেয়ে খারাপ কয়েকটির জন্য জিজ্ঞেস করুন কোড কি সেভাবে ব্যর্থ হয়েছিল, আগে জিজ্ঞেস করা হলে আপনি যেভাবে বাছতেন। আপনি চান এমন প্রমাণ হলো প্রতিটির ওপর ইচ্ছাকৃত লেবেলসহ আপনার সীমানার মানচিত্র, বিশেষত যেখানে অর্থ, নিরাপত্তা বা নাগরিক রেকর্ড জড়িত। লেবেল ও কোড না মিললে আপনি আপনার পরবর্তী সমাধান খুঁজে পেয়েছেন।
আমরা শেষবার কখন ইচ্ছা করে একটি ত্রুটির পথ চালিয়েছিলাম, এবং তা কি নকশা অনুযায়ী আচরণ করেছিল? ত্রুটির পথ সাধারণত আপনার মালিকানার সবচেয়ে কম-পরীক্ষিত কোড, তবু সেখানেই বিশ্বাস জেতা বা হারানো হয়, এবং “আমরা নিরাপদে ব্যর্থ হই” এমন দাবি যা আপনি কখনো ঘটতে দেখেননি তা সমর্থন করতে পারবেন না। আইডেমপোটেন্স ছাড়া রিট্রাই লুপ, ভুল সীমার সার্কিট ব্রেকার, বিরল শাখায় গিলে-ফেলা এক্সেপশন: এগুলো লুকিয়ে থাকে যতক্ষণ না প্রকৃত ঘটনা আপনার জন্য তাদের খুঁজে পায়। একটি বাস্তবসম্মত পরিবেশে ইচ্ছাকৃতভাবে ব্যর্থতা ঢোকানোর ফল আনুন (একটি মেরে ফেলা নির্ভরতা, একটি প্ররোচিত টাইমআউট, একটি বিকৃত পেলোড)। অনুসরণীয় পদক্ষেপ হলো ব্যর্থতা-ইনজেকশন রুটিন করা, যাতে পুনরুদ্ধার, অবনমন ও নিরাপদ-ব্যর্থতা আচরণ আশা করার বদলে নিরন্তর যাচাই হয়। আপনি কখনো ট্রিগার করেননি এমন যেকোনো ত্রুটির পথ একটি অপরীক্ষিত প্রতিশ্রুতি।
আমাদের কোন রাইট অপারেশন আইডেমপোটেন্ট, এবং হারানো স্বীকৃতির পরের রিট্রাই কোথায় একটি পেমেন্ট বা রেকর্ডের মতো বাস্তব-জগতের প্রভাব ডুপ্লিকেট করত? রিট্রাই সবচেয়ে সাধারণ স্থিতিস্থাপকতার প্রতিবর্ত, এবং অসাবধানে করলে একটি সাময়িক ঝলক ডুপ্লিকেট অর্থ বা ডেটায় পরিণত হওয়ার সবচেয়ে সাধারণ উপায়। বড় দলে রিট্রাই যুক্তি প্রায়ই ভাগ করা ক্লায়েন্ট, মিডলওয়্যার ও পৃথক সার্ভিসে একসঙ্গে থাকে, তাই একটি একক রাইট কয়েক স্তরে রিট্রাই হতে পারে, কেউ মোট আচরণের মালিক নন। প্রতিদ্বন্দ্বী টান হলো আইডেমপোটেন্সি কী, ডিডুপ্লিকেশন ও সংরক্ষিত অনুরোধ ফলাফল সংরক্ষণ ও কোড যোগ করে, এবং সরবরাহের চাপে থাকা দল ভুলভাবে নিরাপদ ধরে নেওয়া রাইটের জন্য তা এড়িয়ে যায়। আপনার বাহ্যিকভাবে দৃশ্যমান রাইটের একটি তালিকা আনুন, প্রতিটি চিহ্নিত করে আইডেমপোটেন্সি কী বহন করে কি না এবং প্রাপক কীভাবে পুনরাবৃত্তি চিনে ডিডুপ করে। এন্টারপ্রাইজ ও সরকারি পরিবেশে অর্থ সরায় বা নাগরিকের রেকর্ড বদলায় এমনগুলো আগে চিহ্নিত করুন, কারণ ডাবল পেমেন্ট বা ডুপ্লিকেট সুবিধা কেবল ত্রুটি নয়, একটি নিরীক্ষা পর্যবেক্ষণ এবং কখনো আইনি ঝুঁকি।
আমাদের টাইমআউট, সার্কিট ব্রেকার ও বাল্কহেড কি একটি ভাগ করা, পরীক্ষিত লাইব্রেরি থেকে আসে, নাকি প্রতিটি দল হাতে বানায়? এই প্যাটার্ন বর্ণনা করা সহজ এবং সূক্ষ্মভাবে ভুল করাও সহজ: একটি অনুপস্থিত টাইমআউট, কখনো ট্রিপ না করা ব্রেকার সীমা, একটি সংযোগ পুলের এমন আকার যাতে একটি ধীর নির্ভরতা পুরো প্রসেসকে অনাহারে রাখে। প্রতিটি দল পুনর্বাস্তবায়ন করলে আপনি অনেক সামান্য ভাঙা কপি জমান এবং একটি ত্রুটি খুঁজে পেলে একবারে সারানোর একক জায়গা থাকে না। প্রতিদ্বন্দ্বী বিবেচনা হলো ভাগ করা লাইব্রেরি একটি সাধারণ ইন্টারফেস ও আপগ্রেড ছন্দ চাপায়, এবং অস্বাভাবিক রানটাইম বা লেটেন্সি প্রয়োজনের দল বিরক্ত হতে বা তা এড়িয়ে যেতে পারে। প্রোডাকশনে আসলে কতগুলো ভিন্ন রিট্রাই-ও-ব্রেকার বাস্তবায়ন চলে, এবং কোন সার্ভিসের বাইরের কলে এখনো কোনো টাইমআউটই নেই, তার একটি জরিপ আনুন। একটি বড় এন্টারপ্রাইজ বা সংস্থার জন্য একটি যাচাইকৃত ভাগ করা লাইব্রেরি নিরাপত্তা পর্যালোচক ও নিরীক্ষকদের ডজন ডজনের বদলে সনদ দেওয়ার জন্য একটি উপাদানও দেয়, যা প্রতিটি পর্যালোচনার খরচ কমায়।
গত রাতে কোনো ঘটনা ঘটলে কোনো অন-কল ইঞ্জিনিয়ার কি একটিমাত্র লগ লাইন থেকে তা অনুসরণ করতে পারতেন, এবং একজন নিরীক্ষক কি পরে সিস্টেমের লিপিবদ্ধ প্রতিটি ব্যর্থতা দেখতে পারতেন? একটি মোড়ানো, শ্রেণিবদ্ধ, ভালো-লগ করা ত্রুটি দশ মিনিটের নির্ণয় ও মধ্যরাতের খননকাজের পার্থক্য, আর গিলে-ফেলা একটি আপনার নিজের কাছ থেকে লুকানো ভবিষ্যৎ ঘটনা। বড় দলে ব্যর্থতা অনেক সার্ভিস হপ পেরোয়, তাই মূল্য আসে সামঞ্জস্যপূর্ণ প্রসঙ্গ ও সেই হপ পেরোনো সহসম্পর্ক শনাক্তকারী থেকে, কোনো একক দলের অধ্যবসায় থেকে নয়। প্রতিদ্বন্দ্বী টানাপোড়েন খরচ ও গোলমাল: সবকিছু লগ করলে সংকেত ডোবে এবং সংরক্ষণে অর্থ লাগে; খুব কম লগ করলে কী ঘটেছিল তা পুনর্গঠন করা যায় না। একটি বাস্তব সাম্প্রতিক ব্যর্থতা আনুন এবং তার পথ শুরু থেকে শেষ পর্যন্ত হাঁটুন, প্রতিটি হপ চিহ্নিত করে যেখানে প্রসঙ্গ হারিয়েছে বা ত্রুটি ধরে ফেলে দেওয়া হয়েছে। নিয়ন্ত্রিত ও সরকারি সিস্টেমে এটিকে সম্মতির বৈশিষ্ট্য ভাবুন, কারণ নিরীক্ষণ-অযোগ্য ব্যর্থতা, বা বছর পরে ব্যাখ্যা করতে না পারা সিদ্ধান্ত, কেবল পরিচালনগত ফাঁক নয়, আইনি ঝুঁকি।
খাতভেদে দৃষ্টিভঙ্গি
স্টার্টআপ। মুষ্টিমেয় ইঞ্জিনিয়ার ও বাড়তি রানওয়ে ছাড়া আপনার ত্রুটি-সামলানোর বাজেট ব্যয় করুন যেখানে ব্যর্থতা আপনার একজন গ্রাহক বা ডেটা খরচ করে: প্রতিটি বাইরের কলে টাইমআউট দিন, অর্থ-সরানো রাইট আইডেমপোটেন্ট করুন, এবং উপেক্ষা-করা ত্রুটির বিরুদ্ধে একটি লিন্ট নিয়ম যোগ করুন। বিস্তৃত ফ্রেমওয়ার্ক এড়িয়ে যান; মূল ফাংশনের জন্য একটি Result টাইপ এবং অপরিহার্য নয় এমন নির্ভরতায় মার্জিত অবনমন কয়েক দিনের কাজে অধিকাংশ নিরাপত্তা কেনে। উন্নয়নে ফেইল-ফাস্ট করুন যাতে বাগ জোরে প্রকাশ পায়, এবং এমন নির্ভরতা সত্যিই না থাকলে সার্কিট ব্রেকার হাতে বানানো প্রতিরোধ করুন, যা তা দাবি করে।
ছোট ব্যবসা। কর্মীদের মধ্যে কোনো স্থিতিস্থাপকতা বিশেষজ্ঞ নেই আর বাজেট কম, তাই স্ক্র্যাচ থেকে প্যাটার্ন বানানোর বদলে আপনার ভাষা, ফ্রেমওয়ার্ক ও ক্লাউড প্রদানকারী ইতিমধ্যে যা দেয় তার ওপর নির্ভর করুন: ম্যানেজড কিউ, প্রদানকারী-পক্ষের রিট্রাই, এবং লাইব্রেরি টাইমআউট বেশিরভাগ দলের প্রত্যাশার চেয়ে বেশি ঢাকে। সিদ্ধান্তকে কেনা-বনাম-বানানো হিসেবে দেখুন, এবং যেখানে পরিপক্ব নির্ভরতা আপনার জন্য রিট্রাই, ব্যাকঅফ ও আইডেমপোটেন্সি সামলায় সেখানে কিনুন। আপনার দুর্লভ মনোযোগ রাখুন সেই এক-দুটি সীমানায়, যেখানে ভুল বা হারানো লেনদেন সত্যিই ক্ষতি করবে, এবং নিশ্চিত করুন সেগুলো নিরাপদে ব্যর্থ হয় ও চিহ্ন রাখে।
এন্টারপ্রাইজ। অনেক দল জুড়ে পুরস্কার সামঞ্জস্য: একটি ভাগ করা ত্রুটি শ্রেণিবিন্যাস, টাইমআউট, রিট্রাই, সার্কিট ব্রেকার ও বাল্কহেডের জন্য একটি সাধারণ লাইব্রেরি, এবং পাইপলাইনে সেগুলো প্রয়োগ করা একটি লিন্টার ও পর্যালোচনা চেকলিস্ট। প্রতিটি ত্রুটি সহসম্পর্ক শনাক্তকারীসহ একটি একীভূত অবজার্ভেবিলিটি প্ল্যাটফর্মে পাঠান যাতে সার্ভিস হপ জুড়ে ব্যর্থতা অনুসরণযোগ্য হয়, এবং প্রতি সীমানায় ফেইল-ফাস্ট বনাম ফেইল-সেফ সিদ্ধান্ত প্রমিত করুন যাতে নিরীক্ষা স্থানীয় অভ্যাসের ছড়ানো বিক্ষিপ্ততার বদলে নথিবদ্ধ, রক্ষণযোগ্য ধরন পায়। ভাগ করা লাইব্রেরিকে প্রকৃত পণ্য হিসেবে শাসন করুন, কারণ সেখানে একবার সারানো ত্রুটি সর্বত্র সারানো।
সরকার। সঠিকতা, নিরাপদ ব্যর্থতা এবং টেকসই নিরীক্ষা ট্রেইল বাধ্যবাধকতা, পছন্দ নয়। অর্থ বা যোগ্যতা ছোঁয়া যেকোনো লঙ্ঘিত ইনভ্যারিয়ান্টে দ্রুত ব্যর্থ হন, প্রতিটি নাগরিক-মুখী ইনপুট সীমানায় যাচাই করুন, এবং প্রতিটি ব্যর্থতা একটি অপরিবর্তনীয় লগে যথেষ্ট প্রসঙ্গসহ লিখুন যাতে বছর পরে একটি সিদ্ধান্ত ব্যাখ্যা ও পর্যালোচনা করা যায়। ক্রয় ও সিস্টেমের দীর্ঘ জীবনকাল মানে ত্রুটি চুক্তি নথিবদ্ধ হতে হবে যাতে মূল রচয়িতারা চলে যাওয়ার অনেক পরেও সরকারি কর্মচারীরা কোড রক্ষণাবেক্ষণ করতে পারেন, এবং যেকোনো বিক্রেতা উপাদানকে অস্বচ্ছ ইন্টারফেসের পেছনে লুকানোর বদলে তার ব্যর্থতা আচরণ প্রকাশ করতে হবে।
উদাহরণ
স্টার্টআপ। চারজনের একটি স্টার্টআপ এমন একটি অ্যাপ পাঠায় যা একটি তৃতীয়-পক্ষ পেমেন্ট প্রদানকারী ও একটি ইমেল সার্ভিস ডাকে। শুরুতে তারা একটি সরল রিট্রাই লুপ যোগ করে এবং একটি টাইমআউট সফল চার্জ ঢেকে দিলে একজন গ্রাহককে তৎক্ষণাৎ দুবার চার্জ করে ফেলে। সমাধান শিক্ষা দেয়: তারা প্রতিটি রাইটে আইডেমপোটেন্সি কী যোগ করে, প্রতিটি বাইরের কলে টাইমআউট দেয়, এবং জিটারসহ সূচকীয় ব্যাকঅফে যায়। তারা মূল সার্ভিস ফাংশনের জন্য একটি Result টাইপ গ্রহণ করে যাতে ব্যর্থতা স্বাক্ষরে দেখা যায়, এবং একটি লিন্ট নিয়ম যেকোনো উপেক্ষা-করা ত্রুটি চিহ্নিত করে। ইমেল পাঠানো ব্যর্থ হলে চেকআউট বিক্রি আটকানোর বদলে বার্তা কিউ করে মার্জিতভাবে অবনমিত হয়। এই শৃঙ্খলা কয়েক দিন খরচ করে এবং এমন এক শ্রেণির ঘটনা থেকে তাদের বাঁচায়, যা রিফান্ড ও বিশ্বাসে অনেক বেশি খরচ করত।
এন্টারপ্রাইজ। একটি বৈশ্বিক লজিস্টিক্স কোম্পানি শত শত সার্ভিস চালায় এবং সবগুলোতে ত্রুটি সামলানো প্রমিত করে। প্রতিটি সার্ভিস ব্যর্থতাকে একটি ভাগ করা শ্রেণিবিন্যাসে (যাচাইকরণ, পাওয়া-যায়নি, দ্বন্দ্ব, নির্ভরতা-অনুপলব্ধ, অভ্যন্তরীণ) মেলায়, তাই কলাররা বার্তা পার্স না করে বিভাগ ধরে শাখা করে। একটি সাধারণ লাইব্রেরি সার্কিট ব্রেকার, ব্যাকঅফ ও জিটারসহ সীমিত রিট্রাই, এবং বাল্কহেড করা সংযোগ পুল দেয়, তাই কেউ এই প্যাটার্ন ভুলভাবে হাতে বানায় না। প্রতিটি ত্রুটি সহসম্পর্ক প্রসঙ্গসহ লগ হয় যা অধ্যায় 9.2-এর অবজার্ভেবিলিটি প্ল্যাটফর্মে জোগান দেয়, তাই একজন অন-কল ইঞ্জিনিয়ার একটিমাত্র লাইন থেকে সার্ভিস হপ জুড়ে ব্যর্থতা অনুসরণ করতে পারেন। মান অভিন্ন এবং পাইপলাইনে প্রয়োগ করা বলে ইঞ্জিনিয়াররা অপরিচিত সার্ভিস জুড়ে আত্মবিশ্বাসে চলাচল করেন এবং নিরীক্ষকরা দেখতে পান প্রতিটি ব্যর্থতা লিপিবদ্ধ, শ্রেণিবদ্ধ ও অনুসরণযোগ্য।
সরকার। একটি জাতীয় সুবিধা সংস্থা এমন একটি যোগ্যতা ও পেমেন্ট সিস্টেম বানায় যেখানে ভুল উত্তর কাউকে ভাড়ার অর্থ থেকে বঞ্চিত করতে বা জনগণের তহবিল থেকে বেশি দিতে পারে। সঠিকতা ও নিরাপদ ব্যর্থতা আলোচনাযোগ্য নয়, তাই কোড যেকোনো লঙ্ঘিত আর্থিক ইনভ্যারিয়ান্টে দ্রুত ব্যর্থ হয়: না-মেলা গণনা ভুল অঙ্ক পোস্ট করার বদলে পোস্ট করতে অস্বীকার করে। প্রতিটি নাগরিক-মুখী ইনপুট সীমানায় যাচাই হয়, এবং ডোমেইন টাইপে অবৈধ অবস্থা অপ্রকাশযোগ্য করা হয়। প্রতিটি ব্যর্থতা পূর্ণ প্রসঙ্গসহ একটি অপরিবর্তনীয় নিরীক্ষা লগে লেখা হয়, যা আইনি প্রয়োজন পূরণ করে যে সিদ্ধান্ত বছর পরে ব্যাখ্যা ও পর্যালোচনাযোগ্য হতে হবে। ডকুমেন্ট প্রিভিউয়ের মতো অপরিহার্য নয় এমন নির্ভরতা বন্ধ থাকলে সিস্টেম মার্জিতভাবে অবনমিত হয় যাতে একজন কেসওয়ার্কার তবুও দাবি প্রক্রিয়া করতে পারেন। নতুন সরকারি কর্মচারীরা এমন কোড পান যার ত্রুটি চুক্তি নথিবদ্ধ, তাই মূল রচয়িতারা সরে যাওয়ার অনেক পরেও তা নিরাপদে রক্ষণাবেক্ষণ করতে পারেন।
ব্যবসায়িক যুক্তি: প্রেরণা, ROI ও TCO
শৃঙ্খলাবদ্ধ ত্রুটি সামলানোর প্রতিদান দেখা দেয় কম ঘটনা, সংক্ষিপ্ত ঘটনা এবং সস্তা ঘটনায়। বেশিরভাগ প্রোডাকশন বিভ্রাট অদ্ভুত নয়; তা ফিরে যায় একটি গিলে-ফেলা এক্সেপশন, একটি অনুপস্থিত টাইমআউট, একটি রিট্রাই ঝড়, বা যাচাই করা উচিত ছিল এমন ডেটায় বিশ্বাস করা একটি সীমানায়। প্রতিটি এখানকার প্যাটার্ন দিয়ে প্রতিরোধযোগ্য, এবং প্রতিটি প্রতিরোধ করা ঘটনা কেবল ডাউনটাইমের সরাসরি খরচ নয়, জরুরি সাড়া, গ্রাহক হারানো ও তদন্তের চক্রবৃদ্ধি খরচও বাঁচায়। একটি মোড়ানো, ভালো-লগ করা ত্রুটি ঘণ্টার বদলে মিনিটে নির্ণয় করা যায় বলে পুনরুদ্ধারের গড় সময় কমে, এবং ইঞ্জিনিয়াররা ত্রুটির পথ নিয়ে ভয় পাওয়া বন্ধ করলে পরিবর্তন-ব্যর্থতার হারও কমে।
গ্রহণের খরচ মাঝারি এবং বেশিরভাগ এককালীন। আপনি একটি ত্রুটি শ্রেণিবিন্যাস লিখে রাখেন, রিট্রাই ও সার্কিট ব্রেকারের জন্য একটি ভাগ করা লাইব্রেরি দেন যাতে দলগুলো সেগুলো খারাপভাবে পুনরাবিষ্কার না করে, উপেক্ষা-করা ত্রুটির বিরুদ্ধে লিন্ট নিয়ম যোগ করেন, এবং ব্যর্থতা-ইনজেকশনের অভ্যাস গড়েন। অবহেলার খরচ নিঃশব্দে চক্রবৃদ্ধি হয়: গিলে-ফেলা ত্রুটি নষ্ট ডেটায় জমে যা খুলে ফেলা ব্যয়বহুল, এবং অসামঞ্জস্যপূর্ণ সামলানো প্রতিটি ইন্টিগ্রেশন ও প্রতিটি নিরীক্ষার খরচ বাড়ায়। নিয়ন্ত্রিত ও সরকারি পরিবেশে নিরীক্ষণ-অযোগ্য ব্যর্থতা সম্মতি ও আইনি ঝুঁকি, কেবল প্রকৌশল সমস্যা নয়। নেতৃত্বের কাছে যুক্তি দিতে ত্রুটি-সামলানোর শৃঙ্খলাকে তাঁরা ইতিমধ্যে যে মেট্রিক দেখেন তার সঙ্গে যুক্ত করুন: ঘটনার ফ্রিকোয়েন্সি, পুনরুদ্ধারের গড় সময়, পরিবর্তন-ব্যর্থতার হার এবং নিরীক্ষা পর্যবেক্ষণ।
অ্যান্টি-প্যাটার্ন ও ফাঁদ
- নীরব গিলে ফেলা: ফাঁকা catch ব্লক ও উপেক্ষা-করা রিটার্ন মান যা ব্যর্থতাকে বিলম্বিত, বিচ্ছিন্ন রহস্যে পরিণত করে।
- ক্যাচ-অল মুছে ফেলা: একটি বিস্তৃত
catchযা সাধারণ বার্তা লগ করে এবং মূল ত্রুটি ও তার প্রসঙ্গ ফেলে দেয়। - আইডেমপোটেন্স ছাড়া রিট্রাই: টাইমআউটের পরে অ-আইডেমপোটেন্ট রাইট পুনরায় চালানো, ডাবল-চার্জ বা রেকর্ড ডুপ্লিকেট করা।
- রিট্রাই ঝড়: ব্যাকঅফ, জিটার ও সীমা নেই, তাই ক্লায়েন্ট সমলয় হয়ে সেরে-ওঠা নির্ভরতাকে আবার ফেলে দেয়।
- টাইমআউট নেই: সীমাহীন দূরবর্তী কল যা একটি আটকে-যাওয়া নির্ভরতাকে থ্রেড শেষ করতে এবং পুরো প্রসেস জমাতে দেয়।
- নিয়ন্ত্রণ প্রবাহ হিসেবে এক্সেপশন: “পাওয়া যায়নি”-র মতো সাধারণ ফলাফলে ছোড়া ও ধরা, যুক্তি লুকানো ও কোড ধীর করা।
- রক্ষণাত্মক প্যারানয়া: প্রতিটি লাইনে পরীক্ষা যা যুক্তি চাপা দেয় এবং প্রকৃত ব্যর্থতাকে নীরব ডিফল্টে রূপান্তর করে।
- স্ট্রিং-টাইপ ত্রুটি: কলাররা ত্রুটি বার্তার পাঠ্য পার্স করছে কারণ শাখা করার মতো কোনো স্থিতিশীল, শ্রেণিবদ্ধ শ্রেণিবিন্যাস নেই।
- যেখানে ফেইল-ফাস্ট দরকার সেখানে ফেইল-সেফ: নষ্ট অবস্থায় চালিয়ে যাওয়া এমন সিস্টেমে, যেখানে ভুল উত্তর কোনো উত্তর না থাকার চেয়ে খারাপ।
পরিপক্বতা মডেল
- স্তর ১, সূচনা: ত্রুটি সামলানো অ্যাড হক ও প্রতিক্রিয়াশীল, প্রতি ডেভেলপারে ঠিক হয়। ফাঁকা catch ব্লক ও উপেক্ষা-করা রিটার্ন সাধারণ, রিট্রাই সরল, টাইমআউট অনুপস্থিত, এবং ব্যর্থতা সামঞ্জস্যপূর্ণ লগিং ছাড়াই নষ্ট ডেটা বা রহস্যময় ত্রুটি হিসেবে প্রকাশ পায়।
- স্তর ২, বিকাশ: দলগুলো মৌলিক চর্চা গ্রহণ করে, কিন্তু অসঙ্গতভাবে। ত্রুটি কিছু প্রসঙ্গসহ লগ হয়, স্পষ্ট গিলে ফেলা পর্যালোচনায় নিরুৎসাহিত, এবং টাইমআউট ও সরল রিট্রাই আছে, তবু সার্ভিসের মধ্যে রীতি ভিন্ন, আইডেমপোটেন্স অসম, এবং ত্রুটির পথ কদাচিৎ পরীক্ষিত।
- স্তর ৩, মানসম্মতকরণ: একটি ভাগ করা ত্রুটি শ্রেণিবিন্যাস ও সামলানোর রীতি নথিবদ্ধ এবং প্রতিষ্ঠান জুড়ে প্রয়োগ করা। সীমানা যাচাইকরণ, ব্যাকঅফ ও জিটারসহ আইডেমপোটেন্ট রিট্রাই, সার্কিট ব্রেকার, বাল্কহেড ও ত্রুটি মোড়ানো আদর্শ, সাধারণ লাইব্রেরি দ্বারা সরবরাহ করা, এবং প্রতিটি ত্রুটি একটি একীভূত অবজার্ভেবিলিটি পাইপলাইনে জোগান দেয়।
- স্তর ৪, ব্যবস্থাপনা: ত্রুটি-সামলানোর আচরণ ভিত্তিরেখার বিপরীতে মাপা ও তথ্য দিয়ে নিয়ন্ত্রিত। রিট্রাই হার, সার্কিট-ব্রেকার ট্রিপ, টাইমআউট সংখ্যা, স্ট্যাটিক বিশ্লেষণ থেকে গিলে-ফেলা-ত্রুটি পর্যবেক্ষণ, পুনরুদ্ধারের গড় সময় ও পরিবর্তন-ব্যর্থতার হার প্রতি সার্ভিসে অনুসরণ করা হয়; সার্কিট-ব্রেকার সীমা ও টাইমআউট অনুমানের বদলে পর্যবেক্ষিত লেটেন্সি ও ব্যর্থতা তথ্য থেকে টিউন করা হয়; ব্যর্থতা-ইনজেকশন সময়সূচি অনুযায়ী চলে; এবং দলগুলো রিগ্রেশন ধরতে এবং প্রতিটি ফেইল-ফাস্ট বা ফেইল-সেফ পছন্দ প্রমাণের সামনে ধরে রাখতে এই মেট্রিক পর্যালোচনা করে।
- স্তর ৫, সমন্বয়: স্থিতিস্থাপকতা সরবরাহ ও ঝুঁকি পরিকল্পনার সঙ্গে একীভূত এবং নিরন্তর উন্নত। শ্রেণিবিন্যাস, ভাগ করা লাইব্রেরি ও মান প্রতিটি ঘটনা থেকে বিবর্তিত হয়, কেয়স ও ব্যর্থতা-ইনজেকশন পরীক্ষা রুটিন, এবং ট্রাফিক, নির্ভরতা ও ঝুঁকির চিত্র সরলে প্রতিষ্ঠান টাইমআউট, ব্রেকার সীমা, অবনমন কৌশল ও সীমানা সিদ্ধান্ত খাপ খাওয়ায়।
আলোচনার ভাবনা
- আপনার কোডবেসের কোথায় বর্তমানে ত্রুটি গিলে ফেলা হয়, এবং আপনি ভুল হলে, যে তা হয় না, কীভাবে জানবেন?
- আপনার কোন রাইট অপারেশন আইডেমপোটেন্ট, এবং হারানো স্বীকৃতির পরে রিট্রাই চালু হলে কোনগুলো দুবার কার্যকর হত?
- “ব্যবহারকারী পাওয়া যায়নি” কি এক্সেপশন, ত্রুটি-মান, নাকি স্বাভাবিক ফলাফল হওয়া উচিত, এবং আপনার দল কি সামঞ্জস্যপূর্ণভাবে তার উত্তর দেয়?
- যাচাইকরণ কোথায় ঘটে সে বিষয়ে আপনার প্রকৃত নিয়ম কী, এবং আপনি কি এমন সীমানা দেখাতে পারেন যা বিশ্বাস না করা উচিত এমন ডেটায় বিশ্বাস করে?
- সার্কিট ব্রেকারের সীমা ও কুলডাউন কীভাবে ঠিক করেন, এবং বর্তমান সেটিং ভুল কি না কীভাবে জানবেন?
- একজন নিরীক্ষক যদি গত মাসে আপনার সিস্টেমের অভিজ্ঞতা করা প্রতিটি ব্যর্থতা দেখতে চান, আপনি কি তা শ্রেণিবদ্ধ ও প্রসঙ্গসহ দিতে পারতেন?
প্রধান শিক্ষা
- ত্রুটির উৎস, ভুল ও ব্যর্থতা আলাদা করুন, এবং অভ্যন্তরীণ ভুল দৃশ্যমান ব্যর্থতা হওয়ার আগে শৃঙ্খল ভাঙুন।
- প্রতি সীমানায় ইচ্ছাকৃতভাবে ফেইল-ফাস্ট বা ফেইল-সেফ বাছুন, এবং প্রতিটি ফাংশনের ত্রুটি-সামলানোর চুক্তি সুস্পষ্ট করুন।
- আস্থা সীমানায় কঠোরভাবে যাচাই করুন এবং ভেতরে বিশ্বাস করুন; যে রক্ষণশীলতা ব্যর্থতা ঢাকে তা নিরাপত্তা নয়, স্থগিতকরণ।
- আইডেমপোটেন্স, টাইমআউট, সূচকীয় ব্যাকঅফ ও জিটার দিয়ে রিট্রাই নিরাপদ করুন, এবং কোডে সার্কিট ব্রেকার ও মার্জিত অবনমন যোগ করুন।
- প্রসঙ্গসহ ত্রুটি মুড়ুন, অবজার্ভেবিলিটিতে জোগান দিন, এবং কখনো গিলবেন না; প্রতিটি ত্রুটি সামলানো, ছড়ানো, বা লগ ও প্রকাশ করতে হবে।
তথ্যসূত্র ও আরও পড়ার জন্য
- Michael T. Nygard, Release It! Design and Deploy Production-Ready Software
- Andrew Hunt ও David Thomas, The Pragmatic Programmer
- Steve McConnell, Code Complete: A Practical Handbook of Software Construction
- Betsy Beyer, Chris Jones, Jennifer Petoff ও Niall Richard Murphy (সম্পা.), Site Reliability Engineering: How Google Runs Production Systems
- Marc Brooker, “Timeouts, Retries, and Backoff with Jitter,” Amazon Builders’ Library
- Martin Fowler, “CircuitBreaker,” martinfowler.com
- Nassim Nicholas Taleb, Antifragile: Things That Gain from Disorder