2012-08-16 3 views
4

웹 사이트의 비밀번호 재설정 기능을 만들고 있습니다. 비밀번호 재설정을위한 첫 번째 단계는 구현되어야합니다.절차 코드를 리팩토링하는 방법은 무엇입니까?

  1. 사용자가 비밀번호 재설정 양식으로 이메일을 입력합니다.
  2. 이메일이있는 사용자가 등록되어 있는지 시스템에서 확인합니다.
  3. 사용자가 발견되면 시스템은 uniqe 토큰과 함께 비밀번호 재설정 URL이 포함 된 이메일을 전송합니다.
  4. 사용자를 찾을 수없는 경우 시스템은이 전자 메일에 대해 암호 재설정이 시작되었음을 알리는 전자 메일을 보내지 만 사용자 계정은 존재하지 않습니다.

나는 공공 메소드를 구현하는 서비스 클래스가 - RequestPasswordReset 및이 방법은 매우 절차입니다 :

public void RequestPasswordReset(string email) 
{ 
    if(!IsValidEmail(email)) 
    { 
     throw new ArgumentException("email"); 
    } 

    var user = this.repository.FindByEmail(email); 
    if(user != null) 
    { 
     user.PasswordResetToken.Set(this.tokenGenerator.NewToken()); 
     this.emailService.Send(this.from, 
           user.Email, 
           "Password reset", 
           "Your reset url: http://mysite.com/?t=" + 
            user.PasswordResetToken.Value); 
    } 
    else 
    { 
    this.emailService.Send(this.from, 
         user.Email, 
         "Requested password reset", 
         "Someone requested password reset at http://mysite.com"); 
    } 
} 

이 방법은 원리 싱글 책임을 위반 - 그것은, 사용자의 존재를 확인하여 사용자 토큰을 재설정 이메일을 보냅니다.

이러한 솔루션의 주된 문제는 추가 단계를 추가해야하는 경우 RequestPasswordReset 메서드 및 메서드에 대한 구현을 추가해야한다는 것이므로 점점 더 복잡해집니다. 추가 단계는 예를 들어 사용자가 이미 다른 관련 시스템에 등록되어 있는지 확인하고 시스템에 새 계정을 만들거나 사용자 계정을 만들도록 조언 할 수 있습니다.

커맨드 패턴을 보았습니다. 서비스 클래스를 별도의 명령으로 리팩토링하는 것이 좋을 수 있으며 RequestPasswordReset은 이러한 명령 중 하나 일 수 있습니다. 그러나 RequestPasswordReset 메서드 내부의 주요 문제는 해결되지 않습니다.

또한 Chain of Responsibility 패턴을 보았습니다. 순서대로 단계를 처리하는 것이 좋지만 제어 흐름을 처리하는 데 사용할 수있는 방법이 다른지 - 구현해야하는 여러 조건을 모릅니다. 또한 각 처리기가 유사한 동작을 수행해야하며 전체 제어 흐름이 어떻게 변경되는지는 명확하지 않은 것으로 보입니다.

이러한 절차 코드를 리팩터링하는 것이 가장 좋은 방법은 무엇입니까?

+1

패턴에 대한 접근 방식은 거의 거꾸로 보입니다. 패턴을 조사하여 문제에 대한 해결책을 찾으십시오. 시도하고 솔루션을 (심하게?) 그들이 거기에 있기 때문에 패턴에 맞게하지 마십시오. 리팩토링은 코드가 작성된 방식에 문제가있을 때 필요합니다. 일부 답변에서 알 수 있듯이 사용자의 접근 방식에는 문제가없는 것 같습니다. –

+0

예제는 간단합니다. 그러나 외부 시스템에서 사용자를 검색하고 추가 된 사용자가 있으면 새로 생성 된 사용자의 비밀번호를 재설정하도록 이메일을 보내야합니다. 달성하기 위해 더 많은 단계가 필요한 경우 어떻게해야합니까? – marisks

+0

필요시 리 팩터. 그리고 전에. –

답변

2

나는 코드가 그대로 있다고 생각합니다. 리팩터링을 절대적으로 원한다면 main 메소드의 가독성을 단순화하기 위해 코드를 조금 더 나눌 수 있습니다. 이 같은 : 그대로보다

public void RequestPasswordReset(string email) 
{ 
    ValidateEmail(email); // May throw exception if invalid 

    var user = this.repository.FindByEmail(email); 
    if(user != null) 
    { 
     GenerateTokenAndSendPasswordResetEmail(user); 
    } 
    else 
    { 
     SendPasswordResetEmail(email); 
    } 
} 

다른, 나는 그것을 떠날 것이다. 문제는 실제로 매우 간단하므로 복잡한 솔루션을 찾을 이유가 없습니다! :)

+0

고마워, 나는 이런 걸했다. 예제는 실제 코드에서 단순화 된 버전이므로 다른 리팩터 액션도 수행했습니다. – marisks

6

이 방법은 단일 책임 원칙을 실제로 나는 그것을하지 생각하지 않는다

을 위반하는 것입니다. 서비스의 "단일 책임"은 사용자 암호를 재설정하는 것이며 다른 개체 (사용자 저장소 및 메일 서비스)와의 조정을 통해이 작업을 수행합니다. 암호 재설정 프로세스가 변경되면이 클래스가 변경되고 그에 대한 잘못된 것은 없습니다.

+0

+1 로버트 C 마틴 (Robert C Martin)은 책임을 '변화해야 할 이유'라고 정의합니다. 클래스를 볼 수있는 한, 관련된 몇 가지 작업을 수행하는 동안 여전히 변경해야 할 한 가지 이유가 있습니다. – MattDavey

2

이 코드와 함께하는 가장 좋은 방법은 철저한 테스트를 거치는 것입니다. 모든 코드 경로가 테스트되었는지 확인하십시오.

그런 다음 이 (가)!

모든 코드가 디자인 패턴, 단일 책임 원칙 및 기타 이와 같은 것들을 준수해야한다는 아이디어를 얻으십시오. 그 패턴은 이며 작업 코드를 조사하여을 발견했습니다.

여기에 작업 코드가 있습니다. 그것을 극복하고 다음 작업을 시작하십시오.

+0

"철저히 테스트 된"코드는 반드시 잘 설계되거나 유지 보수하기가 쉽지 않습니다. 테스트가 코드 자체만큼 이해하기 어려운 경우를 보았습니다. 코드베이스의 유지 보수 가능성을 향상시키는 데 디자인에 약간의 아이디어를 넣으면됩니다. – casablanca

관련 문제