• 《编写可读代码的艺术》第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 };
  • 相关阅读:
    layui iframe版点击左侧菜单栏实现加载等待动画
    概率论基础内容
    fatal error LNK1123:转换COFF期间失败:文件无效或损坏
    ERROR 2003:Can't connect to MySQL server on ‘localhost’...
    HttpWebRequest 无法连接到远程服务器
    Android Error: java.lang.IllegalStateException: Could not execute method of the activity
    创建.aspx页面
    CodeFile Inherits
    Unable to execute dex:Target out of range
    fatal error C1083: 无法打开包括文件“jni.h”
  • 原文地址:https://www.cnblogs.com/yyqng/p/14215798.html
Copyright © 2020-2023  润新知