2

最近、作成した既存のアプリケーションに新しい機能を追加する必要がありました。コードのこのセクションを見ると、リファクタリングと改善の時期が来ている可能性があることがわかりました。

オリジナルのインデックス方法:

  • IsUserEnrolled <-WCF呼び出し
    • 登録されていない場合
      • ユーザーが登録できる場合はルールを実行する <-WCFCall
        • ユーザーが有効でない場合は、アクセスなしにリダイレクトします
        • ユーザーが登録するためのリダイレクトを登録するのに有効な場合
    • ユーザーが登録されている場合
      • アイテムを取得<-WCFCall
      • インデックスページを表示

バックエンドWebサービスへの3つのwcf呼び出し

新しい追加で、私はいくつかの新しい情報、いくつかのユーザーオプションが必要でした。

  • IsUserEnrolled <-WCF呼び出し
    • 登録されていない場合
      • ユーザーが登録できる場合はルールを実行する<-WCFCall
        • ユーザーが有効でない場合は、アクセスなしにリダイレクトします
        • ユーザーが登録するためのリダイレクトを登録するのに有効な場合
    • ユーザーが登録されている場合
      • アイテムを取得<-WCFCall
      • ユーザーオプションを取得<-WCFCall
      • インデックスページを表示

この機能により、新しいWCF呼び出しが発生し、この1つのメソッドに4つの呼び出しがネットワーク上で行われるようになりました。より良い方法が必要です。

私の提案は、これを1つのwcf呼び出しにラップして、ユーザーに関するすべての情報、それらが登録されているか、アイテム、必要に応じてルールを実行するか、およびユーザーオプションを収集することでした。

  • ユーザー情報の取得(略して結果オブジェクト)<-WCF呼び出し
    • 結果がない場合。IsEnrolled
      • result.RulesResult.UserIsValidプロパティがfalseの場合
        • アクセスなしにリダイレクト
      • そのプロパティがtrueの場合
        • 登録にリダイレクト
    • 結果の場合。IsEnrolled
      • ViewModelにresult.UserOptionsとresult.Itemsを入力します

良い電話は1つだけですが、私の質問は

  • 結果として、1つのオブジェクトを持つことは意味がありますか?

  • IsEnrolledがtrueの場合、RulesResultはnullになりますが、この場合、nullプロパティを持つことは意味がありますか?後で検査される場合に備えて、ユーザーが登録されているという結果を提供するのではないでしょうか。

  • IsEnrolledがfalseの場合、RulesResultは入力されます(意味があります)が、アイテムはnullになります(意味があります)ユーザーオプションもnullになりますこの場合、アイテムとユーザーオプションの空のリストがあると、nullよりも意味がありますか?

  • API設計の観点から、2番目のオプションは意味がありますか、それとも結果はUIに密接に関連していますか?

両方のバージョンのコード例:
バージョン1:

public ActionResult Index()
{

    using (var client =ServiceFactory.CreateChannel())
    {
        var isMemberEnrolled = client.IsMemberEnrolled(User.Identity.Name);

        if (!isMemberEnrolled)
        {
            var accessResult = client.RunRules(User.Identity.Name);

            if (!accessResult.UserIsValid)
            {
                return RedirectToAction("NoAccess");
            }
            return RedirectToAction("Register");
        }

        var userOptions = client.GetUserOptions(User.Identity.Name);

        List<Item> items = client.GetUserItems(User.Identity.Name);

        var viewModel = new ViewModel(userOptions, items);

        return View(viewModel);
    }
}

バージョン2(リファクタリング):

public ActionResult Index()
{

    using (var client = ServiceFactory.CreateChannel())
    {
        var userInformation = client.GetUserInformation(User.Identity.Name);

        if (!userInformation.IsMemberEnrolled)
        {
            return RedirectToAction(!userInformation.RulesResult.UserIsValid ? "NoAccess" : "Register");
        }

        var viewModel = new ViewModel(userInformation.UserOptions, userInformation.Items);

        return View(viewModel);
    }
}
4

1 に答える 1

2

APIの効率については、オプション#2の方が確実にパフォーマンスが向上すると思います。

未使用のパラメーターをすべて1つの結果オブジェクトに含める限り、これは抽象結果クラスで簡単に解決でき、2つの異なる応答を2つの異なる具象サブタイプに分割できます。

  [KnownType( typeof( UserInfoEnrolledResult ) )]
  [KnownType( typeof( UserInfoNotEnrolledResult ) )]
  [DataContract]
  public abstract class UserInfoResult
  {
  }

  [DataContract]
  public class UserInfoEnrolledResult : UserInfoResult
  {
    [DataMember]
    public string UserOptions { get; set; }

    [DataMember]
    public string[] Items { get; set; }
  }

  [DataContract]
  class UserInfoNotEnrolledResult : UserInfoResult
  {
    [DataMember]
    public bool UserIsValid { get; set; }
  }

次に、クライアントコードは次のようになります...

  using ( var client = ServiceFactory.CreateChannel() )
  {
    var userInformation = client.GetUserInformation( User.Identity.Name );

    if ( userInformation is UserInfoNotEnrolledResult )
    {
      return RedirectToAction( ((UserInfoNotEnrolledResult)userInformation).UserIsValid ? "NoAccess" : "Register" );
    }

    var enrolledUserInformation = (UserInfoEnrolledResult)userInformation;

    var viewModel = new ViewModel( enrolledUserInformation.UserOptions, enrolledUserInformation.Items );

    return View( viewModel );
  }

これにより、2つの異なる応答が可能であることがクライアントに明確になり、どのパラメーターがどの種類の応答に使用または必要であるかが明確になります。

これは完璧に良い方法だと思います。多くの異なる種類の関数を作成していることに気付いたときに、ケースに出くわし始めた場合、それらはすべてほぼ同様の手順ですが、次のようなわずかな違いがあります...

UserInfoResult GetUserInformation( string name );
UserInfoResult GetUserInformationWithoutRuleCheck( string name );
UserInfoResult GetUserInformationWithDoubleSecretChecks( string name );

次に、これらの大きな関数を複数のWCF呼び出しに分割して、APIメソッドが急増しないようにすることをお勧めします。

于 2012-07-10T21:59:51.120 に答える