문제

getEmployeeNameByBatchId(int 배치ID)
getEmployeeNameBySSN(객체 SSN)
getEmployeeNameByEmailId(문자열 이메일 ID)
getEmployeeNameBySalaryAccount(SalaryAccount 급여계정)

또는

getEmployeeName(int typeOfIdentifier, byte[] 식별자) -> 이 메소드에서 typeOfIdentifier는 식별자가 배치ID/SSN/emailID/salaryAccount인지 알려줍니다.

위 중 get 메소드를 구현하는 더 좋은 방법은 무엇입니까?

이러한 메소드는 서블릿에 있으며 호출은 고객에게 제공되는 API에서 이루어집니다.

도움이 되었습니까?

해결책

getEmployeeName(??) 메소드를 오버로드하지 않는 이유는 무엇입니까?

getEmployeeName(int 배치 ID)
getEmployeeName(개체 SSN)(나쁜 생각)
getEmployeeName(문자열 이메일)
등.

나에게는 좋은 '다수' 접근 방식인 것 같습니다.

다른 팁

다음과 같은 것을 사용할 수 있습니다.

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 절을 구성하는 인터페이스입니다.

이 접근 방식의 장점은 다음과 같이 두 개의 필터를 쉽게 결합할 수 있다는 것입니다.

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.

나는 "다수" 접근 방식을 사용하겠습니다.나에게는 더 직관적이고 오류가 덜 발생하는 것 같습니다.

나는 getXByY()를 좋아하지 않습니다. PHP에서는 좋을 수도 있지만 Java(ymmv)에서는 마음에 들지 않습니다.

동일한 데이터 유형의 속성이 없으면 오버로드를 사용하겠습니다.이 경우 두 번째 옵션과 비슷한 작업을 수행하지만 유형 안전성과 명확성을 위해 int를 사용하는 대신 Enum을 사용합니다.그리고 byte[] 대신 Object를 사용합니다(오토박싱 때문에 이는 기본 요소에서도 작동합니다).

이 방법은 오버로딩 사용에 대한 완벽한 예입니다.

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

메소드 내부에 공통 처리가 있는 경우 getEmplyeeNameImpl(...)을 하나 더 작성하고 중복을 피하기 위해 공통 코드를 추출하십시오.

첫 번째 옵션은 질문이 없습니다.명시적으로 설명하세요.유지 관리에 큰 도움이 되며 실제로 단점이 없습니다.

@스테판:매개변수 유형이 구별되지 않을 수 있기 때문에 (일반적으로) 이와 같은 사례를 오버로드하는 것은 어렵습니다.

  • getEmployeeNameByBatchId(int 배치Id)
  • getEmployeeNameByRoomNumber(int roomNumber)

원본 게시물의 getEmployeeNameBySSN, getEmployeeNameByEmailId 두 가지 메서드도 참조하세요.

명시적인 메소드 이름을 사용하겠습니다.해당 코드를 유지 관리하는 모든 사람과 나중에는 XML 주석을 작성하지 않고도 해당 메서드가 수행하는 작업을 이해할 수 있습니다.

때로는 다음을 사용하는 것이 더 편리할 수 있습니다. 사양 패턴.

예:GetEmployee(ISpecification<Employee> 사양)

그런 다음 사양 정의를 시작하십시오.

이름사양 :ISpecification<직원>
{
개인 문자열 이름;
public NameSpecification(문자열 이름) { this.name = 이름;}
public bool IsSatisFiedBy(직원 직원) { return Employee.Name == this.name;}
}

NameSpecification spec = new NameSpecification("Tim");
직원 tim = MyService.GetEmployee(spec);

나는 첫 번째 옵션을 사용하거나, 이 경우에는 4개의 서로 다른 매개변수 서명이 있는 것을 보고 오버로드하겠습니다.하지만 구체적으로 설명하면 3개월 후 코드를 이해하는 데 도움이 됩니다.

각 메서드 내부의 논리는 거의 동일합니까?

그렇다면 식별자 매개변수를 사용하는 단일 메서드가 더 적합할 수 있습니다(단순하고 반복되는 코드를 줄임).

유형별로 논리/절차가 크게 다른 경우 유형별 방법이 선호될 수 있습니다.

다른 사람들이 제안한 것처럼 첫 번째 옵션이 좋은 것 같습니다.두 번째 방법은 코드를 작성할 때 의미가 있을 수 있지만 나중에 다른 사람이 오면 코드 사용 방법을 파악하기가 더 어렵습니다.(알고 있습니다. 의견이 있고 언제든지 코드를 자세히 알아볼 수 있지만 GetemployeeNameById는 설명이 더 필요합니다.)

메모:그런데 어떤 경우에는 Enum 사용을 고려해야 할 수도 있습니다.

이와 같은 사소한 경우에는 과부하를 사용합니다.그건:

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

etc.

특별한 경우에만 메소드 이름에 인수 유형을 지정합니다.인수 유형을 결정하기 어려운 경우, 동일한 데이터 유형(batchId 및 EmployeeId, 둘 다 int)을 갖는 여러 유형의 인수가 있는 경우 또는 직원을 검색하는 방법이 각 인수 유형마다 근본적으로 다른 경우.

내가 왜 이것을 사용하는지 알 수 없습니다

getEmployeeName(int typeOfIdentifier, byte[] identifier)

typeOfIdentifier를 기반으로 값을 캐스팅하려면 호출 수신자와 호출자 모두가 필요하기 때문입니다.나쁜 디자인.

질문을 다시 작성하면 다음과 같이 질문하게 될 수 있습니다.

"다음에서 이름 선택..."
"다음에서 SSN을 선택하세요..."
"다음에서 이메일을 선택하세요..."

"선택 * ...에서"

그리고 이에 대한 답은 쉽고 모두가 알고 있다고 생각합니다.

Employee 클래스를 변경하면 어떻게 되나요?예:이메일을 제거하고 부서와 같은 새 필터를 추가해야 합니다.두 번째 솔루션을 사용하면 int 식별자 "상수"의 순서를 변경하면 오류를 발견하지 못할 큰 위험이 있습니다.첫 번째 해결 방법을 사용하면 오랫동안 잊혀진 일부 클래스에서 메서드를 사용하고 있는지 항상 알 수 있으며 그렇지 않으면 새 식별자로 수정하는 것을 잊어버릴 것입니다.

나는 개인적으로 "...ByRoomNumber"라는 명시적인 이름을 선호합니다. 왜냐하면 많은 "오버로드"가 발생하면 결국 원치 않는 오류가 발생하게 되기 때문입니다.명시적인 것이 가장 좋은 방법입니다.

나는 스테판의 말에 동의합니다:하나의 작업, 하나의 메서드 이름, 여러 가지 방법으로 할 수 있다고 해도 마찬가지입니다.귀하의 경우에 정확하게 메소드 오버로딩 기능이 제공되었습니다.

  • getEmployeeName(int 배치 ID)
  • getEmployeeName(문자열 이메일)
  • 등.

그리고 피하다 어떤 대가를 치르더라도 두 번째 솔루션을 선택하세요."C의 오래된 공허함 *" 냄새가 납니다.마찬가지로 Java "Object"를 전달하는 것은 C "void *"만큼 좋지 않은 스타일입니다.

좋은 디자인을 가지고 있다면 오버로딩 접근 방식을 사용할 수 있는지, 아니면 오버로드하면 동일한 매개변수 유형을 가진 두 개의 메소드를 가지게 되는 문제에 직면하게 될지 결정할 수 있어야 합니다.

처음에는 오버로딩이 가장 좋은 방법인 것처럼 보이지만 나중에 메서드를 추가할 수 없고 이름 지정이 엉망이 되면 번거로운 일이 될 것입니다.

개인적으로 나는 메소드별로 고유한 이름을 사용하는 방식을 원합니다. 그렇게 하면 나중에 동일한 매개변수인 Object 메소드를 오버로드하려고 할 때 문제가 발생하지 않습니다.또한 누군가가 나중에 클래스를 확장하고 또 다른 void getEmployeeName(String name)을 구현하면 해당 클래스가 재정의되지 않습니다.

요약하자면, 각 메서드에 대해 고유한 메서드 이름을 사용하세요. 오버로드는 장기적으로 문제를 일으킬 수 있습니다.

jrudolf가 그의 예에서 제안한 검색 프로세스와 검색 기준 간의 분리는 훌륭합니다.왜 이것이 가장 많이 투표된 솔루션이 아닌지 궁금합니다.제가 뭔가를 놓치고 있는 걸까요?

나는 함께 갈 것이다 쿼리 개체.테이블에 직접 액세스하는 데 적합합니다.저장 프로시저에만 국한된 경우 그 기능이 일부 손실되지만 여전히 작동하게 만들 수 있습니다.

첫 번째는 (다른 것과 달리) 유형이 안전하다는 점을 고려하면 아마도 Java에서 최고일 것입니다.또한 "일반" 유형의 경우 두 번째 솔루션은 사용자에게 번거로운 사용법만 제공하는 것 같습니다.그러나 Object를 SSN의 유형으로 사용하고 있으므로(Object 이상의 의미적 의미를 가짐) 아마도 해당 유형의 API를 사용하지 못할 것입니다.

전반적으로, 이 특별한 경우에는 많은 게터와 함께 접근 방식을 사용했을 것입니다.모든 식별자에 고유한 클래스 유형이 있는 경우 두 번째 경로를 택했을 수도 있지만 제공된/애플리케이션 정의 유형 식별자 대신 클래스에서 내부적으로 전환했습니다.

모든 옵션을 열거형에 추가하면 다음과 같은 결과가 나타납니다.

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
}

당신은 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
}

잘못된 입력을 알리려면 확인되지 않은 예외를 사용하는 것이 더 낫다고 생각합니다.

고객이 어떤 물건을 기대하는지 알 수 있도록 문서화하세요.또는 자신만의 래퍼를 만드세요.나는 첫 번째 옵션을 선호합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top