Webサイトのパスワードリセット機能を作成しています。パスワードリセットの最初のステップを実装する必要があります。
- ユーザーは自分のメールアドレスをパスワードリセットフォームに入力します。
- 電子メールを持つユーザーが登録されているかどうかをシステムがチェックします。
- ユーザーが見つかった場合、システムはパスワードリセットURLとuniqeトークンを含む電子メールを送信します。
- ユーザーが見つからない場合、システムはこの電子メールに対してパスワードのリセットが開始されたことを通知する電子メールを送信しますが、ユーザーアカウントは存在しません。
publicメソッド--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はそれらのコマンドの1つである可能性があります。ただし、RequestPasswordResetメソッド内のステップに関する主な問題は解決されません。
また、Chain of Responsibilityパターンも調べていました。ステップを順番に処理するのがよいのですが、制御フローを処理するためにどのように使用できるのかわかりません。さまざまな条件を実装する必要があります。また、各ハンドラーが同様のアクションを実行する必要があるように見え、制御フロー全体がどのように変化するかは明確ではありません。
そのような手続き型コードをリファクタリングするための最良のアプローチは何でしょうか?