关于返回 Null 值的问题

fmms 12年前
     <p>本文是从 <a href="/misc/goto?guid=4958327203715500471" target="_blank">Returning Null</a> 这篇文章翻译而来。</p>    <hr />    <p>我总感觉一个方法返回null值有问题。当读了Misko Hevery关于<a href="/misc/goto?guid=4958327204539350003" target="_blank">how to think about OO</a>的博客文章后,又让我想起这个问题。</p>    <p>我感觉返回null值是有问题的,它大量的被使用在一个方法有不同的返回类型时。简单的用谷歌搜索一下“returning null”,你就会发现有建议把返回类型做成一个null对象。返回一个Null对象在某些情况下是合适的,但并不适合当你需要向客户端传送两种不同的东 西的情形。用Misko重构的一段代码来说明这个问题。他重构的是一段登录代码(我非常喜欢他的过程),这段代码大概是这个样子:</p>    <pre>  Cookie login(Ldap ldap) {      if ( ldap.auth(user, password) )        return new Cookie(user);      return null;    }</pre>    <p>从这段代码,可以看出两种情况(从结构上讲)</p>    <ol>     <li>如果认证通过,客户端会被通知验证成功,生成一个新的Cookie</li>     <li>如果认证失败,则通过返回的null值通知客户端</li>    </ol>    <p>客户端的方法应该是什么样的?</p>    <pre>  public void authenticateUser(User user) {       Cookie userCookie = user.login(ldap);       if (userCookie == null) {             //notify someone that auth failed       } eles {             //register them as logged in       }    }</pre>    <p>我们在两个地方做了相同的事情,只是在语法上有稍微的不同,每个地方,我们都要检查验证是否成功。如果我们使用<a href="/misc/goto?guid=4958327205344872581" target="_blank">IoC(反向控制)</a>模式,或“Tell Don’t Ask”模式或“Hollywood原则”,会如何?</p>    <pre>  Cookie login(Ldap ldap, AuthenticationRegistry authenticationRegistry) {      if ( ldap.auth(user, password) )        authenticationRegistry.authSucceeded(new Cookie(user));      authenticationRegistry.authFailed(user);    }</pre>    <p>客户端:</p>    <pre>  public void authenticateUser(User user) {       user.login(ldap,this);    }      public void authSucceeded(Cookie cookie) {       //register them as logged in    }      public void authFailed(User user) {       //register them as auth failed    }</pre>    <p>新代码稍微有点复杂,但我感觉它很清晰,实现的更直接。现在我们的两个实体能够相互通信,我们定义了它们通信的方式。我喜欢Misko的重构,我只是更进了一步。好坏可以再讨论,但我想,如果你遇到了这种需要返回两种情况的方法时,IoC是你应该的选择。<br /> <br /> 本文转载自: 外刊IT评论 <a href="/misc/goto?guid=4958183272158702965" rel="nofollow" target="_blank">http://www.aqee.net/</a> </p>