Laravel செயலிகளை உருவாக்கும் டெவலப்பர்கள், தங்கள் கன்ட்ரோலர்களுக்குள் (controllers) new என்ற keyword-ஐ தவிர்த்துவிட்டு, Factory Method pattern-க்கு மாறுமாறு அறிவுறுத்தப்படுகிறார்கள். ஆப்ஜெக்ட் உருவாக்கத்தை (object creation) பிரத்யேக ஃபேக்டரிகளுக்குள் (factories) மாற்றுவதன் மூலம், குறியீட்டை (code) எளிதாக விரிவாக்கவும், சோதனை செய்யவும் மற்றும் பராமரிக்கவும் முடியும்—திட்டங்கள் சில எண்ட்-பாயிண்ட்களைத் தாண்டி வளரும்போது இந்த நன்மைகள் மிகவும் முக்கியமானவை.

new keyword ஏன் ஒரு மறைமுகச் சுமை

ஒரு கன்ட்ரோலரில்

$processor = new StripePaymentProcessor($config);

போன்ற ஒரு வரி இருக்கும்போது, அந்த கன்ட்ரோலர் StripePaymentProcessor வகுப்போடு (class) நெருக்கமான பிணைப்பைக் (tightly coupled) கொண்டுள்ளது. பேமெண்ட் ப்ராசஸர் தேவைப்படும் ஒவ்வொரு இடத்திலும் அந்த வரி மீண்டும் மீண்டும் பயன்படுத்தப்படுவதால், அதன் உருவாக்கும் தர்க்கம் (construction logic) முழு குறியீட்டிலும் சிதறிவிடுகிறது. பிற்காலத்தில் அந்த ப்ராசஸருக்கு ஒரு லாகர் (logger), கேச் மேனேஜர் (cache manager) அல்லது வேறு ஒரு கான்ஃபிகரேஷன் வடிவம் தேவைப்பட்டால், அந்த ஒவ்வொரு இடத்திலும் மாற்றங்களைச் செய்ய வேண்டியிருக்கும். இதன் விளைவாக, மாற்றங்களை ஏற்காத மற்றும் யூனிட் டெஸ்ட்களில் (unit tests) எளிதாக மாக் (mock) செய்ய முடியாத பலவீனமான குறியீடு உருவாகிறது.

Factory Method pattern-ன் பங்களிப்பு

Factory Method pattern, நேரடி இன்ஸ்டான்சியேஷனுக்கு (direct instantiation) பதிலாக, ஒரு குறிப்பிட்ட இன்டர்ஃபேஸின் (interface) இன்ஸ்டன்ஸைத் திருப்பித் தரும் ஒரு முறையை (method) பயன்படுத்துகிறது. கன்ட்ரோலர் அந்த இன்டர்ஃபேஸைச் சார்ந்து இருக்கும், அதே நேரத்தில் ஒரு ஃபேக்டரி கிளாஸ் எந்த கன்கிரீட் கிளாஸை (concrete class) உருவாக்க வேண்டும் மற்றும் அதன் சார்புகளை (dependencies) எவ்வாறு இணைக்க வேண்டும் என்பதைத் தெரிந்து வைத்திருக்கும். அனைத்து உருவாக்கும் தர்க்கங்களும் ஒரே இடத்தில் இருப்பதால், ஒரு புதிய சார்பைச் சேர்ப்பதோ அல்லது செயல்பாடுகளை மாற்றுவதோ ஃபேக்டரியை மட்டும் பாதிக்கும்.

முக்கிய நன்மைகள்

  • தளர்வான பிணைப்பு (Loose coupling) – கன்ட்ரோலர்கள் கன்கிரீட் கிளாஸ்களுக்குப் பதிலாக அப்ஸ்ட்ராக்ஷன்களுடன் (abstractions) செயல்படுகின்றன.
  • மையப்படுத்தப்பட்ட உருவாக்கம் (Centralized construction) – உருவாக்கும் முறையை மாற்ற ஒரே ஒரு கோப்பைத் திருத்தினால் போதுமானது.
  • சோதனைத்திறன் (Testability) – ஃபேக்டரிகளை ஸ்டப் (stub) செய்யவோ அல்லது மாக்ஸுகளால் (mocks) மாற்றவோ முடியும், இது கன்ட்ரோலர்களைத் தனிமைப்படுத்திச் சோதனை செய்ய அனுமதிக்கிறது.
  • Open/Closed Principle – ஏற்கனவே உள்ள கன்ட்ரோலர் குறியீட்டை மாற்றாமல் புதிய அம்சங்களை (உதாரணமாக, ஒரு புதிய பேமெண்ட் கேட்வே) சேர்க்க முடியும்.

ஒரு காபி ஷாப் உதாரணம்

ஒவ்வொரு ஆர்டருக்கும் பீன்ஸ் அரைப்பது, பால் ஆவியில் வேகவைப்பது மற்றும் தண்ணீர் ஊற்றுவது போன்ற வேலைகளை ஒரு பாரிஸ்டா (barista) நீண்ட if-else அறிக்கைகளைப் பயன்படுத்தித் தனித்தனியாகச் செய்வதாகக் கற்பனை செய்து பாருங்கள். லேட்டே (latte) செய்முறை மாறினால், ஒவ்வொரு பாரிஸ்டாவும் அந்தப் படிநிலைகளைக் கற்றுக்கொள்ள வேண்டும். ஆனால், ஆர்டர் வகையைப் பெற்று, தயாரிப்பைத் தானாகவே கையாளும்தொறும் ஒரு காபி இயந்திரம் இருந்தால் இந்தப் பிரச்சனை தீர்ந்துவிடும்: பாரிஸ்டா இயந்திரத்திடம் என்ன தேவை என்று சொன்னால் போதும், இயந்திரமே அனைத்துப் படிநிலைகளையும் கவனித்துக்கொள்ளும். இப்போது செய்முறையை மாற்ற வேண்டுமென்றால், இயந்திரத்தை மட்டும் மாற்றினால் போதும், ஒவ்வொரு பாரிஸ்டாவையும் மாற்ற வேண்டியதில்லை.

Laravel ஏற்கனவே ஃபேக்டரிகளைப் பயன்படுத்துகிறது

Laravel-ன் முக்கியக் கூறுகள் இந்த முறையை எவ்வாறு பயன்படுத்துகின்றன என்பதைப் பின்வருமாறு காணலாம்:

  • Database – ConnectionFactory, MySQL அல்லது PostgreSQL இணைப்பை உருவாக்க வேண்டுமா என்பதைத் தீர்மானிக்கிறது.
  • Queues – QueueManager, Redis, SQS அல்லது பிற பேக்-எண்ட்களுக்கான (back-ends) டிரைவர்களை உருவாக்குகிறது.
  • Filesystem – FilesystemManager, லோக்கல் அல்லது S3 டிஸ்க் இன்ஸ்டன்ஸ்களை உருவாக்குகிறது.
  • Mail – MailManager, SMTP, Mailgun அல்லது பிற மெயில் டிரைவர்களைத் தீர்மானிக்கிறது.

இந்த முக்கியமான சேவைகளுக்கு பிரேம்வொர்க் (framework) ஃபேக்டரிகளை நம்பியிருந்தால், நமது சொந்த குறியீடும் அதைப் பின்பற்ற வேண்டும்.

எப்போது ஒரு ஃபேக்டரியை அறிமுகப்படுத்த வேண்டும்

பின்வரும் சூழல்களில் ஒரு ஃபேக்டரியைப் பயன்படுத்தவும்:

  • ஆப்ஜெக்ட் உருவாக்கம் பல கான்ஃபிகரேஷன் படிநிலைகள் அல்லது வெளிப்புறச் சேவைகளை உள்ளடக்கியிருக்கும் போது.
  • ஒன்றுக்கொன்று மாற்றக்கூடிய பல செயல்பாடுகள் (வெவ்வேறு பேமெண்ட் கேட்வேகள், ஸ்டோரேஜ் ப்ரொவைடர்கள் போன்றவை) இருக்கும் போது.
  • சாத்தியமான செயல்பாடுகளின் பட்டியல் வளரும் என்று எதிர்பார்க்கப்படும் போது.

பின்வரும் சூழல்களில் ஃபேக்டரியைத் தவிர்க்கவும்:

  • உருவாக்கம் என்பது கூடுதல் அமைப்புகள் ஏதுமில்லாத ஒரு ஒற்றை, மாற்ற முடியாத new அழைப்பாக இருக்கும் போது.
  • ஒரே ஒரு செயல்பாடு மட்டுமே பயன்படுத்தப்படும் என்றால், கூடுதல் அப்ஸ்ட்ராக்ஷன் தேவையற்ற சுமையாக அமையும்.

விரைவான விளக்கம்: ஒரு பேமெண்ட் கன்ட்ரோலரை ரீஃபாக்டரிங் (refactoring) செய்தல்

  1. ஒரு இன்டர்ஃபேஸை வரையறுக்கவும் – process(array $data) முறையுடன் கூடிய PaymentProcessorInterface.
  2. கன்கிரீட் கிளாஸ்களைச் செயல்படுத்தவும் – StripePaymentProcessor, PayPalPaymentProcessor, இவை ஒவ்வொன்றும் இன்டர்ஃபேஸைப் பூர்த்தி செய்ய வேண்டும்.
  3. ஒரு ஃபேக்டரியை உருவாக்கவும் – make(string $driver): PaymentProcessorInterface முறையுடன் கூடிய PaymentProcessorFactory. இதற்குள், பொருத்தமான கிளாஸைத் திருப்பித் தர ஒரு switch அல்லது மேப்பை (map) பயன்படுத்தவும், மேலும் Laravel-ன் சர்வீஸ் கன்டெய்னரில் (service container) இருந்து தேவையான சேவைகளை இன்ஜெக்ட் (inject) செய்யவும்.
  4. ஃபேக்டரியை இன்ஜெக்ட் செய்யவும் – கன்ட்ரோலரின் கன்ஸ்ட்ரக்டரில் (constructor), PaymentProcessorFactory-ஐ டைப்-ஹின்ட் (type-hint) செய்யவும். Laravel அதைத் தானாகவே கண்டறியும்.
  5. ஃபேக்டரியைப் பயன்படுத்தவும் – $processor = $this->processorFactory->make('stripe'); $processor->process($request->all());

இப்போது கன்ட்ரோலர் new அல்லது ஒரு கன்கிரீட் ப்ராசஸரைப் பற்றி ஒருபோதும் குறிப்பிடாது. ஒரு புதிய கேட்வேயைச் சேர்ப்பது என்பது ஒரு கிளாஸை உருவாக்கி ஃபேக்டரியின் மேப்பை விரிவாக்குவதாகும்—கன்ட்ரோலரில் எந்த மாற்றமும் தேவையில்லை.

சாத்தியமான குறைபாடுகள் மற்றும் அவற்றை எவ்வாறு குறைப்பது

தொழிற்சாலைகளின் (factories) முக்கிய விமர்சனம், அவை தேவையற்ற மறைமுகத் தன்மையை (indirection) ஏற்படுத்துகின்றன, இது சாதாரணப் பொருட்களுக்கு (trivial objects) அதிகப்படியான விளக்கமளிப்பதாக (verbose) உணரப்படலாம். ஒரு எளிய சேவையைத் தேவையில்லாமல் சிக்கலாக்குவது (over-engineering), எந்தப் பயனும் இன்றி குறியீட்டுத் தொகுப்பை (codebase) பெரிதாக்கக்கூடும். கட்டுமானத்தின் சிக்கலை மதிப்பிடுவதே முக்கியமானது: ஒரு பொருள் எந்தத் சார்புகளும் (dependencies) இல்லாத ஒரு சாதாரணத் தரவுத் தொகுப்பாக (plain data holder) இருந்தால், நேரடியாக new பயன்படுத்துவது ஏற்றுக்கொள்ளத்தக்கது. மேலும், factories தொடர்பில்லாத தர்க்கங்களுக்கான (unrelated logic) குப்பைத் தொட்டியாக மாறிவிடக்கூடும். factories-களைப் பொருள் உருவாக்கத்தில் மட்டும் கவனம் செலுத்தச் செய்வதும், configuration-களை பிரத்யேக service providers-களிடம் ஒப்படைப்பதும் தெளிவைப் பேண உதவும்.

அடுத்து கவனிக்க வேண்டியவை

  • Service container bindings – ஒரு service provider-இல் interface-ஐ factory class-உடன் இணைத்தால், Laravel-இன் container தானாகவே factories-களைத் தீர்மானிக்க (resolve) முடியும்.
  • Auto-discovery – சில packages அவற்றின் சொந்த factories-களை வெளிப்படுத்தும்; naming collisions ஏற்படாமல் பார்த்துக் கொள்ளவும்.
  • Testing strategies – Controllers-களை unit testing செய்யும்போது, factory-க்கு பதிலாக ஒரு stubbed processor-ஐத் திருப்பித் தரும் mock-ஐப் பயன்படுத்துங்கள்; இது சோதனைகள் வேகமாகவும் தனித்தன்மையுடனும் (isolated) இருப்பதை உறுதி செய்யும்.

சுருக்கமாக

சிதறிக்கிடக்கும் new அழைப்புகளுக்குப் பதிலாக, சரியான இடத்தில் ஒரு factory-யைப் பயன்படுத்துவது கட்டுமானத்தை மையப்படுத்துகிறது, coupling-ஐக் குறைக்கிறது மற்றும் உங்கள் custom code-ஐ Laravel-இன் வடிவமைப்புத் தத்துவத்துடன் (design philosophy) ஒருங்கிணைக்கிறது. புதிய payment providers, storage back-ends அல்லது எந்தவொரு plug-in பாணி கூறுகளையும் (plug-in-style component) எதிர்கொள்ளத் தயாராக இருக்கும் குழுக்களுக்கு, Factory Method pattern என்பது குறைந்த செலவில் அதிக நெகிழ்வுத்தன்மையையும் (flexibility) நம்பிக்கையையும் தரும் ஒரு முதலீடாகும். உங்கள் எதிர்காலத் தேவைகளுக்கும், இந்த குறியீட்டைப் பயன்படுத்தப் போகும் மற்றவர்களுக்கும் இது பெரும் உதவியாக இருக்கும்.