好的,我想要一些意见,我可以解决这个方法的混乱!
它与许多嵌套的'if'语句有关。
但是我意识到我必须确切地知道方法失败的地方,目前在每个相应的'else'子句中我记录错误(失败的'if'条件')。
注意:忽略事物背后的任何逻辑,请关注样式和结构,因为我已经创建了所有的函数名称等。
这是骨架结构:
public void MyMethod()
{
try
{
bool tryAgain = false;
string filename = DownloadFile();
if( IsFileFormatOk(filename) )
{
blah = GetBlah(filename);
if(blah.ID > 0)
{
if(ImportFile(filename)
{
string username = GetUserFromFile(filename);
if(isValidUser(username))
{
// few more levels to go
//
//
//
}
else
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
}
}
else
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
}
}
else
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
}
}
else
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
}
}
catch
{
}
finally
{
if(tryAgain)
{
// blah
}
}
}
答案 0 :(得分:5)
我会努力改变你的逻辑,这样你就可以尽快从方法中返回,而不是嵌套更多的逻辑。例如:
// GOOD
if (!file.exists())
return;
// Rest of the code
// BAD
if (file.exists()){
// Code goes here
}
return;
这可能有助于删除一些嵌套并使事情变得不那么复杂。
答案 1 :(得分:3)
我猜有很多逻辑等待在其他地方提取,但无论如何这是另一种平铺嵌套的方法:
try
{
if( !IsFileFormatOk(filename) )
throw new MySpecificException(...); // pass specific log params
blah = GetBlah(filename);
if(blah.ID <= 0)
throw new MySpecificException(...); // pass specific log params
if(!ImportFile(filename)
throw new MySpecificException(...); // pass specific log params
string username = GetUserFromFile(filename);
// ...
}
catch (MySecificException e)
{
LogError(filename, e.LogParams)
// blah
}
答案 2 :(得分:1)
您可以先将toplevel if(true branch)放在一个单独的方法中。并继续直到满意为止。
所以一般来说你改变了:
if (condition) {
// Block1
} else {
// Block2
}
向
if (condition) {
Block(...);
} else {
Block2(...);
}
请注意需要传递给新方法的局部变量。
答案 3 :(得分:0)
编辑:现在我知道有这么多级别,我们需要采取另一种方法。我不知道“再试一次”中的内容,但你需要改变逻辑,以便测试失败案例,而不是成功案例。如果它失败了,记录并返回(或以某种方式再做一次尝试)。否则,你可以继续走if if。
if(EndOfWorld)
{
WriteLastLogEntryEver();
return; //run away
}
//we're safe (for now)
ChargeOnAhead();
在我知道嵌套的级别之前,我建议如下。
public void MyMethod()
{
try
{
bool tryAgain = false;
string filename = DownloadFile();
if( IsFileFormatOk(filename) )
{
tryAgain = DoBlah(filename, ...);
}
else
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
}
}
catch
{
}
finally
{
if(tryAgain)
{
// blah
}
}
}
private bool DoImport(string filename, blah)
{
if(ImportFile(filename))
{
// and so forth!
return false;
}
LogError(filename, ...); // specific to this if statement
return true;
}
private bool DoBlah(string filename)
{
blah = GetBlah(filename);
if(blah.ID > 0)
{
return DoImport(filename, ...);
}
LogError(filename, ...); // specific to this if statement
return true;
}
我确信你可以再重构一次,并将// and so forth
拉入新方法。这取决于你要来回传递多少东西。如果你传递的太多,请考虑成为参数或类字段是否更有意义。
答案 4 :(得分:0)
如果出现错误,您应该尝试让所有正在调用的方法抛出异常。抛出的异常应包含您要记录的任何错误消息。创建一个LogError()方法,该方法接受任何异常并记录嵌入的消息。像这样(伪代码):
MyMethod()
{
try
{
string filename = DownloadFile()
blah = GetBlah(filename)
ImportFile(filename)
...
}
catch DownloadFileException, GetBlahException, ImportFileException e
{
LogError(e)
}
}
当然,您必须创建所有这些例外,但这非常简单。在大多数语言中,您只需子类化顶级异常对象。
答案 5 :(得分:0)
这是jjnguy的建议,已实施:
public void MyMethod() {
try
{
bool tryAgain = false;
string filename = DownloadFile();
if( !IsFileFormatOk(filename) )
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
return;
}
blah = GetBlah(filename);
if(blah.ID <= 0)
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
return;
}
if(!ImportFile(filename))
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
return;
}
string username = GetUserFromFile(filename);
if(!isValidUser(username))
{
LogError(filename, ...); // specific to this if statement
tryAgain = true;
return
}
// few more levels to go
//
finally
{
if(tryAgain)
{
// blah
}
}
}
答案 6 :(得分:0)
对于这类问题,http://refactormycode.com/非常有用。
虽然SO人员真的致力于重构一些代码。 ;)