عارضی حل (انگریزی: workaround, kludge, hotfix) — کوڈ میں کسی مسئلے کا ایک عارضی یا غیر بہترین حل ہے جو کام کرتا ہے لیکن صاف آرکیٹیکچر، پڑھنے کی اہلیت یا کارکردگی کے اصولوں کی خلاف ورزی کرتا ہے۔ حقیقی ڈیولپمنٹ میں عارضی حل ناگزیر ہیں: ڈیڈ لائنز، ورژن کی عدم مطابقت، لیگیسی کوڈ اور فریم ورکس کا غیر دستاویزی رویہ ڈیولپرز کو سمجھوتہ کرنے پر مجبور کرتا ہے۔ Martin Fowler (2025) کے مطابق، ایک جائز عارضی حل اور تکنیکی قرض کے درمیان بنیادی فرق — اسے ختم کرنے کے منصوبے اور کوڈ میں واضح نشان زدگی کی موجودگی ہے۔
اہم نکات
عارضی حل — ایک سافٹ ویئر حل کے لیے بول چال کی اصطلاح ہے جو فعال طور پر درست ہے لیکن تکنیکی طور پر غیر بہترین ہے۔ ایسا کوڈ کام کرتا ہے، ٹیسٹ پاس کرتا ہے اور پروڈکشن تک بھی پہنچتا ہے، لیکن اسے پڑھنے سے سب کچھ شروع سے دوبارہ لکھنے کی خواہش ہوتی ہے۔ انگریزی بولنے والے ماحول میں، workaround، kludge (kluge)، hack یا quick-and-dirty fix کی اصطلاحات استعمال ہوتی ہیں۔
یہ اصطلاح ایک گھریلو استعارے سے آئی ہے: اگر کرسی کی ٹانگ ٹوٹ جائے تو اسے ٹیپ سے باندھا جا سکتا ہے — کرسی دوبارہ کام کرتی ہے، لیکن حل عارضی اور بدصورت ہے۔ پروگرامنگ میں بھی یہی بات لاگو ہوتی ہے: ایک بگ کو ہارڈکوڈ، ٹائم آؤٹ عارضی حل یا غیر دستاویزی API کے ذریعے ٹھیک کیا جاتا ہے۔ کوڈ کمپائل ہوتا ہے، ایپلیکیشن کریش نہیں ہوتی، لیکن حل کو معیاری نہیں کہا جا سکتا۔
ایک اہم فرق: بگ — جب کوڈ توقع کے مطابق کام نہ کرے۔ عارضی حل — جب کوڈ کام کرے لیکن خراب ڈیزائن کیا گیا ہو۔ عارضی حل ہمیشہ ڈیولپر کا شعوری انتخاب ہوتا ہے: «میں جانتا ہوں کہ یہ بدصورت ہے، لیکن ابھی یہ مسئلہ حل کرتا ہے۔»
Stripe (2024) کے مطابق، ڈیولپرز اوسطاً 17 گھنٹے فی ہفتہ تکنیکی قرض اور عارضی حلوں پر کام کرنے میں گزارتے ہیں — ان کے کام کے تقریباً آدھے وقت کے برابر۔ یہ ٹیم کی پیداواری صلاحیت کا براہ راست نقصان ہے۔
پہلی اور بنیادی وجہ ڈیڈ لائنز ہیں۔ جب ریلیز میں ایک دن باقی ہو اور ایک سنگین بگ ابھی تک ٹھیک نہ ہوا ہو، تو ٹیم صحیح حل کے بجائے فوری حل کا انتخاب کرتی ہے۔ کسی قدر کو ہارڈکوڈ کرنا، جانچ کو غیر فعال کرنا، sleep() شامل کرنا — ڈیڈ لائن عارضی حلوں کی کلاسک مثالیں ہیں۔ ایک تجربہ کار ڈیولپر ہمیشہ ایسی جگہوں کو TODO یا FIXME سے نشان زد کرتا ہے۔
دوسری وجہ API عدم مطابقت ہے۔ کوئی تیسرے فریق کی لائبریری یا فریم ورک دستاویز سے مختلف برتاؤ کرتا ہے۔ فریم ورک مطلوبہ کلاس کو ایکسپورٹ نہیں کرتا، کوئی طریقہ متروک قرار دیا گیا ہے اور کوئی متبادل نہیں ہے۔ ڈیولپر ریفلیکشن، داخلی API یا متبادل حل استعمال کرنے پر مجبور ہوتا ہے۔ Java میں، یہ setAccessible(true) کے ذریعے رسائی ہو سکتی ہے؛ Swift میں — @objc اور performSelector۔
تیسری وجہ لیگیسی کوڈ ہے۔ ایک ڈیولپر کو 5-10 سال پہلے فریم ورک کے پرانے ورژن پر لکھا ہوا پروجیکٹ وراثت میں ملتا ہے۔ پورے ماڈیول کو دوبارہ لکھنے کا وقت یا بجٹ نہیں ہے، اس لیے نئی فعالیت کو عارضی حلوں کے ذریعے پرانے کوڈ سے «چپکایا» جاتا ہے۔ آہستہ آہستہ اتنی تہیں جمع ہو جاتی ہیں کہ ماڈیول «کیچڑ کا بڑا گولہ» (big ball of mud) بن جاتا ہے۔
چوتھی وجہ ٹیسٹوں کی کمی ہے۔ ٹیسٹوں کے بغیر ری فیکٹرنگ خطرناک ہے: آرکیٹیکچر تبدیل کرنے سے کام کرنے والی فعالیت ٹوٹ سکتی ہے۔ جب ٹیسٹ نہیں ہوتے، تو ڈیولپر استحکام کو خطرے میں ڈالنے کے بجائے کام کرنے والے کوڈ کے اوپر عارضی حل شامل کرنے کو ترجیح دیتا ہے۔ Google Testing Blog (2024) کے مطابق، ٹیسٹوں کے بغیر ٹیمیں 3 گنا زیادہ عارضی حل استعمال کرتی ہیں۔
عارضی حلوں کی درجہ بندی ٹیم کو یہ سمجھنے میں مدد دیتی ہے کہ وہ کس قسم کے تکنیکی قرض سے نمٹ رہی ہے اور صحیح خاتمے کی حکمت عملی کا انتخاب کرتی ہے۔ آئیے اہم اقسام پر نظر ڈالتے ہیں۔
ہارڈکوڈ — سب سے عام قسم۔ کنفیگریشن، وسائل یا پیرامیٹر کے بجائے کوڈ میں ایک مقررہ قدر استعمال ہوتی ہے۔ مثال: ہارڈکوڈڈ سرور URL، 5 سیکنڈ کا ٹائم آؤٹ، 16pt فونٹ سائز۔ ہارڈکوڈ کوڈ کو ناقابل توسیع بناتا ہے اور کسی بھی تبدیلی کے لیے دوبارہ کمپائلیشن کی ضرورت ہوتی ہے۔
کاپی پیسٹ — مشترکہ منطق نکالنے کے بجائے معمولی تبدیلیوں کے ساتھ کوڈ کے ٹکڑے کو نقل کرنا۔ کلاسک علامت: پروجیکٹ میں 3 ملتے جلتے طریقے ہیں جو ایک سطر میں مختلف ہیں۔ کاپی پیسٹ کام کے وقت کوڈ لکھنے کو تیز کرتا ہے لیکن مستقبل میں دیکھ بھال کو 10 گنا سست کر دیتا ہے — اصلاح ایک کی بجائے 3 جگہوں پر لگانی پڑتی ہے۔
خالی try-catch — ایک catch بلاک جو کچھ نہیں کرتا یا صرف غلطی کو لاگ کرتا ہے بغیر اسے سنبھالے۔ ایسا عارضی حل استثنا کو «دبا» دیتا ہے لیکن اس کی وجہ حل نہیں کرتا۔ ایپلیکیشن کام کرتی رہتی ہے، لیکن ڈیٹا خراب ہو سکتا ہے اور صارف کو فیڈبیک نہیں مل سکتا۔
کوڈ میں نیند (Sleep) — Thread.sleep(500) یا DispatchQueue.main.asyncAfter انتظار کے لیے جب کوئی ایونٹ یا کال بیک ہونا چاہیے۔ ایسا کوڈ ناقابل بھروسہ ہے: سست ڈیوائس پر 500 ms کافی نہیں ہو سکتے؛ تیز ڈیوائس پر، توقف غیر ضروری ہوگا۔ CountDownLatch، Semaphore یا مناسب ٹائمنگ کے ساتھ async/await استعمال کریں۔
مطابقت کے جھنڈے — OS ورژن، ڈیوائس ماڈل یا فیچر کی دستیابی کو جانچنے والے if-else کاسکیڈ۔ جب 3-4 سے زیادہ جھنڈے ہوں تو کوڈ اسپگیٹی میں بدل جاتا ہے۔ حل — Strategy پیٹرن یا کنفیگریشن کے ذریعے Feature Flags۔
بہت سے ڈیولپر عارضی حل اور تکنیکی قرض میں الجھ جاتے ہیں۔ فرق پیمانے اور آگاہی میں ہے۔ عارضی حل — ایک مقامی، مخصوص حل (ایک طریقہ، ایک کلاس)۔ تکنیکی قرض — ایک نظامی مسئلہ جو ماڈیول یا پوری ایپلیکیشن کے آرکیٹیکچر کو متاثر کرتا ہے۔
Ward Cunningham کا استعارہ (تکنیکی قرض کی اصطلاح کے خالق): تکنیکی قرض بینک سے قرض لینے جیسا ہے۔ آپ ابھی پیسے لیتے ہیں تاکہ گھر تیزی سے بنا سکیں، لیکن بعد میں سود ادا کرتے ہیں۔ عارضی حل — کیل بندوق کی بجائے ہتھوڑے سے کیل ٹھوکنے جیسا ہے: کام ہو جاتا ہے، لیکن کم مؤثر طریقے سے۔
ایک عارضی حل تکنیکی قرض نہیں بناتا۔ لیکن ایک ماڈیول میں 50 عارضی حل = آرکیٹیکچرل قرض۔ اس لیے، ٹیم کا اصول: ہر عارضی حل کو کوڈ ریویو یا ٹاسک ٹریکر میں ریکارڈ کیا جاتا ہے، اور ٹیم باقاعدگی سے (ہر سپرنٹ میں ایک بار) جمع شدہ عارضی حلوں کا جائزہ لیتی ہے۔
Spotify Engineering (2023) کے مطابق، جو ٹیمیں کوڈ میں عارضی حلوں کو ٹریک کرتی ہیں (خصوصی TODO لیبل یا کسٹم اینوٹیشن کے ذریعے)، ری فیکٹرنگ کا وقت 30% کم کرتی ہیں — کیونکہ وہ مسائل والی جگہیں تلاش کرنے میں گھنٹے ضائع نہیں کرتیں۔
پہلا قدم — انوینٹری۔ کوڈ بیس میں کلیدی الفاظ تلاش کریں: TODO, FIXME, HACK, WORKAROUND, KLUDGE۔ جدید IDE انہیں الگ رنگ میں نمایاں کرتے ہیں۔ GitHub بھی Pull Request انٹرفیس میں TODO دکھاتا ہے۔ ترجیح کے ساتھ تمام عارضی حلوں کی فہرست بنائیں۔
دوسرا قدم — ترجیح دینا۔ تمام عارضی حلوں کو فوری طور پر ٹھیک کرنے کی ضرورت نہیں ہے۔ ترجیح = فائل میں تبدیلی کی تعدد × سنگینی۔ اگر فائل سال میں 2 بار بدلتی ہے، عارضی حل انتظار کر سکتا ہے۔ اگر ماڈیول ہر سپرنٹ میں چھوا جاتا ہے — عارضی حل کو پہلے ٹھیک کیا جانا چاہیے۔
تیسرا قدم — ٹیسٹوں کے ساتھ ری فیکٹرنگ۔ بغیر ٹیسٹوں کے کبھی عارضی حل کی ری فیکٹرنگ نہ کریں۔ پہلے ایک ٹیسٹ لکھیں جو موجودہ رویے (عارضی حل کے ساتھ) کی تصدیق کرتا ہے، پھر ری فیکٹر کریں، پھر یقینی بنائیں کہ ٹیسٹ پاس ہوتا ہے۔ اس کے بغیر، عارضی حل کی ری فیکٹرنگ اس فعالیت کو توڑ سکتی ہے جس کے لیے وہ لکھا گیا تھا۔
// Before: ہارڈکوڈڈ URL عارضی حل
fun getApiUrl(): String {
return "https://api.example.com/v2"
}
// After: BuildConfig کے ذریعے کنفیگریشن
fun getApiUrl(): String {
return BuildConfig.API_BASE_URL
}
چوتھا قدم — آٹومیشن۔ ایک لنٹر سیٹ کریں جو مخصوص عارضی حل پیٹرن کو منع کرتا ہے۔ مثال کے طور پر، Kotlin کے لیے Detekt پروڈکشن کوڈ میں Thread.sleep() کی غیر موجودگی کی جانچ کر سکتا ہے، ESLint پروجیکٹ میں console.log کو منع کر سکتا ہے۔ یہ اسی قسم کے نئے عارضی حلوں کے ظہور کو روکتا ہے۔
اصطلاح کے منفی مفہوم کے باوجود، ایک عارضی حل جائز حل ہو سکتا ہے۔ بنیادی شرط: عارضی حل عارضی ہو، واضح طور پر نشان زد ہو اور اس کا متبادل منصوبہ ہو۔ ہر بڑے پروجیکٹ کے پروڈکشن کوڈ میں سینکڑوں جائز عارضی حل ہوتے ہیں۔
صورت حال 1: پروڈکشن میں ہاٹ فکس۔ ایک سنگین بگ تمام صارفین کو متاثر کرتا ہے۔ ٹیم کو ایک گھنٹے میں اصلاح کی ضرورت ہے۔ صحیح طریقہ: بگ کو کسی بھی طرح ٹھیک کریں، ہاٹ فکس ڈیپلائے کریں۔ پھر، اگلے دن، مناسب حل لکھیں اور ٹکٹ بند کریں۔ ایک ہاٹ فکس جائز عارضی حل ہے اگر وہ 48 گھنٹے سے زیادہ زندہ نہ رہے۔
صورت حال 2: نئے لائبریری ورژن کا انتظار۔ ایک فریم ورک میں بگ ہے جو master میں ٹھیک ہو گیا ہے، لیکن ریلیز 2 ہفتوں میں آئے گی۔ پیچیدہ متبادل کوڈ لکھنے کے بجائے، ٹیم ایک عارضی حل شامل کرتی ہے جس میں نوٹ ہو «REMOVE after library 3.2»۔ جب 3.2 ریلیز ہوتا ہے، عارضی حل ہٹا دیا جاتا ہے۔
صورت حال 3: اسٹارٹ اپ یا MVP بند کرنا۔ MVP مرحلے میں، رفتار آرکیٹیکچر سے زیادہ اہم ہے۔ شروع میں عارضی حل عام ہیں۔ مسئلہ اس وقت پیدا ہوتا ہے جب اسٹارٹ اپ پروڈکٹ میں نہیں بدلتا، لیکن عارضی حل باقی رہ جاتے ہیں۔ سفارش: فنڈنگ راؤنڈ کے بعد، اہم تکنیکی قرض ادا کرنے کے لیے ایک سپرنٹ مختص کریں۔
بنیادی اصول: «لیگیسی کوڈ وہ کوڈ ہے جس کے ٹیسٹ نہیں ہیں» (Michael Feathers)۔ اگر عارضی حل ٹیسٹ سے ڈھکا ہوا ہے اور واضح طور پر دستاویز کیا گیا ہے — یہ قابل انتظام ہے۔ اگر یہ 2 سال سے بغیر کمنٹس کے بھولے ہوئے ماڈیول میں لٹکا ہے — یہ عارضی حل نہیں، بلکہ ایک آرکیٹیکچرل مسئلہ ہے۔
اکثر پوچھے گئے سوالات
بگ — کوڈ توقع کے مطابق کام نہیں کرتا۔ عارضی حل — کوڈ کام کرتا ہے لیکن غیر بہترین طریقے سے لکھا گیا ہے۔ عارضی حل ہمیشہ ڈیولپر کا شعوری فیصلہ ہے؛ بگ عام طور پر ایک غیر شعوری غلطی ہے۔
// TODO: refactor — ... یا فیلڈز کے ساتھ کسٹم @Workaround اینوٹیشن استعمال کریں: وجہ، تاریخ، ذمہ دار شخص، ہٹانے کی آخری تاریخ۔ وضاحت کے بغیر ننگے // HACK سے بچیں۔
اگر ماڈیول نہیں بدلتا اور عارضی حل مستحکم ہے — نہیں۔ بغیر وجہ ری فیکٹرنگ رجعت کا خطرہ بڑھاتی ہے۔ صرف ان عارضی حلوں کو ٹھیک کریں جو نئی فعالیت شامل کرنے میں رکاوٹ ہیں۔
وقت کا موازنہ کریں: «ہم فی الحال ان عارضی حلوں کی وجہ سے دستی جانچ پر 4 گھنٹے صرف کرتے ہیں۔ ری فیکٹرنگ میں 8 گھنٹے لگیں گے اور وقت 30 منٹ تک کم ہو جائے گا۔ سرمایہ کاری پر واپسی — 2 سپرنٹ۔» رفتار اور پیسے کی زبان میں بولیں، صاف آرکیٹیکچر کی نہیں۔
پورے پروجیکٹ میں grep کے ذریعے TODO, FIXME, HACK, WORKAROUND تلاش کریں۔ 100 سطروں سے لمبے طریقوں اور 5 سے زیادہ انحصار والی کلاسز کا تجزیہ کریں۔ خودکار پتہ لگانے کے لیے حسب ضرورت اصولوں والے لنٹر استعمال کریں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں