2012-07-17 21 views
22

कई पदों और स्टैक ओवरफ़्लो संसाधनों को पढ़ने के बाद, मुझे अभी भी "व्यापार तर्क कहां रखना है" के बारे में प्रसिद्ध प्रश्न के बारे में कुछ समस्याएं मिली हैं? StackOverflow Question और A Blog Post पढ़ना, मेरा मानना ​​है कि मुझे कोड अलगाव के मुद्दे को अच्छी तरह से समझ लिया गया है।Symfony2 में व्यावसायिक तर्क कहां रखा जाए?

मान लीजिए कि मेरे पास एक वेब फॉर्म है जहां आप एक उपयोगकर्ता जोड़ सकते हैं जिसे डीबी में जोड़ा जाएगा। यह उदाहरण इन अवधारणाओं को शामिल है:

  • फार्म
  • नियंत्रक
  • इकाई
  • सेवा
  • भंडार

मैं कुछ याद नहीं था, तो आप के साथ एक इकाई बनाने के लिए कुछ गुण, गेटर्स, सेटर्स और इतने पर एक डीबी में बने रहने के लिए। यदि आप उस इकाई को लाने या लिखना चाहते हैं, तो आप entityManager और "गैर-कैननिकल" क्वेरी के लिए, entityRepository (जहां आप अपनी "क्वेरी भाषा" क्वेरी फिट कर सकते हैं) का उपयोग करेंगे।

अब आपको सभी व्यावसायिक तर्कों के लिए एक सेवा परिभाषित करना है (जो एक "आलसी" उदाहरण वाला PHP वर्ग है); यह "भारी" कोड डालने का स्थान है। एक बार जब आप अपने आवेदन में सेवा रिकॉर्ड कर लेते हैं, तो आप इसे लगभग हर जगह उपयोग कर सकते हैं और इसमें कोड पुन: उपयोग शामिल है और इसी तरह।

जब आप कोई फॉर्म प्रस्तुत करते हैं और पोस्ट करते हैं, तो आप इसे अपनी इकाई (और पाठ्यक्रम की बाधाओं के साथ) से बांधते हैं और सभी को एक साथ रखने के लिए ऊपर परिभाषित सभी अवधारणाओं का उपयोग करते हैं।

तो, "पुराने मुझे" इस तरह से एक नियंत्रक की कार्रवाई लिखते थे:

public function indexAction(Request $request) 
    { 
     $modified = False; 
     if($request->getMethod() == 'POST'){ // submit, so have to modify data 
      $em = $this->getDoctrine()->getEntityManager(); 
      $parameters = $request->request->get('User'); //form retriving 
      $id = $parameters['id']; 
      $user = $em->getRepository('SestanteUserBundle:User')->find($id); 
      $form = $this->createForm(new UserType(), $user); 
      $form->bindRequest($request); 
      $em->flush(); 
      $modified = True; 
     } 

     $users = $this->getDoctrine()->getEntityManager()->getRepository('SestanteUserBundle:User')->findAll(); 
     return $this->render('SestanteUserBundle:Default:index.html.twig',array('users'=>$users)); 
    } 

"नई-मुझे" इस तरह से कोड पुनर्संशोधित गया है:

public function indexAction(Request $request) 
    { 
     $um = $this->get('user_manager'); 
     $modified = False; 
     if($request->getMethod() == 'POST'){ // submit, so have to modify data 
      $user = $um->getUserById($request,False); 
      $form = $this->createForm(new UserType(), $user); 
      $form->bindRequest($request); 
      $um->flushAll(); 
      $modified = True; 
     } 
     $users = $um->showAllUser(); 
     return $this->render('SestanteUserBundle:Default:index.html.twig',array('users'=>$users)); 
    } 

कहाँ $um एक है कस्टम सेवा जहां सभी कोड जिन्हें आप # 1 कोड टुकड़े से # 2 कोड टुकड़े में नहीं देख सकते हैं, संग्रहीत किया जाता है।

  1. मैं, अंत में, symfony2 का सार मिलता है और सामान्य रूप में {M} कुलपति था:

    तो, यहाँ मेरी सवाल कर रहे हैं?

  2. क्या रिफैक्टर अच्छा है? यदि नहीं, तो बेहतर तरीका क्या होगा?

पोस्ट स्क्रिप्टम: मुझे पता है कि मैं उपयोगकर्ता की दुकान और प्रमाणन के लिए FOSUserBundle उपयोग कर सकते हैं, लेकिन यह अपने आप को सिखाने Symfony के साथ काम करने के लिए एक बुनियादी उदाहरण है। इसके अलावा, मेरी सेवा को ORM.Doctrine के साथ इंजेक्शन दिया गया था। * काम करने के लिए (केवल एक नोट जो इस प्रश्न को मेरे भ्रम के साथ पढ़ता है)

+0

क्या $ संशोधित करने के उद्देश्य से है और क्या (getUserById को दूसरा पैरामीटर का उद्देश्य है)? – redbirdo

+0

ठीक है, डोमेन व्यवसाय तर्क [मॉडल परत] में जाता है (http://stackoverflow.com/a/5864000/727208)। [डोमेन ऑब्जेक्ट्स] में मोस्ले (http://c2.com/cgi/wiki?DomainObject)। –

+0

@redbirdo: इससे सवाल के उद्देश्य के लिए कोई फर्क नहीं पड़ता। – DonCallisto

उत्तर

3

व्यापार तर्क कहां रखना है इसके बारे में दो मुख्य दृष्टिकोण हैं: एसओए वास्तुकला और डोमेन संचालित वास्तुकला। यदि आपके व्यवसाय की वस्तुएं (संस्थाएं) एनीमिक हैं, तो मेरा मतलब है, अगर उनके पास व्यापार तर्क नहीं है, तो बस गेटर्स और सेटर्स, तो आप एसओए पसंद करेंगे। हालांकि, अगर आप अपने व्यावसायिक वस्तुओं के अंदर व्यापार तर्क बनाते हैं, तो आप दूसरे को पसंद करेंगे।जावा ईई 6 के साथ http://www.javaworld.com/javaworld/jw-05-2009/jw-05-domain-driven-design.html

झुक सेवा आर्किटेक्चर:

डोमेन पर ही आधारित जावा ईई 6 के साथ डिजाइन: एडम बिएन इन तरीकों पर चर्चा http://www.javaworld.com/javaworld/jw-04-2009/jw-04-lean-soa-with-javaee6.html

यह जावा है, लेकिन आप अनुमान लगा सकते हैं।

+2

मेरे प्रश्न के उत्तर के लिए धन्यवाद। मैंने उन लेखों को पढ़ा है, लेकिन मुझे कुछ और नहीं है जो मुझे पता है :) यदि आप अधिक जानकारी के साथ अपना उत्तर बढ़ा सकते हैं और इसे मेरे "वास्तविक" उदाहरण के साथ फिट कर सकते हैं, तो मैं खुश रहूंगा (जैसा कि सभी कॉम्यूनिटी होगी) पढ़ने, समझने और यहां तक ​​कि - आपको सकारात्मक प्रतिक्रिया दें। – DonCallisto

0

मुझे एहसास है कि यह एक पुराना सवाल है, लेकिन चूंकि मुझे एक ही समस्या थी, इसलिए मैं अपने अनुभव को साझा करना चाहता था, उम्मीद कर रहा था कि यह किसी के लिए मदद की जा सकती है। मेरा सुझाव एक कमांड बस पेश करना और कमांड पैटर्न का उपयोग करना शुरू करना होगा। कार्यप्रवाह इस तरह काफी है:

  1. नियंत्रक अनुरोध प्राप्त करता है और एक कमांड को इसकी अनुवाद (एक रूप है कि ऐसा करने के लिए इस्तेमाल किया जा सकता है, और आप कुछ डीटीओ दूसरे से एक परत से सफाई से डेटा स्थानांतरित करने की आवश्यकता हो सकती है)
  2. नियंत्रक आदेश बस
  3. है कि आदेश भेजता आदेश बस एक हैंडलर करता है और आदेश
  4. नियंत्रक तो यह क्या जरूरत के आधार पर प्रतिक्रिया उत्पन्न कर सकते हैं संभालती है।

कुछ अपने उदाहरण के आधार पर कोड:

public function indexAction(Request $request) 
{ 
    $command = new CreateUser(); 
    $form = $this->createForm(new CreateUserFormType(), $command); 
    $form->submit($request); 
    if ($form->isValid()) { 
     $this->get('command_bus')->handle(); 
    } 
    return $this->render(
     'SestanteUserBundle:Default:index.html.twig', 
     ['users' => $this->get('user_manager')->showAllUser()] 
    ); 
} 

फिर अपने आदेश हैंडलर (जो वास्तव में सेवा परत का हिस्सा है) उपयोगकर्ता बनाने के जिम्मेदार होगा।

  • आपका नियंत्रकों, बहुत कम फूला हुआ बनने की संभावना है, क्योंकि वे कोई तर्क
  • आपका व्यापार तर्क आवेदन (HTTP) तर्क से अलग किया जाता करने के लिए कम है
  • आपका कोड अधिक हो जाता है: यह कई फायदे हैं परीक्षण योग्य
  • आप एक ही आदेश हैंडलर का पुन: उपयोग कर सकते हैं लेकिन एक अलग बंदरगाह से आ (जैसे CLI)

डेटा के साथ भी कुछ कमियां हैं:

  • वर्गों की संख्या आप इस पद्धति लागू करने के लिए की जरूरत अधिक है और यह आमतौर पर सुविधाओं की संख्या आपके आवेदन को उजागर करता है के साथ रैखिक पैमाने
  • वहाँ अधिक चलती टुकड़े कर रहे हैं और इसके बारे में तर्क करने थोड़ा मुश्किल है, तो एक टीम के लिए सीखने की अवस्था थोड़ा खड़ी हो सकती है। ध्यान देने योग्य बात

एक जोड़े को आदेश बसों के लायक:

https://github.com/thephpleague/tactician https://github.com/SimpleBus/MessageBus

0

refactor एक अच्छा एक है? यदि नहीं, तो बेहतर तरीका क्या होगा?

सबसे अच्छा ढांचा प्रथाओं में से एक परम कन्वर्टर्स उपयोग कर रहा है सीधे उपयोगकर्ता अनुरोध से एक इकाई आह्वान करने के लिए।Symfony प्रलेखन से

उदाहरण:

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; 

/** 
* @Route("/blog/{id}") 
* @ParamConverter("post", class="SensioBlogBundle:Post") 
*/ 
public function showAction(Post $post) 
{ 

} 

अधिक परम कन्वर्टर्स पर:

http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html

+0

हाँ मुझे पता है, यह एक बहुत पुराना जवाब है और, बीटीडब्ल्यू, आपको एक टिप्पणी होना चाहिए: आप मेरे प्रश्न का उत्तर नहीं दे रहे हैं। हालांकि अब मुझे पता है कि व्यापार तर्क कहां रखना है: यह कहां से संबंधित है। मेरा मतलब है, अगर तर्क किसी इकाई से संबंधित है, तो इसे लगभग अनिवार्य है (कम से कम मेरे लिए) इसे इकाई में रखने के लिए; अन्यथा अब मैं इसके लिए एक सेवा का उपयोग करता हूं जो एकल सिद्धांत उत्तरदायित्व को वैध रखने के लिए तर्क को उप-सेवाओं में विभाजित कर सकता है। चीयर्स! – DonCallisto

संबंधित मुद्दे