重构嵌套的 if-else 以处理像日志记录这样的横切问题
refactoring nested if-else to handle cross cutting concerns like logging
在不使用太多嵌套 if 语句的情况下以更简洁的方式处理不断变化的需求是一个经典问题。
这是我在 javascript.
中的当前代码
fetchApiData(url){
//log before start
Logger.logFetchStartedEvent();
try {
data = backendApi.get(url);
Logger.logFetchSucceededEvent();
return data;
} catch (error) {
Logger.logFetchFailedEvent();
}
}
一切都走上了幸福的道路。但是我收到一个要求,对于某些特定的 URL,我们根本不想记录。
没问题。我添加了一个标志和开关并结束了它。
fetchApiData(url, shouldLog){
//log before start
if(shouldLog) {
Logger.logFetchStartedEvent();
}
try {
data = backendApi.get(url);
if(shouldLog) {
Logger.logFetchSucceededEvent();
}
return data;
} catch (error) {
if(shouldLog) {
Logger.logFetchFailedEvent();
}
}
}
它并没有就此停止。
新要求出现并要求更改以适应以下要求
- 一些 url 会记录所有内容
- 一些url将只记录错误
- 有些 url 仅当 API 调用 url 是外部站点时才会记录
- 在某些情况下需要记录 fetchSucceeded 事件,在某些情况下则不需要。
我想你明白了。
我可以添加无数嵌套 if/else 条件并完成它,但现在我确信必须有更好的方法来解决此类问题。现在感觉一个方法就变成了一个完整的if/else状态机神法
这是我想出来的
fetchApiData(url,logOnStart, logOnSuccess, logOnFailure, logOnlyExternalLink){
//log on start
if(logOnStart) {
if(logOnlyExternalLink) {
if(isExternalLink(url)) {
Logger.logFetchStartedEvent();
}
} else {
Logger.logFetchStartedEvent();
}
}
try {
data = backendApi.get(url);
//log on success
if(logOnSuccess) {
// may need external url check again
Logger.logFetchSucceededEvent();
}
return data;
} catch (error) {
if(logOnFailure) {
if(errorType(error) === TimeOut)
{
Logger.logFetchFailedTimeOutEvent();
} else if (errorType(error) === 404) {
Logger.logFetchFailed404Event();
} else {
Logger.logFetchFailedEvent();
}
}
}
}
我确实阅读了很多关于嵌套 if/else 问题的问题,但大多数问题最终都是 foo/bar 类型的示例和模糊的解释,由于缺乏经验,这对我来说没有实际意义.
请指出正确的方向。
你的函数应该是这样的:
fetchApiData(url, onEvent){
//log on start
onEvent(event.Start);
try {
data = backendApi.get(url);
//log on success
onEvent(event.Success, url);
return data;
} catch (error) {
onEvent(event.Failure, url, error);
}
}
编写onEvent回调是应该单独处理的事情。
此外,您可以将 class 实例 (eventHandler) 注入到您的函数中,而不是 onEvent 函数。
在不使用太多嵌套 if 语句的情况下以更简洁的方式处理不断变化的需求是一个经典问题。 这是我在 javascript.
中的当前代码fetchApiData(url){
//log before start
Logger.logFetchStartedEvent();
try {
data = backendApi.get(url);
Logger.logFetchSucceededEvent();
return data;
} catch (error) {
Logger.logFetchFailedEvent();
}
}
一切都走上了幸福的道路。但是我收到一个要求,对于某些特定的 URL,我们根本不想记录。
没问题。我添加了一个标志和开关并结束了它。
fetchApiData(url, shouldLog){
//log before start
if(shouldLog) {
Logger.logFetchStartedEvent();
}
try {
data = backendApi.get(url);
if(shouldLog) {
Logger.logFetchSucceededEvent();
}
return data;
} catch (error) {
if(shouldLog) {
Logger.logFetchFailedEvent();
}
}
}
它并没有就此停止。 新要求出现并要求更改以适应以下要求
- 一些 url 会记录所有内容
- 一些url将只记录错误
- 有些 url 仅当 API 调用 url 是外部站点时才会记录
- 在某些情况下需要记录 fetchSucceeded 事件,在某些情况下则不需要。
我想你明白了。 我可以添加无数嵌套 if/else 条件并完成它,但现在我确信必须有更好的方法来解决此类问题。现在感觉一个方法就变成了一个完整的if/else状态机神法
这是我想出来的
fetchApiData(url,logOnStart, logOnSuccess, logOnFailure, logOnlyExternalLink){
//log on start
if(logOnStart) {
if(logOnlyExternalLink) {
if(isExternalLink(url)) {
Logger.logFetchStartedEvent();
}
} else {
Logger.logFetchStartedEvent();
}
}
try {
data = backendApi.get(url);
//log on success
if(logOnSuccess) {
// may need external url check again
Logger.logFetchSucceededEvent();
}
return data;
} catch (error) {
if(logOnFailure) {
if(errorType(error) === TimeOut)
{
Logger.logFetchFailedTimeOutEvent();
} else if (errorType(error) === 404) {
Logger.logFetchFailed404Event();
} else {
Logger.logFetchFailedEvent();
}
}
}
}
我确实阅读了很多关于嵌套 if/else 问题的问题,但大多数问题最终都是 foo/bar 类型的示例和模糊的解释,由于缺乏经验,这对我来说没有实际意义.
请指出正确的方向。
你的函数应该是这样的:
fetchApiData(url, onEvent){
//log on start
onEvent(event.Start);
try {
data = backendApi.get(url);
//log on success
onEvent(event.Success, url);
return data;
} catch (error) {
onEvent(event.Failure, url, error);
}
}
编写onEvent回调是应该单独处理的事情。
此外,您可以将 class 实例 (eventHandler) 注入到您的函数中,而不是 onEvent 函数。