2012-07-17 6 views
22

多くの投稿とStack Overflowリソースを読んだ後、私は「ビジネスロジックをどこに置くべきか」という有名な質問についていくつかの問題が残っています。 StackOverflow QuestionA Blog Postを読むと、私はコード分離の問題をよく理解していると思います。Symfony2にビジネスロジックを配置する場所は?

データベースに追加されるユーザーを追加できるWebフォームがあるとします。この例では、これらの概念が含ま:

  • フォーム
  • コントローラ
  • エンティティ
  • サービス
  • リポジトリを、私は何かを逃さなかった場合は、あなたが持つエンティティを作成する必要が

いくつかのプロパティ、getter、setterなどをdbに永続させるために使用します。そのエンティティを取得または書き出したい場合は、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)); 
    } 

"新-meが" このようにコードをリファクタリングしています:

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がある

ので、 "古い-meが" このように、コントローラのアクションを記述します#1コード片から#2コード片まで見ることができないすべてのコードが保存されているカスタムサービス。

だから、ここは私の質問は以下のとおりです。

  1. 私は、最終的には、Symfony2のの本質と一般的には、{M} VCを取得しましたか?
  2. リファクタリングは優れていますか?そうでない場合は、より良い方法は何でしょうか?

ポストScriptum:私はユーザストアおよび認証のためのFOSUserBundleを使用できることを知っているが、これはどのようにsymfonyので動作するように自分自身を教えるための基本的な例です。 さらに、私のサービスにORM.Doctrine。*を注入しました(同じ混乱でこの質問を読んだ人の注釈)

+0

:PARAMコンバータ上

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) { } 

詳細)? – redbirdo

+0

ドメインビジネスロジックは、[モデルレイヤ](http://stackoverflow.com/a/5864000/727208)に入ります。 [ドメインオブジェクト]のモズレー(http://c2.com/cgi/wiki?DomainObject)。 –

+0

@redbirdo:質問の目的には関係ありません。 – DonCallisto

答えて

3

ビジネスロジックを置く場所については、主に2つのアプローチがあります。 SOAアーキテクチャとドメイン駆動型アーキテクチャあなたのビジネスオブジェクト(エンティティ)が貧血であれば、ビジネスロジックを持たず、ゲッターとセッターだけなら、SOAを好むでしょう。しかし、ビジネス・オブジェクト内にビジネス・ロジックを構築する場合は、そのビジネス・ロジックを優先します。アダム・ビエンは、これらのアプローチについて説明します。Java EE 6と

ドメイン駆動設計:http://www.javaworld.com/javaworld/jw-05-2009/jw-05-domain-driven-design.html

のJava EE 6でリーンサービスアーキテクチャ:http://www.javaworld.com/javaworld/jw-04-2009/jw-04-lean-soa-with-javaee6.html

それはJavaのですが、あなたのアイデアを得ることができます。

+2

私の質問にお答えいただきありがとうございます。私はそれらの記事を読んだが、それは私が何を知っていると思っているものを私に与えるより多くの詳細とあなたの答えを拡大し、私の "本物の"例に適合することができれば、あなたに肯定的なフィードバックをお寄せください。 – DonCallisto

0

私はこれが古い質問であることを理解していますが、同様の問題があったので、私は自分の経験を共有したいと思っていました。 私は、コマンドバスを導入し、コマンドパターンの使用を開始することを提案します。ワークフローはかなりこのようなものです:

  1. コントローラは、(フォームがそれを行うために使用されるかもしれない、とあなたは他の1つの層からきれいにデータを移動するために、いくつかのDTOを必要とするかもしれない)要求を受信し、コマンドに変換し
  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

は良いものリファクタリングますか?そうでない場合は、より良い方法は何でしょうか?ベストプラクティスフレームワークの

一つは直接ユーザ要求からエンティティを呼び出すためにPARAMコンバータを使用しています。symfonyのドキュメントから

例:($変更の目的と何がgetUserByIdの2番目のパラメータの目的では何

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

+0

はい私は知っています、これは非常に古い答えです、あなたはコメントでなければなりません:あなたは私の質問に答えるつもりはありません。しかし今、私はビジネスロジックをどこに置くべきかを知っています。つまり、ロジックがエンティティに関連している場合、エンティティをエンティティ内に保つことは、少なくとも(少なくとも私にとって)必須です。さもなければ、私は今、単一の主義の責任を有効にするために論理をサブサービスに分けることのできるサービスを使用します。乾杯! – DonCallisto

関連する問題