10

getEmployeeNameByBatchId(int batchID)
getEmployeeNameBySSN(Object SSN)
getEmployeeNameByEmailId(String emailID)
getEmployeeNameBySalaryAccount(SalaryAccount salaryAccount)

また

getEmployeeName(int typeOfIdentifier, byte[] identifier) -> このメソッドでは、typeOfIdentifier は識別子が batchID/SSN/emailID/salaryAccount であるかどうかを示します

上記のどれが get メソッドを実装するより良い方法ですか?

これらのメソッドはサーブレットにあり、呼び出しは顧客に提供される API から行われます。

4

22 に答える 22

9

getEmployeeName(??)メソッドをオーバーロードしてみませんか?

getEmployeeName(int BatchID)
getEmployeeName(object SSN)(悪い考え)
getEmployeeName(String Email)
など。

私には良い「多くの」アプローチのようです。

于 2008-09-17T07:49:00.120 に答える
7

次のようなものを使用できます。

interface Employee{
    public String getName();
    int getBatchId();
}
interface Filter{
    boolean matches(Employee e);
}
public Filter byName(final String name){
    return new Filter(){
        public boolean matches(Employee e) {
            return e.getName().equals(name);
        }
    };
}
public Filter byBatchId(final int id){
    return new Filter(){
        public boolean matches(Employee e) {
            return e.getBatchId() == id;
        }
    };
}
public Employee findEmployee(Filter sel){
    List<Employee> allEmployees = null;
    for (Employee e:allEmployees)
        if (sel.matches(e))
            return e;
    return null;
}
public void usage(){
    findEmployee(byName("Gustav"));
    findEmployee(byBatchId(5));
}

SQL クエリによるフィルタリングを行う場合は、Filterインターフェイスを使用して WHERE 句を作成します。

このアプローチの良い点は、2 つのフィルターを次のように簡単に組み合わせることができることです。

public Filter and(final Filter f1,final Filter f2){
    return new Filter(){
        public boolean matches(Employee e) {
            return f1.matches(e) && f2.matches(e);
        }
    };
}

そのように使用します:

findEmployee(and(byName("Gustav"),byBatchId(5)));

Criteria得られるものは、Hibernateの API に似ています。

于 2008-09-17T08:10:02.767 に答える
3

私は「多くの」アプローチを採用します。私にはより直感的で、エラーが発生しにくいようです。

于 2008-09-17T07:48:55.737 に答える
3

私は getXByY() が好きではありません - PHP ではクールかもしれませんが、Java (ymmv) では好きではありません。

同じデータ型のプロパティがない限り、オーバーロードを使用します。その場合、2 番目のオプションと同様のことを行いますが、int を使用する代わりに、型の安全性と明確さのために Enum を使用します。また、byte[] の代わりに Object を使用します (オートボクシングのため、これはプリミティブでも機能します)。

于 2008-09-17T08:08:39.650 に答える
2

これらのメソッドは、オーバーロードの使用の完璧な例です。

getEmployeeName(int batchID)
getEmployeeName(Object SSN)
getEmployeeName(String emailID)
getEmployeeName(SalaryAccount salaryAccount)

メソッドの内部に共通の処理がある場合は、もう 1 つ getEmplyeeNameImpl(...) を記述し、重複を避けるために共通のコードを抽出します。

于 2008-09-17T07:59:57.970 に答える
1

最初のオプション、質問はありません。明示的にしてください。それは保守性を大いに助け、実際にはマイナス面はありません。

于 2008-09-17T07:50:26.357 に答える
1

@Stephan:パラメータタイプが識別できない可能性があるため、このようなケースを(一般的に)オーバーロードすることは困難です。

  • getEmployeeNameByBatchId(int batchId)
  • getEmployeeNameByRoomNumber(int roomNumber)

元の投稿の2つのメソッドgetEmployeeNameBySSN、getEmployeeNameByEmailIdも参照してください。

于 2008-09-17T07:55:49.870 に答える
1

明示的なメソッド名を使用します。そのコードを維持するすべての人、および後で私がそのメソッドが何をしているかを、xml コメントを書かなくても理解できるようになります。

于 2008-09-17T08:46:52.353 に答える
1

場合によっては、仕様パターンを使用する方が便利な場合があります。

例: GetEmployee(ISpecification<従業員> 仕様)

そして、仕様の定義を開始します...

NameSpecification : ISpecification<従業員>
{
プライベート文字列名;
public NameSpecification(文字列名) { this.name = name; }
public bool IsSatisFiedBy(Employee employee) { return employee.Name == this.name; NameSpecification spec = new NameSpecification("Tim"); }
} 従業員ティム = MyService.GetEmployee(spec);



于 2008-09-17T08:15:49.383 に答える
0

最初のオプションを使用するか、この場合はオーバーロードします。4つの異なるパラメーターシグネチャがあるためです。ただし、具体的にすることは、3か月後のコードを理解するのに役立ちます。

于 2008-09-17T07:49:07.873 に答える
0

最初のものは、(他とは異なり)タイプセーフであることを考えると、おそらくJavaで最高です。さらに、「通常の」タイプの場合、2番目のソリューションはユーザーにとって面倒な使用法しか提供しないようです。ただし、SSNのタイプとしてObjectを使用しているため(Objectを超えたセマンティックな意味があります)、おそらくそのタイプのAPIを使用することはできません。

全体として、この特定のケースでは、私は多くのゲッターでアプローチを使用したでしょう。すべての識別子が独自のクラスタイプを持っている場合は、2番目のルートを使用した可能性がありますが、提供された/アプリケーション定義のタイプ識別子ではなく、クラスを内部的に切り替えます。

于 2008-09-17T07:52:58.237 に答える
0

これらの各メソッド内のロジックはほぼ同じですか?

その場合、識別子パラメータを使用した単一のメソッドの方が理にかなっている可能性があります(単純で繰り返しコードを減らす)。

ロジック/手順がタイプ間で大きく異なる場合は、タイプごとのメソッドが推奨される場合があります。

于 2008-09-17T07:54:18.780 に答える
0

他の人が示唆したように、最初のオプションは良いもののようです。2つ目は、コードを書いているときに意味があるかもしれませんが、後で誰かがやってくると、コードの使い方を理解するのが難しくなります。(コメントがあり、いつでもコードを深く掘り下げることができますが、GetemployeeNameByIdの方がわかりやすいです)

注:ところで、列挙型の使用法は、場合によっては考慮すべき点があるかもしれません。

于 2008-09-17T07:55:50.197 に答える
0

個人的には、「...ByRoomNumber」という明示的な名前を付けることを好みます。多くの「オーバーロード」が発生すると、最終的に不要なエラーが発生するからです。明示的であることは、最善の方法です。

于 2008-09-17T08:09:16.607 に答える
0

検索プロセスと jrudolf が彼の例で提案する検索基準との間の分離は優れています。なぜそれが最も投票数の多いソリューションではないのだろうか。私は何かが恋しいですか?

于 2008-09-17T13:16:59.707 に答える
0

Stephan: One task, one method name に同意します。複数の方法で実行できる場合でも。メソッドのオーバーロード機能は、まさにあなたのケースに合わせて提供されました。

  • getEmployeeName(int BatchID)
  • getEmployeeName(文字列メール)

そして、2 番目の解決策は絶対に避けてください。「thy olde void * of C」の匂いがします。同様に、Java の「オブジェクト」を渡すのは、C の「void *」と同じくらい貧弱なスタイルです。

于 2008-09-17T08:20:45.223 に答える
0

私はQuery Objectsを使います。テーブルに直接アクセスするのに適しています。ストアド プロシージャに限定されている場合、その機能の一部が失われますが、機能させることはできます。

于 2008-09-18T00:15:20.810 に答える
0

このような些細なケースでは、オーバーロードを使用します。あれは:

getEmployeeName( int batchID );
getEmployeeName( Object SSN );

etc.

メソッド名に引数の型を指定するのは、特別な場合のみです。つまり、引数の型を判別するのが難しい場合、同じデータ型 (batchId と employeeId、両方とも int) を持つ引数の型が複数ある場合、または従業員を取得するメソッドは、引数の型ごとに根本​​的に異なります。

なぜこれを使うのか理解できない

getEmployeeName(int typeOfIdentifier, byte[] identifier)

呼び出し先と呼び出し元の両方が typeOfIdentifier に基づいて値をキャストする必要があるためです。悪いデザイン。

于 2008-09-17T07:58:07.273 に答える
0

質問を書き直すと、次のように尋ねることになります。

"SELECT name FROM ..."
"SELECT SSN FROM ..."
"SELECT email FROM ..."
vs.
"SELECT * FROM ..."

これに対する答えは簡単で、誰もが知っていると思います。

Employee クラスを変更するとどうなりますか? 例: メールを削除し、部門などの新しいフィルターを追加する必要があります。2 番目の解決策では、int 識別子の「定数」の順序を変更しただけでは、エラーに気付かないという大きなリスクがあります。最初の解決策を使用すると、長い間忘れられていたクラスでメソッドを使用している場合、そうでなければ新しい識別子に変更するのを忘れていることに常に気付くでしょう。

于 2008-09-17T07:58:59.253 に答える
0

適切な設計があれば、オーバーロード アプローチを使用できるかどうか、またはオーバーロードすると同じパラメータ タイプの 2 つのメソッドが作成されるという問題が発生するかどうかを判断できるはずです。

最初はオーバーロードが最善の方法のように思えますが、後でメソッドを追加できなくなり、名前付けを台無しにするのは面倒です。

個人的には、メソッドごとに一意の名前を付けるアプローチが必要です。これにより、後で同じパラメーター オブジェクト メソッドをオーバーロードしようとして問題が発生することはありません。また、誰かが将来あなたのクラスを拡張し、別の void getEmployeeName(String name) を実装した場合、それはあなたのクラスをオーバーライドしません。

要約すると、各メソッドに一意のメソッド名を使用すると、オーバーロードは長期的にのみ問題を引き起こす可能性があります。

于 2008-09-17T08:26:56.470 に答える
-1

すべてのオプションを列挙型に貼り付けます。次のようなものがあります

GetEmployeeName(Enum identifier)
{
    switch (identifier)
    case eBatchID:
    {
        // Do stuff
    }
    case eSSN:
    {
    }
    case eEmailId:
    {
    }
    case eSalary:
    {
    }
    default:
    {
        // No match
        return 0;
    }
}

enum Identifier
{
    eBatchID,
    eSSN,
    eEmailID,
    eSalary
}
于 2008-09-17T10:12:48.293 に答える
-2

あなたはC/C++を考えています。

識別子バイト(またはint)の代わりにオブジェクトを使用します。

私の悪い点、過負荷アプローチの方が優れており、SSNを主キーとして使用するのはあまり良くありません

public ??? getEmployeeName(Object obj){

if (obj instanceof Integer){

  ...

} else if (obj instanceof String){

...

} else if .... // and so on


} else throw SomeMeaningFullRuntimeException()

return employeeName
}

間違った入力を通知するには、チェックされていない例外を使用する方が良いと思います。

それを文書化して、顧客がどのオブジェクトを期待するかを理解できるようにします。または、独自のラッパーを作成します。私は最初のオプションを好みます。

于 2008-09-17T07:57:07.870 に答える