DRY (Don't Repeat Yourself) ایک بنیادی ڈیولپمنٹ اصول ہے جسے اینڈی ہنٹ اور ڈیو تھامس نے کتاب «The Pragmatic Programmer» میں وضع کیا۔ یہ کہتا ہے: سسٹم میں علم کے ہر حصے کی ایک واحد، غیر مبہم، مستند نمائندگی ہونی چاہیے۔ The Pragmatic Programmer, 20th Anniversary Edition کے مطابق، DRY کی خلاف ورزی کرنے کا مطلب ہے کہ ایک عنصر کو تبدیل کرنے کے لیے درجنوں جگہوں پر ترمیم کی ضرورت ہوتی ہے، اور ہر چھوٹا ہوا ٹکڑا بگ کا ذریعہ بن جاتا ہے۔
اہم نکات
DRY (Don't Repeat Yourself) ایک ڈیولپمنٹ اصول ہے جس میں پروجیکٹ میں ہر علم کے عنصر کو بالکل ایک بار ذخیرہ کرنے کی ضرورت ہوتی ہے۔ اس کا مطلب ہے کہ کوئی بھی منطق، ترتیب یا میٹا ڈیٹا صرف ایک جگہ پر موجود ہونا چاہیے۔
یہ اصطلاح اینڈی ہنٹ اور ڈیو تھامس نے 1999 میں کتاب «The Pragmatic Programmer» میں متعارف کرائی۔ مصنفین نے DRY کی تعریف کی «علم کے ہر حصے کی سسٹم کے اندر ایک واحد، غیر مبہم، مستند نمائندگی ہونی چاہیے»۔ DRY کے برعکس WET (Write Everything Twice) طریقہ کار ہے، جہاں ڈپلیکیشن کو معمول سمجھا جاتا ہے۔
University of California, Davis (2019) کی ایک تحقیق کے مطابق، کوڈ ڈپلیکیشن کی بلند سطح والے پروجیکٹ بگز ٹھیک کرنے میں 42% زیادہ وقت صرف کرتے ہیں۔ وجہ یہ ہے کہ ڈیولپرز کو ایک ہی ٹکڑے کی تمام کاپیاں ڈھونڈنی اور تبدیل کرنی پڑتی ہیں — اور دستی تلاش ناگزیر طور پر چھوٹنے کا باعث بنتی ہے۔
DRY کو کوڈ کوالٹی کے معیار کے طور پر لاگو کریں۔ اگر آپ دیکھتے ہیں کہ ایک ہی پیٹرن پروجیکٹ میں تین بار ظاہر ہوتا ہے — چوتھی بار کا انتظار کیے بغیر اسے تجریہ میں نکالیں۔
SOLID سے واحد ذمہ داری کا اصول (SRP) کہتا ہے کہ ایک کلاس میں تبدیلی کی ایک ہی وجہ ہونی چاہیے۔ DRY وسیع تر ہے: یہ نہ صرف کلاسز بلکہ ڈیٹا، ترتیب، دستاویزات اور یہاں تک کہ کاروباری قواعد کو بھی شامل کرتا ہے۔ SRP ذمہ داری کی حدود کے بارے میں ہے؛ DRY کاپی روکنے کے بارے میں ہے۔
موبائل ڈیولپمنٹ میں، یہ فرق خاص طور پر نمایاں ہے۔ اگر ایک ہی کاروباری قاعدہ (ٹیکس کا حساب، تاریخ کی فارمیٹنگ) پروجیکٹ کے Android اور iOS دونوں حصوں میں دہرایا جاتا ہے — یہ DRY کی خلاف ورزی ہے، چاہے SRP ہر پلیٹ فارم کے اندر باضابطہ طور پر پیروی کیا جاتا ہو۔ حل مشترکہ منطق کو ایک مشترکہ ماڈیول (KMM, C++) میں نکالنا ہے۔
Google Android Architecture Guidelines (2023) رپورٹ کے مطابق، کاروباری منطق کے لیے مشترکہ ماڈیول استعمال کرنے والی ٹیمیں پلیٹ فارمز کے درمیان منطق دہرانے والے پروجیکٹس کے مقابلے میں ضروریات تبدیل ہونے پر بگز کی تعداد 37% کم کرتی ہیں۔
ڈپلیکیشن موبائل پروجیکٹس میں تکنیکی قرض کا بنیادی ذریعہ ہے۔ کوڈ کی ہر کاپی ایک پوشیدہ انحصار پیدا کرتی ہے: رویہ تبدیل کرنے کے لیے، آپ کو تمام کاپیاں ڈھونڈنی اور اپ ڈیٹ کرنی ہوں گی۔ ایک کو بھی چھوڑنے کا مطلب بگ ہے۔
ایک کلاسک منظر نامے پر غور کریں: ایک Android ایپ میں، تاریخ کی فارمیٹنگ تین مختلف Activities میں کی جاتی ہے۔ نئے فارمیٹ (مثلاً ISO 8601) پر سوئچ کرتے وقت، ڈیولپر دو فائلوں کو ٹھیک کرتا ہے، تیسری کو بھول جاتا ہے — اور صارف پرانے فارمیٹ میں تاریخیں دیکھتا ہے۔ ایپ کی درجہ بندی گر جاتی ہے اور بگ ڈھونڈنے میں دوگنا وقت لگتا ہے۔
Google Research (2020) کی ایک تحقیق سے پتہ چلا کہ موبائل ایپلیکیشنز میں 68% اہم بگز ڈپلیکیٹ کوڈ میں غیر ہم وقت تبدیلیوں سے متعلق ہیں۔ مزید برآں، پروڈکشن میں اس طرح کے بگ کو ٹھیک کرنے کی لاگت 4.5 گنا زیادہ ہوتی ہے اگر کوڈ شروع سے یکجا ہوتا۔
جامد تجزیہ کار (Detekt, SwiftLint) ان اصولوں کے ساتھ استعمال کریں جو copy-paste کا پتہ لگاتے ہیں۔ CI کو ترتیب دیں تاکہ N سے زیادہ سطروں کے ڈپلیکیشن والے پل ریکویسٹ بغیر جواز کے جائزہ پاس نہ کریں۔
ایک عام مخالف نمونہ ہے RecyclerView اڈاپٹر کو معمولی تبدیلیوں کے ساتھ کاپی کرنا۔ ایک عالمگیر اڈاپٹر کے بجائے، ڈیولپرز ہر اسکرین کے لیے علیحدہ کلاس بناتے ہیں۔ مشترکہ بنیادی کلاس نکال کر ری فیکٹرنگ کوڈ کو 30–50% تک کم کر دیتی ہے۔
// ڈپلیکیشن: دو الگ الگ اڈاپٹر
class UserAdapter {
fun bind(item: User) { /* ... */ }
}
class ProductAdapter {
fun bind(item: Product) { /* ... */ }
}
// DRY ری فیکٹرنگ: مشترکہ بنیادی کلاس
abstract class BaseAdapter<T> {
abstract fun bind(item: T)
}
class UserAdapter : BaseAdapter<User>() { /* ... */ }
class ProductAdapter : BaseAdapter<Product>() { /* ... */ }
پہلی مثال میں، ہر اڈاپٹر بائنڈ میکانزم کو شروع سے دوبارہ نافذ کرتا ہے۔ نئی منطق (تجزیہ، لاگنگ) شامل کرتے وقت، ہر فائل کو تبدیل کرنا ہوگا۔ ایک بنیادی کلاس اس ڈپلیکیشن کو ختم کرتی ہے: مشترکہ منطق ایک جگہ رہتی ہے، مخصوص منطق ذیلی کلاسز میں۔
iOS پروجیکٹس میں، URLSession کی ترتیب — ہیڈرز، ٹائم آؤٹ، غلطی کا انتظام — اکثر ڈپلیکیٹ کی جاتی ہے۔ ہر سروس بار بار ترتیبات کے ساتھ اپنا سیشن بناتی ہے۔
// ڈپلیکیشن: ہر سروس سیشن کو نئے سرے سے ترتیب دیتی ہے
class UserService {
let session = URLSession(configuration: {
let cfg = URLSessionConfiguration.default
cfg.timeoutIntervalForRequest = 30
cfg.httpAdditionalHeaders = ["Authorization": "Bearer ..."]
return cfg
}())
}
// DRY: متحد سیشن فیکٹری
struct NetworkConfig {
static var session: URLSession {
let cfg = URLSessionConfiguration.default
cfg.timeoutIntervalForRequest = 30
cfg.httpAdditionalHeaders = ["Authorization": "Bearer ..."]
return URLSession(configuration: cfg)
}
}
ترتیب کو متحد NetworkConfig میں نکالنے سے یقینی بنتا ہے کہ تمام خدمات ایک ہی ہیڈرز اور ٹائم آؤٹ استعمال کریں۔ ایک جگہ تبدیلی خود بخود تمام درخواستوں پر لاگو ہوتی ہے — یہ API کلید یا پروٹوکول ورژن تبدیل کرتے وقت غلطیوں کے خطرے کو کم کرتا ہے۔
وراثت ڈپلیکیشن ختم کرنے کا ایک قدرتی طریقہ ہے: مشترکہ منطق بنیادی کلاس میں منتقل کی جاتی ہے اور مخصوص منطق ذیلی کلاسز میں۔ تاہم، موبائل ڈیولپمنٹ میں، وراثت کا زیادہ استعمال سخت درجہ بندی پیدا کرتا ہے جسے برقرار رکھنا مشکل ہوتا ہے۔ ترکیب (انحصار انجیکشن) ایک زیادہ لچکدار متبادل ہے۔
Google I/O 2023: Modern Android Architecture کے تجزیے سے پتہ چلا کہ 76% Google ٹیمیں ڈپلیکیشن ختم کرنے کے لیے وراثت پر ترکیب کو ترجیح دیتی ہیں۔ درجنوں طریقوں والے BaseViewModel کے بجائے، ہر کاروباری آپریشن کے لیے علیحدہ UseCase کلاسز نکالنے اور انہیں ضرورت کی جگہ پر انجیکٹ کرنے کی سفارش کی جاتی ہے۔
«ہے» کے تعلقات کے علاوہ تمام صورتوں میں ترکیب کا انتخاب کریں۔ اگر کلاس A کلاس B کی خصوصیت ہے — وراثت مناسب ہے۔ اگر A صرف B کی فعالیت استعمال کرتا ہے — ترکیب استعمال کریں۔
یوٹیلیٹی کلاسز (Extensions, Helpers) ڈپلیکیشن سے بچنے کا سب سے آسان طریقہ ہے۔ عام امیدوار: تاریخ کی فارمیٹنگ، ای میل کی تصدیق، اکائی کی تبدیلی، SharedPreferences/UserDefaults کے ساتھ کام کرنا۔
// DRY: متحد تاریخ فارمیٹنگ فنکشن
fun Date.toDisplayFormat(): String {
val sdf = SimpleDateFormat("dd.MM.yyyy", Locale.getDefault())
return sdf.format(this)
}
// ایپلیکیشن میں کہیں بھی استعمال
textView.text = Date().toDisplayFormat()
Date.toDisplayFormat() توسیع ایک بار اعلان کی جاتی ہے اور پورے پروجیکٹ میں دستیاب ہوتی ہے۔ اگر فارمیٹ کو «dd.MM.yyyy» سے «yyyy-MM-dd» میں تبدیل کرنے کی ضرورت ہے — اصلاح ایک فائل میں ہے، ہر Activity یا Fragment میں نہیں جہاں فارمیٹنگ ہوتی ہے۔ یہ DRY کا جوہر ہے۔
ملٹی ماڈیول Android پروجیکٹ اکثر ہر build.gradle میں انحصار کے ورژن ڈپلیکیٹ کرتے ہیں۔ حل ایک ورژن کیٹلاگ (libs.versions.toml) ہے جو تمام ورژنز کو ایک فائل میں مرکوز کرتا ہے۔
Android ڈیولپر دستاویزات (2024) کے مطابق، ورژن کیٹلاگ میں منتقلی انحصار کے تنازعات کو 52% کم کرتی ہے اور ترمیم کے ایک نقطہ کے ذریعے بلڈ کو تیز کرتی ہے۔
پروجیکٹ کے شروع میں یا پہلی ماڈیول تنظیم نو کے دوران ورژن کیٹلاگ لاگو کریں۔ اگر پروجیکٹ میں پہلے سے ڈپلیکیشن ہے — منتقلی کے لیے ایک دن مختص کریں: یہ اگلی لائبریری اپ ڈیٹ پر منافع بخش ہوگا۔
قبل از وقت تجریہ ابتدائیوں کی سب سے عام غلطی ہے۔ ایک ڈیولپر کوڈ کی دو ملتی جلتی سطریں دیکھتا ہے اور فوراً انہیں ایک مشترکہ فنکشن میں نکال لیتا ہے۔ ایک ماہ بعد، ضروریات بدل جاتی ہیں اور مشترکہ فنکشن پیرامیٹرز اور جھنڈوں سے بھر جاتا ہے — اصل ڈپلیکیشن سے زیادہ پیچیدہ۔ تین کا قاعدہ بالکل اس سے بچاتا ہے: ایسی چیز کو تجریہ نہ کریں جو صرف ایک یا دو بار ظاہر ہوئی ہو۔
مارٹن فاؤلر اپنی کتاب Refactoring (2019) میں سفارش کرتے ہیں: «کوڈ ڈپلیکیشن ہمیشہ برا نہیں ہوتا۔ علم کی ڈپلیکیشن بری ہوتی ہے۔» اگر دو سطریں اتفاقیہ طور پر ملتی ہیں لیکن مختلف تصورات کا اظہار کرتی ہیں — یہ ڈپلیکیشن نہیں، اتفاق ہے۔ تین کا قاعدہ اتفاقی اتفاق کو منظم ڈپلیکیشن سے الگ کرنے میں مدد کرتا ہے۔
تجریہ کرنے سے پہلے، معنی کا اندازہ کریں۔ ایک ہی معنی کے ساتھ کاپی شدہ کوڈ — DRY کی خلاف ورزی۔ مختلف معنی لیکن ایک جیسی نحو والا کوڈ — اتفاق جسے تجریہ کی ضرورت نہیں۔
ضرورت سے زیادہ پیرامیٹرائزیشن اس وقت ہوتی ہے جب ایک فنکشن جھنڈوں اور بولین پیرامیٹرز کے ذریعے تمام ممکنہ منظرناموں کا احاطہ کرنے کی کوشش کرتا ہے۔ ایسا کوڈ SRP کی خلاف ورزی کرتا ہے اور ناقابل مطالعہ ہو جاتا ہے۔ علامت: اگر کسی فنکشن میں دو سے زیادہ بولین پیرامیٹر ہوں — یہ ضرورت سے زیادہ تجریہ کی کوڈ سمل ہے۔
useCache: Boolean جھنڈے والے ایک فنکشن کے بجائے، واضح ناموں والے دو علیحدہ فنکشن بنانا بہتر ہے: fetchFromNetwork() اور fetchFromCache()۔ واضحیت خشک تجریہ سے زیادہ اہم ہے — یہ KISS اصول سے مطابقت رکھتا ہے۔
جب کوئی فنکشن 3+ بولین پیرامیٹر تک پہنچ جائے تو ضرورت سے زیادہ پیرامیٹرائزیشن کو ری فیکٹر کریں۔ واضح ناموں والے علیحدہ فنکشنز میں تقسیم کریں — ہر کال خود دستاویزی بن جائے گی۔
اکثر پوچھے گئے سوالات
DRY (Don't Repeat Yourself) ایک اصول ہے جس میں ہر منطقی اکائی کو ایک جگہ ذخیرہ کرنے کی ضرورت ہوتی ہے۔ اگر ایک ہی کوڈ پروجیکٹ کے متعدد حصوں میں ظاہر ہوتا ہے — یہ DRY کی خلاف ورزی ہے۔ حل: بار بار آنے والی منطق کو علیحدہ فنکشن، کلاس یا ماڈیول میں نکالیں۔
WET (Write Everything Twice) DRY کے برعکس ہے، جہاں ڈپلیکیشن قابل قبول سمجھی جاتی ہے۔ WET پروجیکٹس میں، کوڈ کا ایک ہی ٹکڑا پانچ کاپیوں میں موجود ہو سکتا ہے، اور جب ضروریات بدلتی ہیں، ڈیولپر ہر کاپی کو علیحدہ طور پر ٹھیک کرتا ہے۔ WET بگ کے خطرے کو بڑھاتا ہے اور ترقی کو سست کرتا ہے۔
DRY نقصان دہ ہوتا ہے جب یہ قبل از وقت تجریہ کی طرف لے جائے: جب دو ملتے جلتے لیکن معنوی طور پر مختلف کوڈ حصوں کو زبردستی ایک فنکشن میں ملا دیا جائے۔ یہ پیچیدہ، پیرامیٹر سے بھرا کوڈ پیدا کرتا ہے۔ تین کا قاعدہ اس غلطی سے بچنے میں مدد کرتا ہے: تیسری تکرار کے بعد ہی تجریہ کریں۔
Android میں، DRY ورژن کیٹلاگ (libs.versions.toml)، اڈاپٹر کے لیے مشترکہ بنیادی کلاسز، ViewModel فیکٹریز اور یوٹیلیٹی Kotlin توسیعات کے ذریعے لاگو کیا جاتا ہے۔ کاروباری منطق کو مشترکہ ماڈیولز (KMM) میں نکالنے اور findViewById ڈپلیکیشن ختم کرنے کے لیے View Binding استعمال کرنے کی سفارش کی جاتی ہے۔
iOS میں، DRY ڈیفالٹ نفاذ والے پروٹوکولز، مشترکہ نیٹ ورک کنفیگریشنز (NetworkConfig)، UICollectionView سیل فیکٹریز اور مشترکہ کاروباری منطق والے SPM پیکیجز کے ذریعے حاصل کیا جاتا ہے۔ معیاری اقسام (Date, String, URL) کی توسیعات فارمیٹنگ اور تصدیق میں ڈپلیکیشن کو کم کرتی ہیں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں