Code Smell کوڈ میں ایک سطحی اشارہ ہے جو ایپلی کیشن کے ڈیزائن یا آرکیٹیکچر میں ممکنہ مسئلے کی نشاندہی کرتا ہے۔ یہ اصطلاح کینٹ بیک نے وضع کی اور مارٹن فاولر نے کتاب “Refactoring: Improving the Design of Existing Code” میں مقبول بنائی۔ Martin Fowler کے مطابق، کوڈ کی بدبو کا لازماً بگ ہونا ضروری نہیں، لیکن یہ تقریباً ہمیشہ برقرار رکھنے کی صلاحیت کو بہتر بنانے کے لیے ریفیکٹرنگ کی ضرورت کی نشاندہی کرتی ہے۔
اہم نکات
Code Smell سورس کوڈ میں علامات کے لیے ایک استعارہ ہے جو زیادہ امکان کے ساتھ گہرے مسائل کی نشاندہی کرتی ہے۔ اس اصطلاح کی کوئی رسمی تعریف نہیں ہے — یہ ڈویلپرز کے تجربے پر مبنی ایک تحقیقی طریقہ ہے۔ مارٹن فاولر اور کینٹ بیک نے 1999 میں پہلی بار کتاب “Refactoring” میں 22 بدبوؤں کو منظم کیا، اور ان میں سے اکثر دہائیوں بعد بھی متعلقہ ہیں۔
Code Smell اور بگ کے درمیان فرق کو سمجھنا ضروری ہے۔ بدبو کوئی غلطی نہیں ہے: کوڈ کمپائل ہوتا ہے، کام کرتا ہے اور درست نتائج پیدا کرتا ہے۔ مسئلہ یہ ہے کہ ایسے کوڈ کو پڑھنا، تبدیل کرنا اور جانچنا مشکل ہے۔ وقت کے ساتھ، ہر تبدیلی کی لاگت بڑھتی ہے اور ریفیکٹرنگ کی درستگی پر اعتماد کم ہوتا ہے۔ جامد تجزیہ کے اوزار (SonarQube, Detekt, SwiftLint) خود بخود بہت سی بدبوؤں کا پتہ لگاتے ہیں۔
Code Smell کی تحقیقی نوعیت کا مطلب ہے کہ ہر لمبے طریقہ کو تقسیم کرنے کی ضرورت نہیں ہے، اور ہر بڑی کلاس کو ریفیکٹرنگ کی ضرورت نہیں ہے۔ فیصلہ ڈویلپر سیاق و سباق کا جائزہ لے کر کرتا ہے: تبدیلیوں کی تعدد، ماڈیول کی اہمیت، ترقی کے منصوبے۔ تجربہ کار انجینئر بدبو کو بدیہی طور پر محسوس کرتے ہیں — کوڈ “بدبودار” ہوتا ہے چاہے تمام رسمی اصولوں پر عمل کیا گیا ہو۔
فاولر نے 22 بدبوؤں کی نشاندہی کی جو کئی زمروں میں تقسیم ہیں۔ موبائل ڈویلپمنٹ کے لیے، سب سے زیادہ متعلقہ ساختی بدبو، آبجیکٹ اورینٹڈ ڈیزائن کی بدبو، اور پلیٹ فارم کی رکاوٹوں سے متعلق مخصوص مسائل ہیں۔ آئیے حقیقی مثالوں کے ساتھ ہر گروپ کا جائزہ لیں۔
Long Method موبائل ایپلی کیشنز میں سب سے عام بدبو ہے۔ رجسٹریشن فارم اسکرین میں اکثر 200+ سطروں کا ایک ہی setupUI طریقہ ہوتا ہے جو تمام Views بناتا ہے، رکاوٹیں مرتب کرتا ہے، واقعات کو سبسکرائب کرتا ہے اور غلطیوں کو ہینڈل کرتا ہے۔ حل: منطقی بلاکس کے مطابق طریقوں میں تقسیم کریں — configureEmailField, configurePasswordField, setupConstraints, bindViewModel۔
Large Class — ایک Activity یا ViewController جو ڈسپلے، نیویگیشن، کاروباری منطق اور نیٹ ورک کے تعاملات سب کے لیے ذمہ دار ہے۔ ایسی کلاس واحد ذمہ داری کے اصول کی خلاف ورزی کرتی ہے اور درجنوں فیلڈز اور طریقوں پر مشتمل ہوتی ہے۔ Android میں، یہ اکثر 1000+ سطروں کا Fragment ہوتا ہے جس میں مختلف اسکرینوں کی منطق ہوتی ہے۔ حل: presenter/ViewModel نکالیں، نیٹ ورک کوڈ کو ریپوزٹری میں اور نیویگیشن کو کوآرڈینیٹر میں منتقل کریں۔
Duplicate Code — ایپلی کیشن کے مختلف حصوں میں ایک جیسے بلاکس کاپی کرنا۔ ایک عام مثال: دو اسکرینیں پروڈکٹ کارڈ دکھا رہی ہیں — کیٹلاگ میں اور پسندیدہ میں۔ اگر ڈسپلے منطق کاپی کی گئی ہے، تو ایک جگہ بگ ٹھیک کرنے سے دوسری جگہ ٹھیک نہیں ہوگا۔ حل: مشترکہ منطق کو دوبارہ قابل استعمال جزو یا ایکسٹینشن میں نکالیں۔
Feature Envy — ایک کلاس کا طریقہ دوسری کلاس کے ڈیٹا کو بھرپور طریقے سے استعمال کرتا ہے۔ Android میں، یہ اس وقت ظاہر ہوتا ہے جب ViewModel ماڈل کا طریقہ بلانے کے بجائے براہ راست User ماڈل کے فیلڈز تک رسائی حاصل کرتی ہے۔ اشارہ: اگر کسی طریقہ کو اس کلاس میں منتقل کیا جا سکتا ہے جس کا ڈیٹا وہ استعمال کرتا ہے — تو منتقل کریں۔ Switch Statements (شرطی سلسلے) — ایک switch تعمیر یا if-else سلسلہ جو آبجیکٹ کی قسم چیک کرتا ہے۔ اس کے بجائے، کثیر شکلیت یا حکمت عملی کا نمونہ استعمال کریں۔
Data Class — ایک کلاس جو صرف ڈیٹا ذخیرہ کرتی ہے لیکن اس میں کوئی رویہ نہیں ہے۔ Kotlin میں data classes یا Swift میں ڈھانچے خود بدبو نہیں ہیں۔ مسئلہ اس وقت پیدا ہوتا ہے جب اس ڈیٹا کے ساتھ کام کرنے والی کاروباری منطق کوڈ بیس میں بکھری ہوتی ہے بجائے اس کے کہ انکیپسلیٹڈ ہو۔ Refused Bequest — ایک ذیلی کلاس والدین کے زیادہ تر طریقے استعمال نہیں کرتی اور انہیں خالی اسٹبس سے اوور رائڈ کرتی ہے۔ غلط وراثت کی علامت: وراثت کو ترکیب سے بدلیں۔
God Activity / God Fragment — ایک Activity یا Fragment جو سب کچھ جانتی ہے: لائف سائیکل، ڈیٹا، نیویگیشن، اجازتیں، DI۔ ایپلی کیشن میں یہ سب سے مہنگی کلاس ہے جسے برقرار رکھنا ہے۔ حل: MVVM، MVI یا Clean Architecture جیسے آرکیٹیکچرل نمونے ذمہ داریوں کو الگ کرتے ہیں۔ Giant ViewController — iOS میں مساوی، جہاں ایک UIViewController اسکرین کی تمام منطق پر مشتمل ہوتا ہے اور اکثر 500 سطروں سے تجاوز کر جاتا ہے۔
Hardcoded Resources — سٹرنگز، رنگ، سائز، API URLs براہ راست کوڈ میں شامل۔ Android میں، یہ R ریسورس سسٹم کی خلاف ورزی کرتا ہے؛ iOS میں، NSLocalizedString اور Asset Catalog۔ اصلاح: تمام سٹرنگز کو strings.xml یا Localizable.strings میں، URLs کو کنفیگریشن فائل میں، سائز کو dimens میں منتقل کریں۔ Leaking Context — Activity یا ViewController کے حوالے کو جزو کی اپنی زندگی سے زیادہ دیر تک رکھنا۔ میموری لیک اور کریش کا سبب بنتا ہے۔ حل: کمزور حوالہ جات، Jetpack Lifecycle، RxSwift DisposeBag۔
| بدبو | کہاں پائی جاتی ہے | حل |
|---|---|---|
| Long Method | Android/iOS | Extract Method, تقسیم |
| Large Class | Activity, ViewController | MVVM, VIPER, Clean Arch |
| Duplicate Code | کوئی بھی اسکرین | مشترکہ جزو, DRY |
| Feature Envy | ViewModel, Presenter | Move Method |
| Leaking Context | Android | Lifecycle-aware اجزاء |
کوڈ کا جائزہ بدبو کا پتہ لگانے کا سب سے قابل اعتماد طریقہ ہے۔ انسانی آنکھ غیر فطری ساختوں کو نوٹس کرتی ہے جو خودکار تجزیہ کار چھوڑ دیتے ہیں۔ کوڈ کے جائزے کی تاثیر اس وقت بہتر ہوتی ہے جب ٹیم عام بدبو کی جانچ پڑتال کی فہرست استعمال کرتی ہے۔ ہر سیشن میں 200–400 سطروں سے زیادہ کوڈ کا جائزہ لینے کی سفارش نہیں کی جاتی — اس حد کے بعد توجہ کم ہو جاتی ہے اور بدبو چھوٹنے لگتی ہے۔
جامد تجزیہ ساختی بدبو کی تلاش کو خودکار بناتا ہے۔ Android کے لیے، معیاری اوزار Detekt (Kotlin) اور Android Lint ہیں؛ iOS کے لیے، SwiftLint اور SonarQube۔ یہ اوزار لمبے طریقے، بڑی کلاسیں، ڈپلیکیٹ کوڈ اور بہت سے دیگر مسائل تلاش کرتے ہیں۔ پراجیکٹ کے مطابق اصولوں کو ترتیب دینا ضروری ہے — ڈیفالٹ کنفیگریشنز اکثر بہت سخت ہوتی ہیں یا اس کے برعکس اہم بدبو کو چھوڑ دیتی ہیں۔
کوڈ میٹرکس معروضی معیار فراہم کرتے ہیں: چکریی پیچیدگی (حد >10 توجہ کی ضرورت ہے)، فی طریقہ کوڈ کی سطریں (حد >30)، وراثت کی گہرائی (>3 — سوچنے کی وجہ)۔ CodeMetrics (Xcode) اور Gradle Metrics Plugin جیسے اوزار وقت کے ساتھ میٹرکس تبدیلیوں کے گراف بناتے ہیں۔ اگر آخری commit کے بعد کسی طریقہ کی پیچیدگی 5 سے 15 تک بڑھ گئی — تو یہ ریفیکٹرنگ کا اشارہ ہے۔
// مثال: چکریی پیچیدگی = 7 والا طریقہ (حد 5 سے اوپر)
fun processOrder(order: Order) {
if (order.status == Status.NEW) { /* 10 سطریں */ }
else if (order.status == Status.PAID) { /* 15 سطریں */ }
else if (order.status == Status.SHIPPED) { /* 20 سطریں */ }
else if (order.status == Status.DELIVERED) { /* 8 سطریں */ }
else if (order.status == Status.CANCELLED) { /* 5 سطریں */ }
else { throw IllegalStateException() }
}
// اصلاح: switch کے بجائے کثیر شکلیت
interface OrderHandler {
fun handle(order: Order)
}
خودکار بدبو کا پتہ لگانا کوڈ کے جائزے کی جگہ نہیں لیتا: جامد تجزیہ کار صرف ساختی مسائل تلاش کرتے ہیں لیکن معنوی بدبو (Feature Envy, Inappropriate Intimacy) کو نہیں پکڑتے۔ خودکار اوزاروں اور انسانی جائزے کا امتزاج بہترین نتائج دیتا ہے۔ اپنی CI/CD پائپ لائن کو اس طرح ترتیب دیں کہ جب پیچیدگی یا طریقہ کی لمبائی کی حدیں تجاوز ہوں تو بلڈ ناکام ہو۔
ریفیکٹرنگ کوڈ کی بدبو کو ختم کرنے کا بنیادی طریقہ ہے۔ فاولر درجنوں ریفیکٹرنگ تکنیکوں کی وضاحت کرتا ہے، ہر ایک مخصوص بدبو پر لاگو ہوتی ہے۔ Extract Method — لمبے طریقوں کے لیے، Extract Class — بڑی کلاسوں کے لیے، Move Method — Feature Envy کے لیے۔ ہر تبدیلی کے بعد کوڈ کو کام کرنے والا رکھتے ہوئے چھوٹے قدموں میں ریفیکٹرنگ کرنا ضروری ہے۔
ریفیکٹرنگ سے پہلے ٹیسٹ لازمی ہیں۔ اگر کوڈ یونٹ ٹیسٹ سے کور نہیں کیا گیا ہے، تو ریفیکٹرنگ نامعلوم نتائج کے ساتھ دوبارہ لکھنے میں بدل جاتی ہے۔ ٹیسٹ کے بغیر لیگیسی کوڈ کے لیے، Characterization Tests استعمال کریں — وہ ٹیسٹ لکھیں جو موجودہ رویے کو قید کرتے ہیں، پھر ریفیکٹر کریں۔ ٹیسٹنگ یہ یقین دلاتی ہے کہ ریفیکٹرنگ کے بعد کاروباری منطق نہیں ٹوٹی۔
تدریج موبائل ڈویلپمنٹ میں بدبو کو کامیابی سے ٹھیک کرنے کی کلید ہے۔ God Activity کو مکمل طور پر دوبارہ لکھنے کی کوشش نہ کریں۔ پہلے نیویگیشن پرت نکالیں، پھر ڈیٹا پرت، پھر ڈسپلے منطق۔ ہر قدم کے ساتھ ایک commit اور ٹیسٹ رن ہونا چاہیے۔ صارفین کے ایک ذیلی سیٹ کے لیے ریفیکٹرنگ کو فعال کرنے اور مسائل ہونے پر واپس آنے کے لیے فیچر ٹوگل استعمال کریں۔
IDE اوزار بہت سی ریفیکٹرنگ تکنیکوں کو خودکار بناتے ہیں۔ Android Studio اور IntelliJ IDEA بلٹ ان ریفیکٹرنگ پیش کرتے ہیں: Extract Method, Extract Interface, Pull Members Up, Encapsulate Fields۔ Xcode (ورژن 14 سے شروع) نے Swift کے لیے ریفیکٹرنگ سپورٹ کو بہتر کیا۔ خودکار ریفیکٹرنگ کا استعمال دستی کوڈ کاپی کرنے کے مقابلے میں غلطیوں کے خطرے کو کم کرتا ہے۔
موبائل ڈویلپمنٹ پلیٹ فارم کی رکاوٹوں سے متعلق اپنی مخصوص بدبو شامل کرتی ہے۔ Android میں، اس میں Context لیک، بند نہ کیے گئے Cursor، اور Lifecycle کا غلط استعمال شامل ہے۔ iOS میں، closures کے ذریعے retain cycle، Auto Layout کا غلط استعمال، اور بڑے ViewController شامل ہیں۔ یہ بدبو نہ صرف برقرار رکھنے کی صلاحیت کو خراب کرتی ہیں بلکہ براہ راست ایپلی کیشن کی کارکردگی اور استحکام کو متاثر کرتی ہیں۔
Callback Hell غیر متزامن کارروائیوں کے ساتھ کام کرنے والے کوڈ کی ایک خاص بدبو ہے۔ نیسٹڈ کال بیکس کوڈ کو ناقابل پڑھنے اور ڈیبگ کرنا مشکل بنا دیتے ہیں۔ حل: coroutines (Kotlin), async/await (Swift 5.5+), RxJava/RxSwift یا Combine۔ Google I/O 2023 کے مطابق، جو پروجیکٹس کال بیک اسٹائل سے coroutines میں منتقل ہوئے انہوں نے بگ کی تعداد میں 30% کمی کی اور نئی خصوصیات کے اضافے کو تیز کیا۔
Platform Coupling — کاروباری منطق کا پلیٹ فارم اجزاء سے مضبوط تعلق۔ ایسی منطق کی جانچ کے لیے ایمولیٹر شروع کرنے کی ضرورت ہوتی ہے، جو فیڈ بیک سائیکل کو سست کر دیتا ہے۔ اصلاح: Clean Architecture کوڈ کو Domain (پلیٹ فارم انحصار کے بغیر خالص Kotlin/Swift) اور Data/UI (پلیٹ فارم انحصار کے ساتھ) پرتوں میں الگ کرتا ہے۔ کاروباری منطق ایمولیٹر کے بغیر JVM پر جانچی جاتی ہے۔
اکثر پوچھے گئے سوالات
نہیں — Code Smell کوئی غلطی نہیں ہے۔ بدبو والا کوڈ صحیح طریقے سے کام کرتا ہے، لیکن اسے برقرار رکھنا، تبدیل کرنا اور جانچنا مشکل ہے۔ بگ غلط رویہ ہے؛ بدبو مستقبل کے ممکنہ مسائل کے بارے میں انتباہ ہے۔
22 بدبو “Refactoring” (2019) کے دوسرے ایڈیشن میں۔ ان میں Long Method, Large Class, Primitive Obsession, Data Clumps, Switch Statements, Speculative Generality اور دیگر شامل ہیں۔ کمیونٹی نے جدید نمونوں اور پلیٹ فارمز کے لیے درجنوں نئی بدبو شامل کی ہیں۔
ایک امتزاج بہترین نتیجہ دیتا ہے: خودکار تجزیہ کے لیے Detekt (Android/Kotlin), SwiftLint (iOS), SonarQube (دونوں) اور معنوی بدبو کے لیے کوڈ کا جائزہ۔ کوئی ایک ٹول 100% مسائل نہیں ڈھونڈ سکتا — انسانی تجربہ فیصلہ کن رہتا ہے۔
ہاں، اگر کوڈ شاذ و نادر ہی تبدیل ہوتا ہے یا جلد ہی مکمل طور پر دوبارہ لکھا جائے گا۔ تاہم، بدبو کا جمع ہونا تکنیکی قرض میں بدل جاتا ہے: ہر نئی تبدیلی مشکل تر ہوتی جاتی ہے اور ٹھیک کرنے کی لاگت تیزی سے بڑھتی ہے۔
ہاں — اعلانیہ فریم ورکس نے نئی بدبو پیدا کی ہیں: بڑے @State بلاکس، بار بار رینڈر کا غلط استعمال، ضرورت سے زیادہ دوبارہ تشکیل، اور علیحدہ Views میں نکالنے کی کمی۔ SwiftUI کے لیے، ایک عام بدبو درجنوں @State متغیرات والا Massive View ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں