遇见问题
什么是嵌套的流程判断?嵌套又会带来什么问题?举例一个实际的例子来说:「验证用户输入的信息」。 要达成这个目的就必须对输入检查,例如:检查信息是否为空、检查信息是否符合规范、检查任何可能的错误情境……等。
function signupUser(username, password, passwordConfirmation) { if (username === '') { return '用户名是必填的'; } else { if (password === '') { return '密码是必填的'; } else { if (password !== passwordConfirmation) { return '密码确认不符'; } else { return '执行注册'; } } }}
目前问题在于,它的嵌套层级太深了,这样的代码会让人很难阅读,而且也很难维护与更动! 让我们试试看使用 Guard Clauses (守卫判断)来改写这段程序:
function signupUser(username, password, passwordConfirmation) { if (username === '') { return '用户名是必填的'; }
if (password === '') { return '密码是必填的'; }
if (password !== passwordConfirmation) { return '密码确认不符'; }
return '执行注册';}
只要改动思考判断的模式(尽早返回,终止整个函数),就可以达到更好的可读性,也可以减少嵌套的层级。
总结
如果你需要大于 3 层的嵌套,说明你已经搞砸了,应考虑重构代码。
会出现这么多嵌套的原因是因为我们的思考模式是“先检查错误,再执行正常的流程”,但这样会让代码变得很难阅读,因此我们可以改变思考模式,先返回掉反面的条件,这就是 Guard Clauses 的概念。最后总结两种终结嵌套的方式:
反转
提早返回异常的状态可以让我们更加专注在 Happy Path (无异常流程)上,并且能随着需求的增加轻易地改动与理解逻辑。
封装
如果程序真的太复杂,应考虑抽离片段出来独立成一个单一功能的函数,这样可以让代码更加清晰且专一。
参考资料
- Why You Shouldn’t Nest Your Code - Code Aesthetic
- Replace Nested Conditional with Guard Clauses - REFACTORING GURU
- Why I Don’t Use Else When Programming - Web Dev Simplified