7

私はGWT + Hibernateプロジェクトに取り組んでいます。これは、Company と Login の 2 つに名前を付けるさまざまなモジュールで構成されています。モジュールごとに RPC サービスを作成したので、プロジェクトが 1 つの神のようなサービスですべてを実行してしまうことはありません。

データベースと対話するために、Hibernate API を使用します。具体的には、POJO の EntityManager と Annotations です。

また、基本的な CRUD 操作を処理する Generic DAO クラスも作成しました。GenericDAO クラスも EntityManager を処理します。各モジュール サービス クラスは、独自のクエリ メソッドを追加できるように、この GenericDAO を拡張します。

以下は GenericDAO クラスのスタブです -

public class GenericDataAccessService<EntityType, PrimaryKeyType extends Serializable> {

    // Constructor

    @Override
    public void save(EntityType newEntity) {
        // TODO Auto-generated method stub
    }

    @Override
    public void update(EntityType entity) {
        // TODO Auto-generated method stub

    }

    @Override
    public EntityType find(PrimaryKeyType primaryKey) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<EntityType> findByProperty(String property) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<EntityType> findAll() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void delete(PrimaryKeyType primaryKey) {
        // TODO Auto-generated method stub

    }

    @Override
    public void delete(EntityType entity) {
        // TODO Auto-generated method stub

    }
}

ここで、Company モジュールの find メソッドがもう 1 つ必要だとします。だから、私は CompanyService クラスを次のように書きます -

public class CompanyService extends GenericDataAccessService<Company, int> {

    public void addCompany(Company company) {
        super.save(company);
    }

    public Company updateCompany(Company company) {
        return super.update(company);
    }

    public List<Company> findMatchingCompanies(String companyName) {
        return super.findByProperty(companyName);
    }

    public void deleteCompany (int companyId) {
        super.delete(companyId);
    }

    public List<Company> findThroughSomeCustomSearch() {
        // custom query code.
    }
}

他のモジュールも同様の足跡をたどります。そうすれば、データ アクセス以外のメソッドを各モジュールのサービスに追加することもできます。

ここで、これらのモジュールをクライアント側で公開する必要があります。GenericDAO クラスを公開しないことにしました。そのためのインターフェースはありません。代わりに、モジュールごとにインターフェイスを作成します。

したがって、CompanyService の場合は -

public interface CompanyService {

    public void addCompany(Company company);

    public Company updateCompany(Company company);

    public List<Company> findMatchingCompanies(String companyName);

    public void deleteCompany (int companyId);

    public List<Company> findThroughSomeCustomSearch();
}

他のモジュールのインターフェースも同様です。

これは良いデザインですか?GenericDAO は、セッション管理と基本的な CRUD 操作のいくつかの定型コードを節約します。ただし、Hibernate API のおかげで、メソッドあたりのコードはすでに 3 ~ 4 行に減っています。この場合、GenericDAO の他の用途は見つかりません。それとも、間違った方法で実装していますか?

このデザインが十分でない場合に備えて、これよりも良い方法を提案してください。

編集: この場合、サービス モジュールに付ける名前を知りたいです。私は今、「Impl」という接尾辞を使っていますが、喉に詰まっているように感じます。たとえば、Company モジュールの場合、Interface - CompanyService Class - CompanyServiceImpl

より良い提案?

4

1 に答える 1

9

これを改善するためにできることがいくつかあると思います。

カップリング:

ほとんどの場合、合成は継承よりも好ましいです。そのような関係があるため、サービスは強く結合されています。私はそれを変更することを目的としており、次のように代わりに構成を使用します。

public class CompanyService  {
    private GenericDataAccessService<Company, int> dao; // interface 

    public void addCompany(Company company) {
        dao.save(company);
    }
    ....
}

依存関係を解消するには、dao フィールドを抽象クラスまたはインターフェイス (コードもニーズも Java もわかりません) にして、注入できるようにする必要があります。

試験容易性:

これらのクラスの依存関係を注入すると、モック インスタンスを注入してコードを簡単にテストするのにも役立ちます。

不要な操作:

継承を使用すると、おそらく許可したくない操作が強制されます。たとえば、次のような AuditingDataService があるとします。

public class AuditingService extends GenericDataAccessService<Audit, int> 

そうすれば、 yout AuditingService はDeleteメソッドを継承します!!! 私と同じくらい強いにおいを感じることができますか?それはあなたを次のポイントに導きます。

アンチパターン

前の例 (ログ エントリを監査するための削除メソッド) では、誰かが使用できないようにするために、何もしない例外をスローするメソッドでオーバーライドする必要があります...うーん...うーん...うーん...良いデザイン?

結論

ここでは継承があまり適していないため、そうではないと思います。

LoC のことはしばらく忘れて、設計の変更に集中してください。

更新

Java には独自の命名規則があり、Impl がひどいサフィックスであるとしても、それはすべての Java プログラマーが理解し、共有している規則の 1 つです。だから、大丈夫だと思います。

于 2013-01-26T21:46:03.907 に答える