2010-11-24 13 views
7

サービス層が本当に必要な場合は、私は考えています。Java Swingアプリケーションのサービス層

私はデスクトップスイングアプリケーションにspring + hibernateを使用しています。この時点で私はgui/swing層 - > service層 - > dao層を持っています。私は@トランザクションサポートとIOC注射のためだけにスプリングを使用します。

ベストプラクティスでは、私のdaosを使用するサービスを作成し、すべてのトランザクション管理をサービスに入れなければならないと言います。

しかし、私は非常に非常に多くの場合、サービス層はだけなので、たとえば、DAOのメソッドを複製することを実現しています:

// a DAO example 
@Repository 
public class CustomerHibernateDAO extends BaseHibernateDAO implements CustomerDAO { 

public List<Customer> findAllCustomerILikeName(String name){ 
    return getSession() 
    .createCriteria(Customer.class) 
    .add(Restriction.ilike("name", name)) 
    .list(); 
} 
} 

// Customer service to use this dao... 
@Service 
@Transactional 
public class CustomerService { 

@Autowired 
CustomerDAO customerDAO; 

// Why i can't call DAO instead the service? 
public List<Customer> getAllCustomersByName(String name){ 
     return customerDAO.findAllCustomerILikeName(name); 
} 

} 

これは、サービス層の鉱山tipical使い方です... HibernateはDBに依存しないで、春は専門学には無関係です:私は本当にそれが必要ですか?

すべてのDAOを管理するユニークなサービスクラスについて教えてください。私はこれが良い妥協であるかもしれないと思うか、または悪い習慣ですか?

私は悪い方法でDAOに@Transactionalを置くが、この時点で私はそれだけプット@Transactionalのためのサービスを記述する必要があります...私について

EDIT

詳細に関する情報を知っていますアプリ。

私のアプリケーションは管理ソフトウェアであり、ユーザー登録、製品、注文などを管理します。 実際には、多くの読み込みエンティティ - >編集 - >保存エンティティまたは作成 - >編集 - >保存操作が含まれており、休止状態のおかげで、これらの操作はほとんどの場合、@manyto ... collectionおよびcascade.save_updateは、同じ持続操作で2つ以上のエンティティを保存することを許可します。

ので、例えば、私の項目にJFrameの私は、インサート編集または(販売する製品)項目を作成することができる場所があります。

public ItemFrame(){ 
// the constructor 
itemService=springAppContext.getBeans(ItemService.class); 
} 

public boolean validateForm(){ 
// test if the gui is correctly filled by user 
} 

public boolean save(){ 
// create an Item entity taking value from swing gui(JTextField etc) 
Item item=new Item(); 
item.setName(nameTextField.getText()); 
item.setEtc... 
// ItemService ' save method is a wrap around itemDao.save(item)... 
itemService.save(item); 
} 

private void saveItemActionPerformed(ActionEvent evt){ 
// When i press SAVE button 
if(validateForm()){ 
    save(); 
} 
} 

これは私がほとんどの場合持っているもので、だから私は貧血ドメインの反パターンに落ちたと思う...

ありがとう。

+0

に使用する後者を可能考えるcorrectly.Services entity.Itウィルあたりにあるはずです私は標準的なパターンを維持する+もしあなたがDAO層を構築しているだけで、DBに変更が来たら、+ 1 btw –

+0

DBの変更が来たら、私はサービスを使用しなかった。私はDAOを再構築するだけです。 – blow

+0

ここで少し話題になっていますが、ItemFrameコンストラクタのコンテナからBeanを取得する理由は何ですか?コンテナによって注入されたBeanを取得することよりも、このアプローチの利点はありません。 – prasopes

答えて

3

サービス層がdaoを複製する場合、サービス層はまったく使用されていません。私はいくつかのアプリケーションで同じミスを犯しましたが、私は "なぜサービスレイヤーが醜く見え、DAOの複製であるのか"と不思議に思っていました...

サービス層はあなたのアプリケーションのインターフェイスでなければなりません。いくつかの方法はDAOとサービスで同じではありませんが、主要部分は大きく異なります。私はあなたのコードの残りの部分を見ることなくこれを言うことはできませんが、あなたの質問(これは2,3ヶ月前の私の質問とほとんど同じです)では、私にはあなたがanemic domain model antipatternを使用しているようです。貧血ドメインモデルでは、あなたのモデルはフィールドとゲッターだけを含み、基本的なオブジェクト指向の原則(オブジェクト==データ+ビヘイビア)に違反する実際のメソッド(ビヘイビアー)はありません...あなたの振る舞いはおそらく、あなたのモデル(ドメイン層)になければなりません。

リッチドメインモデル(@Configurableを介してモデル化するために注入されたBean)を使用する方法です。これはレイヤのパターンに違反し、おそらく正しいと言えるかもしれません。しかし私は、アプリケーション(ドメイン+ DAO +サービス)を単一のコンポーネントとして考えるべきだと確信しています(Alistair Cockburn Hexagonal architecture/Ports and adapters参照)。

あなたのスイングアプリ/ウェブクライアントは、あなたのコアコンポーネントのクライアントになります。そして、あなたは何の制限もなくスイッチすることができます。

しかし、このアプローチには制限/欠点があります。休止状態で何らかのセキュリティ(春のセキュリティ)やアクティブなレコードを使用する場合は、DTO(エンティティ自体ではなく)を介してすべてのクライアントとコミュニケートするよりも、エンティティに連絡するとサービスを呼び出すことができます。データベースを変更することができます(セキュリティをバイパスします)。

私はあなたのアーキテクチャを推測していると思いますが、そうでない場合はここでホイールを発明して申し訳ありませんが、この投稿はこれを知っていない人を助けるかもしれません。あなたの編集へ

EDIT

:でも、単純なCRUDアプリケーションでは、アクションのいくつかの種類がサービス層にする必要があります - 例の検証(ない検証「これは数ある」が、いくつかのビジネスの具体的な検証のために)。あなたがそれを変更した場合は、&のコピーをもう一度貼り付けることになるので、これはあなたの視野に入るはずです。あなたがあなたのコードを見るときには、「シンクライアント(Webブラウザで表示する)を書くことにしたら、どうすればいいですか?」と質問してください。答えがYESの場合は、このリモート呼び出しの可能性のあるサービスメソッドを作成する必要があります。

サービスレイヤ上で実行できる必要があることは、自動化(このエントリの削除を許可されたこのユーザーのユーザー)です。シンプルなユーザーは自分のエントリを編集(削除)できるはずですが、おそらく他のユーザーを削除しないでください。ほとんどのエンティティについてサービスレイヤーを用意する必要があります。しかし、ロール管理のユーザーはこれを行うことができます。

コード例(私のアプリでは、物品・サービス・インターフェースの一部(春のセキュリティ)):サービス誰もが記事へのコメントを保存することができます

@Secured("ROLE_EDITOR") 
public void save(ArticleDTO selectedArticle, ArticleDetailsDTO selectedArticleDetails); 

コメントで

....

そして最後のノートあなたはおそらく、あなたがの場合には、のサービス層が必要であると考えるべきでしょう。いい方法で書かれていると、あなたのアプリは、その柔軟性、再利用性、および保守性において多くの特質を得るでしょう。しかし、それを書くのはかなり難しく時間がかかります。あなたはこのすべてのこのようなもの(セキュリティ、豊富なドメインモデル、複数のインターフェイス(ビューの実装を変更)からの呼び出しを)やりたいいけない場合は、

+0

非常に便利です、私は私の最初の投稿に多くの情報を追加して、それについてコメントを残してください!ありがとうございました! – blow

+0

私のエンティティにはgetterとsetterだけが含まれていますが、私のdaosにはCRUDよりも多くのメソッドが含まれていますので、実際のリポジトリ(DDD、駆動型domaninデザインに従って)です。私がエンティティを書くとき、私は常にOOの方法で考えようとします。だから私は貧血とドメインモデルの組み合わせがあります。 – blow

+0

偉大なリンク、私はファウラーがこれに関する記事を持っていたことに気づいていませんでした。 – prasopes

0

最終的に、複数のDAO間で動作を調整する必要があります。また、ビジネスルールにいくつかの複雑さを導入することもできます(例:[特定の状態にある場合]を更新しないでください)。これは、サービス層が便利な場所です。

つまり、サービス層を完全に排除することには「技術的に」何の問題もありません。あなたが最終的にあなたが1つを必要とすると決めるときにはもうちょっと痛いでしょう。

1

ある時点で、アプリケーションにはビジネスロジックが必要です。また、入力が妥当であることを確認して、悪意のある行為や要求されていない行為がないことを確認することもできます。このロジックはサービス層に属します。

また、DAOを非常に汎用的にすることができます。そのため、1つまたは2つのメソッドだけがあまり変更されません。これにより、アプリケーションの機能を追加/変更するたびにDAOクラスに間違ったやり方をするリスクが軽減されます。

DAOはアクセスデータ用です。サービスはビジネスロジック用です。それらを別々にしておくと、長期的にはより幸せになれます。

0

代わりの

ui -> service -> DAO 

を強制:-)それなしで生きることができますすべての操作のために、両方の

ui -> DAO 
ui -> service -> DAO 

あなたはそれをやっている私によると、より複雑な操作

関連する問題