2018年1月1日 星期一

note for "The Art of Readable Code" - CH5 Knowing What to Comment


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



note for "The Art of Readable Code" - CH1 & CH2


CH1, Code Should Be Easy to Understand

Code should be written to minimize the time it would take for someone else to understand it.

越容易理解的code是越好的, 雖然減少程式碼數量是很好的目標, 但是縮短理解的時間是更為重要的, 甚至於超越效能, 比如
bucket = FindBucket(key);
if (bucket != NULL) assert(!bucket->IsOccupied());
會比下面這行更容易被理解
assert((!(bucket = FindBucket(key))) || !bucket->IsOccupied());

CH2, Pack information into your names

提高可讀性可以從"好的名稱", "好的註解", "簡潔的編排方式"著手, 比如, 將資訊放入名稱中
void download_page(url);
或
void fetch_page(url);
會比下面這行更容易被理解
void get_page(url);


名稱選擇上也需要注意, 比如open(), begin(), create(), launch()會比start()來的明確, 盡量用明確的命名, 比如tmp_file會比tmp更明確, 比如
var start = (new Date()).getTime();
...
var elasped = (new Date()).getTime();
..
會比下面這行更容易被明確
var ms_start = (new Date()).getTime();
...
var ms_elasped = (new Date()).getTime();
..


排除不必要的詞彙, 比如
ToString();
會比下面這行更簡潔
ConveterToString();

ServerLoop();
會比下面這行更簡潔
DoServerLoop();


我也習慣在static function,使用"_"開頭, 比如
static void _sleep();
void sleep();


Pack information into your names的幾個重點

• Use specific words—for example, instead of Get, words like Fetch or Download might be
better, depending on the context.
• Avoid generic names like tmp and retval, unless there’s a specific reason to use them.
• Use concrete names that describe things in more detail—the name ServerCanStart() is
vague compared to CanListenOnPort().
• Attach important details to variable names—for example, append _ms to a variable
whose value is in milliseconds or prepend raw_ to an unprocessed variable that needs
escaping.
• Use longer names for larger scopes—don’t use cryptic one- or two-letter names for
variables that span multiple screens; shorter names are better for variables that span only
a few lines.
• Use capitalization, underscores, and so on in a meaningful way—for example, you
can append “_” to class members to distinguish them from local variables.

    參考資料:
  • The Art of Readable Code



熱門文章