𝗠𝗮𝘀𝘁𝗲𝗿𝗶𝗻𝗴 𝗘𝘃𝗲𝗻𝘁-𝗗𝗿𝗶𝘃𝗲𝗻 𝗗𝗲𝗰𝗼𝘂𝗽𝗹𝗶𝗻𝗴 𝗶𝗻 𝗟𝗮𝗿𝗮𝘃𝗲𝗹

మీ Laravel కంట్రోలర్లు తరచుగా బిజినెస్ లాజిక్ (business logic) ని నింపే డంపింగ్ గ్రౌండ్స్‌గా మారుతుంటాయి.

మీరు ఒక సాధారణ రిజిస్ట్రేషన్ ఫ్లోతో ప్రారంభిస్తారు. త్వరలోనే, మీరు ఒకే మెథడ్‌లో ఈమెయిల్ నోటిఫికేషన్లు, Slack అలర్ట్‌లు, ఆడిట్ లాగ్‌లు మరియు API కాల్స్‌ను జోడిస్తారు. ఇది ఒక 'fat controller'ను సృష్టిస్తుంది.

Fat కంట్రోలర్లు మీ కోడ్‌ను బలహీనంగా (fragile) మారుస్తాయి. వాటిని టెస్ట్ చేయడం కష్టం. అవి Single Responsibility Principleను ఉల్లంఘిస్తాయి.

దీనిని సరిచేయడానికి మీకు RabbitMQ వంటి సంక్లిష్టమైన సాధనాలు అవసరం లేదు. చాలా అవసరాలకు సరిపోయేలా Laravelలో ఒక ఇన్-బిల్ట్ ఈవెంట్ సిస్టమ్ ఉంది.

Tight coupling వల్ల కలిగే సమస్యలు: ఒకవేళ న్యూస్‌లెటర్ API నెమ్మదిగా ఉంటే, మీ యూజర్ రిజిస్ట్రేషన్ కూడా నెమ్మదిస్తుంది. ఒకవేళ మెయిల్ సర్వీస్ విఫలమైతే, మొత్తం రిక్వెస్ట్ విఫలమవుతుంది.

పరిష్కారం: Event-Driven Architecture.

ఈవెంట్‌లు ఒక మిడిల్ లేయర్‌లా పనిచేస్తాయి. మీ కంట్రోలర్ ఒక చర్యను (action) ప్రకటిస్తుంది. లిజనర్‌లు (Listeners) ఆ చర్యకు స్వతంత్రంగా స్పందిస్తారు.

ఒక లీన్ (lean) కంట్రోలర్ ఇలా ఉంటుంది:

public function register(RegisterRequest $request)
{
    $user = User::create($request->validated());

    UserRegistered::dispatch($user);

    return response()->json(['message' => 'Success'], 201);
}

కంట్రోలర్ ఇప్పుడు కేవలం డేటా పర్సిస్టెన్స్ (data persistence)ను మాత్రమే నిర్వహిస్తుంది. ఇది సైడ్ ఎఫెక్ట్స్ (side effects) గురించి పట్టించుకోదు.

మీరు మూడు ప్రధాన ప్రయోజనాలను పొందుతారు:

  • Performance: వినియోగదారులకు వెంటనే రెస్పాన్స్ లభిస్తుంది. భారీ పనులు (Heavy tasks) ShouldQueue ఇంటర్‌ఫేస్‌ను ఉపయోగించి బ్యాక్‌గ్రౌండ్‌లో నడుస్తాయి.
  • Resilience: ఒక సర్వీస్ డౌన్ అయినప్పటికీ, మెయిన్ అప్లికేషన్‌ను దెబ్బతీయకుండా లిజనర్ ఆ పనిని మళ్ళీ ప్రయత్నించగలదు (retry).
  • Extensibility: కొత్త లిజనర్‌ను జోడించడం ద్వారా మీరు పుష్ నోటిఫికేషన్ల వంటి కొత్త ఫీచర్లను సులభంగా జోడించవచ్చు. దీని కోసం మీరు ఒరిజినల్ కంట్రోలర్‌ను మార్చాల్సిన అవసరం లేదు.

పాటించవలసిన ఉత్తమ పద్ధతులు (Best practices):

  • సైడ్ ఎఫెక్ట్స్‌పై దృష్టి పెట్టండి: పోస్ట్-ప్రాసెసింగ్ (post-processing) కోసం ఈవెంట్‌లను ఉపయోగించండి. వెంటనే జరగాల్సిన కోర్ లాజిక్ కోసం వాటిని ఉపయోగించకండి.
  • వివరణాత్మక పేర్లను ఉపయోగించండి: OrderPlaced లేదా UserRegistered వంటి పాస్ట్ టెన్స్ (past-tense) పేర్లను ఉపయోగించండి. ఇది ఆ చర్య ఇప్పటికే పూర్తయిందని సూచిస్తుంది.
  • ఓవర్-అబ్‌స్ట్రాక్షన్ (over-abstraction)ను నివారించండి: ఒక కోడ్ ముక్క సరళంగా ఉండి, ఒకే చోట ఉపయోగించబడుతుంటే, ఈవెంట్ కంటే ఫంక్షన్ కాల్ చేయడం ఉత్తమం.

డేటాబేస్ మార్పుల కోసం Eloquent Observers ఉపయోగించండి. బిజినెస్ చర్యల కోసం Events ఉపయోగించండి.

ఈవెంట్‌లకు రీఫ్యాక్టరింగ్ (Refactoring) చేయడం అనేది కోడ్ మన్నిక (durability) గురించి. ఇది మీ కోడ్‌ను డీబగ్ చేయడం సులభతరం చేస్తుంది మరియు టెస్టింగ్ వేగవంతం చేస్తుంది.

మీ కంట్రోలర్‌లోని ఏదైనా ఒక అనవసరమైన సైడ్ ఎఫెక్ట్‌ను ఎంచుకుని, ఈరోజే దానిని ఒక లిజనర్‌కు మార్చండి.

ఈ సాండ్‌బాక్స్ ఉదాహరణను ప్రయత్నించండి: https://onlinephp.io/c/1f7b2

Fat Controllers కంటే మించి: Laravelలో Event-Driven Decoupling ద్వారా నైపుణ్యం సాధించడం

సమస్య: Fat Controllers

Laravel డెవలప్‌మెంట్‌లో, కంట్రోలర్లు పరిమాణంలో పెరగడం (Fat Controllers) అనేది ఒక సాధారణ సమస్య. ఒకే store లేదా update మెథడ్ ఈ క్రింది పనులన్నింటినీ చేసేటప్పుడు ఇది జరుగుతుంది:

  • Validation
  • Database operations
  • ఇమెయిల్స్ పంపడం
  • Third-party APIs ని ట్రిగ్గర్ చేయడం
  • Logging

దీనివల్ల కొన్ని సమస్యలు ఎదురవుతాయి:

  • టెస్ట్ చేయడం కష్టం: ఒకే చర్యను టెస్ట్ చేయడానికి అన్నింటినీ మోక్ (mock) చేయాల్సి ఉంటుంది.
  • నిర్వహించడం కష్టం: ఒక చిన్న మార్పు వల్ల సంబంధం లేని ఇతర ఫీచర్లు కూడా దెబ్బతినవచ్చు.
  • SRPని ఉల్లంఘిస్తుంది: ఇది Single Responsibility Principle ని పాటించదు.

పరిష్కారం: Event-Driven Architecture

కంట్రోలర్ అన్ని పనులను చేసే బదులు, అది కేవలం ఒకే పని చేయాలి: రిక్వెస్ట్‌ను హ్యాండిల్ చేయడం మరియు ఒక ఈవెంట్‌ను డిస్పాచ్ చేయడం.

Laravelలో ఇది ఎలా పనిచేస్తుంది

Laravel ఒక శక్తివంతమైన ఈవెంట్ సిస్టమ్‌ను అందిస్తుంది. మీరు ఒక Event మరియు ఒకటి లేదా అంతకంటే ఎక్కువ Listenersలను నిర్వచించవచ్చు.

స్టెప్ 1: Event మరియు Listenerని సృష్టించడం

php artisan make:event UserRegistered
php artisan make:listener SendWelcomeEmail --event=UserRegistered

స్టెప్ 2: Controllerలో Eventని డిస్పాచ్ చేయడం

public function store(Request $request)
{
    $user = User::create($request->all());

    event(new