如何写出漂亮的代码——不应有的返回值

项目中有下面这样一段代码,大家看有什么问题:

1 public class TemplateService
2     {
3         public Template Add(Template template)
4         {
5             //do save it to db
6             return template;
7         }
8     }

 上面的代码我们可能经常都在写,好像看不出有什么问题。但我认为上面这个Add方法读起来就不通顺。如果代码是上面这么写的,那么调用的代码可能就像下面的这样:

var service = new TemplateService();
var template = new Template(){...};
template = service.Add(template);

注意到上面最后一行代码,读起来是不是非常别扭?

我认为好的代码应该是这样的:

1 var service = new TemplateService();
2 var template = new Template(){...};
3 service.Add(template);

(在Add方法体里面,可能会对template实例的某些属性进行赋值,比如ID,因此没有必要再返回template)。

其实,除了Add, 我认为还有很多方法都不应该带返回值。我可以随便列举一些非常常见的调用例子:

userService.Save(user);
userService.Update(user);
userService.Delete(user.Id);
userService.Login(user);

你可能会想,上面这些方法可以返回bool值啊。事实上,在很多代码里可以看到这些方法确实返回了bool值,甚至是有经验的程序员也在这么写。但我并不认为这是一种好的做法。对于那些返回bool值的方法(无非就是想告诉调用者方法是否执行成功),我认为应该用抛出异常的方式来处理。这样做有多个好处:

  1. 可以根据输入抛出多个不同的异常信息,而不是将异常吃掉,只是返回一个简单的true/false。
  2. 调用处的代码读起来更通顺。

对于某些方法如果你确实不想抛出详细的异常信息,只想告诉调用者成功与否,也就是说你的方法体里面自己会处理异常,那么我建议给方法名称加前缀“Try”. 然后你的代码就会变成这样:

var success = userService.TryLogin(username, password);

上面这段代码就告诉调用者不用处理异常了,因为service里面已经有try/catch了。如果使用抛出异常的模式,我也简单写个例子吧:

 1 public void Login(username, password){
 2     var user = Get(username);
 3     if(user == null){
 4         throw new Exception("The user doesn't exist");
 5         // throw new UserNotExistException();
 6     }
 7     if(user.Password != EncodePassword(password)){
 8         throw new Exception("Incorrect password!");
 9          // throw new PasswordDosntMatchException();
10     }
11     // do other logic
12 }

最后,我再举更多的那些不应该带返回值的方法调用例子:

1 var person = new Person();
2 person.Talk();
3 person.MoveTo(target.X, target.Y);
4 person.Go();
5 
6 var browser = new Browser();
7 browser.Open();
8 browser.Go(url);
9 browser.Close();

假如上面的这些方法带有返回值,你很难想象它们应该返回什么。

好了,本文就写到这里了。本文想说的是,想要写出漂亮的代码,那么你的代码读起来要朗朗上口。如果你有些不同意本文的观点,非常欢迎交流探讨。

posted @ 2013-04-08 21:32  Leo C.W  Views(1090)  Comments(5Edit  收藏  举报