Laravel ایپلی کیشنز بنانے والے ڈویلپرز کو مشورہ دیا جا رہا ہے کہ وہ اپنے کنٹرولرز کے اندر new کی ورڈ کا استعمال چھوڑ دیں اور Factory Method pattern کی طرف منتقل ہو جائیں۔ آبجیکٹ کی تخلیق (object creation) کو مخصوص فیکٹریز میں منتقل کر کے، کوڈ کو وسعت دینا، ٹیسٹ کرنا اور برقرار رکھنا آسان ہو جاتا ہے—یہ وہ فوائد ہیں جو اس وقت اہمیت اختیار کرتے ہیں جب پروجیکٹس چند اینڈ پوائنٹس سے بڑھ کر بڑے ہو جاتے ہیں۔
کیوں new کی ورڈ ایک پوشیدہ نقصان (liability) ہے
جب ایک کنٹرولر میں ایسی لائن ہو جیسے
$processor = new StripePaymentProcessor($config);
تو اب کنٹرولر StripePaymentProcessor کلاس کے ساتھ مضبوطی سے جڑ (tightly coupled) چکا ہے۔ جہاں کہیں بھی پیمنٹ پروسیسر کی ضرورت ہوتی ہے، وہاں یہ لائن بار بار دہرائی جاتی ہے، جس سے کنسٹرکشن لاجک (construction logic) پورے کوڈ بیس میں بکھر جاتی ہے۔ اگر بعد میں پروسیسر کو کسی logger، cache manager، یا کسی مختلف کنفیگریشن فارمیٹ کی ضرورت پڑتی ہے، تو ان تمام جگہوں کو اپ ڈیٹ کرنا پڑے گا۔ اس کا نتیجہ ایک ایسا کمزور (fragile) کوڈ ہوتا ہے جو تبدیلی کے خلاف مزاحمت کرتا ہے اور unit tests میں اسے mock کرنا مشکل ہوتا ہے۔
Factory Method pattern کا کردار
Factory Method pattern براہ راست instantiation کو ایک ایسے میتھڈ سے بدل دیتا ہے جو کسی دی گئی interface کا instance واپس کرتا ہے۔ کنٹرولر interface پر انحصار کرتا ہے، جبکہ ایک factory class جانتی ہے کہ کون سی concrete class بنانی ہے اور اس کی dependencies کو کیسے ترتیب دینا ہے۔ تمام تخلیقی لاجک (creation logic) ایک ہی جگہ ہوتی ہے، اس لیے نئی dependency شامل کرنے یا implementations کو تبدیل کرنے کے لیے صرف فیکٹری میں تبدیلی کرنا کافی ہوتا ہے۔
بنیادی فوائد
- Loose coupling – کنٹرولرز abstractions کے خلاف کام کرتے ہیں، نہ کہ concrete classes کے۔
- Centralized construction – بلڈ پروسیس کو تبدیل کرنے کے لیے صرف ایک فائل کو ایڈٹ کرنے کی ضرورت ہوتی ہے۔
- Testability – فیکٹریز کو stub کیا جا سکتا ہے یا mocks سے بدلا جا سکتا ہے، جس سے کنٹرولرز کے الگ تھلگ (isolated) ٹیسٹ ممکن ہو جاتے ہیں۔
- Open/Closed Principle – موجودہ کنٹرولر کوڈ کو چھیڑے بغیر نئی خصوصیات (مثلاً ایک نیا payment gateway) شامل کی جا سکتی ہیں۔
کافی شاپ کی ایک مثال
تصور کریں کہ ایک بارسٹا (barista) کو ہر آرڈر کے لیے if-else اسٹیٹمنٹس کے ایک طویل سلسلے کا استعمال کرتے ہوئے خود سے بیन्स پیسنے، دودھ گرم کرنے اور پانی ڈالنے پڑتے ہیں۔ اگر لیٹے (latte) کی ترکیب بدل جائے، تو ہر بارسٹا کو قدم دوبارہ سیکھنے پڑیں گے۔ ایک کافی مشین جو آرڈر کی قسم وصول کرتی ہے اور تیاری کو اندرونی طور پر سنبھالتی ہے، اس مسئلے کو حل کر دیتی ہے: بارسٹا صرف مشین کو بتاتا ہے کہ کیا چاہیے، اور مشین تمام مراحل کو اپنے اندر سمو (encapsulate) لیتی ہے۔ اب ترکیب کو اپ ڈیٹ کرنے کا مطلب مشین میں تبدیلی کرنا ہے، نہ کہ ہر بارسٹا کو۔
Laravel پہلے ہی فیکٹریز پر انحصار کرتا ہے
Laravel کے اپنے بنیادی اجزاء (core components) اس پیٹرن کی عملی مثال پیش کرتے ہیں:
- Database –
ConnectionFactoryفیصلہ کرتا ہے کہ MySQL یا PostgreSQL کنکشن بنانا ہے۔ - Queues –
QueueManagerRedis، SQS، یا دیگر back-ends کے لیے drivers تخلیق کرتا ہے۔ - Filesystem –
FilesystemManagerlocal یا S3 disk instances تیار کرتا ہے۔ - Mail –
MailManagerSMTP، Mailgun، یا دیگر mail drivers کو حل (resolve) کرتا ہے۔
اگر فریم ورک ان اہم سروسز کے لیے فیکٹریز پر بھروسہ کرتا ہے، تو کسٹم کوڈ کو بھی اسی طرز پر عمل کرنا چاہیے۔
فیکٹری کب متعارف کروانی چاہیے
فیکٹری کا استعمال تب کریں جب:
- آبجیکٹ کی تخلیق میں متعدد کنفیگریشن مراحل یا بیرونی سروسز شامل ہوں۔
- کئی متبادل implementations موجود ہوں (مختلف payment gateways، storage providers وغیرہ)۔
- ممکنہ implementations کی فہرست کے بڑھنے کی توقع ہو۔
فیکٹری سے کب بچنا چاہیے:
- کنسٹرکشن صرف ایک سادہ، ناقابل تبدیلی
newکال ہو جس میں کوئی اضافی سیٹ اپ نہ ہو۔ - صرف ایک ہی implementation استعمال کی جائے گی، جس کی وجہ سے اضافی abstraction غیر ضروری بوجھ (overhead) بن جائے۔
ایک فوری جائزہ: پیمنٹ کنٹرولر کی ریفیکٹورنگ (refactoring)
- ایک interface کی تعریف کریں –
PaymentProcessorInterfaceجس میںprocess(array $data)میتھڈ ہو۔ - concrete classes کو نافذ کریں –
StripePaymentProcessorاورPayPalPaymentProcessorجو interface پر پورا اترتے ہوں۔ - ایک فیکٹری بنائیں –
PaymentProcessorFactoryجس میںmake(string $driver): PaymentProcessorInterfaceمیتھڈ ہو۔ اس کے اندر، مناسب کلاس واپس کرنے کے لیےswitchیا ایک میپ (map) کا استعمال کریں، اور Laravel کے service container سے مطلوبہ سروسز کو انجیکٹ (inject) کریں۔ - فیکٹری کو انجیکٹ کریں – کنٹرولر کے کنسٹرکٹر میں،
PaymentProcessorFactoryکو type-hint کریں۔ Laravel اسے خود بخود حل (resolve) کر لے گا۔ - فیکٹری کا استعمال کریں –
$processor = $this->processorFactory->make('stripe'); $processor->process($request->all());
اب کنٹرولر میں کبھی بھی new یا کسی concrete processor کا ذکر نہیں ہوتا۔ ایک نیا گیٹ وے شامل کرنے کا مطلب ہے ایک نئی کلاس بنانا اور فیکٹری کے میپ کو وسعت دینا—کنٹرولر میں کوئی تبدیلی کرنے کی ضرورت نہیں ہے۔
ممکنہ نقصانات اور ان کا حل
فیکٹریز پر بنیادی تنقید یہ ہے کہ یہ ایک اضافی ان ڈائریکشن (indirection) پیدا کرتی ہیں، جو معمولی اشیاء (trivial objects) کے لیے ضرورت سے زیادہ طویل محسوس ہو سکتی ہیں۔ ایک سادہ سروس کی اوور انجینئرنگ (over-engineering) بغیر کسی حقیقی فائدے کے کوڈ بیس (codebase) کو غیر ضروری طور پر بڑھا سکتی ہے۔ اصل بات تعمیر کی پیچیدگی کا اندازہ لگانا ہے: اگر کوئی آبجیکٹ بغیر کسی انحصار (dependencies) کے محض ڈیٹا رکھنے والا (plain data holder) ہے، تو براہ راست new کا استعمال قابلِ قبول ہو سکتا ہے۔ اس کے علاوہ، فیکٹریز غیر متعلقہ لاجک (logic) کے لیے ایک ڈھیر (dumping ground) بن سکتی ہیں۔ فیکٹریز کو صرف آبجیکٹ کی تخلیق تک محدود رکھنا اور کنفیگریشن (configuration) کا کام مخصوص سروس پرووائیڈرز (service providers) کے سپرد کرنا وضاحت کو برقرار رکھتا ہے۔
آگے کن چیزوں کا خیال رکھنا ہے
- Service container bindings – اگر آپ سروس پرووائیڈر میں انٹرفیس (interface) کو فیکٹری کلاس کے ساتھ بائنڈ (bind) کر دیں، تو Laravel کا کنٹینر خود بخود فیکٹریز کو ریزالو (resolve) کر سکتا ہے۔
- Auto-discovery – کچھ پیکیجز اپنی فیکٹریز فراہم کرتے ہیں؛ ناموں کے ٹکراؤ (naming collisions) سے ہوشیار رہیں۔
- Testing strategies – کنٹرولرز کی یونٹ ٹیسٹنگ (unit testing) کرتے وقت، فیکٹری کو ایک mock سے بدل دیں جو ایک stubbed processor واپس کرے، تاکہ یہ یقینی بنایا جا سکے کہ ٹیسٹ تیز اور الگ تھلگ (isolated) رہیں۔
خلاصہ
بکھرے ہوئے new کالز کو ایک مناسب فیکٹری سے بدلنا تعمیر کے عمل کو مرکزی (centralize) بناتا ہے، کپلنگ (coupling) کو کم کرتا ہے، اور آپ کے کسٹم کوڈ کو Laravel کے اپنے ڈیزائن فلسفے کے مطابق رکھتا ہے۔ ان ٹیموں کے لیے جو مستقبل میں توسیع (growth) کی توقع رکھتی ہیں—جیسے نئے پیمنٹ پرووائیڈرز، اسٹوریج بیک اینڈز، یا کوئی بھی پلگ ان اسٹائل کا کمپوننٹ—Factory Method pattern ایک کم لاگت کی سرمایہ کاری ہے جو لچک اور اعتماد کی صورت میں فائدہ دیتی ہے۔ آپ کا مستقبل کا ورژن، اور وہ کوئی بھی جو اس کوڈ کو وارث بنائے گا، آپ کا شکر گزار ہوگا۔
