你会如何重构这样的东西?
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;
}
}
小心
答案 0 :(得分:3)
首先:
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;
}
}
请注意,有必要稍微改写一些消息。
答案 1 :(得分:3)
试试这个
首先创建一个用户信息对象
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;
}
答案 2 :(得分:2)
当两种方法相似时,我通常会采用两种方法。
在任何一种情况下,我通常会将它们更改为单个方法,并将彼此相似的行放在一起。
一个是拥有一个知道你所处方法的变量,并用它来确定要做什么。
如果(更新) //使用更新行 其他 //使用添加行
您还必须能够处理可能无法在一种状态下初始化变量的情况(例如更新设置userPK,但添加不使用它)
这是一个快速简便的重构器,可以轻松组合2种方法,如果您的代码相当干净,很难搞乱。
另一种方式更复杂,用于将这种“组合”方法变成可重用的东西。我经常先做前一个,然后在必要时再继续......
有两种方法可以让您的组合课程更具可重用性。一个是“传入”差异。传入实现不同代码行的对象。
第二个是使它成为“父”类,并在你孩子的方法中实现不同的行。因此,当父级点击它必须进行创建时,它只会调用create()方法。将在子类中重写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");
我知道这看起来很明显,但提取数据对于重构来说是一个巨大的帮助,如果你不知道接下来要做什么,这将是一个很好的开始......
答案 3 :(得分:2)
首先,摆脱这些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,这个视图只有代码来获取控件中的用户信息(在其他地方定义了一个类)并将事件转发给演示者。
答案 4 :(得分:2)
我将在这里发表意见并建议这段代码并不特别需要重构。可能有空间使它更优雅,更简洁,或更强大,但因为它代表了死的简单和易于阅读。在这种情况下,我的直觉反应是,“如果它没有破裂,就不要修复它。”
编辑:所有说过的话,我至少推翻了其他三个答案。那里有一些很棒的想法。
编辑#2:看了之后,对我来说最明显的问题是重复以下代码:
string username = txtUsername.Text.Trim().ToLower();
string password = txtPassword.Text.Trim().ToLower();
string email = txtEmail.Text.Trim().ToLower();
string status = ddlStatus.SelectedValue.Trim();
这里真正的问题是,如果UI更改为添加,删除或重命名其中一个字段,则需要在两个位置更改此支持代码。如同其他几个答案所暗示的那样,在支持班级中发生这种情况要好得多。
答案 5 :(得分:1)
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);
}
然后将Save参数处理放在Factory中 (或在某处的另一种方法
.. 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.
}
}
}
答案 6 :(得分:0)
在方法中封装变量赋值以便重用
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();
}
答案 7 :(得分:0)
此外,您还会获取用户/密码/电子邮件/状态两次。我将这四个至少封装到一个具有单个Get方法或属性的类中。如果它们在表单上,我将它们封装在用户控件中,将各个值公开为用户控件的属性。
不重构,但仍然:
我摆脱了try / catch块。您向用户显示的消息不是他们想要看到的,也不能做任何事情。最好让它传播并由ASP.NET记录。使用自定义错误页面为用户提供更漂亮的内容,例如“抱歉,我们蠢蠢欲动”。