2015-06-28

虎屋羊羹+山田哥斯大黎加


via Instagram http://ift.tt/1BYhjrG

鴿朋友


via Instagram http://ift.tt/1Jfbo0R

機會成本

Opportunity Cost (OC)。維基百科是這麼寫的,
In microeconomic theory, the opportunity cost of a choice is the value of the best alternative forgone, in a situation in which a choice needs to be made between several mutually exclusive alternatives given limited resources.
翟本喬在創新是一種態度中提到:機會成本,才是公司最大的成本。
機會成本簡單來說,是指你決定去做一件事情而使用了一些資源,包括金錢、時間、人力等等,而這些資源如果用在別的事情上,你能得到的最大利益。
在這本書中,翟本喬舉了台北市公車專用道以及玩線上遊戲或學習當例子。拆除公車專用道花費四百萬元,兩年後重建花費六百萬元。金錢的花費至少一千萬元,但是考慮機會成本後,不拆公車專用道造成的交通阻礙、浪費的時間等等,很有可能超過一千萬元。線上遊戲的金錢花費是兩百小時四百五十元(月卡),但是這兩百小時若用來學習精進某個領域,有條件找到更好的工作,就算每個月只多一千元的薪資,一輩子下來會多幾十萬元。

書中談論機會成本的主軸是員工福利。為什麼Google的福利這麼好?因為考量過機會成本後,給予這樣的福利可以為Google帶來最大的效益。我認為可以得出這樣的結論的原因在於,對所有成本的管控都非常精細。不單單只是考慮有形的成本,連最難評估的人力時間(man-hour)成本都要能精準的掌握。

看了這本書後發現,平常在做決定的時候,沒有想過要考慮機會成本。應該要把考量機會成本內化成一種習慣。

2015-06-27

[Clean Code] 閱讀筆記 - Ch. 6

第六章的標題是物件及資料結構(Objects and Data Structures)。這個章節可以歸納為兩個重點:物件(object)與資料(data)的差異;德摩特爾法則(The Law of Demeter)。

使用單純的資料結構時,只定義成員(member)而不提供方法(method),就像是C語言的struct [link],資料內的成員可以直接被使用,所有的邏輯運算都在資料結構的外部操作。以Python實作的話如下:
使用物件時,同時定義成員與方法,但是成員變數被封裝在物件內,所有的操作只能透過物件提供的方法。Python實作如下:
物件與資料結構間存在著反對稱性(anti-symmetry)。從外部來看,資料結構提供可操作的成員,但是無法使用方法(因為根本沒有);物件提供可操作的方法,但是隱藏其內部成員的細節(Python無法封裝其成員不被外部使用,但是可以透過命名慣例來區隔避免誤用:self._fooself.__bar)。

這樣的反對稱性,會影響新功能的擴充。假設未來想要增加一個計算周長的方法,在資料結構的實作中,只需要變更class Geometry就好,在其內部增加def perimeter即可;但是對於物件的實作來說,卻需要變更class Shape, class Square, class Rectangle, class Circle,變動非常大。相反地,假設要增加一個新的形狀class Triangle,在物件的實作中,就只需要新增class Triangle(Shape);在資料結構的實作中,除了新增class Triangle外,還必須修改class Geometry內所有的操作方法。

使用物件好還是使用資料結構好?需要看未來可能的需求而定。如果類別可能增加但是類別的方法不會再改變,比較適合使用物件;如果類別變動的機會少,但是有可能一直增加新的方法,比較適合使用資料結構。

這一章的另一個主題為The Law of Demeter,這個法則是針對物件的實作的定。
More precisely, the Law of Demeter says that a method f of a class C should only call the methods of these:
* C
* An object created by f
* An object passed as an argument to f
* An object held in an instance variable of C
Python的實作: The Law of Demeter提供物件封裝其成員變數的法則,避免外部直接取得物件的成員而操作,所有對物件成員的操作必須封裝在物件的方法之內。物件本身必然瞭解其內部成員如何使用與操作,因此將運算邏輯實作於物件的方法內是合理的,也讓整體的程式架構更好維護。這樣做的好處是,當該物件必須變更其內部成員時,外部的使用者不需要修改其操作,如此一來可將所有的變更侷限於該物件本身,程式的維護性更好。

2015-06-19

git merge or rebase?

昨天在Hacking Thursday (H4)參與Git Workflow的讀書會,突然想到一個問題:
feature branch完成後,在發送pull request前,如果master branch(或develop branch)又有新的commit,如圖

這時候應該要先git rebasegit mergefeature branch追上master branch才好呢?
一直以來我都是用git mergefeature branch的程式碼整理好才發pull request,也不知道我這樣用到底是不是大家習慣的用法,想不到在H4也是兩派人都有。上網一查才發現,這個問題的爭論,不亞於Emacsvim哪種編輯器比較好?看了兩篇文章Git team workflows: merger or rebase?Merge or Rebase?,覺得整理得還不錯。

使用git merge會像這樣

這種做法的優點是:容易了解與使用;保留完整的歷史紀錄,便於追蹤;如果feature branch也有分享出去的話,用git merge才不會搞爛大家的歷史紀錄。而其最大的缺點就是會讓歷史紀錄變得非常複雜,如果分支(fork)的人很多,歷史紀錄很有可能變成網狀的,而不再只是樹枝狀的結構。

使用git rebase會像這樣

這種做法最大的優點就是:簡化歷史紀錄,讓雜訊消失,變得更容易閱讀。但是其缺點是:git rebase使用起來不夠直覺,而且處理衝突(conflict)時不方便;由於歷史紀錄被簡化過,部分的資訊會消失,不利於後續追蹤;對於公開分享的feature branch,常常搞壞其他人的歷史紀錄。

看了大家的討論,會覺得當初何必多弄一個指令git rebasegit merge著重的點是完整記錄所有的歷史;而git rebase則讓歷史紀錄更容易閱讀。對專案管理者來說,或許git rebase有比較大的誘因,因為歷史紀錄容易閱讀,也很容易產生進度報告及報表。但是對於開發者來說,最重要的反而是詳盡的歷史紀錄,H4的Thinker說:
你要誠實面對你自己
其實在這之前我並沒有深入想過這個問題,純粹只是覺得git merge就夠用了,而且常聽說git rebase要小心使用。因此在Github上貢獻專案時就會想說避免闖禍,先用git merge就好。認真瞭解後才發現這真是一個有趣的問題,為了保留完整的歷史紀錄,現在可以更有信心的使用git merge了~

2015-06-14

[Clean Code] 閱讀筆記 - 2

第二章討論的主題是有意義的命名(Meaningful Names)。命名真的是很大的學問,看看The 9 hardest things programmers have to do,第一名就是“命名”,就連母語是英語的人,也會覺得寫程式的時候命名很困難。

命名可以分成兩個面向,一個是意義(meaning);另一個則是樣式(style)。意義是很主觀的,會因為變數或函式的功能不同而改變命名的用字。Clean Code這本書將命名的重點集中在如何使命名有意義,但是變數或函式的命名會隨著使用的時機及其存在的範圍(scope)而有所調整,因此很難有一固定的命名方法。作者列出一些參考的方向,有好的也有不好的。例如dayd容易了解,而finishDay又比day描述得更清楚;但是用finishDay或是completeDay則需是使用狀況而定,很難說哪一個比較好。我認為有意義的命名就像寫文章時的用字遣詞一樣,要表達同一個意思,有人用字精準,也有人喜歡華麗的辭藻,但是重點就是要讓人看得懂,而不只是一堆文字的堆疊,這樣的好處是讓閱讀的人可以更快看懂程式碼。

Mosky五月在Taipei.py的演講Beyond the Style Guides,也跟有意義的命名有關。

命名的樣式是屬於比較客觀的部分,主要用於定義名稱的結構。例如同樣是指account data,可以有很多寫法:accountdata, AccountData, accountData, account_data。很多團隊會事先定義好固定的樣式,希望大家遵守,只是為了閱讀習慣。Python PEP8也提供了命名樣式的規則讓大家參考。

另外之前一直以為匈牙利標誌法(Hungarian Notation, HN)包含CamelCase的規則,後來才發現是自己誤會了。匈牙利標誌法是指在各個變數之前,加上資料型別的小寫字母縮寫,讓閱讀程式碼的人得以快速知道該變數的資料型別。寫程式會常用到Windows C API的人應該知道,MSDN上的API說明,每個變數前面都有一串資料型別,例如DeviceIoControl

看完第二章的感想是除了讓命名有意義外,我覺得一致性也很重要,命名的一致性可以降低閱讀的人的疑惑。書上也舉例:manager, controller, driver這三者的目的是類似的,如果沒有特別的差異不要混用,否則會讓看的人更困擾。看懂別人寫的程式碼已經有點困難了,還要去猜這裡的controller跟那裡的driver有什麼不一樣,那就太浪費時間了。

@classmethod and @staticmethod in Python

In C++ or Java, the static identifier used in a Class method is to declare the function to be bound to that Class. This are also known as class methods and you could use them in class level without initiating an instance first. In Python, however, the ideas of static method and class method are different. Take the following Python code as example:

class MethodDemo(object):
    class_number = 100

    def __init__(self):
        self.number = 0

    def Show(*arg):
        print "instance method", arg

    @classmethod
    def ClassShow(*arg):
        print "class method", arg

    @staticmethod
    def StaticShow(*arg):
        print "static method", arg

def main():
    d = MethodDemo()
    d.Show()
    d.ClassShow()  # same as MethodDemo.ClassShow()
    d.StaticShow() # same as MethodDemo.StaticShow()

if __name__ == '__main__':
    main()

And the result on my computer is:

instance method (<__main__.MethodDemo instance at 0x10cef93f8>,)
class method (<class __main__.MethodDemo at 0x10ceb3ae0>,)
static method ()

The first argument in instance method Show() is the instance object of that class (bound to instance). Usually this kind of method is defined as "def Show(self):", and self is instance argument. By passing instance itself to a instance method, other instance methods or instance variables, such as self.number, are accessible.

If decorator @classmethod is used to define a method then that method is a class method. From above code snippet, the first argument to be passed into a class method is the class object (bound to class). As a result, from a class method, you could access other class methods or class variables, such as class_number.

If decorator @staticmethod is used to define a method then that method is a static method. There is no arguments to be passed into a static method by default (bound to nothing). It is like a normal function outside a class in global scope. The usage of static methods are like global functions and the class name will be namespace to solve the conflict of same function names in global scope.

2015-06-13

[Clean Code] 閱讀筆記 - 1

最近參加一個讀書會,討論Clean Code -- 無瑕的程式碼(博客來連結),雖然念中文書比較輕鬆,但是有些翻譯的部分讓人很想看看原文,所以又買了原文版的來讀,除了分享讀書的筆記外,順便分享中英文的內容。

書本第2頁,程式碼將一直存在的小節中第四段,
某些傢伙認為程式碼總有一天會消失,就像期望數學不必太正式的數學家。
數學家那一句話實在無法理解,找出原文如下:
The folks who think that code will one day disappear are like mathematicians who hope one day to discover a mathematics that does not have to be formal.
這裡formal翻譯成正式的似乎怪怪的。根據formal第19的解釋,意思應該是經過嚴謹證明的

第一章屬於理念的闡釋,作者訪問許多大師對於clean code的看法,在此列出這些大師所說內容的原文。

Bjarne Stroustrup, inventor of C++ and author of The C++ Programming Language
I like my code to be elegant and efficient. The logic should be straightforward to make it hard for bugs to hide, the dependencies minimal to ease maintenance, error handling complete according to an articulated strategy, and performance close to optimal so as not to temp people to make the code messy with unprincipled optimizations. Clean code does one thing well.


Grady Booch, author of Object Oriented Analysis and Design with Applications
Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer's intent but rather is full of crisp abstractions and straightforward lines of control.


"Big" Dave Thomas, founder of OTI, godfather of the Eclipse strategy
Clean code can be read, and enhanced by a developer other than its original author. It has unit and acceptance tests. It has meaningful names. It provides one way rather than many ways for doing one thing. It has minimal dependencies, which are explicitly defined, and provides a clear and minimal API. Code should be literate since depending on the language, not all necessary information can be expressed clearly in code alone.


Michael Feathers, author of Working Effectively with Legacy Code
I could list all of the qualities that I notice in clean code, but there is one overarching quality that leads to all of them. Clean code always looks like it was written by someone who cares. There is nothing obvious that you can do to make it better. All of those things were thought about by the code's author, and if you try to imagine improvements, you're led back to where you are, sitting in appreciation of the code someone left for you--code left by someone who cares deeply about the craft.


Ron Jeffries, author of Extreme Programming Installed and Extreme Programming Adventures in C#
In recent years I begin, and nearly end, with Bech's rules of simple code. In priority order, simple code:
* Runs all the tests;
* Contains no duplication;
* Express all the design ideas that are in the system;
* Minimizes the number of entities such as classes, methods, functions, and the like.

Of these, I focus mostly on duplication. When the same thing is done over and over, it's a sign that there is an idea in our mind that is not well represented in the code. I try to figure out what it is. Then I try to express that idea more clearly.

Expressiveness to me includes meaningful names, and I am likely to change the names of things several times before I settle in. With modern coding tools such as Eclipse, renaming is quite inexpensive, so it doesn't trouble me to change. Expressiveness goes beyond names, however. I also look at whether an object or method is doing more than one thing. If it's an object, it probably needs to be broken into two or more objects. If it's a method, I will always use the Extract Method refactoring on it, resulting in one method that says more clearly what it does, and some submethods saying how it is done.

Duplication and expressiveness take me a very long way into what I consider clean code, and improving dirty code with just these two things in mind can make a huge difference. There is, however, one other thing that I'm aware of doing, which is a bit harder to explain.

After years of doing this work, it seems to me that all programs are made up of very similar elements. One example is "find things in a collection." Whether we have a database of employee records, or a hash map of keys and values, or an array of items of some kind, we often find ourselves wanting a particular item from that collection. When I find that happening, I will often wrap the particular implementation in a more abstract method or class. That gives me a couple of interesting advantages.

I can implement the functionality now with something simple, say a hash map, but since now all the references to that search are covered by my little abstraction, I can change the implementation any time I want. I can go forward quickly while preserving my ability to change later.

In addition, the collection abstraction often calls my attention to what's "really" going on, and keeps me from running down the path of implementing arbitrary collection behavior when all I really need is a few fairly simple ways of finding what I want.

Reduced duplication, high expressiveness, and early building of simple abstractions. That's what makes clean code for me.


Ward Cunningham, inventor of Wiki, inventor of Fit, convector of eXtreme Programming. Motive force behind Design Patterns. Smalltalk and OO thought leader. The godfather of all those who care about code.
You know you are working on clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem.

2015-06-10

Embedding Python with multi-thread in C++ application

Initial work flow
1. Application starts from C++ layer
2. C++ layer invokes function in Python layer in main thread
3. The Python layer function in main thread creates an event thread
4. Starts the event thread in Python layer and go back to C++ layer
5. Main loop starts in C++ layer
6. The event thread invokes callback function in C++ layer if needed

From the beginning, the event thread works unexpected. I guess this is due to GIL from the situation I encountered so I tried to solve this from GIL. Here is my solution.

Analysis
First, from note in PyEval_InitThreads,
When only the main thread exists, no GIL operations are needed. ... Therefore, the lock is not created initially. ...
So if multi-thread is needed, PyEval_InitThreads() must be called in main thread. And I call PyEval_InitThreads() before Py_Initialize(). Now GIL is initialized and main thread acquires GIL.

Second, each time before Python function is invoked from C++ layer, PyGILState_Ensure() is called to get GIL. In addition, after Python function is invoked, PyGILState_Release(state) is called to go back to previous GIL state. As a result, before step 2, PyGILState_Ensure() is called, and after step 4, PyGILState_Release(state) is called.

But there is a problem. From PyGILState_Ensure and PyGILState_Release, these two functions are to save current GIL state to get GIL and restore previous GIL state to release GIL. However, after calling PyEval_InitThreads() in main thread, main thread owns GIL definitely. And the GIL state in main thread is as follows:

/* main thread owns GIL by PyEval_InitThreads */
state = PyGILState_Ensure();
/* main thread owns GIL by PyGILState_Ensure */
...
/* invoke Python function */
...
PyGILState_Release(state);
/* main thread owns GIL due to go back to previous state */

From above code sample, main thread always owns GIL so the event thread never runs. To overcome this situation, let main thread not acquire GIL before calling PyGILState_Ensure(). Therefore, after calling PyGILState_Release(state), main thread could release GIL to let event thread run. So GIL should be released in main thread immediately when GIL is initialized.

Here PyEval_SaveThread() is used. From PyEval_SaveThread,
Release the global interpreter lock (if it has been created and thread support is enabled) and reset the thread state to NULL, ...
By doing so, embedding Python with multi-thread works.

Work flow after modification
1. Application starts from C++ layer
2. PyEval_InitThreads(); to enable multi-thread
3. save = PyEval_SaveThread(); to release GIL in main thread
4. state = PyGILState_Ensure(); to acquire GIL in main thread
5. C++ layer invokes function in Python layer in main thread
6. The Python layer function in main thread creates an event thread
7. Starts the event thread in Python layer and go back to C++ layer
8. PyGILState_Release(state); to release GIL in main thread
9. Main loop starts in C++ layer
10. The event thread invokes callback function in C++ layer if needed

2015-06-04