web-dev-qa-db-ja.com

APIユーザーがUnsupportedOperationExceptionを実装することを期待していますか?

データのダウンロード/インポート用のハンドラーを書いています。データベースにデータを挿入した後、いくつかのインポートジョブを呼び出すことができますが、通常は1つだけです。したがって、インポートジョブを取得する方法は2つあり、抽象基本クラスからオーバーライドできます。1つは抽象で、もう1つは最初のメソッドを使用します。

私のコードとドキュメントを見て、この設計が大丈夫だと思うかどうか、またはどのような方法が最善かを教えてください。 UnsupportedOperationExceptionをスローするためだけにgetImportJob()を実装する必要があるサブクラスを作成するものを持っているという私の設計に特にイライラしていますが、どういうわけか自然に思い浮かびました。しかし、太字でマークされた部分は大丈夫ですか、それとも私はそれでいくつかの慣習を破っていますか?

/**
 * Returns the name and parameters of the import job that may be called
 * after the data has been added to the database in
 * {@link #insertDataIntoDatabase(Map)}.<br>
 * If the import job is called or not in the aforementioned method is
 * determined by {@link #isExecutingImports()}. If there is no import job to
 * execute ever, this method should return <code>null</code>. If there are
 * several import jobs to be done, this method should throw a
 * {@link UnsupportedOperationException} and {@link #getImportJobList()}
 * should be overridden to return the names and parameters of the import
 * jobs in the order they should be executed.
 * 
 * @return the name of the single import job that can be executed or
 *         <code>null</code> if none can ever be executed.
 * @throws UnsupportedOperationException
 *             If this method was called when there are several import jobs.
 * 
 * @see #getImportJobList()
 */
protected abstract String getImportJob();

/**
 * Returns a list of names and parameters of import jobs that may be called
 * after the data has been added to the database in
 * {@link #insertDataIntoDatabase(Map)}.<br>
 * The default implementation calls {@link #getImportJob()} and returns an
 * empty or a singleton list depending on <code>getImportJob()</code> having
 * returned <code>null</code> or a concrete object. When this method is
 * overridden to provide several import jobs to be done,
 * <code>getImportJob()</code> should also be overriden, according to its
 * documentation.
 * 
 * @return a list of names and parameters of import jobs
 * @throws UnsupportedOperationException
 *             If <code>getImportJob()</code> was overridden to throw an
 *             <code>UnsupportedOperationException</code> without this
 *             method being overridden accordingly.
 * 
 * @see #getImportJob()
 */
public List<String> getImportJobList() {
    String singleImport = getImportJob();
    if (singleImport == null)
        return Collections.emptyList();
    return Collections.singletonList(singleImport);
}

ちょうど私が両方のメソッドを抽象化して2つのインターフェイスを提供できることに気づきました。1つはシングル用で、もう1つはマルチユース用です。それぞれが1つのメソッドを残し、契約に従ってデフォルトで他のメソッドを実装します...デフォルトの概念の誤用ですが、それは私の目的に役立つと思います。私の質問はまだ残っています。

編集:回答のおかげで、基本クラスをシングルジョブメソッドのないインターフェイスに変更し、シングルジョブメソッドを継承するインターフェイスと、ジョブリストメソッドのデフォルトを追加しました。

3
GreenThor

アカデミック:インターフェイス要件を満たすためにインターフェイスの一部を実装する必要がない場合、インターフェイスはユースケースに対して適切に定義されていません。あなたが本当に持っているのは別のインターフェースです。

したがって:いいえ、UnsupportedOperationExceptionをスローすることはできません。例外も存在してはなりません。 「サポートされていない操作」と「実装されていないメソッド」は、それらをサポートするためのインターフェースをコーディングしなかったという事実によって明確に伝えられます。そのようなものは、貧弱なデザインの上のバブルガムとダクトテープです。

実用的:インターフェース全体ではなく一部のみを実装することは間違いなくコードの臭いであり、実装のコンシューマーがインターフェースから予期されるべきではない動作を経験するリスクをもたらします。自分の危険。

すべてのプログラマーが、デザイナーの住んでいる場所を知っている精神病の斧殺人者であるかのように、システムを設計する必要があります。あなたはそのようなことをする最初の人ではないでしょう、そしてWin32の経験を持っている人なら誰でもあなたにため息、目玉、そして息を切らしてつぶやいた形容詞を与えるでしょう。その後、彼らは先に進みます。あなたはおそらく安全でしょう。

4
K. Alan Bates

APIユーザーがUnsupportedOperationExceptionを実装することを期待していますか?

私はそうは思いません。 リスコフの置換原則 に違反している可能性があります。引用:

これらの例外自体がスーパータイプのメソッドによってスローされる例外のサブタイプである場合を除いて、サブタイプのメソッドによって新しい例外がスローされることはありません。

したがって、基本メソッドがUnsupportedOperationException(またはスーパークラス)をスローするように宣言されていない限り、その動作は予期せず、 驚き最小の原則 に違反します。

3
Brian Agnew