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运算符的方式:)我从来没有想过那样…谢谢!是的,我也从来没有想过那样使用特瑞操作系统。谢谢!