2018年1月7日 星期日

note for "The Art of Readable Code" - CH6


CH6, Making Comments Precise and Compact

Comments should have a high information-to-space ratio.當你準備寫註解時, 請盡可能的精簡, 因為註解會佔版面, 而且需要時間了解
// CategoryType -> (score, weight)
typedef hash_map<int, pair<float, float> > ScoreMap;
會比下面例子精簡
// The int is the CategoryType.
// The first float in the inner pair is the 'score',
// the second is the 'weight'.
typedef hash_map<int, pair<float, float> > ScoreMap;


// Return the number of lines in this file.
int CountLines(string filename) { ... }
這段註解不精確, 因為一行有很多種定義, 下面例子會相對精準
// Count how many newline bytes ('\n') are in the file.
int CountLines(string filename) { ... }


Use Input/Output Examples That Illustrate Corner Cases有時候用範例當註解可以更容易讓人理解,比如
// Rearrange 'v' so that elements < pivot come before those >= pivot;
// Then return the largest 'i' for which v[i] < pivot (or -1 if none are < pivot)
// Example: Partition([8 5 9 8 2], 8) might result in [5 2 | 8 9 8] and return 1
int Partition(vector<int>* v, int pivot);


"Named Function Parameter” Comments即在function參數上加上註解
Connect(/* timeout_ms = */ 10, /* use_encryption = */ false);



    參考資料:
  1. The Art of Readable Code





2018年1月1日 星期一

note for "The Art of Readable Code" - CH5


CH5, Knowing What to Comment

The purpose of commenting is to help the reader know as much as the writer did.千萬別為了註解而註解, 因為凌亂的畫面, 不會讓人對程式碼更清晰

無意義的註解範例
// The class definition for Account
    class Account {
      public:
        // Constructor
Account();
        // Set the profit member to a new value
        void SetProfit(double profit);
        // Return the profit from this Account
        double GetProfit();
    };


不要註解不好的名稱, 直接修正名稱
// Enforce limits on the Reply as stated in the Request,
// such as the number of items returned, or total byte size, etc. 
void CleanReply(Request request, Reply reply);
直接修改上述function name從CleanReply()改為EnforceLimitsFromRequest()會比註解一堆來得有意義,
// Make sure 'reply' meets the count/byte/etc. limits from the 'request' 
void EnforceLimitsFromRequest(Request request, Reply reply);

Recording Your Thoughts / directory commentary,註解重要的紀錄,比如以下幾個註解
// This heuristic might miss a few words. That's OK; solving this 100% is hard.
...
// This class is getting messy. Maybe we should create a 'ResourceNode' subclass to
// help organize things.
...


Comment the Flaws in Your Code,程式會不斷的被修改, 不要害怕記錄這些需要改進的地方, 以下是常用的標記
TODO:Stuff I haven’t gotten around to yet
FIXME:Known-broken code here
HACK:Admittedly inelegant solution to a problem
XXX:Danger! major problem here

// TODO: move this into sched_fork()
...
// FIXME: do we need to worry about rq being invalidated by the
...


Summary Comments,對一些code給予一些comment, 比如
# Find all the items that customers purchased for themselves.
    for customer_id in all_customers:
        for sale in all_sales[customer_id].sales:
            if sale.recipient == customer_id:
                ...

def GenerateUserReport():
    # Acquire a lock for this user
    ...

    # Read user's info from the database
    ...

    # Write info to a file
    ...

    # Release the lock for this user
    ...


    參考資料:
  1. The Art of Readable Code





2017年12月23日 星期六

note for "The Art of Readable Code" - CH3 & CH4


CH3, Names That Can’t Be Misconstrued

Actively scrutinize your names by asking yourself, “What other meanings could someone interpret from this name?”

  1. 比如results = Database.all_objects.filter("year <= 2011")的結果是<= 2011還是過濾了<= 2011的結果?如果用select()或exclude()會更為明確


  2. 對於含有邊界意思的, 可以使用"min_"與"max_"加以辨識.


  3. 對於閉區間使用first與end, 而半開放區間使用begin與end, 因為這些已經在C++中成為慣例了.


  4. 關於bool則可以加上is, has, can, should等意思會更明確, 如
  5. bool user_is_authed = true
    會比下面這行更容易被明確
    bool read_password = true
    


  6. get*()(開頭的function), 通常指直接回傳內部成員, 如果還需要計算, 最好改用compute*()或count*(),


CH4, Aesthetics

這個章節是在講述, 好的排版會讓人更容易看懂code, 以下是我摘要的幾個範例
  1. 給予參數一些註解
  2. public class PerformanceTester {
       // TcpConnectionSimulator(throughput, latency, jitter, packet_loss)
       //                            [Kbps]   [ms]     [ms]    [percent]
       public static final TcpConnectionSimulator wifi =
           new TcpConnectionSimulator(500,     80,     200,     1);
       public static final TcpConnectionSimulator t3_fiber =
           new TcpConnectionSimulator(45000,   10,       0,     0);
       public static final TcpConnectionSimulator cell =
           new TcpConnectionSimulator(100,    400,     250,     5);
    }
    

  3. 讓參數對齊
  4. CheckFullName("Doug Adams"  , "Mr. Douglas Adams" , "");
    CheckFullName(" Jake Brown ", "Mr. Jake Brown III", "");
    CheckFullName("No Such Guy" , ""                  , "no match found");
    CheckFullName("John"        , ""                  , "more than one result");
    

  5. 段落分明
  6. def suggest_new_friends(user, email_password):
      # Get the user's friends' email addresses.
      friends = user.friends()
      friend_emails = set(f.email for f in friends)
    
      # Import all email addresses from this user's email account.
      contacts = import_contacts(user.email, email_password)
      contact_emails = set(c.email for c in contacts)
    
      # Find matching users that they aren't already friends with.
      non_friend_emails = contact_emails - friend_emails
      suggested_friends = User.objects.select(email__in=non_friend_emails)
    

Consistent style is more important than the “right” style. 無論你是用什麼coding style, 一致性會比你用“對”的style更重要.
    參考資料:
  • The Art of Readable Code