Java Swingアプリケーションのサービスレイヤー
-
28-09-2019 - |
質問
本当にサービスレイヤーが必要かどうか私は考えています。
デスクトップスイングアプリケーションにSpring + Hibernateを使用しています。現時点では、GUI/SWINGレイヤー - >サービスレイヤー - > DAOレイヤーがあります。 @TransactionalサポートとIOC-InjectionにのみSpringを使用しています
ベストプラクティスは、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);
}
}
これは鉱山のサービスレイヤーの純粋な使用法です...冬眠はDBに依存しています、春はテクノロジーと存在します:それで、私は本当にそれが必要ですか?
すべてのDAOを管理するユニークなサービスクラスはどうですか?これは良い妥協かもしれないと思いますか、それとも悪い習慣ですか?
DAOの@TransactionalをPut @Transactionalは悪い方法であることを知っていますが、現時点では@Transactionalのみのためにサービスを書かなければなりません...
編集
私のアプリに関するより多くの情報。
私のアプリケーションは管理ソフトウェアであり、ユーザーの登録、製品、注文などを管理しています。実際には、多くの読み取りエンティティ - >編集 - > edit-> endity-> edit-> operationsの保存が含まれています。また、Hibernateのおかげで、これらの操作はほとんどの場合、 @manytoと冬眠します。 ..コレクションと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();
}
}
これは私がほとんどの場合に持っているものなので、私は貧血領土antipatternに落ちたと思います...
ありがとう。
解決
サービスレイヤーがDAOを複製する場合、サービスレイヤーをまったく使用していません。私は私のアプリケーションのいくつかで同じ間違いを犯しました、私は「なぜサービスレイヤーがとても醜く、Duplicationg Daoです」と思っていました...
サービスレイヤーは、Appleiacationのインターフェイスである必要があります。これは、一部の方法がDAOおよび使用中で同じではないことを意味しますが、主要な部分は大きく異なります。あなたのコードの残りの部分を表示せずにこれを言うことはできませんが、あなたの質問(これは数ヶ月前の私の質問とほぼ同じです)、それは私にはあなたが使用しているように思えます 貧血ドメインモデルアンチパッター. 。貧血ドメインモデルでは、モデルにはフィールドとゲッターのみが含まれており、基本的なオブジェクト指向の原理(Object == Data + Behavior)に違反する実際の方法(動作)はありません...あなたの動作はおそらくサービスのトランザクションスクリプトのように見えるものですレイヤーですが、モデル(ドメインレイヤー)にある必要があります。
これから抜け出す方法は、リッチドメインモデル(@Configurableを介してモデルに注入された豆)を使用することです。これはレイヤーパターンに違反し、おそらく正しいと言うかもしれません。しかし、私たちはアプリケーション(ドメイン+DAO+サービス)を単一のコンポーネントとして考える必要があると確信しています(Alistair Cockburnを参照してください 六角形のアーキテクチャ/ポートおよびアダプター).
Swing App/Webクライアントは、コアコンポーネントのクライアントになり、制限なしでそれらを切り替えることができます(Modiefiesデータがコアにあるすべてのもの)。
しかし、このアプローチには制限/欠点があります。 Hibernateを介して何らかのセキュリティ(Spring Security)またはActive Recordsを使用する場合、DTO(エンティティ自体ではなく)を介してすべてのクライアントと同意する必要があります。トランザクションとデータベースを変更できます(セキュリティをバイパス)。
私はあなたのアーキテクチャを推測したことを願っています。そうでない場合、ここでホイールを発明して申し訳ありませんが、この投稿はこれを知らない人を助けるかもしれません(私は数件前のように)。
編集
編集するには、単純なCRUDアプリケーションであっても、何らかの種類のアクションがサービスレイヤーにある必要があります - たとえば、検証(これは数字です」ではなく、ビジネス固有の検証)。これはあなたの見解にあるはずです。なぜなら、あなたがそれを変更すると、再びコピーして貼り付けるからです。コードを見ると、「Thin Client(Web Browserで表示)を書くことにした場合」というQeustingを尋ねる必要があります。コピーがありますか?回答の場合、この場合、このリモートコールのサービスメソッドを作成する必要があります。
サービスレイヤーですべき/できるもう1つのことは自動化です(この役割のユーザーは、このエントリを削除することが許可されています)。シンプルなユーザーは自分のエントリを編集(削除)できるはずですが、おそらく他のユーザーを削除すべきではないため、ほとんどすべてのエンティティにサービスレイヤーを使用する必要があります。ただし、役割管理者のユーザーはこれを行うことができます。
例コード(アプリの記事サービスインターフェイスの一部(Spring Security)):
@Secured("ROLE_EDITOR")
public void save(ArticleDTO selectedArticle, ArticleDetailsDTO selectedArticleDetails);
コメントサービスでは、誰もが記事にコメントを保存できます。
そして最後の注意:あなたがおそらくあなたが考慮すべきです、あなたが 必要 サービスレイヤー。それが良い方法で書かれているとき、あなたのアプリはその柔軟性、再利用性、保守性に多くの資質を獲得します。しかし、それを書くのはかなり難しく、時間がかかります。これをすべてやりたくない場合(セキュリティ、リッチドメインモデル、より多くのインターフェイスから呼び出し(ビューの実装の変更))、それなしで生きることができます:-)
他のヒント
ある時点で、アプリケーションはビジネスロジックを必要とします。また、入力を検証して、リクエストされている邪悪なまたは不良不履行がないことを確認することをお勧めします。このロジックは、サービスレイヤーに属します。
さらに、DAOを非常に一般的にすることができるかもしれません。そうすれば、あまり変わらない方法が1つまたは2つしかありません。これにより、アプリの機能を追加/変更するたびに、DAOクラスにひどく間違ったことをするリスクが減ります。
DAOはアクセスデータ用です。サービスはビジネスロジック用です。それらを別々にしておくと、長期的には幸せになります。
最終的には、複数のDAOの間で動作を調整する必要があります。また、ビジネスルールに複雑さを紹介することもできます(例:[これ]が特定の状態にある場合、[これ]を更新しないでください)。これは、サービスレイヤーが役立つ場所です。
とはいえ、サービスレイヤーを完全に排除することに「技術的に」問題はありません。最終的に必要だと判断すると、もう少し苦痛になります。
実施する代わりに
ui -> service -> DAO
すべての操作について、両方を許可することを検討してください
ui -> DAO
ui -> service -> DAO
後者は、より複雑な操作に使用されます