posts - 11, comments - 9, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          2013年6月29日

          原來Markdown如此之方便,github又提供了page服務,還能用上git,真是無法無天了!

          http://www.100hack.com

          或者
          http://cuixin.github.com

          posted @ 2013-06-29 01:30 steven.cui 閱讀(238) | 評論 (0)編輯 收藏

          2012年8月13日

          第5章 調試你的大腦


          我從來都不想成為怪人,但別人都認為我想。

          ——弗蘭克.扎帕,美國作曲家、音樂家、電影導演


          直覺是偉大的, 除了當它不偉大的時候。

          我們必須直視自己,“調試”(debug)自己的大腦。

          關于debugging,可以自己擴展閱讀,軟件是有人創造的,錯誤難免。

          為什么這么說呢?人類大腦又不是開源軟件,沒法找到代碼去修正,只是展示出錯的地方,但你卻能知道自己的缺陷在哪里,只能盡量避免,卻幾乎難以修正。這就是人,而不是計算機:

               1.認知偏見:思維如何被誤導

               2.時代影響:同代人如何影響你

               3.個性傾向:個性如何影響思維

               4.硬件故障:大腦較老區域如何壓制較聰明的區域


          了解認知偏見

               Wikipedia列舉了大約90多種認知偏見,書中著重舉了幾個值得重視的偏見:

             思維定勢

               思維定勢(Thinking Set) 是由先前的活動而造成的一種對活動的特殊的心理準備狀態,或活動的傾向性。在環境不變的條件下,定勢使人能夠應用已掌握的方法迅速解決問題。而在情境發生變化時,它則會妨礙人采用新的方法。消極的思維定勢是束縛創造性思維的枷鎖。

             基本歸因錯誤

               歸因理論的一個現象,即人們常常把他人的行為歸因于人格或態度等內在特質上,而忽略他們所處情境的重要性。比如,盡管我們在評價他人的行為時有充分的證據支持,但我們總是傾向于低估外部因素的影響,而高估內部或個人因素的影響。這種現象解釋了當銷售人員的業績不佳時,銷售經理更傾向于將其歸因于下屬的懶惰而不是競爭對手的實力。

            基本歸因錯誤(fundamental attribution error,FAE)描繪人們在考察某些行為或后果的原因時高估傾向性因素(譴責或贊譽人)、低估情境性因素(譴責或贊譽環境)的雙重傾向。

             自私的偏見

               這種偏見使人們相信,項目的成功是我的功勞,失敗則與我無關。這種行為可能是一種個人防御機制導致的,但是請記住你也是系統的一部分——無論結果好與壞。

              需要定論

               我們對疑問和不確定性感到不舒服,我們會竭盡全力解決不確定性。其實不確定性有時候是件好事,選擇是開放的。如果強行把不確定的事情強行的定論,會迫使你選擇放棄,易于犯錯,例如你宣布了一項項目截止日期,并沒有能力移除內在的不確定性,它只是一種自我掩飾。說到這里,我們常說靠譜還是不靠譜,我個人是比較煩不靠譜的人,而我愛人卻總結出,不靠譜的人有時候往往做朋友比靠譜的人好相處,而且有時候能幫到你。

               因為不靠譜的人在事情模棱兩可的時候就可以承諾,但你別太把承諾當回事,也許他看似不靠譜的事情,真的就能辦到。因為靠譜的人從來不做沒把握的事情,不敢于嘗試,不去爭取嘗試甚至,特別覺得一旦說出去的話就得全部做到,要不就只字未提,聽她說完,身邊的朋友的確,雖然有些看似不靠譜的,卻真心對待的朋友,他們不是不靠譜,而是敢于給你幫助。


              認可上的偏見

               每個人都根據自己的成見和喜好原則來選擇相應的事實。

              曝光效應

               會因為習慣和熟悉某種事物對其偏愛,這包括不在好用或者出錯的工具或者技術。

               霍桑效應/宣泄效應

               1)社會心理學家所說的“霍桑效應”也就是所謂“宣泄效應”。霍桑工廠是美國西部電器公司的一家分廠。為了提高工作效率,這個廠請來包括心理學家在內的各種專家,在約兩年的時間內找工人談話兩萬余人次,耐心聽取工人對管理的意見和抱怨,讓他們盡情地宣泄出來。結果,霍桑廠的工作效率大大提高。這種奇妙的現象就被稱作“霍桑效應”。

               2)1924年11月,以哈佛大學心理專家梅奧為首的研究小組進駐西屋(威斯汀豪斯)電氣公司的霍桑工廠,他們的初衷是試圖通過改善工作條件與環境等外在因素,找到提高勞動生產率的途徑。他們選定了繼電器車間的六名女工作為觀察對象。在七個階段的試驗中,支持人不斷改變照明、工資、休息時間、午餐、環境等因素,希望能發現這些因素和生產率的關系——這是傳統管理理論所堅持的觀點。但是很遺憾,不管外在因素怎么改變,試驗組的生產來效率一直未上升。

               歷時九年的實驗和研究,學者們終于意識到了人不僅僅受到外在因素的刺激,更有自身主觀上的激勵,從而誕生了管理行為理論。就霍桑試驗本身來看,當這六個女工被抽出來成為一組的時候,她們就意識到了自己是特殊的群體,是試驗的對象,是這些專家一直關心的對象,這種受注意的感覺使得她們加倍努力工作,以證明自己是優秀的,是值得關注的。

               有一所國外的學校,在入學的時候會對每個學生進行智力測試,以智力測驗的結果將學生分為優秀班和普通班。結果有一次在例行檢查時發現,一年之前入學的一批學生的測驗結果由于某種失誤被顛倒了,也就是說現在的優秀班其實是普通的孩子,而真正聰明的孩子卻在普通班。但是這一年的課程成績卻如同往年一樣,優秀班明顯高于普通班,并未出現異常。原本普通的孩子被當作優等生關注,他們自己也就認為自己是優秀的,額外的關注加上心理暗示使得丑小鴨真的成了白天鵝。

               實驗結論

          1. 改變工作條件和勞動效率之間沒有直接的因果關系;
          2. 提高生產效率的決定因素是員工情緒,而不是工作條件;
          3. 關心員工的情感和員工的不滿情緒,有助于提高勞動生產率。

          研究者認為,這種自然形成的非正式組織(群體),它的職能,對內在于控制其成員的行為,對外則為了保護其成員,使之不受來自管理階層的干預。這種非正式的組織一般都存在著自然形成的領袖人物。至于它形成的原因,并不完全取決于經濟的發展,主要是與更大的社會組織相聯系。

          霍桑實驗最初的研究是探討一系列控制條件(薪水、車間照明度、濕度、休息間隔,等)對員工工作表現的影響。研究中意外發現,各種試驗處理對生產效率都有促進作用,甚至當控制條件回歸初始狀態時,促進作用仍然存在。這一現象發生在每一名受試驗者身上,對于受試驗者整體而言,促進作用的結論亦為真。

          很顯然,實驗假設的各項條件并非是唯一的或決定性的生產效率影響因素。對此,喬治·埃爾頓·梅奧George Elton Mayo)以及他的助手們所做的解釋是,受試者對于新的實驗處理會產生正向反應,即由于環境改變(試驗者的出現)而改變行為。所以績效的提高,并非由實驗操控造成。這種效果就是我們所稱的“霍桑效應”或“霍索恩效應”(Hawthorne Effect)。

               霍桑效應的優點

          • 能夠清楚地發現員工關心的事項。
          • 如果模型建設適當、準確的話,它所給出的解決生產力的辦法具有長期的、可持續的特點。
          • 對員工工作條件進行持續性衡量評估,有助于管理者指定長期的戰略決策。

               霍桑效應的缺點

          • 一些內在的工作環境屬性難以辨識,如組織動力。
          • 生產力模型的參數選擇a、b、c比較主觀,取決于管理人員的個人認識。
          • 關鍵性的工作環境屬性是動態的,模型需要不斷調整反映現實情況。
          • 從總體上來看,生產力模型的準確度與管理人員的個人判斷力、敏銳性緊密相關。

               霍桑效應的啟示

               “霍桑效應”,也就是社會心理學所說的“宣泄效應”,它給我們的啟示是:人在生產或者生活的過程中,對自己未能實現和不能滿足的情緒,要把它發泄出來,情緒的發泄對人的身心健康和工作效率都非常有利。

              虛假記憶(讓我想到一部片子《羅生門》)

               虛假記憶(pseudo memory)是大腦記憶的信息之間自動的組合導致不真實的回憶。每個人的大腦都可能產生虛假的記憶,或將事物的真實情況扭曲。人們會對自己的記憶堅信不疑,甚至會對大腦編造的謊言信以為真。這并非一種發病過程。所有人都會產生虛假記憶”,特別是關于童年時期親身經歷的場景的記憶。

               符號約簡謬論和名詞謬論

               移位給事物貼上個標簽就意味著理解或者能解釋它,例如:當你嘗試畫一只人手時,L型思維的人會把光線、陰影、紋理的負責性簡化為“五條線加一個棍”。就如同人們一直認為天鵝只能是白的。

          在這里本人強烈推薦《怪誕心理學》,《影響力》,《引爆點》,《烏合之眾》等等,關于心理方面的書籍,每個人都應該讀點心理學,不是在于說自己腦子有問題,每個人都是有心理偏差的,正因為心理偏差造成的個體不同,才有各種不同的性格,社會進步的重要標志是能包容各種形式的不同形態存在。

          心理偏差是你的個性也好性格也罷,敢于去了解別人和自己本身就是一種對自己思維的挑戰,或許說你再向自己發出改變的挑戰,也許習慣是最難改變的,我們看似對新鮮事物充滿好奇,但如果熟悉一種事物,卻很難接受和改變自己替換原有思維。

          如果說中國古代皇帝最有作為的——李世民,如果只是但從人心理角度出發分析,對與其“元認知”的能力讓其能把國建建設的如此強大——自我批判和自我重塑,而這份能力恰恰是管理者最需要的能力。

          預言的失敗

               做預言太困難了,特別是關于未來的預測。

                                                          ——瑜伽.貝拉,偉大的智者、哲學家兼棒球手

               符號約簡(請注意:不是符號簡約,這兩個字前后顛倒,卻意思相差萬里)是個非常有害的問題,看個例子,你在嘗試畫一只人手時,L型把光線、陰影、紋理的復雜性簡化為“五條線加一個棍”。這種簡化被認為把復雜的現實看做由基本原素的組成:柏拉圖立體。

               我們善于將復雜的東西進行簡化和抽象,并且計算機編程也是如此之思想,但會讓我們陷入誤區。

               以前從來沒有人認為有黑天鵝的存在,以至于科學界認為沒有黑天鵝,知道有一只黑天鵝真的出現了。沒發現不等于不存在,很少也不代表沒有。

               作為一個團隊,我們往往會錯過重要的發展,因為我們關注了錯誤的事情或者提了錯誤的問題。

               現在,還有人在討論學習java好還是.net好?N年前的各種爭吵:RMI還是CORBA能取得中間件的勝利?Windows還是Linux能贏得桌面的勝利?

               就像是WEB的發展讓這些問題毫無意義,Web是典型的黑天鵝,其出乎意料的改變了游戲規則。


          “很少“不意味著”沒有“

               2012,7.21北京據說60年一遇的暴雨,幾乎每年都喊。程序員在寫程序的時候,不可能出現這樣的bug啊,其實應該說概率低,但不代表沒有這種情況發生,花時間查一下認為的不可能的事情吧。不要說:”絕不可能“!


          推遲下結論

               軟件的制作過程在我本人看來就是一個消除不確定性的過程,而且跟時間成正比,如下圖所示:

               到項目末尾時你會達到智力巔峰,而在項目開始時則是最無知的。

               頂住壓力。你會做出決策,事情會解決,只不過不是今天。

               適應不確定性,適應敏捷開發,盡可能的用更靈活的技術適應不確定性,適應了不確定性也就等于提高了效率。


          難以回憶

               記憶是靠不住的,舊的記憶會隨著時間改變,這反而會是你以為某些誤解和偏見是對的,不要僅僅依賴你的記憶。中國有句諺語說得好:好記性不如爛筆頭。


          認清時代的影響

               在這章里作者給出了美國從1901到現在經歷的幾個時代,從技術和人的思維的變化,相似年齡段的人對某種事物的開發更接近,也就是不同年齡層次的人有代溝。本人不再贅述作者講述的美國各年代的歷史,其實這是我們都難以去逾越的,要想避免你所處時代的特有偏見,最好的方法就是保持多樣性。承認一種事物的存在,但卻能淡定的確很難。


          了解個性傾向

               他人即地獄。

                    ——讓.保羅.薩特,法國思想家、作家、存在主義哲學

               尊重不同人的不同性格,當你跟別人爭辯時,請想一想這點。

               MBTI(Myers Briggs Type Indicator)性格評估測試,在國內有些機構可以做些專業評測,如果想找免費的,可以借助谷歌去找,但如果英文一般的同學想做這個測試,我建議你去百合網,雖然是個婚戀網站,但這個MBTI還是比較專業哦,不過MBTI的測試結果就如同你自己的性格一樣,性格有些人會發生改變,但有些人可能一輩子難以改變,曾經我做過測試,經歷過幾年后的測試有個界限發生了改變,所以不要讓MBTI成為你潛意識的引導,而是作為了解自己的途徑,但不要太過于相信,而是時常打破自己的”符號約簡“。


          找出硬件問題

               大腦常犯一些低級錯誤——硬件問題。

               我曾見看過各種報到,為了一個誤會能讓人失去理智。。。

               蜥蜴邏輯:

                    戰斗、逃跑或者恐懼

                    立刻行動,不加思考

                    領頭意識,隨意指使你的隊友

                    守衛領土,不分享信息和秘訣

                    受到傷害,憤憤不平,讓所有人都知道這是不公平的

                    像我這樣==好,不像我這樣==不好

               你或許認識到以上幾點我們都有過呢?

               見樣學樣,近朱者赤,近墨者黑,情緒就像傳染病,常跟一些樂觀的人在一起你也就變得樂觀了。

               進化行為:當你開始重播這些喜歡的電影時,努力阻止自己,記住:這只是一部電影。

               心靈是自己的地方,在那里可以把地獄變成天堂,也可以把天堂變成地獄。

                                                                                                         ——約翰.米爾頓《失樂園》


          現在我不知道該思考什么

               在上幾章提過,直覺是一種強大的工具,是專家的標志。但直覺可能完全錯誤,我們認為“正常的”未必是正常的。除了各種偏見,你可能被你自己誤導,認為一切都好。

               之前提到關于創造一個R型到L型的轉化,也就是說,思考時是全局性和經驗性的,然后轉換成更常規的實踐和技能,從而實現學習過程。

               相信直覺,但是要驗證。


          最后,測試你自己

               當你堅信某種事情時,問問自己原因。

               嘗試問問自己以下問題:

                    你怎么知道的?

                    誰說的?

                    有什么特別的?

                    我的做法會如何影響你?

                    與什么或者誰比較?

                    這總是發生么?你能想到一個特例么?

                    如果你這樣做了(或者不這樣做)會怎么樣?

                    什么阻止了你?

               實踐:

               當發生沖突時,考慮基本性格類型、不同年代的價值觀、你的偏見、別人的偏見和情境。通過司考更多因素,是不是更容易解決沖突?

               仔細檢查你的立場。你是如何知道你所知道的?什么使你這樣認為?


               我們通過邏輯來證明,通過直覺去發現。

                                                       ——龐加萊

           

          posted @ 2012-08-13 01:38 steven.cui 閱讀(375) | 評論 (0)編輯 收藏

          2012年7月31日

          原文請參考,如有問題和歧義請指正,謝謝:)

          http://clojure.org/vars

          變量和全局環境

          Clojure是個很實用的語言,偶爾需要將維護和改變數據的值。她提供了4種不同的方式來操作變量:Vars, Refs, Agents, 和Atoms。Vars機制是是指向一個可改變的數據的位置,你可以為每個線程動態的綁定(制定一個新的存儲位置)一個新值。Vars可以初始化根綁定(不是必須的),綁定的值對于所有線程都是共享的,但卻別的線程就不能重新綁定。因此,要么Var可以為每個線程綁定值,要么使用根綁定。

          下面的special form def 創建了一個Var,如果Var不存在和沒有給初始化,var就是不綁定的(不允許創建非動態的Var,必須顯式指定根綁定):

          user=> (def x)
          #'user/x
          user=> x
          java.lang.IllegalStateException: Var user/x is unbound.

          為根值初始化(如果存在,就被再次綁定)

          user=> (def x 1)
          #'user/x
          user=> x
          1
           

          默認情況下(定義的時候初始化了根綁定),Vars是靜態的(static),但是,建立動態Var的定義可以通過元數據標記的方式,然后在線程用時通過binding來指定。

          user=> (def ^:dynamic x 1)

          user=> (def ^:dynamic y 1)

          user=> (+ x y)

          2

          user=> (binding [x 2 y 3]

                   (+ x y))

          5

          user=> (+ x y)

          2

           

          binding被創建后其他線程是是不可見的。創建的binding可以被賦值,也就是在沒有離開調用堆棧之前可以被上下文訪問。可以在一塊代碼之前設置matadata標簽:dynamic來指定:

          user=> (def ^:dynamic x 1)

          #'user/x

          user=> (meta #'x)

          {:ns #<Namespace user>, :name x, :dynamic true, :line 30, :file "NO_SOURCE_PATH"}

          user=> (binding [x 2] (println x))

          2

          nil

          user=> x

          1

          user=>

           

          如果你想讓函數編譯為static的,并且指定返回值,可以看下面的例子(速度提升不少,關鍵的調用函數可以采用這種方式加速):

           (defn fib [n]   (if (<= n 1)

              1

              (+ (fib (dec n)) (fib (- n 2)))))

          #'user/fib

           (defn ^:static fib2 ^long [^long n]

            (if (<= n 1)

              1

              (+ (fib2 (dec n)) (fib2 (- n 2)))))

          #'user/fib2

          user=> (time (fib 38))

          "Elapsed time: 1831.113 msecs"

          63245986

          user=> (time (fib2 38))

          "Elapsed time: 328.715 msecs"

          63245986

          user=> (meta (var fib))

          {:arglists ([n]), :ns #<Namespace user>, :name fib, :line 1, :file "NO_SOURCE_PATH"}

          user=> (meta (var fib2))

          {:arglists ([n]), :ns #<Namespace user>, :name fib2, :static true, :line 4, :file "NO_SOURCE_PATH"}

          user=>

           

          在上下文中可能需要重定義靜態變量,從Clojure1.3開始提供with-redefswith-redefs-fn這兩個宏來修改。

          定義函數的defn也是Vars的存儲方式,也可以在運行時被重定義。這也為aop編程帶來很多方便,例如:你可以封裝一個類似logging函數給調用的上下文或者或者線程。

           

          (set! var-symbol expr)

          將Vars指定為special form

          當地一個操作符為symbol的時候,它必須是全局變量。當前線程綁定的值就是后面的expr,也就是說必須是Thread-local的才可以,否則將會拋出一個使用set!來設定根綁定變量的錯誤。變量的表達式expr必須有返回值。

          注意,你不能賦值給一個函數的參數或者本地綁定,只能是java的字段Vars Refs和Agents,因為這些數據在Clojure里可不變的。

          使用set為java字段設置值,可以查看 Java Interop.

           

          Interning

          命名空間維護了每個Var對象的全局符號映射。如果使用def定義變量沒有在當前的命名空間找到該符號,就創建一個,否則使用現有的。創建或者尋找的過程被稱作interning。這就意味著,除非Var對象取消映射,否則Var對象每次被查詢,所以請在循環中千萬不要引用Var的全局變量,否則將非常慢,通過let或者binding讓全局變量取消映射來提高速度。命名空間在Evaluation中構建了全局環境,編譯器也把所有free symbols當做Vars來解析了。

          可以使用閱讀宏(Reader)#’來得到Var對象的內部的值。

           

          Non-interned的類型的變量

          可以通過with-local-vars來創建non-interned類型的變量,在free symbol解析的時候將不會被發現,這些值只能被手工的訪問,但是也可以用作當前線程的變量。

          user=> (defn factorial [x]

                   (with-local-vars [acc 1, cnt x]

                     (while (> @cnt 0)

                       (var-set acc (* @acc @cnt))

                       (var-set cnt (dec @cnt)))

                     @acc))

          #'user/factorial

          user=> (factorial 7)

          5040

          posted @ 2012-07-31 01:48 steven.cui 閱讀(1493) | 評論 (0)編輯 收藏

          2012年7月29日

          原文章寫在Google Groups thread里,但是還是值得再說下。

          有朋友把Java和Clojure的一些代碼片段放在Clojure Google group里比較,并提到Java的性能要比Clojure快太多了,疑問到底Clojure能不能趕上Java?

          在我的一個開源項目clj-starcraft中,關于java的性能問題,實際上也是我始終面對的,在我寫這篇文章的時,我的Clojure代碼還是慢了Java代碼6倍(Clojure花了70秒解析了1050個文件,Java則只有12秒)

          然而,70秒對過去的速度而言不算太糟糕,在剛開始的時候,竟然花了10分鐘來分析1050個文件。甚至比我用Python實現的還要慢。

          感謝Java的profiler和熱情的Clojure朋友,下面列出了我在提升Clojure性能方面的一些tips:


          (set! *warn-on-reflection* true)

          這恐怕是最重要的一個提升:打開這個設置將會警告你在任何一處用到Java反射API的方法和屬性。如你所想,直接調用永遠比反射要快,不管哪里Clojure都會你不能解析這個方法,你需要自己用type hint方式來避免反射調用。關于使用type hint,Clojure官方站點給了一個如何使用和提速的例子。

          修復所有關于*warn-on-reflection* 的編譯警告后,我的clj-starcraft從10分鐘降到了3分半。


          強制設置數據類型

          Clojure可以使用Java的基礎數據類型,無論何時在循環的時候,堅決考慮將你的值強制轉換成基礎類型,這將大幅提高你的性能。基礎數據類型在Clojure官方網站有例子和如何進行強制轉換來提高性能。


          使用二元運算符

          Clojure可以在一行里面支持多個表達式,但對于運算操作符,只有在兩個的時候才被inlined,如果你發現自己的運算符已經超過了兩個,或許該考慮重寫你的代碼讓操作符顯示的成為兩個。下面請看兩者之間的比較:

          user> (time (dotimes [_ 1e7] (+ 2 4 5)))

          "Elapsed time: 1200.703487 msecs"

          user> (time (dotimes [_ 1e7] (+ 2 (+ 4 5))))

          "Elapsed time: 241.716554 msecs"


          使用==代替=

          使用==比較數字來代替=,提升性能那是相當明顯:

          user> (time (dotimes [i 1e7] (= i i)))

          "Elapsed time: 230.797482 msecs"

          user> (time (dotimes [i 1e7] (== i i)))

          "Elapsed time: 5.143681 msecs"


          避免vectors的destructing binding

          在一段循環種,如果你想為了提升可讀性從vector中傳出值,考慮下標訪問來代替destructing binding。雖然代碼看起來更清晰,但卻非常慢。

          user> (let [v [1 2 3]]

                  (time

                   (dotimes [_ 1e7]

                     (let [[a b c] v]

                       a b c))))

          "Elapsed time: 537.239895 msecs"

          user> (let [v [1 2 3]]

                  (time

                   (dotimes [_ 1e7]

                     (let [a (v 0)

                           b (v 1)

                           c (v 2)]

                       a b c))))

          "Elapsed time: 12.072122 msecs"


          優先使用本地變量

          如果你需要在循環中查詢一個值,你或許需要考慮使用本地變量(通過let定義)來代替全局變量。看下兩者的時間對比:

          user> (time

                 (do

                   (def x 1)

                   (dotimes [_ 1e8]

                     x)))

          "Elapsed time: 372.373304 msecs"

          user> (time

                 (let [x 1]

                   (dotimes [_ 1e8]

                     x)))

          "Elapsed time: 3.479041 msecs"

          如果你想使用本地變量來提升性能,可以考慮下面比較土的式的方式來避免全局變量:

          (let [local-x x]

            (defn my-fn [a b c]

              ...))

          使用profiler工具:

          JVM有兩個profiler工具, -Xprof和-Xrunhprof,找到程序瓶頸而不是瞎猜。


          最后說明:

          你已經注意到,在這些性能提升中,通過調用百萬量的執行來提升了幾百毫秒的性能。所以,不到萬不得已需要提升性能的時候,沒必要讓你的代碼看起來不夠清晰。

          原文地址: http://gnuvince.wordpress.com/2009/05/11/clojure-performance-tips/

          最后補充:可以通過指定編譯為static方法來提高性能:

          pasting

           

          (defn
            ^{:static true}
            fib
            [n]
            (loop [a (long 1) b (long 1) i (long 1) r (list 1 1)]
              (if (== n i)
              r
              (recur b (+ a b) (inc i) (conj r (+ a b))))))

           

           

          posted @ 2012-07-29 14:15 steven.cui 閱讀(1952) | 評論 (2)編輯 收藏

          2012年7月10日

          第4章  利用右腦


          人應該努力學習洞察和培養自己內心深處的靈光一現,這遠遠勝于外面流光溢彩的整個世界。然而,人總會下意識地拋棄自己特有的想法,僅僅因為那是他自己的想法。

          ——拉爾夫.瓦爾多.愛默生(1803-1882)


          啟動感官輸入:

               研究顯示,使用多感官技術可以讓學生的學習效果提高5倍,目前我本人見過的電子產品ibooks2 已經算是圖文聲并茂的最棒的學習產品了,也許以后全息技術的普及將帶來所有電子感官輸入和交互的一場革命。

               當你困在一個乏味的電話會議或者思考一個棘手的問題時,把玩下回形針或者晚些觸覺游戲能緩解疲勞。

               增加感官體驗以促進大腦的使用。

               在這里作者推薦不是使用商業工具(UML或者類似的東西)直接創建或者記錄設計和架構信息,而是通過積木,樂高積木等等來增加感官輸入。

               為什么這樣做呢?實際就是刺激你的大腦,大腦總是渴望接受這種額外的、新奇的刺激。另外作者提到,團隊成員可以進行角色扮演,試試吧,無意中你可能會想到xx的幾句話真是讓人捧腹,但你卻對這個過程記憶猶新,比你寫上去的或者總結下來的文字要強好多倍。


          用右腦畫畫:

               繪畫既是觀察。

               繪畫是一種R型活動,共享總線被占用,如果你進行的L型活動,同時R型就必須停止。很多休閑活動都能夠激活R型停止L型的占用:聽音樂、繪畫、靜思、慢跑、針線活、攀巖,等等。

               角色扮演:

               書中有個角色扮演的例子,有興趣的可以去看《項目管理修煉之道》,琳達.萊辛描述了扮演的另一個用途:培訓團隊。在向團隊介紹一種新框架的次數屢遭經歷之后,她和同事大衛.得拉諾決定在下一個團隊中用表演來模擬框架。這次,開發人員不再抱怨沒有聽明白,而是抱怨表演簡直浪費時間,因為演出的內容簡直是“太簡單了!”

               這是因為角色扮演真的有效果

               認知轉變,感受R型

               《用右腦繪畫》,或者叫《像藝術家一樣思考》,來自作者的推薦


          促成R型到L型的轉變

               去攀巖吧

               羅扎諾夫教學法(谷歌搜索:羅扎諾夫的音樂暗示學習法)

               酒酣寫作,酒醒修改(R型先行,L型做整理)

               結對編程(一人L型,一人R型),結對編程每個程序員都應該嘗試

               隱喻相同(抽象與具體事物互相融合,嘗試將復雜的計算機用形象化的比喻將給不懂的人,你可以玩玩魔方,實際能恢復不難,轉得快需要很長時間的聯系,本人沒有繼續研究下去的勇氣,但嘗試了恢復的樂趣,是個很有意思的過程)

               并列參照系(隨機并列,也許兩個想法相隔十萬八千里,你卻能將其并列起來。例如,香煙和交通燈可以引出這樣一個概念:在香煙上使用紅色標志區來作為幫助戒煙的提示。)

               系統隱喻(隱喻思維是編程的基礎,因為它存在于所有的抽象思維中)

               講個笑話吧(幽默既不是浪費時間,也不是無害的消遣,而是反映了思維、學習和創造所必須的重要能力。它與聯系有關。培養幽默感以建立更強的隱喻)


          收獲R性線索

               你已經知道

               你是否曾經聽到電臺里播放的一首老歌,然后在若干天突然想起歌名或者歌手?你的R型思維一直在背后異步地思考這個問題,直到最終找到相應的記憶。

               伊萊亞斯.豪的奇遇


           

               在1845年,一個名叫伊萊亞斯.豪的美國人嘗試發明一種實用縫紉機。進展不是非常順利。在經歷了漫長、艱苦、一無所獲的一天之后,晚上他做了一個非常可怕的噩夢,在尖叫中驚醒,直冒冷汗。

               在噩夢中,他身處非洲,被饑餓的食人魚綁架。他馬上就要被扔進沸水里煮死。他努力掙扎,而獵手們就一直用一種看起來非常可笑的長矛戳向他。

               第二天他描述噩夢時說,他的注意力集中在“可笑的長矛”上。因為這些長矛的前端鉤子上有洞,這就像是手持縫紉針上的洞,只不過后者是在末梢上。

               伊萊亞斯接著獲得了自動縫紉機的第一份美國專利,這要歸功于他來之不易的靈感:縫紉機針的洞需要與平常的針持針方向相反。


               利用圖像流

                    1.觀察圖像,努力看清所有細節

                    2.大聲地描述出來(真正發出聲音,這很關鍵)。

                    3.利用全部五種感官想象它

                    4.使用現在時態,即使該圖像都溜跑了。


               利用自由日記

                    寫信是一種偉大的習慣。blog這種模式很受歡迎,wordpress或者blogspot(墻外)推薦。

               晨寫技術

                    早上起來第一件事情。

                    至少寫三頁,最好不用電腦,如果使用電腦關掉所有跟寫作無關的東西(只開evernote)

                    不要審查刪減你寫的東西。不論是優秀的還是陳腐的,只管寫下來。

                    堅持天天寫

               “自由寫”技術

                    開個blog,將你的想法隨時記錄,或者用evernote,保持隨時隨地可以自由寫

               利用散步

                    遇到問題的時候,試著找個安靜的地方散散步,不要坐在電腦旁,離開鍵盤去解決難題。當你不寄希望于它時,就會發現答案自己冒了出來。


          收獲模式

               代碼中的模式

                    如果你不是一個特別在意編碼排版的人,那我可以負責任的告訴你,你離真正程序員的路還很遠,反而用lisp的人,更注意代碼排版,看代碼的時間遠遠高于你寫代碼的時間,如果你連代碼都排列不好,問題自然避免不了。切記,你可以桌子混亂,實際是為了保持上下文不被切換,而代碼卻不能格式混亂,格式都混亂甭提邏輯了。


               換換腦子

                    改變解決問題的角度,前面一章提到過,了解一只青蛙不是解剖它,而是如何創造它!


               神諭沖擊的魔力

                    在古代,教堂的大主教經常通過神諭求的建議。像大多數算命者或者占星師一樣,神諭給予的響應或者信息通常非常模糊,就像謎一樣。你不得不自己來“解釋”它。這就是對大腦的一次沖擊。

                   作曲家布萊恩.伊諾和彼得.施密特提出了一套100種間接策略來換腦。去看:http://www.rtqe.net/ObliqueStrategies/



           

                    例子:

                         這項別的什么東西么?

                         不做任何改變,堅持始終如一

                         關上門,從外面聽

                         錯誤是一種潛在的提示(其實可能不是一種錯誤,一種形態)


               莎士比亞的謎語

                    莎士比亞做過很多語言重造的工作:

                         Full circle(繞圈子

                         Method of the madness(貌似瘋狂實則有理的行為)

                         Neither rhyme nor reason(莫名其妙)

                         Eaten out of house and home(吃的傾家蕩產)


               在此,也感謝譯者(崔康)對本書的給力翻譯,沒有對語言的融會貫通很難將兩者聯系起來,謝謝。


          試一試:


                    使用樂高積木做項目模塊討論。

                    使用雙人機制,讓同伴激勵你,討論你的進展。

                    使用隱喻描述你當前的項目。

                    觀察你認識的專家,看看他們有什么“奇怪”的習慣讓你覺得更能理解?

          posted @ 2012-07-10 01:21 steven.cui 閱讀(382) | 評論 (0)編輯 收藏

          2012年6月19日

          第3章  認識你的大腦

          我們的大腦就是雙CPU,單主機設計總線。




          1號CPU即線性的,也稱為L型處理模式或者叫思考模式。程序員大多喜歡step by step這種方式,一步步的去線性處理。

          2號CPU是非線性的,也稱為R型處理模式,更多的是直接和創造性,但兩者之間訪問內存(大腦)的時候,都是互相搶占系統總線的。


          你的記憶更像是全息影像方式在存儲,在我剛上午看過的書,下午可能就忘記了,但是我看到什么位置竟然是書中的插圖提醒的我。人們對圖像和聲音的記憶更強于文字,L型記錄的是一些循規蹈矩,有規律可循的記憶,而R型則是突發奇想,在你不經意間(睡夢中,洗澡時等等)想到了一個解決方案,R型是異步的,并且有時候是你不經意間,而不是刻意去想就能聯系到另外一件事情上。


          隨時隨地記錄你的想法


               作者的推薦: http://www.pocketmod.com

               語音備忘錄/信箱

               Fisher Space鋼筆

               Moleskine筆記本


          我本人推薦:

               你應該有個tablet/pad(我個人推薦ipad)

               你需要一臺不錯的智能手機可以跟你的電腦或者pad進行同步,iphone? 還是android都可以,屏幕至少4.0寸以上

               軟件方面:EverNote, GoodNotes,Penultimate,OmniFocus,Mindjet, AwesomeNote等等。


          我們每個人都有好點子,可真正付諸實踐的卻少的可憐。



          L型和R型處理方式的特點

               L型:

               處理令人感到舒適、熟悉而放松,提供以下九種能力:

          •      語言能力
          •      分析能力
          •      符號能力
          •      抽象能力
          •      時間能力
          •      推理能力
          •      數字能力
          •      邏輯能力
          •      線性思維能力

               R型:

               非語言性的,喜歡綜合學習,集成事物形成整體。

          • 非語言
          • 綜合
          • 具體
          • 分析
          • 非理性
          • 空間性
          • 直覺
          • 全面

          R型思維能力是很難衡量的,至少比起L型來說要難的多。R型思維更是一種綜合,大局觀的體現,也是一種逆向思維和想象力,創新能力的體現。我個人推薦程序員應該至少了解一門藝術,例如繪畫、攝影、音樂啊等等,這些是R型非線性思維給與你的靈感和想象力,并且會給你猶如突發奇想這樣的奇跡,我們了解一種事物不是通過逆向倒推來了解他,而是通過它是如何出現和創造的而去想如何構建它。我個人推薦,無論學什么至少應該去了解這么技術或者藝術的誕生歷史,為什么如此產生的,為什么會有這樣的想法,想法和初衷是什么?


          作者給出一個很精辟的理論:真正想要了解一只青蛙,傳統的解剖不是辦法,更好的方式是構造一只青蛙。


          綜合學習與分析學習并重。


          設計勝于功能

               無論什么產品,面向的終端用戶都需要理解你的產品。蘋果的ipod的廣告上從來不說能容納多少個G,一個G等于多少多少字節,這樣用戶會瘋掉,誰會聽你扯淡這些他們不理解的東西,他們只需要知道能存放多少首歌曲罷了。


          吸引力更有效

               吸引力的界面比不具有吸引力的界面更易于使用。盡最大努力爭取好的設計,它真的很有效,好的設計也是需要不斷修改出來的。

               美來自于選擇——路易.康,對于一個程序員來說,好的設計很多都是構建于各種選擇(開源穩定的組件),基于某種設計理論SEDA,CELL等等。


          R型看森林,L型砍樹木

               如果你想發現全局、整體的模式,你需要R型,如果你需要分析部分和細節,你需要L型。講述一個程序員看開源項目的例子,在拿到一個開源項目的時候,下面幾個步驟開始:

          1. 了解開源想的初衷和目標,解決了什么問題,把握這個開源項目的方向性。
          2. 開始了解開源項目的大致結構(導出UML圖,或者大致瀏覽項目的接口文件),以及開源項目中依賴的組件。
          3. 有了整體全局觀以后,下來試驗下開源項目提供的tutorial。
          4. 開發調試并親手實踐一個例子,對整個流程有個具體把握。
          5. 嘗試在開源項目上進行你自己項目的試驗和業務邏輯:
            1. 構建一個具體的業務邏輯。
            2. 。。。。
            3. 。。。。
            4. 。。。。
          6. 回頭再來看一些代碼,這樣實踐相結合,更容易理解。


          訓練自己的大腦

               程序員大多數都顯得死板和缺少R型思維能力,學習一些新鮮的事物,可以看看科幻電影或者小說等等,增加自己的想象力,想象力來源于生活,而生活卻是無所不包,包羅萬象的百科全書,你甚至可以說任何的發明都是來源于生活,唯有熱愛生活的人才能做出好產品,產品也許不需要你創造,只是在選擇不同的組合。

          posted @ 2012-06-19 22:40 steven.cui 閱讀(749) | 評論 (0)編輯 收藏

          2012年6月17日

           

           此讀書筆記并不完全作為闡述想法,所以在闡述一些問題的時候可能沒有前因后果,更是一種總結性的話語和書上言語的精華,這有點悖論,如果你想了解,請去看《程序員的思維修煉》,這本書可以跨學科,即便你不懂程序,都值得一看,是從思維和大腦層面來開展介紹的。

           

          2 從新手到專家的歷程

           

               新手到專家需要經歷5個階段(德雷福斯技能獲取模型

               真正的專家不怕考驗,而輕松面對~

               真正的專家很難將自己的行為解釋清楚,而熟練到已經無意識了。

               

               新手:在乎自己是否能成功,不知道自己是對是錯,不是特別想要學習,只是實現一個立竿見影的目標,不知道如何應付錯誤,錯誤出現不知所措。新手需要指令清單,有規則,有順序。但規則只能讓你啟程,不會讓你走的更遠。

               高級新手:高級新手不想要全局思維,當公司在展示全年銷售測量表和數據時,你可能不感興趣,可這預示著明年你在這家公司是否還能繼續干下去。但是,你看不到這種聯系,因為你層次還不夠,只處于較低的技能水平

               勝任者:可以獨立解決自己遇到的問題,并開始考慮如何解決新的問題。處于這樣水平的人通常具備主動性足智多謀,往往在團隊中發揮著領導作用,他們是團隊里的好人,但缺乏足夠的能力——自我反思和糾正。

               精通者:精通者需要全局思維,而且需要更大的概念框架,過于簡單化的信息,他們會非常沮喪。在精通者中,最明顯的特征:自我改進和反思。同時他們善于傾聽別人的意見,并從那些失敗或者成功的項目中認真觀察、學習和總結。

               專家(大師):專家憑直覺工作,并不需要理由。他們有豐富的經驗,并能家當運用,他們著書、寫文章、做演講等等。專家往往通過觀察一些細節(可能常人根本無法覺察到的一些細節)就能判定特征和問題所在,那些無關緊要的會自動過濾更是專家具備的能力。

           

          實踐:

          你不知道自己不知道

                       達爾文:無知往往來自于自信而不是知識

           

          上面兩句話,剛開始理解的時候沒有突然頓悟的感覺,但跟媳婦一番討論后,更加理解了:

          學生問老師自己所掌握的知識到底有多少?

          老師給出了下面的回答:

          你現在的知識就仿佛是一個點,而老師比你要多一些,是個圈,老師知道你不知道的,你有可能知道自己不知道的而老師知道的,你通過學習將來會知道老師知道的,然后超過老師去知道老師不知道的,老師也在不停地學習,但隨著知道的越來越多,也就意識到自己不知道的越來越多,因為越大的圓外面就會有更大的圓。

                       

          達爾文的總結,一語道破了無知的自信(無知者無畏這句古話更是說明了假自信),潛意識層面根本就是不知道自己不知道。有時候自信也很可怕,因為你要確認自己到底是否真的知道。

           

          大師都是憑直覺辦事,可公司更希望通過數據或者規則來確定事情是否是對的,這種方式試圖在毀滅"專家,公司往往輕視專家的直覺,認為這是不科學不可重復。新手使用規則,而專家使用直覺,具備元認知能力metacognitive),或者叫具備自我認知能力的人往往出現在較高層次中。

          知道你不知道什么

          專家!=老師,教學是一門技能,你在某個領域是專家,但這并不能保證你可以將它教給別人。

           

               有效地使用德雷福斯模型

               十年磨一劍,也許需要一輩子或者更長?學漫漫路漫漫,我們需要積極實踐自己:

                需要一個明確定義的任務

                任務需要有適當的難度——有挑戰性但可行

                任務環境可以提供大量反饋,以便于你采取行動

                提供重復犯錯和糾正錯誤的機會

                一旦你成為某個領域的專家,在別的領域成為專家就會變得更容易。你已經有了現成的獲取知識的技能和模型構建的能力。

               軟件開發的職業特征:

                程序員往往認為自己是一種工具,從而漠視工作,只是執行分析師的指令,而不期望自己對項目的設計和架構有所創見。

                由于薪酬等級的不平等,專家級的程序員爭先恐后的離開一線編碼,通過管理、教學或者巡回演講賺更多的錢。

                軟件工程教育開始受到質疑。很多人認為正規的實踐模式是最好的教育方法。這種對正規方法和工具的過度依賴削弱了實踐中真正經驗的作用。

                     R&D精神(Rip off and duplicate, 偷學技藝/偷師學藝),我們可以從他們的工作中借鑒很多經驗教訓并應用到軟件開發中。

           

               勇于承擔責任:

                新手往往只是執行命令,新手過渡到勝任者最大的區別在于能獨立解決問題
          和承擔責任。

                通過觀察和模仿來學習(R&D)。如果你有孩子你會發現,他們很少照你說的做,而是大多時候在模仿你。

                模仿的同時就是實踐的過程,沒有實踐就沒有技能。模仿->吸收->創新

                保持實踐以維持專家水平,全世界最優秀的那些專家沒有因為做了20年以上開發而不去編碼了,實踐是保持技能的唯一手段。

               警惕工具陷阱:

               曾經,在我剛接觸軟件領域的時候,曾一度認為UMLMDA以及TDD是未來解決軟件的必要良方,甚至也將其濫用,然而合宜的工具需要放到合宜的

               環境去運用,模型只是工具,而非鏡子。如果你需要創造力、直覺或者獨創能力,避免使用形式方法。

           

               再次考慮情境:

               高端的顧問最喜歡回答說:具體情況具體分析,當然他們是對的,他們的分析依賴于很多事情——所有那些專業人士懂得去尋找至關重要的細節,同

               時也忽略無關的細節。

               在系統思維中,如面向對象編程,往往是事物之間的聯系最讓人感興趣,而不是事物本身。這也是面向對象化編程的特點,你大多數時候在想事物本身的聯系,而實際問題的解決卻放到了后面,本人的目前的理解是,面向對象編程真的有那么重要么?或許只是在某些方面比較重要罷了,擴展性和低耦合的確是面向對象的實踐的目的,可除此之外純為了面向對象而行動,就存在濫用傾向了。例如java這種語言的面向對象純屬為統一思想而設置的程序員枷鎖。

           

               日常中的德雷福斯模型:

                   新手需要快速成功和與情節無關的規則,而專家需要獲得全貌。理想情況下,你希望團隊里混合各種層次技能水平的人,擁有一個全部是專家的
     團隊存在它的難處。當所有人在考慮森林的時候,你也需要一些人來關注一棵棵大樹。

                   學習如何學習的技能。

           

          總結:

               了解自己出于德雷福斯模型中的哪個階段,并自我評價,了解你的團隊成員,他們的技能階段,以及對你有何幫助。回顧曾經團隊經歷的問題,并運用德雷福斯模型解釋這些問題,對于已知的問題是否能通過德雷福斯模型解決或者避免?

                                   

           

          posted @ 2012-06-17 03:08 steven.cui 閱讀(463) | 評論 (0)編輯 收藏

          2012年6月16日

          java的多線程Thread類提供了setName方法或者通過構造器傳入name,來指定線程的名稱。

          近些時間在開源方面看到Netty,觀察到Netty的重命名線程的策略類:

          ThreadNameDeterminer。這個接口有兩個策略,一個是使用PROPOSED(建議名稱),還有個是CURRENT(當前名稱)

          當前名稱的策略是未實現的,可能為以后擴展考慮吧。

          另外就是ThreadRenamingRunnable這個類,這個類里面構建函數傳入Runnable接口,和proposed建議名稱。

          由于本身ThreadRenamingRunnable也是實現Runnable類的,所以你在自己業務邏輯種還是照樣實現Runnable接口來寫邏輯,完全對業務代碼沒有侵入。

          代碼中大概是這樣的情況:

          public run() {
               //根據規則把線程名字進行修改
               try {
                    runnable.run(); // 調用傳入接口的run方法
               } finally {
                    if (renamed)
                         // 恢復之前的名字
               }
          }


          只需要在構建的你的Runnable的時候,重新包裝一下即可:

          new ThreadRenamingRunnable(new OioWorker(acceptedChannel),

                                         "Old I/O server worker (parentId: " + channel.getId() + ", " + channel + ')'));


          這樣的Decorator模式,重新將Runnable接口進行了“裝飾”,使其具備了線程名稱的功能。

          Runnable接口還是原來的接口,對run方法的再次封裝使其具備了另外一項功能,這就是Decorator模式的精華所在。

          posted @ 2012-06-16 22:32 steven.cui 閱讀(1155) | 評論 (0)編輯 收藏

          判斷一個數是否是2的n次冪

          類似這樣的數字

          1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 …


          if ((n & -n) == n)

          1 public class Is2Power {
          2      public static void main(String[] args) {
          3           for (int i = 0;i <= 1024; i++) {
          4                if ((i & -i) == i)
          5                     System.out.println(Integer.toBinaryString(i) + ", " + Integer.toBinaryString(-i) + " " + i);
          6           }
          7      }
          8 }

          posted @ 2012-06-16 22:26 steven.cui 閱讀(644) | 評論 (0)編輯 收藏

          業務上線后,在有大量并發后,出現了一個線程完全被占用的問題,后來通過得到jvm堆棧信息(kill -3)看出來是死鎖問題。

          由于業務邏輯代碼實在比較復雜,此處濾掉業務代碼把線程競爭關系展示出來:

          1線程———>獲得A鎖———>獲得B鎖———>釋放B鎖————>釋放A鎖

          2線程———>獲得A鎖———>釋放A鎖

          3線程-——————>獲得B鎖———>獲得A鎖


          問題就出在1和3線程之間的AB鎖嵌套導致死鎖問題,1線程在沒有獲得B鎖的時候,3線程開始獲得B鎖然后又得到了A鎖,這時候就完全釋放不了A鎖了,死鎖產生了。

          由于時間關系,問題是理清楚了,只要刪掉1線程的A鎖就可以了,當時還是仔細了解過是否刪除1線程A鎖,發現對業務A鎖是沒必要的。但是線程2會不會也會像剛才一樣產生線程死鎖呢?不會,因為線程2里并不會得到B鎖。

          1線程———>獲得B鎖———>釋放B鎖

          2線程-——————————>獲得A鎖————>釋放A鎖

          3線程———>獲得B鎖———>獲得A鎖————>釋放A鎖————>釋放B鎖


          問題是死鎖,但暴露了兩部分問題:

          1.過早的認為自己能控制好競爭關系,對線程間的競爭過早的做出了判斷

          2.每多設計一個鎖就增加了一個競爭的因素,盡量小心,一個鎖就有可能是一個地雷,一不小心就可能導致嚴重的問題。


          《java并發編程實踐》這本書中介紹過LeftRightLock,詳細了解這個問題的朋友可以去查下這本書的第十章 避免活躍性危險

          此書極其詳細的介紹了LeftRightLock出現的可能,有可能是因為自己編寫程序的疏忽導致,或者由于對鎖的認識不足導致,諸多原因都能找到解釋。

          posted @ 2012-06-16 22:22 steven.cui 閱讀(503) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 榆林市| 大名县| 开远市| 永州市| 郁南县| 社旗县| 铜山县| 洱源县| 沁水县| 遂昌县| 米林县| 新晃| 鹿邑县| 兰州市| 博乐市| 康平县| 武宁县| 黄山市| 南城县| 江西省| 建湖县| 全南县| 奉新县| 晋州市| 澎湖县| 儋州市| 平潭县| 同江市| 北辰区| 凤山县| 当涂县| 且末县| 邵武市| 永年县| 都江堰市| 武邑县| 梧州市| 大姚县| 宁海县| 广水市| 六盘水市|