减少代码嵌套

fmms 13年前
     <p data-mce-="">        <strong>原文链接:</strong><a href="/misc/goto?guid=4958324673565438295" target="_blank">Reducing Code Nesting</a></p>    <p data-mce-="">        “这家伙的代码太差劲了!”当我们遇到我们不喜欢的代码时常常这么说或是这么想。有时候时因为代码有很多 bug,有时候是因为不喜欢它的代码风格,而有时候仅仅只是因为感觉不舒服。最近我仔细想了想,然后突然意识到或许是因为开发者是个新手。这些代码有个明显不招人喜欢的地方:太多的嵌套。当我思考的越多,我越来越意识到,这不是那些我们以前经常讨论的事情。</p>    <p data-mce-="">        那现在让我们讨论讨论这个吧。我首先想说的是什么叫代码嵌套,为什么会影响代码的质量。然后我将用这些年学的一些技巧来减少嵌套。</p>    <p data-mce-="">        <strong>什么是代码嵌套,为什么嵌套是不好的?</strong></p>    <p data-mce-="">        演示比空口而谈更为容易。很抱歉用下面这个不自然的例子来解释什么是深层的代码嵌套。</p>    <p style="text-align:center;"><img style="width:595px;height:237px;" alt="减少代码嵌套" src="https://simg.open-open.com/show/9684c0b0e75cc334419bbf4271b64a46.png" /></p>    <p data-mce-="">        你仅仅从每行的缩进中就可以看到这段巨大的代码有多少嵌套。在我们最终判断“用户不能被找到”前,我们必须穿过 4 个条件语句,而且每个条件句都嵌套在先决条件句中。</p>    <p data-mce-="">        我觉得这是一段糟糕的代码。每个额外嵌套的内容大脑都必须另外记录。每一个嵌套的块你都得关注它是和哪个条件句关联的(即使你的编辑器能帮助你,但是却不能彻底的解决这个问题)。这仅仅是一个最后返回 user 的简单直观的例子,让我们看一个复杂点的例子:</p>    <p style="text-align:center;"><img style="width:589px;height:380px;" alt="减少代码嵌套" src="https://simg.open-open.com/show/6f2db1bdf441c9452b1c2f02646e755d.jpg" /></p>    <p data-mce-="">        对我来说,即使只是写这个例子都显得非常的难。这很明显不自然或者别的什么,但是关键是弄懂它在实现什么都很难。不像之前的例子,这个不是简单的嵌套然后返回;它嵌套然后不嵌套,然后又嵌套,最后返回结果。</p>    <p data-mce-="">        <strong>怎么避免代码嵌套</strong></p>    <p>        我发现最好的避免代码嵌套的方法就是尽早返回结果。缓存对这来说是一个很好的例子。与其测试缓存是否失败然后在条件句中再从数据库获取信息,不如判断缓存是否成功然后尽早的返回结果。</p>    <p data-mce-="">        代码如下:</p>    <p style="text-align:center;"><img style="width:587px;height:130px;" alt="减少代码嵌套" src="https://simg.open-open.com/show/d2c302dbec3876b296ccd04ed49c13c2.jpg" /></p>    <p>        在这个简单的例子中,好像没有改进多少,但是如果将这个技巧运用到第一个例子中会发生什么?它将显著的得到改进:</p>    <p style="text-align:center;"><img style="width:573px;height:135px;" alt="减少代码嵌套" src="https://simg.open-open.com/show/23c19b3a1aa6c7b115784af4fa73c55a.jpg" /></p>    <p>        这不仅使代码阅读起来简单,使我们少关注一些上下文的联系,让代码编辑器少做些自动换行的工作,而且使代码容易分块并更容易进行注释。</p>    <p data-mce-="">        那我们还能使用哪些别的技巧来避免代码嵌套呢?这更多的取决于具体情况。你写一大堆回调函数的时候是不是也容易嵌套?如果是,你通常可以重构你的代码,多用命名函数而不是匿名函数。下面是重构前的效果:</p>    <p data-mce-=""><img style="width:575px;display:block;height:190px;margin-left:auto;margin-right:auto;" alt="减少代码嵌套" src="https://simg.open-open.com/show/0645c4bf72d9dfadcc546262f8b3f5ac.jpg" /></p>    <p data-mce-="">        在第一个回调函数中,我们运用了早点返回结果的技巧,但是就如你看到的一样还是有很多嵌套。现在如果我们转为使用命名函数会怎样呢? </p>    <p style="text-align:center;"><img style="width:576px;height:377px;" alt="减少代码嵌套" src="https://simg.open-open.com/show/4b08b95045df73975b132972b6107a2b.jpg" /></p>    <p data-mce-="">        这在嵌套方面得到了明显改善。不幸的是我们得写一个名为 curry 的辅助函数,但这仅仅只用写一次然后能被所有写在同一类型的代码所复用。同样不幸的是我仍然觉得这种代码很难阅读,这就是我避免写过多的回调类型函数的原因。不管怎样,最起码你能减少嵌套了。老实说,可能有更好的我没想到的减少嵌套的方法。如果你能用 JS 以一种更好的方式重写 getCachedUser 函数,请发博客!</p>    <p data-mce-="">        减少代码嵌套的另外一种方法就是非配一个中间变量。下面这个例子里是 Erlang 语言的一些对文件进行操作的函数,一个 case 语句嵌套在另一个 case 语句中。</p>    <p data-mce-="">        我们可以分配一个名为“Resp”的中间变量,然后把第二 case 语句代入到函数的主代码中,像这样:</p>    <p data-mce-=""><img style="width:560px;display:block;height:234px;margin-left:auto;margin-right:auto;" alt="减少代码嵌套" src="https://simg.open-open.com/show/9371875b167922a5ff6cedf4a8d14a4f.jpg" />        <strong>这是什么意思呢?</strong></p>    <p data-mce-="">        最后,不是说懂得这些就能造就或是毁灭一个程序员。事实上,我并没有要改变代码的逻辑,只是简化它的实现方式。这只是你在写代码或者看别人的代码的时候回想到的一些简单的事。真心希望你能和我一样觉得减少嵌套是一个极好的目标,并希望你能找到越来越多的方法去实现它。</p>