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



2017年12月9日 星期六

Note for Yocto Project Reference Manual v2.4 - ch8.141 update-alternatives.bbclass


當有多個recipes提供相同的命令時, update-alternatives.bbclass可以幫你做替代("alternative"), 例如,可以從busybox,binutils和elfutils中使用ar命令。 update-alternatives.bbclass會幫你重新命名,以便安裝多個package而不會發生衝突。無論安裝或隨後刪除哪些package,ar命令仍然有效。
要使用update-alternatives.bbclass,你需要為這個package定義一些變量:
ALTERNATIVE_ = "name1 name2 name3 ..."
列出所有這個package的alternatives指令

設定name這個命令的link的路徑
ALTERNATIVE_LINK_NAME[name] = "target"

設定該package的預設priority,數值越大,priority越高
ALTERNATIVE_PRIORITY

針對特定命令另外設定priority,數值越大,priority越高
ALTERNATIVE_PRIORITY[name] = "20"


範例

brook這個package的檔案結構
brook@vista:~/oe-core/meta/recipes-devtools/brook$ tree
.
|-- brook-1.0.0
|   |-- brookbox
|   |-- copyright
|   `-- insmod
`-- brook_1.0.0.bb

1 directory, 4 files
brookbox類似busybox,後面會有多個檔案link到該檔案,而insmod是一個獨立檔案

brook_1.0.0.bb
SUMMARY = "Brook demo update-alternatives"
DESCRIPTION = "This package is used for Brook to demo update-alternatives"
LICENSE = "GPLv2+"
LIC_FILES_CHKSUM = "file://${WORKDIR}/copyright;md5=afcc69d729fbf1d0a2af28ce44a23991 \
"
SRC_URI = "file://insmod \
        file://copyright \
        file://brookbox \
"
inherit update-alternatives

ALTERNATIVE_${PN} = "insmod route reboot shutdown poweroff"
ALTERNATIVE_PRIORITY = "100"

ALTERNATIVE_LINK_NAME[insmod] = "${base_sbindir}/insmod"
ALTERNATIVE_PRIORITY[insmod] = "50"

ALTERNATIVE_LINK_NAME[route] = "${base_sbindir}/route"
ALTERNATIVE_PRIORITY[route] = "50"

ALTERNATIVE_LINK_NAME[reboot] = "${base_sbindir}/reboot"

ALTERNATIVE_LINK_NAME[shutdown] = "${base_sbindir}/shutdown"
ALTERNATIVE_PRIORITY[shutdown] = "10"

ALTERNATIVE_LINK_NAME[poweroff] = "${base_sbindir}/poweroff"
ALTERNATIVE_PRIORITY[poweroff] = "500"

do_install () {
        install -d                              ${D}${base_sbindir}
        install -m 0755    ${WORKDIR}/insmod    ${D}${base_sbindir}/insmod
        install -m 0755    ${WORKDIR}/brookbox  ${D}${base_sbindir}/brook
        ln -s ${base_sbindir}/brook ${D}${base_sbindir}/route
        ln -s ${base_sbindir}/brook ${D}${base_sbindir}/reboot
        ln -s ${base_sbindir}/brook ${D}${base_sbindir}/shutdown
        ln -s ${base_sbindir}/brook ${D}${base_sbindir}/poweroff
}
sysvinit也同時註冊了reboot,shutdown與poweroff,其priority都是200,而這裡的priority分別為100,10,500,所以最後結果如下

brook@vista:~/oe-core/build/tmp-glibc/work/oe-linux-gnueabi/image/1.0-r0/rootfs$ ls -al sbin/|grep brook
-rwxr-xr-x  1 jenkins jenkins      6 Dec  9 22:17 brook
lrwxrwxrwx  1 jenkins jenkins     18 Dec  9 22:17 insmod -> /sbin/insmod.brook
-rwxr-xr-x  1 jenkins jenkins      6 Dec  9 22:17 insmod.brook
lrwxrwxrwx  1 jenkins jenkins     20 Dec  9 22:17 poweroff -> /sbin/poweroff.brook
lrwxrwxrwx  1 jenkins jenkins     11 Dec  9 22:17 poweroff.brook -> /sbin/brook
lrwxrwxrwx  1 jenkins jenkins     11 Dec  9 22:17 reboot.brook -> /sbin/brook
lrwxrwxrwx  1 jenkins jenkins     17 Dec  9 22:17 route -> /sbin/route.brook
lrwxrwxrwx  1 jenkins jenkins     11 Dec  9 22:17 route.brook -> /sbin/brook
lrwxrwxrwx  1 jenkins jenkins     11 Dec  9 22:17 shutdown.brook -> /sbin/brook

reboot與shutdown都小於sysvinit,所以不適用brook,poweroff高於sysvinit,所以使用brook這個package提供的命令





熱門文章