IT技术博客大学习 共学习 共进步

关于返回 Null 值的问题

外刊IT评论 2012-02-01 18:01:34 累计浏览 3,102 次
本机暂存
本文是从 Returning Null 这篇文章翻译而来。

    我总感觉一个方法返回null值有问题。当读了Misko Hevery关于how to think about OO的博客文章后,又让我想起这个问题。

    我感觉返回null值是有问题的,它大量的被使用在一个方法有不同的返回类型时。简单的用谷歌搜索一下“returning null”,你就会发现有建议把返回类型做成一个null对象。返回一个Null对象在某些情况下是合适的,但并不适合当你需要向客户端传送两种不同的东西的情形。用Misko重构的一段代码来说明这个问题。他重构的是一段登录代码(我非常喜欢他的过程),这段代码大概是这个样子:

  Cookie login(Ldap ldap) {
    if ( ldap.auth(user, password) )
      return new Cookie(user);
    return null;
  }

    从这段代码,可以看出两种情况(从结构上讲)

  • 如果认证通过,客户端会被通知验证成功,生成一个新的Cookie
  • 如果认证失败,则通过返回的null值通知客户端
  •     客户端的方法应该是什么样的?

      public void authenticateUser(User user) {
         Cookie userCookie = user.login(ldap);
         if (userCookie == null) {
               //notify someone that auth failed
         } eles {
               //register them as logged in
         }
      }

        我们在两个地方做了相同的事情,只是在语法上有稍微的不同,每个地方,我们都要检查验证是否成功。如果我们使用IoC(反向控制)模式,或“Tell Don’t Ask”模式或“Hollywood原则”,会如何?

      Cookie login(Ldap ldap, AuthenticationRegistry authenticationRegistry) {
        if ( ldap.auth(user, password) )
          authenticationRegistry.authSucceeded(new Cookie(user));
        authenticationRegistry.authFailed(user);
      }

        客户端:

      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
      }

        新代码稍微有点复杂,但我感觉它很清晰,实现的更直接。现在我们的两个实体能够相互通信,我们定义了它们通信的方式。我喜欢Misko的重构,我只是更进了一步。好坏可以再讨论,但我想,如果你遇到了这种需要返回两种情况的方法时,IoC是你应该的选择。

    同分类推荐文章

    1. Day for Night (2026-05-29 17:57:14)
    2. Your Prototype Is Not Being Honest With Your Users (And Here’s How To Fix It) (2026-05-25 20:00:00)
    3. Fixed-Height Cards: More Fragile Than They Look (2026-05-04 22:01:36)

    查看更多 设计 文章 →

    建议继续学习

    1. PHP的异常原理与实例说明 Fatal error: Uncaught exception (累计阅读 9,700)
    2. PHP业务逻辑层和数据访问层设计 (累计阅读 7,521)
    3. 面向对象的Shell脚本 (累计阅读 6,040)
    4. 抵制代码重写 (累计阅读 5,441)
    5. 设计模式原则总结 (累计阅读 5,121)
    6. struct与class区别联系 (累计阅读 4,881)
    7. 我对开源的看法 (累计阅读 4,860)
    8. PHP面向对象编程的三大特性 (累计阅读 4,600)
    9. 如何避免重构带来的危险 (累计阅读 4,561)
    10. 什么是重构,什么不是重构 (累计阅读 4,521)