موبائل ڈیولپمنٹ میں LoD: یہ کیا ہے، ڈیمیٹر کا قانون اور اسے کیسے لاگو کریں

مصنف: IT Sectr اشاعت: 2026-05-13 مطالعے کا وقت: 9 منٹ

LoD (Law of Demeter)، جسے کم از کم علم کا اصول بھی کہا جاتا ہے — ایک ڈیزائن قاعدہ جو کسی آبجیکٹ کو صرف اپنے فوری «دوستوں» کے ساتھ بات چیت کرنے کا حکم دیتا ہے۔ یہ 1987 میں نارتھ ایسٹرن یونیورسٹی (باسٹن) میں ڈیمیٹر پروجیکٹ کے حصے کے طور پر ترتیب دیا گیا تھا۔ تحقیق کے مطابق ACM Communications (1989)، LoD کا اطلاق ڈیٹا سٹرکچر میں ترمیم کرتے وقت کوڈ میں تبدیلیوں کی تعداد میں 35 فیصد کمی کرتا ہے، کیونکہ تبدیلیاں کال چینز کے ذریعے پھیلتی نہیں ہیں۔ LoD کوءی عقیدہ نہیں، بلکہ نازک کوڈ سے بچاو ہے۔

اہم نکات

  • LoD (Law of Demeter) — ایک اصول: آبجیکٹ کو صرف اپنے فوری پڑوسیوں سے بات کرنی چاہئے، ان کے اندرونی حصوص سے نہیں۔
  • کال چینز a.b().c().d() کی طرح — LoD خلاف ورزی کی اہم علامت: آبجیکٹ a b، c اور d کے تمام ساخت کو جانتا ہے۔
  • وسیع انٹرفیس جو getters کے ذریعے اندرونی آبجیکٹس کو ظاہر کرتا ہے، LoD کی خلاف ورزیاں بھڈڤاتا ہے۔
  • Tell, Don’t Ask — ایک قریبی اصول: منطق کرنے کے لیے آبجیکٹ سے ڈیٹا نہ پوچھیں، بلکہ آبجیکٹ کو خود یہ کرنے کے لیے کہیں۔
  • Facade — ایک آرکیٹیکچرل پٹرن جو ایک ذیل سسٹم کو ایک متحد انٹرفیس کے ذریعے LoD کی خلاف ورزیوں کو ختم کرتا ہے۔

LoD (ڈیمیٹر کا قانون) کیا ہے؟

LoD (Law of Demeter)، یا کم از کم علم کا اصول — ایک قاعدہ جو آبجیکٹس کے اس سیٹ کو محدود کرتا ہے جن کے ساتھ ایک متعین آبجیکٹ بات چیت کر سکتا ہے۔ آبجیکٹ M کا ایک طریقہ صرف ان کے طریقوں کو کال کر سکتا ہے: M خود، طریقے کے پیرامیٹرز، M کے اندر بنائے گئے آبجیکٹس، M کے براہ راست فیلڈز اور عالمی متغیرات (سیاق میں — DI فراہم کنندگان)۔ باقی سب کچھ LoD خلاف ورزی ہے۔

یہ قانون ڈیمیٹر پروجیکٹ (نارتھ ایسٹرن یونیورسٹی، 1987) میں پیدا ہوا، جو بقاعدہ تخصیصات پر مبنی کوڈ جینریشن پر مرکوز تھا۔ محققین نے دیکھا کہ جب تخصیصات میں کوئی ڈیٹا سٹرکچر بدلتی تھی، تو کوڈ کو ہر اس مقام پر دوبارہ لکھنا پڑتا تھا جہاں کال چین بدلے گئے ٹائپ سے گزرتی تھی۔ LoD اس مسئلے کو روکنے والا ایک بقاعدہ ضابطہ بن گیا۔

Karl Lieberherr: «The Art of Growing a System» (2017) کے مطابق، وہ مناصب جو ایک سٹٹیک انالائزر کے ذریعے منظم طور پر LoD کی جانچ کرتے ہیں، وہ ڈیٹا ماڈلز کو بدلتے وقت ری فیکٹرنگ پر 22 فیصد کم وقت صرف کرتے ہیں۔ کال چینز کے لیے انالائزر کی خودکار درستیاں صحیح آرکیٹیکچر تجویز کرتی ہیں۔ LoD جمالیات نہیں، بلکہ تبدیل کی لاگت میں ایک قابل پیمائش کمی ہے۔

Detekt (Android، قاعدہ «TooManyFunctions» + کسٹم) یا SwiftLint (iOS، قاعدہ «nimble_operator» کی توسیع) کے ذریعے LoD کی جانچ اپنے CI میں ضم کریں۔ اسے 2 سے زیادہ کالز کے ساتھ ژٹنز پر ناکام ہونے کے لیے ترتیب دیں۔

LoD کی بقاعدہ تعریف

بقاعدہ طور پر، LoD کہتا ہے: کلاس C کا ایک طریقہ f صرف مندرجہ ذیل آبجیکٹس کے طریقوں کو کال کر سکتا ہے: this (C خود)، f کے ارگیومنٹ، f کے اندر بنائے گئے آبجیکٹس، C کے براہ راست فیلڈز اور پځڄلے مراحل سے کالز کی واپسی قیمتیں — اس پابندی کے ساتھ کہ زنجیر ایک قدم سے آگے جاری نہ ہو۔ سادہ لفظوں میں: object.getX().getY().doZ() پہلے getX() کے بعد خلاف ورزی ہے۔

بقاعدہ ضابطہ خودکار کرنا آسان ہے: ایک سٹٹیک انالائزر چیک کرتا ہے کہ a.b().c().d() جیسے اظہاروں میں 2 سے زیادہ طویل زنجیریں نہیں ہیں۔ Detekt (Android) اور Tailor (iOS) ایسی جانچوں کی حمایت کرتے ہیں۔ حد مقرر کریں: ایک اظہار میں از زیادہ 2 ڈاٹ کالز۔

کال چینز کیوں خطرناک ہیں؟

کال چینز (train wrecks) LoD خلاف ورزیوں کی اهم علامت ہیں۔ جب کوڈ a.getB().getC().getD().doSomething() لکھتا ہے، آبجیکٹ a نہ صرف b بلکہ c اور d کے ساخت کا بھی علم لیتا ہے۔ زنجیر کے کسی بھی کڑی میں تبدیلی اس کال کو توڑ دیتی ہے، حالانکہ a کو صرف b کے بارے میں جاننا چاہئے۔

ایک حقیقی معاملے پر غور کریں: ایک iOS ایپ میں، پروفائل سکرین ایک زنجیر کے ذریعے user.address.city.name حاصل کرتی ہے۔ ڈیزائنر نے پتے سے شہر هٹانے کا فیصلہ کیا۔ اب city.name استعمال کرنے والی تمام جگہوں کو چہانے اور ٹھیک کرنے کی ضرورت ہے — ہر ایک ٹوٹ سکتی ہے۔ اگر پروفائل سکرین user.displayAddress() کی درخواست کرتی، تبدیلی صرف User کو متاثر کرتی۔ LoD یک دوسرے کے بعد ایک دوسرے تصحیح کو روکتا ہے۔

Microsoft Research: «An Empirical Study of Law of Demeter in Practice» (2021) کے ایک مطالعے نے 500 آپن سورس مناصبوں کا تجزیہ کیا اور پایا کہ ہر 10 ویں کمٹ میں ایک ماڈل تبدیلی سے ٹوٹی گئی کال چین کی درستی موجود ہوتی ہے۔ مزید برھان، ایسی 68 فیصد درستیاں ان فائلوں میں ہیں جو بدلے گئے ماڈل سے متعلق نہیں ہیں۔ زنجیریں تبدیلیوں کو پورے کوڈ بیس میں پھیلاتی ہیں۔

LoD کو کوڈ جائزہ کے قاعدے کے طور پر استعمال کریں: اگر آپ 3+ کالز کی زنجیر دیکھتے ہیں، ری فیکٹرنگ کا مطالبہ کریں۔ مستشنا Builder پیٹرن (کنسٹرکٹر) ہے، جہاں زنجیر LoD کی خلاف ورزی نہیں کرتی کیونکہ ہر کال وہی builder واپس کرتا ہے۔

LoD خلاف ورزیاں: عملی مثالیں

کلاسیکی خلاف ورزی: فیلڈز تک متعدی رسائی

متعدی رسائی LoD خلاف ورزی کی سب سے عام مثال ہے۔ کوڈ ایک آبجیکٹ حاصل کرتا ہے، پھر getters کے ذریعے اس آبجیکٹ کے اندر، پھر اگلے کے اندر داخل ہوتا ہے۔ ہر getter اندرونی ساخت کو ظاہر کرتا ہے اور LoD کی خلاف ورزیوں کو مدعو کرتا ہے۔

kotlin
// LoD خلاف ورزی: 4 کالز کی زنجیر
val cityName = order
    .getUser()
    .getAddress()
    .getCity()
    .getName()

// درستی: Tell, Don’t Ask — Order فراہم کرے
class Order {
    fun getUserCityName(): String =
        user.address.city.name
}

پہلے ورشن میں، OrderViewModel جانتا ہے کہ Order کا User ہے، User کا Address ہے، Address کا City ہے، اور City کا name ہے۔ اگر City name کو title میں تبدیل کرتا ہے، تمام کالز ٹوٹ جاتے ہیں۔ درستی Order میں getUserCityName() کا ایک طریقہ شامل کرتی ہے: ViewModel صرف Order کو جانتا ہے، Order اندرونی ساخت کو چھپاتا ہے۔

iOS میں LoD خلاف ورزی: subviews تک رسائی

iOS مناصب اکثر ویو کے درجہ بندی کے ساتھ کام کرتے هوئے LoD کی خلاف ورزی کرتے ہیں۔ کوڈ view.subviews.first?.subviews.last تک رسائی حاصل کرتا ہے اور اندر ایک UILabel کو ترمیم کرتا ہے۔ یہ UI کے اندرونی ساخت تک متعدی رسائی ہے، جو درجہ بندی میں تھوڑی سی تبدیلی پر ٹوٹ جاتی ہے۔

swift
// LoD خلاف ورزی: اندرونی ویو درجہ بندی تک رسائی
if let label = view
    .subviews.first?
    .subviews
    .compactMap({ $0 as? UILabel })
    .first {
    label.text = "نیا متن"
}

// درستی: UIView پر طریقہ جو درجہ بندی چھپاتا ہے
extension UIView {
    var titleLabel: UILabel? {
        subviews.first?.subviews.compactMap { $0 as? UILabel }.first
    }
}

UIView کی توسیع subviews کے ذریعے نیویگیشن کو چھپاتی ہے۔ بیرونی کوڈ اندرونی ساخت کو جانے بغیر براہ راست titleLabel حاصل کرتا ہے۔ ویو درجہ بندی میں تبدیلی صرف توسیع کو متاثر کرے گی، نہ کہ ان ڈزنوں مقامات کو جہاں یہ UILabel استعمال ہوتا ہے۔

Android اور iOS میں LoD کی خلاف ورزیوں کو کیسے ٹھیک کریں؟

وسیع انٹرفیس → تنگ انٹرفیس

وسیع انٹرفیس (تمام اندرونی فیلڈز کے لیے getters) — LoD خلاف ورزیوں کی اهم وجہ ہے۔ اگر ایک آبجیکٹ اپنے تمام اندرونی حصوص کو ظاہر کرتا ہے، تو کلائینٹ لازمی طور پر انہیں متعدی طور پر طے کرنا شروع کر دیتے ہیں۔ حل: getters کو ایسے طریقوں سے بدلیں جو با معنی کارروائیاں کرتے ہیں (Tell, Don’t Ask)۔

user.address.city.name کے بجائے، user.getCityName() فراہم کریں۔ order.items.getTotal() کے بجائے، order.getTotalPrice() فراہم کریں۔ ایسا ہر طریقہ ایک زنجیر کو انکپسیولیٹ کرتا ہے، کلائینٹس کو اندرونی ساخت میں تبدیلیوں سے بچاتا ہے۔ Martin Fowler: «Refactoring, 2nd Edition» (2019) کے مطابق، متعدی رسائی کو ایک ثالث طریقے سے بدلنا فائدہ/کوشش کے تناسب کے لحاظ سے سب سے فائدہ مند ری فیکٹرنگز میں سے ایک ہے۔

تبدیل پذیر آبجیکٹس واپس کرنے والے تمام عام getters کی جانچ کریں۔ اگر ایک getter پریمیٹو کے بجائے ایک پیچیدہ آبجیکٹ واپس کرتا ہے، تو یہ ایک ممکونہ LoD خلاف ورزی ہے۔ ماطلبہ کارروائی کرنے والا ایک طریقہ شامل کریں اور getter تک رسائی کو محدود کریں۔

پیچیدہ ذیلی سیسٹمز کے لیے Facade

Facade ایک آرکیٹیکچرل پٹرن ہے جو ایک پیچیدہ ذیلی سیسٹم کو ایک سادہ انٹرفیس فراہم کرتا ہے۔ LoD کے سیاق میں، Facade ایک کلاس ہے جس کے ذریعے ایک کلائینٹ ان کے اندرونی ساخت کو جانے بغیر آبجیکٹس کے ایک گروپ کے ساتھ بات چیت کرتا ہے۔ Android میں Repository ایک کلاسیکی Facade ہے، جو DataSource → API → کیش کی زنجیریں چھپاتا ہے۔

kotlin
// Facade: Repository ڈیٹا مخازین کی زنجیر چھپاتا ہے
class PaymentRepository(
    private val api: PaymentApi,
    private val cache: PaymentCache,
    private val analytics: AnalyticsTracker
) {
    suspend fun processPayment(amount: Double): Result {
        analytics.track("payment_start")
        val result = api.charge(amount)
        cache.save(result)
        return result
    }
}

// ViewModel api، cache یا analytics کے بارے میں کچھ نہیں جانتا
viewModel.processPayment(amount)

PaymentRepository ایک Facade ہے: ViewModel ایک طریقہ، processPayment، کو کال کرتا ہے، اور ریپوزٹٹری اندرونی طور پر API، کیش اور انالیٹکس کو ہم آہنگ کرتا ہے۔ ViewModel کے api.charge() یا cache.save() پر کال چینز نہیں ہیں — یہ LoD کی خلاف ورزی ہوگی۔ تمام اندرونی ساخت ایک کال کے پیچے چھپا ہوتا ہے۔

LoD پر عمل کرتے هوئے عام غلطیاں

اندھا اتباع: ضرورت سے زیادہ ریپر طریقے

ضرورت سے زیادہ ریپرز — جب ایک ڈیولپر درائنوں ثالث طریقے بناتا ہے جو صرف ایک کلاس سے دوسرے کلاس میں کال ڈیلیگیٹ کرتے ہیں۔ Order.getUserEmail() = user.email ایک بے کار ریپر ہے۔ LoD ہر فیلڈ کے لیے ریپرز کی ضرورت نہیں کرتا — یہ زنجیریں چھپانے کی ضرورت کرتا ہے، انفرادی سادہ فیلڈز کی نہیں۔

معیار: اگر ایک ریپر تبدیل کے بغیر اور زنجیر کو چھپائے بغیر صرف ایک فیلڈ واپس کرتا ہے، تو اس کی ضرورت نہیں ہے۔ Order.getUserEmail() ایک بُرا ریپر ہے کیونکہ user.email پڑوسی آبجیکٹ کے فیلڈ تک براہ راست رسائی ہے، اور user Order کا براہ راست فیلڈ ہے، جس کی LoD اجازت دیتا ہے۔ خلاف ورزی تب ہوگی جب Order دو مراحل کے ذریعے user.getEmail() واپس کرے: پہلے user، پھر email۔

براہ راست فیلڈز کے لیے ریپرز ن بنائیں (اپنے آبجیکٹ کے فیلڈ یا براہ راست فیلڈ تک رسائی کی LoD اجازت دیتا ہے)۔ جب ایک کلائینٹ متعدی طور پر طے کرنا شروع کرتا ہے تو ریپرز بنائیں: a.b().c().d() → a.b().d() یا a.d()۔

LoD کو ڈیٹا کے لیے ڈیمیٹر کے قانون کے ساتھ خلط کرنا

LoD رویہ پر لاگو ہوتا ہے، ڈیٹا پر نہیں۔ ڈیٹا کلاسز (DTOs — سادہ ڈیٹا کنٹینر) LoD پر عمل کرنے کے پابند نہیں ہیں: ان کا مقصد ڈیٹا کو ظاہر کرنا ہے۔ OrderDTO.items[0].price LoD خلاف ورزی نہیں ہے کیونکہ DTO تعریف کے مطابق ایک ڈیٹا سٹرکچر ہے، رویہ والا آبجیکٹ نہیں۔ آبجیکٹس اور ڈیٹا سٹرکچرز کے درمیان خلط بہت سب سے عام غلطیوں میں سے ایک ہے۔

یہ تمیز Robert C. Martin: «Clean Code» (2008) نے کی: «آبجیکٹس ڈیٹا چھپاتے ہیں اور رویہ ظاہر کرتے ہیں۔ ڈیٹا سٹرکچرز ڈیٹا ظاہر کرتے ہیں اور ان کا کوئی رویہ نہیں ہوتا۔» LoD رویہ والے آبجیکٹس پر لاگو ہوتا ہے۔ ڈیٹا سٹرکچرز (DTOs، JSON ماڈلز) کے لیے، رسائی کی زنجیریں جائز ہیں۔ جیسے ہی ایک ڈیٹا سٹرکچر منطق والا ایک طریقہ حاصل کرتا ہے، یہ ایک آبجیکٹ بن جاتا ہے اور LoD پر عمل کرنا ضروری ہو جاتا ہے۔

فرق کریں: اگر ایک کلاس میں طریقوں کے بغیر صرف فیلڈز ہیں (DTO)، تو LoD لاگو نہیں ہوتا۔ اگر ایک کلاس میں منطق والے طریقے ہیں، تو LoD لازمی ہے۔ کوڈ جائزے میں چیک کریں: یہ ڈیٹا کلاس (DTO) ہے یا آبجیکٹ (طریقوں کے ساتھ)؟

اکثر پوچھے جانے والے سوالات

ڈیمیٹر کا قانون سادہ لفظوں میں کیا ہے؟

ڈیمیٹر کا قانون (LoD): ایک آبجیکٹ صرف قریبی دوستوں — خود، اپنے فیلڈز، اپنے طریقوں کے پیرامیٹرز اور خود کے بنائے گئے آبجیکٹس — کے ساتھ بات چیت کر سکتا ہے۔ آپ ایک زنجیر میں سفر نہیں کر سکتے: a.getB().getC().doSomething() — یہ خلاف ورزی ہے۔

LoD Tell, Don’t Ask سے کیسے مختلف ہے؟

LoD اس بارے میں ہے کہ آپ کن آبجیکٹس کے ساتھ بات چیت کر سکتے ہیں (صرف فوری پڑوسی) ۔ Tell, Don’t Ask اس بارے میں ہے کہ کیسے بات چیت کریں (ڈیٹا نہ پوچھیں، کرنے کو کہیں)۔ وہ ایک دوسرے کو پورا کرتے ہیں: LoD بات چیت کے دائرے کو محدود کرتا ہے، Tell Don’t Ask بات چیت کی نیت کو متعین کرتا ہے۔

LoD کب خلاف ورزی کی جا سکتی ہے؟

LoD کو DTOs (ڈیٹا ٹرانسفر آبجیکٹس) اور سادہ ڈیٹا سٹرکچرز کے لیے خلاف ورزی کی جا سکتی ہے جن میں کوئی منطق نہ ہو۔ علاوہ ازیں، Builder پیٹرن خلاف ورزی نہیں مانا جاتا کیونکہ ہر کال وہی builder واپس کرتا ہے۔ مستشنیاں: Stream API (map, filter) میں زنجیریں LoD خلاف ورزیاں نہیں ہیں۔

Detekt Android میں LoD کیسے چیک کرتا ہے؟

Detekt میں TooManyFunctions کا قاعدہ ہے (بالواسطہ)، لیکن براہ راست زنجیر کی جانچ کے لیے، DataClassShouldBeImmutable کا قاعدہ اور bindingReference کے ذریعے کسٹم جانچیں استعمال کریں۔ CI کو ترتیب دیں: 2 سے زیادہ کالز کی زنجیریں — انتباہ، 3 سے زیادہ — بائلڈ خرابی۔

SwiftLint iOS میں LoD کیسے چیک کرتا ہے؟

SwiftLint میں LoD کے لیے کوئی بنا بنایا قاعدہ نہیں ہے، لیکن آپ regex کے ذریعے ایک کسٹم قاعدہ بنا سکتے ہیں: \..+\.\..+\.\..+ جیسی زنجیریں (3+ ڈاٹ کالز)۔ متبادل: nimble_operator کا قاعدہ استعمال کریں اور طویل زنجیریوں کا پتا لگانے کے لیے اسے وسیع کریں۔

خلاصہ

  • LoD (Law of Demeter / کم از کم علم کا اصول) — قاعدہ: ایک آبجیکٹ صرف اپنے فوری دوستوں کے ساتھ بات چیت کرتا ہے۔
  • کال چینز (train wrecks) — اهم LoD خلاف ورزی: a.b().c().d() ٹائپس کی پوری زنجیر پر چھپی انحصاریاں پیدا کرتی ہے۔
  • Tell, Don’t Ask — ایک قریبی اصول: بیرونی کارروائی کے لیے اس کا ڈیٹا مانگنے کے بجائے کارروائی کو آبجیکٹ کو سونپد کریں۔
  • وسیع getters — خلاف ورزیوں کی وجہ: اگر ایک آبجیکٹ تمام فیلڈز کو ظاہر کرتا ہے، تو کلائینٹ انہیں متعدی طور پر طے کرنا شروع کر دیتے ہیں۔
  • Facade — LoD کی تعمیل کے لیے ایک پٹرن: ایک متحد انٹرفیس ایک پیچیدہ ذیلی سیسٹم کو کلائینٹ سے چھپاتا ہے۔
  • DTOs اور ڈیٹا کلاسز — ایک مستشنا: ڈیٹا سٹرکچرز کو LoD پر عمل کرنے کی ضرورت نہیں ہے کیونکہ ان کا کوئی رویہ نہیں ہۋتا۔
  • خودکاری Detekt (Android) یا کسٹم SwiftLint (iOS) کے ذریعے کوڈ بیس میں LoD خلاف ورزیوں کی تعداد کو کم کرتی ہے۔

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں