Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 您将如何重构它以使其更好?_C#_Asp.net_Refactoring - Fatal编程技术网

C# 您将如何重构它以使其更好?

C# 您将如何重构它以使其更好?,c#,asp.net,refactoring,C#,Asp.net,Refactoring,您将如何重构这样的东西 protected void btnAdd_Click(object sender, EventArgs e) { try { string username = txtUsername.Text.Trim().ToLower(); string password = txtPassword.Text.Trim().ToLower(); string email = txtEmail.Text.Trim().

您将如何重构这样的东西

protected void btnAdd_Click(object sender, EventArgs e)
{
    try
    {
        string username = txtUsername.Text.Trim().ToLower();
        string password = txtPassword.Text.Trim().ToLower();
        string email = txtEmail.Text.Trim().ToLower();
        string status = ddlStatus.SelectedValue.Trim();

        IUser user = UserFactory.getInstance().createUser(username, password, email,status);

        if (user.save())
        {
            jsMsgBox("Successfully added new user");
            Response.Redirect(ConfigurationManager.AppSettings["AdminLink"], true);
        }
        else
        {
            jsMsgBox("An error was encountered while trying to add a new user.");
        }
    }
    catch (Exception ex)
    {
        jsMsgBox("An Error was encountered while trying to add a new user.");
        lblInfo.Text = ex.Message;
        lblInfo.Visible = true;
    }
}

protected void btnUpdate_Click(object sender, EventArgs e)
{
    try
    {
        string username = txtUsername.Text.Trim().ToLower();
        string password = txtPassword.Text.Trim().ToLower();
        string email = txtEmail.Text.Trim().ToLower();
        int userPK = Int32.Parse(txtUserPK.Text.ToString());
        string status = ddlStatus.SelectedValue.Trim();

        IUser user = UserFactory.getInstance().createUser(userPK, username, password, email,status);

        if (user.save())
        {
            jsMsgBox("Successfully updated selected users information.");
            Response.Redirect(ConfigurationManager.AppSettings["AdminLink"], true);
        }
        else
        {
            jsMsgBox("An error was encountered while trying to update the selected users information.");
        }
    }
    catch (Exception ex)
    {
        jsMsgBox("An Error was encountered while trying to update the selected users information.");
        lblInfo.Text = ex.Message;
        lblInfo.Visible = true;
    }
}

小心

将变量的分配封装在方法中,以便重用

private IUser GetUser()
{

    string username = FormatText(txtUsername.Text)
    string password = FormatText(txtPassword.Text);
    string email = FormatText(txtEmail.Text);       
    string status = ddlStatus.SelectedValue.Trim();
    if(txtUserPK.Text!=string.empty){
        int userPK = Int32.Parse(txtUserPK.Text);
        IUser user = UserFactory.getInstance().
                         createUser(userPK, username, password, email, status);
    }
    else
    {
        IUser user = UserFactory.getInstance().
                         createUser(username, password, email, status);
    }
    return user;
}

private string FormatText(string input)
{
    return input.Trim().ToLower();
}
首先:

protected string cleaned(string raw) {
    raw.Text.Trim().ToLower()
    }
protected void attempt_to_save(IUser user, string task) {
    if (user.save()) {
        jsMsgBox("Successfully finished "+task);
        Response.Redirect(ConfigurationManager.AppSettings["AdminLink"], true);
      } else {
        jsMsgBox("An error was encountered while "+task);
        }
    }

protected void btnAdd_Click(object sender, EventArgs e)
{
    try
    {
        IUser user = UserFactory.getInstance().createUser(
            cleaned(txtUsername), 
            cleaned(txtPassword), 
            cleaned(txtEmail),
            ddlStatus.SelectedValue.Trim()
            );

        attempt_to_save(user,"adding a new user.");
    }
    catch (Exception ex)
    {
        jsMsgBox("An Error was encountered while trying to add a new user.");
        lblInfo.Text = ex.Message;
        lblInfo.Visible = true;
    }
}

protected void btnUpdate_Click(object sender, EventArgs e)
{
    try
    {

        IUser user = UserFactory.getInstance().createUser(
            Int32.Parse(txtUserPK.Text.ToString()), 
            cleaned(txtUsername), 
            cleaned(txtPassword), 
            cleaned(txtEmail),
            ddlStatus.SelectedValue.Trim()
            );

        attempt_to_save(user,"updating the selected users information.");
        }
    }
    catch (Exception ex)
    {
        jsMsgBox("An Error was encountered while trying to update the selected users information.");
        lblInfo.Text = ex.Message;
        lblInfo.Visible = true;
    }
}
注意,有必要稍微改写一些消息

protected void btnAdd_Click(object sender, EventArgs e) { SaveUser();}
protected void btnUpdate_Click(object sender, EventArgs e) { SaveUser();}
private void SaveUser()
{
      int? userId = string.IsNullOrEmpty(txtUserPK.Text)? null:
                   Int32.Parse(txtUserPK.Text.ToString());
      UserFactory.Save(userId , txtUsername.Text, txtPassword.Text, 
                      txtEmail.Text, ddlStatus.SelectedValue);  
      jsMsgBox("Successfully added new user");            
      Response.Redirect(
          ConfigurationManager.AppSettings["AdminLink"], true);         
}
然后将保存参数处理放在工厂中 (或者用另一种方法)

.. In UserFactory...
 Save(int? userId, string userName, string password, 
         string eMail, string selvalue)
 {
     // code to process input parameters and save/update user
     userName = userName.Trim().ToLower();
     password = password.Trim().ToLower();
     eMail    = eMail.Trim().ToLower();
     selvalue = selvalue.Trim().ToLower();
     IUser user = userId.HasValue?
                    UserFactory.getInstance().createUser(
                            userId.Value, username, password, 
                            email,status):
                    UserFactory.getInstance().createUser(
                            username, password, 
                            email, status);
     try { user.Save(); }
     catch(DBException dbX)  //   catch/rethrow Database exception 
                             //   as custom expcetion here
     {
         throw new MyCustomAppException(
                 "Save User failed: + dbX.Message",
                 dbX);
     }  
 }
并将异常处理放在web窗体的主入口点

public partial class MyWebPage:  System.Web.UI.Page     
{
    static void Page_Load(object sender, EventArgs e)         
    {
         try 
         {
             // asp.Net Page Load code here ...
         }
         catch(MyMainCustomApplicationException X)
         {
             jsMsgBox("An Error was encountered: " + X.Message);  
             lblInfo.Text = X.Message;        
             lblInfo.Visible = true;
         }
         catch(Exception eX) 
         {  
              // Maybe Log it here...
              throw;   // Important to retrhow all unexpected exceptions to
                       // MAKE web page crash !! as you have no idea
                       // whether web app is in consistent state now.
         }
    }
}

此外,还可以获取用户/密码/电子邮件/状态两次。我会用一个Get方法或属性将这四个值封装到一个类中。如果它们在表单上一起,我会将它们封装在用户控件中,将各个值作为用户控件的属性公开

不是重构,但仍然:


我将清除try/catch块。您向用户显示的消息不是他们想要看到的,也不是他们可以做的任何事情。最好让它传播并由ASP.NET记录。使用自定义错误页为用户提供更漂亮的外观,例如“抱歉,我们搞错了”当两种方法如此相似时,我通常会采用两种方法

在这两种情况下,我通常将它们更改为单个方法,并将相似的行放在彼此旁边

一个是有一个变量,它知道您使用的是哪种方法,并使用它来确定要执行的操作

如果(更新) //使用更新行 其他的 //使用添加行

您还必须能够处理可能无法在一种状态下初始化变量的情况(如update设置userPK,但add不使用它)

这是一个快速而简单的重构,可以轻松地组合两种方法,如果代码相当干净,就很难搞乱

另一种方法更复杂,用于使这种“组合”方法成为可重用的方法。我通常先做上一种方法,然后在必要时继续进行此操作

有两种方法可以使组合类更具可重用性。一种是“传入”差异。传入一个实现不同代码行的对象

第二种方法是将其设置为“Parent”类,并在子类的方法中实现不同的行。因此,当父类到达必须执行创建的点时,它将只调用create()方法方法将在子类中被重写以运行一个或另一个方法。对于每个代码差异,您可能会委托这样的方法

哦,如果只有“数据”不同,那么说你的“组合”方法如下所示:

if(user==0)
    System.out.println("Bill was here");
else if(user==1)
    System.out.println("Bob was here");
System.out.println(users[user]+" was here");
我通常通过创建一个索引数组或枚举来解决这个问题,使其最终看起来像这样:

if(user==0)
    System.out.println("Bill was here");
else if(user==1)
    System.out.println("Bob was here");
System.out.println(users[user]+" was here");
我知道这看起来很明显,但提取数据对重构有很大帮助,如果你不知道下一步该做什么,这将是一个很好的开始…

试试这个

首先创建一个用户信息对象

 class UserInfo
{
    public string username {get;set;}
    public string password {get;set;}
    public string email {get;set;}
    public string status {get;set;}
}
然后像这样重构代码

protected void btnAdd_Click(object sender, EventArgs e)
{
    UserInfo myUser = GetUserInfo();
    try
    {
        IUser user = UserFactory.getInstance().createUser(myUser);

        if (user.save())
        {
            jsMsgBox("Successfully added new user");
            Response.Redirect(ConfigurationManager.AppSettings["AdminLink"], true);
        }
        else
        {
            jsMsgBox("An error was encountered while trying to add a new user.");
        }
    }
    catch (Exception ex)
    {
        jsMsgBox("An Error was encountered while trying to add a new user.");
        lblInfo.Text = ex.Message;
        lblInfo.Visible = true;
    }
}

protected void btnUpdate_Click(object sender, EventArgs e)
{
    UserInfo myUser = GetUserInfo();
    int userPK = Int32.Parse(txtUserPK.Text.ToString());

    try
    {       
        IUser user = UserFactory.getInstance().createUser(userPK,myUser);

        if (user.save())
        {
            jsMsgBox("Successfully updated selected users information.");
            Response.Redirect(ConfigurationManager.AppSettings["AdminLink"], true);
        }
        else
        {
            jsMsgBox("An error was encountered while trying to update the selected users information.");
        }
    }
    catch (Exception ex)
    {
        jsMsgBox("An Error was encountered while trying to update the selected users information.");
        lblInfo.Text = ex.Message;
        lblInfo.Visible = true;
    }
}

private UserInfo GetUserInfo()
{
    UserInfo myUser = new UserInfo();

    UserInfo.username = txtUsername.Text.Trim().ToLower();
    UserInfo.password = txtPassword.Text.Trim().ToLower();
    UserInfo.email = txtEmail.Text.Trim().ToLower();
    UserInfo.status = ddlStatus.SelectedValue.Trim();

    return myUser;
}

首先,摆脱这些try/catch,使用友好的错误页配置asp.net,并记录所有未处理的异常

在处理程序上,您希望它们非常清楚地了解正在发生的事情。我发现此版本对于该场景非常清楚:

protected void btnAdd_Click(object sender, EventArgs e)
{
    bool isInsert = true;
    bool saved = SaveUserFromControlInfo(isInsert);
    ShowJsMessageBox(
        saved, 
        "Successfully added new user", 
        "An error was encountered while trying to add a new user."
        );
    if(saved) RedirectToAdmin();
}
protected void btnUpdate_Click(object sender, EventArgs e)
{
    bool isInsert = false;
    bool saved = SaveUserFromControlInfo(isInsert);
    ShowJsMessageBox(
        saved,
        "Successfully updated selected users information.",
        "An error was encountered while trying to update the selected users information."
        );
    if (saved) RedirectToAdmin();
}
支持方法将是:

void RedirectToAdmin()
{
    Response.Redirect(ConfigurationManager.AppSettings["AdminLink"], true);
}
void ShowJsMessageBox(bool success, string succesMessage, string failedMessage)
{
    jsMsgBox(success ? succesMessage : failedMessage);
}
void SaveUserFromControlInfo(bool isInsert)
{
    string username = txtUsername.Text.Trim().ToLower();
    string password = txtPassword.Text.Trim().ToLower();
    string email = txtEmail.Text.Trim().ToLower();
    string status = ddlStatus.SelectedValue.Trim();
    var userFactory = UserFactory.getInstance();
    IUser user;
    if( isInsert )
        user = userFactory.createUser(username, password, email, status);
    else
    {
        int userPK = Int32.Parse(txtUserPK.Text);
        user = userFactory.createUser(userPK, username, password, email, status);
    }
    return user.save();
}
我会将SaveUserFromControlInfo洗牌一点。我更希望有一个与CreateUser请求关联的类,它包含一个可选的userPK


另外,我通常不会这样做,因为我使用MVP,并且这个视图只有代码来获取控件中的用户信息(在别处定义了一个类)并将事件转发给演示者。

我将在这里冒险指出,这段代码并不特别需要重构。可能会有空间使其更优雅、更简洁或更健壮,但就目前情况而言,代码非常简单且易于阅读。在这种情况下,我的直觉反应是,“如果它没有坏,就不要修理它。”

编辑:说到这里,我至少对其他三个答案投了赞成票。这里有一些很棒的想法

编辑#2:再看一眼,我发现最明显的问题是以下代码的重复:

    string username = txtUsername.Text.Trim().ToLower();
    string password = txtPassword.Text.Trim().ToLower();
    string email = txtEmail.Text.Trim().ToLower();
    string status = ddlStatus.SelectedValue.Trim();

这里真正的问题是,如果用户界面更改为添加、删除或重命名其中一个字段,则此支持代码需要在两个位置进行更改。正如其他几个答案所建议的,最好在支持类中进行更改。

为什么不先尝试一下。请访问refactormycode.com;这可能是一个更好的选择请回答这个问题。我会在userPK赋值上设置一个条件,并使用一个可为null的int来确定要调用哪个createUser方法。@Charles您仍然在其中运行感谢!这就是为什么我喜欢stackoverflow!我非常喜欢您使用Terenery运算符的方式:)我从来没有想过那样…谢谢!是的,我也从来没有想过那样使用特瑞操作系统。谢谢!