2012-02-21 4 views
4

나는 Question라고 이름이 지어지는 클래스를 만들고있다. 이 클래스에는 답변이 있으므로 첨부 된 답변 목록을 반환 할 수 있기를 원합니다.불변의 목록을 되 돌리는 것

그러나 사용자가 답변을 변경하면 추가 검증 등을 할 수 있도록 사용자가 업데이트 방법을 호출하기를 원합니다. 지금 사용자가 답변 목록을 얻으면 그는 여전히 답변을 변경할 수 있습니다. 말하는 question.getAnswers().get(0).setDescription("BLAH BLAH").

그래서 나는 각 대답의 사본을 반환 생각하고 사용자가 이것을 변경하게하고 그는 다시 질문을 병합/업데이트해야합니다. 이 방법을 사용하면 대답은 유효하지만 JPA를 사용하기 때문에 descriptioncorrect 필드를 기반으로하고 id 필드가 아닌 equals 메서드를 기반으로합니다. 사용자가이 방법으로 답변을 변경하면 설명 필드가 변경되어 더 이상 같지 않아 업데이트 메소드가 답변을 찾지 못해 목록에서 해당 설명을 찾지 못합니다.

조언이 있으십니까?

public void updateAnswer(Answer answer) { 
    int index = answers.indexOf(answer); 
    answers.set(index, answer); 
} 

public List<Answer> getAnswers() { 
    return Collections.unmodifiableList(answers); 
} 


@Test 
public void shouldUpdateAnswerInQuestion() { 
    // Get first answer, make an update on the description 
    // and then update answer on question. 
    Answer answerThatWillBeUpdated = question.getAnswers().get(0); 
    String updatedAnswerDescription = "Hey, it is now updated!"; 
    answerThatWillBeUpdated.setDescription(updatedAnswerDescription); 
    question.updateAnswer(answerThatWillBeUpdated); 

    // After updating check that the answer in the list is equal 
    // to the answer updated. 
    Answer answerFromList = question.getAnswers().get(0); 

    assertEquals(answerThatWillBeUpdated, answerFromList); 
} 

대답 클래스 :

public class Answer { 

    private long id; 
    private String description; 
    private Boolean correct; 
    ... 
} 
+0

? 그는 정확히 무엇을 얻습니까? 그 답을 가지고 분리 된 질문입니까, 아니면 그 답을 첨부 한 질문입니까? 그리고 그는 대답이나 질문 및 답변 목록을 수정해야합니까? 서비스 레이어에서'updateAnswer (Answer a)'서비스를 가지고 계시지 않겠습니까? –

+0

질문은 집합 루트 – LuckyLuke

답변

0

가 왜 업데이트 방법의 비교를 위해 id 필드를 사용하지? 사용자에게 응답 객체의 복사본을 제공하면 복사본에 현재 응답 객체와 동일한 ID가 있는지 확인하십시오. 따라서 사용자가 대답을 변경하면 업데이트 유효성 검사 코드에서 id 필드를 기반으로 변경된 답변을 찾을 수 있습니다.

+0

입니다. JPA를 질문의 맥락에 제공 한 이유는 사람들이 그것이 "나쁘다"는 것을 이해할 것이기 때문입니다. – LuckyLuke

+0

하지만 유효성 검사가 될 때까지는 데이터베이스에 물건을 저장하지 않습니다. 유효성 검사가 완료되면 단순히 해당 행을 삭제하고 새로운 행으로 교체 할 수 있습니까? – CodeBlue

1

귀하의 디자인을 다시 생각해야하지만 전반적인 도메인 제약 조건에 대해 잘 모르기 때문에 약간의 재 디자인이나 그와 비슷한 것을 제안 할 수는 없습니다.

간단하고 직접적인 대답은 구현이 아닌 인터페이스에 대한 프로그램입니다. setter를 변경 한 후에 update 메소드를 호출하려면 Decorator 패턴을 사용해보십시오. 의 생성자에서 구체적인 클래스를 받아들이는 인터페이스를 구현

  • 당신의 구체적인 클래스가이 인터페이스를 구현해야 인터페이스 (대답)
  • 구체적인 클래스 (더 나은 이름 만 AnswerDecorator을 선택)를 추가를 만들

    :

위의 점에서 언급 된 클래스는 그럼 그냥 같은 것을 할, 내부 인스턴스 및 업데이트를 호출 할 방법에 대한 모든 방법을 위임

public void setField (int a) { innerInstance.setField (a); 업데이트 (...); }

+0

하지만 엔티티가 읽기 전용이되기를 원하지 않습니다. 사용자는 변경이 허용되어야하지만, 질문은 집합 루트이므로 모든 조치는 그 공용 메소드를 통해 수행되어야합니다. – LuckyLuke

+0

네가 맞아. 나는 명시 적으로 대답하지 않았다. 내 대답을 편집합니다 .... – vinnybad

+0

유용하다고 판단되면이 답변을 허용으로 표시하십시오. 감사. – vinnybad

0

일반적으로 나는 2 가지 해결책을 알고 있습니다.

  1. 원본 목록 대신 목록의 전체 복사본을 반환하십시오. 이 경우 응답의 설명에서 사용자가 변경 한 내용은 아무런 영향을 미치지 않습니다. 이 솔루션은 간단하지만 성능 및 메모리 사용 측면에서 비효율적입니다. 또한 사용자 친화적이지 않습니다. 사용자가 제한된 동작을 시도 할 때 좋은 API는 예외를 발생시킵니다.

  2. 다른 해결책은 변형 할 수없는 개체, 즉 사용자가 설정자에게 전화를 걸 때 예외를 throw하는 개체의 목록을 반환하는 것입니다.

이 솔루션에는 몇 가지 가능한 구현이 있습니다.

2.1. 모델 클래스의 설정자를 수정하십시오. 모든 setter는 객체가 읽기 전용 모드로 생성 된 경우 예외를 throw 할 수 있어야합니다.

2.2. 사용자 래퍼 (데코레이터) 패턴.

2.2.1. 모든 값 객체에 대한 인터페이스를 만들고 각 클래스에 대한 래퍼를 구현합니다. 예를 들어, AnswerWrapper는 Answer를 구현하고, Answer 타입의 래핑 된 객체를 보유하고, setter를 제외한 모든 메소드를이 객체의 적절한 메소드에 위임하고 각 setter에서 예외를 throw합니다.

2.2.2. 동적 프록시 기술을 사용하십시오. 여전히 인터페이스가 필요하지만 모든 클래스에 대해 모든 setter를 구현할 필요는 없습니다. 이 솔루션은 측면과 유사합니다.

2.3. 측면을 사용하십시오. 예를 들어 AspectJ. 이 목록의 인덱스를 알 수 있도록

0

클라이언트 코드 목록을 가지고, 그것은 업데이트 할 일을 알려왔다 :

"사용자가"
public void updateAnswer(int index, Answer newAnswer) { 
    answers.set(index, answer); 
} 

// ... 

Answer answerThatWillBeUpdated = question.getAnswers().get(0); 
String updatedAnswerDescription = "Hey, it is now updated!"; 
answerThatWillBeUpdated.setDescription(updatedAnswerDescription); 
question.updateAnswer(0,answerThatWillBeUpdated); 
관련 문제