《编写可读代码的艺术》第4章 审美

1. 为什么审美这么重要?

    让人愉悦的代码更易读,因此更容易使用。

2. 重新安排换行来保持一致和紧凑

    下面的代码有着优雅一致的风格,并且很容易从头看到尾快速浏览。

    但是缺憾在于用了更多的纵向空间,并且注释重复了三遍。

 1 public class PerformanceTester {
 2     public static final TcpConnectionSimulator wifi =
 3         new TcpConnectionSimulator(
 4             500,   /* Kbps */
 5             80,    /* millisecs latency */
 6             200,   /* jitter */
 7             1      /* packet loss % */);
 8             
 9     public static final TcpConnectionSimulator t3_fiber =
10         new TcpConnectionSimulator(
11             45000, /* Kbps */
12             10,    /* millisecs latency */
13             0,     /* jitter */
14             0      /* packet loss % */);
15             
16     public static final TcpConnectionSimulator cell =
17         new TcpConnectionSimulator(
18             100,   /* Kbps */
19             400,   /* millisecs latency */
20             250,   /* jitter */
21             5      /* packet loss % */);
22 }

    更紧凑的书写方式如下:

 1 public class PerformanceTester {
 2     // TcpConnectionSimulator(throughput, latency, jitter, packet_loss)
 3     //                        [Kbps]        [ms]    [ms]    [percent]
 4     public static final TcpConnectionSimulator wifi =
 5         new TcpConnectionSimulator(500, 80, 200, 1);
 6     public static final TcpConnectionSimulator t3_fiber =
 7         new TcpConnectionSimulator(45000, 10, 0, 0);
 8     public static final TcpConnectionSimulator cell =
 9         new TcpConnectionSimulator(100, 400, 250, 5);
10 }

3. 用方法(函数)整理不规则的东西

    下面这段代码没有什么美感可言。

 1 DatabaseConnection database_connection;
 2 string error;
 3 assert(ExpandFullName(database_connection, "Doug Adams", &error)
 4     == "Mr. Douglas Adams");
 5 assert(error == "");
 6 assert(ExpandFullName(database_connection, " Jake Brown ", &error)
 7     == "Mr. Jacob Brown III");
 8 assert(error == "");
 9 assert(ExpandFullName(database_connection, "No Such Guy", &error) == "");
10 assert(error == "no match found");
11 assert(ExpandFullName(database_connection, "John", &error) == "");
12 assert(error == "more than one result");

    需要一个辅助函数来改进。

 1 void CheckFullName(string partial_name,
 2                    string expected_full_name,
 3                    string expected_error) {
 4     // database_connection is now a class member
 5     string error;
 6     string full_name = ExpandFullName(database_connection, partial_name, &error);
 7     assert(error == expected_error);
 8     assert(full_name == expected_full_name);
 9 }
10 
11 CheckFullName("Doug Adams", "Mr. Douglas Adams", "");
12 CheckFullName(" Jake Brown ", "Mr. Jake Brown III", "");
13 CheckFullName("No Such Guy", "", "no match found");
14 CheckFullName("John", "", "more than one result");

    尽管目的仅仅是让代码更有美感,但是还产生了几个附带的效果

    (1)消除了代码中的重复,使之变得更紧凑

    (2)每个测试用例重要的部分都变得更直白

    (3)添加新的测试更加简单

 4. 在需要时使用列对齐

    对于上面的例子,可以使用列对齐。这样能使得错误更加明显,阅读时很容易从一列跳到另一列。

1 CheckFullName("Doug Adams"  , "Mr. Douglas Adams" , "");
2 CheckFullName(" Jake Brown ", "Mr. Jake Brown III", "");
3 CheckFullName("No Such Guy" , ""                  , "no match found");
4 CheckFullName("John"        , ""                  , "more than one result");
1 commands[] = {
2     ...
3     { "timeout",       NULL,               cmd_spec_timeout },
4     { "timestamping",  &opt.timestamping,  cmd_boolean },
5     { "tries",         &opt.ntry,          cmd_number_inf },
6     { "useproxy",      &opt.use_proxy,     cmd_boolean },
7     { "useragent",     NULL,               cmd_spec_useragent },
8     ...
9 };

    有些人不喜欢列对齐,因为维护工作量大。实际可能不会有太大的工作量,不妨试试。

5. 把声明按块(逻辑)组织起来

 1 class FrontendServer {
 2     public:
 3         FrontendServer();
 4         ~FrontendServer();
 5         
 6         // Handlers
 7         void ViewProfile(HttpRequest* request);
 8         void SaveProfile(HttpRequest* request);
 9         void FindFriends(HttpRequest* request);
10         
11         // Request/Reply Utilities
12         string ExtractQueryParam(HttpRequest* request, string param);
13         void ReplyOK(HttpRequest* request, string html);
14         void ReplyNotFound(HttpRequest* request, string error);
15         
16         // Database Helpers
17         void OpenDatabase(string location, string user);
18         void CloseDatabase(string location);
19 };

6. 把代码分成段落,同时为段落加上总结性注释

 1 def suggest_new_friends(user, email_password):
 2     # Get the user's friends' email addresses.
 3     friends = user.friends()
 4     friend_emails = set(f.email for f in friends)
 5     
 6     # Import all email addresses from this user's email account.
 7     contacts = import_contacts(user.email, email_password)
 8     contact_emails = set(c.email for c in contacts)
 9     
10     # Find matching users that they aren't already friends with.
11     non_friend_emails = contact_emails - friend_emails
12     suggested_friends = User.objects.select(email__in=non_friend_emails)
13 
14     # Display these lists on the page.
15     display['user'] = user
16     display['friends'] = friends
17     display['suggested_friends'] = suggested_friends
18     return render("suggested_friends.html", display)

7. 个人风格与一致性

    一致的风格比“正确”的风格更重要

1 class Logger {
2     //...
3 };
4 
5 class Logger
6 {
7     //...
8 };
原文地址:https://www.cnblogs.com/yyqng/p/14215798.html