星期四, 11月 20, 2014

Kanban: Successful Evolutionary Change for Technology Organizations

  • Continuous Improvement Culture
    • bottleneck
  • setup board
  • prioritize
  • WIP
    • preventing workers from becoming overloaded
  • Pull
  • Metrics & Management Reporting
    • Tracking WIP
    • Cycle Time
    • Due Date Performance
    • Throughput
    • Issues & Blocked Work Items
    • Flow Efficiency
    • Initial Quality
    • Failure Load



星期日, 8月 31, 2014

Bowling Game Kata

看了Uncle Bob的建議,每天想來練一下Kata
而Uncle Bob又力推Bowling Game,所以原本想拿來當kata練一下不同的語言

沒想到實做之後,才發現這是個滿棒的kata
邏輯不會太難,但可能寫成超複雜的,滿多重構的行為,而且很適合當TDD的教材
把所有的team member都抓來練習一下

以下整理最近帶team member的心得
  • Refactoring (clean code)
    • 變數、method的命名
      刻意讓team member命名滾球、局數
      最後讓大家猜別人命名的意思
      最後讓大家直接用保齡球的術語roll, frame
      clean code: 不懂時,直接請domain expert命名,至少以後domain expert能夠說出這是什麼
    • redundant code
      去除重覆的程式
    • decompose condition
      讓程式變的更加clean, isSpare,isStrike,getSpareBonus那段
    • 隱藏細節
      上一段的延伸,有些team member把整段getSpareBonus做成calSpareBonus
      感覺上沒什麼差,但在看code感覺差很多
      • calSpareBonus
        這個function叫做score(算總分),因此這function最重要的事就是"算分數"
        但這裡把算分的邏輯隱藏了,因此未來看code的人,不易注意到score被其他function異動了
        int score = 0;//成員變數 - 總分 
        public int score(){
            //略
            if (isSpare())
                calSpareBonus(); 
            //略
        }
      • getSpareBonus
        關於score的異動,能夠清楚掌握
        而Spare的Bonus算法在這不重要,因此隱藏起來
        讓程式更容易閱讀
        public int score(){
            int score = 0;//總分
            //略
            if (isSpare())
                score += getSpareBonus(); 
            //略
        }
  • Pair-Programming
    自己開發會有盲點,跟幾個同事練習的過程中
  • 在算跨局的輯邏會想的滿複雜的,但partner會參與討論 也許沒能討論出更好、更簡單的解法,但至少那段神邏輯有另一個人"看的懂"
  • TDD
    只滿足目前的需求即可
    開發上,大家容易被分數算法綁住,因此一開始想把邏輯寫對
    但這不太容易,因為算法還得考慮Spare, Strike,因此一次要把邏輯寫出來有點難
    寫完,你也不會寫test case了,因為已經寫完繳卷了

    這點最適合TDD指的只滿足目前的需求即可
    先寫個最簡單的算法驗證,再來spare,再來strike,一個個拼出完整的邏輯
    也許整個寫法得翻掉重寫,但令人放心的是test case已經寫好了
    所以可以放心重寫

    雖然一直說TDD很棒,但沒實際體會過,大家只會覺得很難達成
    實際經歷好幾次的大改結構,但重新測試的時間,卻只是一瞬間
    大家就能體會TDD好處

回想其實好久以前就看過這Bowling Game的練習(很多對話那個)
不過就只有用"看"的,沒有實際寫過,身體力行的體驗果然不一樣
大家也來kata一下

p.s. 不過我以為這保齡球算法的方法大家應該都瞭解
沒想到大家都忘了... 話說上次打應該也是5年前了...

更多的Kata題目

星期六, 8月 23, 2014

CentOS 7 無法access apache

前陣子聽到CentOS 7出了,載下來裝好發現連不到網頁
搞不清楚問題在哪,最後猜是SELinux~
# sestatus
SELinux status:                 enabled    
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        targeted
果然是開啟的
再來就來關掉selinux
改成disabled
# vi /etc/selinux/config
--
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#       enforcing - SELinux security policy is enforced.
#       permissive - SELinux prints warnings instead of enforcing.
#       disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
#       targeted - Targeted processes are protected,
#       mls - Multi Level Security protection.
SELINUXTYPE=targeted
再一次
# sestatus
SELinux status:                 disabled

很高興的以為抓到問題,但restart後一樣連不到... QQ
試好久,猜應該是firewall問題
果然一查CentOS 7 firewall,就找到答案了
以下截錄 關閉 CentOS 7 上的 Firewall
關閉 Firewall
# systemctl stop firewalld

預設不啟動 Firewall
# systemctl disable firewalld
rm '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'
rm '/etc/systemd/system/basic.target.wants/firewalld.service'

總於... 連的到網頁了... ya

星期日, 8月 17, 2014

How to undo the last Git commit?

如何調整已經commit的.... commit



$ git commit "待調整的commit"   (1)commit後
$ git reset --soft 'HEAD^'       (2)回剛才的commit 
$ edit                           (3)重新調整
$ git add ....                 (4)
$ git commit -c ORIG_HEAD      (5)跳視窗修改commit message"待調整的commit"


p.s. 上次回復(revert)到太早期的版本,造成一堆commit都不見
幸好git還是有保留下來,不然就挫咧等...

星期六, 8月 16, 2014

[書]The Clean Coder

滿精采的一本書,讓開發人員要自我要求,更要表現出專業,勇敢的說Yes/NO

Chapter 1. 專業主義
  • Minimal-list
    Uncle Bob說軟發開發人員"至少"需"精通"的項目
    • Design Patterns
    • Design Principles
      SOLID
    • Methods
      XP, Scrum, Lean, Kanban, Waterflow,結構化分析及結構化設計等
    • Disciplines
      TDD, OOD, Continuous Integration, Pair Programming
    • Artifacts
      UML, DFD, 結構圖, Petri網路圖, 狀態圖,流程圖和決策表
Chapter 2. Say "NO"
能就是能,不能就是不能。不要說「說說看」 --Yoda
每次專案一趕,就一定會說的話... (泣)

Chapter 6. 練習
熟能生巧,訓練手指和大腦,每天來一、兩個kata保持技巧純熟
reference: Code Kata
  • Bowling Game
  • Prime Factors
Chapter 9. 時間管理
開會的成本很高,有時又是沒有效益的
管理自己的時間是自己的責任
  • 離席
    如果發現會議是在浪費時間,應在合適的時機,禮貌地離席
    如果已經偏離原有的議程,應要求列新的議題和議程
  • 爭論/反對
    Kent Beck:凡是不能在5分鐘內解決的爭論,都不能靠辯論解決。」因各方拿不出「足夠有的有的證據」
    唯一解決方法是「去取得資料,讓資料來說話」

星期六, 8月 09, 2014

Google表單發確認信

Google表單挺方便的,又是免費使用,資料又自動整理到Google Drive的試算表
而內含的編輯器也可加trigger發送確認信


  1. 新增表單
    點選「新增/Google表單」
  2. 查看回應
    表單的設計就不多說了,直接看回應
    點選「查看回應」
  3. 編輯指令
    點選「工具/指令碼編輯器」
  4. 新增Script檔案
    點選「檔案/新增/指令碼檔案」
  5. 編輯Script
    以下程式碼即為上圖的程式,參考以下改來的
    reference: Send Google Forms by Email
    /* Send Confirmation Email with Google Forms */
    function SendGoogleForm(e) {  
      var message = '';
      for (var filed in  e.namedValues) {
            message += filed + ": " +  e.namedValues[filed] + '< br />';        
        }
         var recipient = e.namedValues['電子信箱']; //e即為回覆的試算表,而namedValues即取得該欄位名的內容
        var cc = 'yup.japan@gmail.com';          //cc一份給自己
        var subject = "Yup!代購單確認單";
        var sendername = 'Yup!代購';
        var textbody = message.replace('< br />', '\n');
        GmailApp.sendEmail(recipient, subject, textbody, 
                                {cc: cc, name: sendername, htmlBody: message});
    }
    
    function Initialize() {
      var triggers = ScriptApp.getProjectTriggers();
     
      for(var i in triggers) {
        ScriptApp.deleteTrigger(triggers[i]);
      }
      
      ScriptApp.newTrigger("SendGoogleForm")
      .forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
      .onFormSubmit()
      .create();
    }
  6. 啟動程序
    寫好Script,現在還得設定觸發
    點選「資源/現在專案的啟動程序」
    p.s. 如果仍收不到信的話 要先跑一次initialize(),手動執行or設觸發都可
  7. 新增觸發程序
    由於尚未建立任何觸發程序,因此會跳出這個視窗
    點選「尚未建立觸發程序,按一下....」
  8. 設定觸發程序
    設定user提交表單時,才會觸發程序

這樣就完成了,user提交表單後,就會發信通知

p.s. 在google form及google試算表都可以寫script,但在form觸發會抓不到內容
p.p.s. 好像得先按「執行」run過一次程式裡的Initialize()

星期日, 7月 27, 2014

如何寫unit test

以前覺得unit test不就寫test case
想到啥,就寫啥,沒有目標的亂寫
記得以前連搬檔案都寫了一個case來測
最近領悟了點東西,趕緊來整理一下

  • 測試資料
    寫test case最麻煩的地方在準備測試資料
    由於資料大多存取DB,因此得準備一個測試DB
    但資料被改後,還得再倒回去,否則test case會fail
    以前都用dump,再整個倒回去
    開發上還挺累人的

    個人測試還好,多人用同一個測試DB,就會互相蓋DB
    難道要一人一DB嗎... 這提出申請,一定被上頭打槍...

    後來才瞭解,這不是unit test
    這已經是integration test(接DB)
    unit test應該在幾秒內跑完才叫unit test
  • 利用Mock & Stub模擬測試資料
    後來就利用這做法,避免接DB,及外部API的動作
    說方便... 是比接DB方便... 但也還好...還是得寫一堆code,只為了準備測試資料
    想利用TDD寫好unit test,還是挺花時間的
    要說服其他人用,力道上還是不夠
  • 測邏輯就好
    直到前陣子,Kent Beck, Martin Fowler及DHH在討論「 IS TDD DEAD
    DHH在說實務上用TDD不可行,當然是被兩位大師訓了一頓...
    不過影響最深刻的是Martin Fowler說他幾乎沒在寫Mock

    實在太令人驚訝了...居然沒在寫mock.....
    很想實際看一下些大師怎麼寫的...

    雖然還是不知道大師怎麼寫的
    不過自己重新領悟unit test就是在測試邏輯
    即然是測邏輯.... 那.... 就把邏輯這段再抽成一個function獨立出來就容易測了
    YA~~
    現有終於可以輕鬆的寫test case (泣)
當然~ 難免有些地方還是不好寫unit test
大師也說... 不好寫的就不要刻意寫,工具有他的極限
不要硬寫,而搞死自己 <= 好吧 這句是我自己將來為了辯解沒寫unit test的藉口

星期日, 7月 13, 2014

[書]敏捷與Scrum軟體開發速成

最近在聽同事在提Scrum
自己的team都是用XP開發
Scrum這詞也聽好幾年了,但一直不知道有何差異
聽完同事說的,還是掌握不到做法
有點見樹不見林的感覺
說完還是不知怎麼做











今天正好路過書店逛了一下
看到「敏捷與Scrum軟體開發速成」Amazon有4.5顆星的評價
嘖嘖~ 直接買來看

章節安排挺不錯,很順暢的一篇篇讀,也不會太多廢話,有些真的話很多...
從敏捷方法的緣起說起
再強調敏捷的價值觀與原則,不會硬套方法
最後帶入實務做法
感覺讀完就上手了~ 怪不得4.5顆星了~
近期來試一下...

翻譯也挺不錯的,用詞都很到味,可以感覺譯者懂這方面的domain knowledge
譯注也很用心在寫,第一次看過這麼多譯注
某些文化梗也有翻,而有些資料也得花時間找~
真是佛心來著~

星期五, 5月 23, 2014

程式應易抽換,而非再利用

幾年前看到這句話「程式應易抽換,而非再利用」,一直看不懂這意思
過去觀念一直是程式應模組化,以便「重覆使用」
怎麼會這麼說呢

最近在學軟體架構,講師又提到這詞
沒說沒感覺,再回去review Design Patterns
還真的都在說易更換,而非重覆使用
為什麼呢

先看這句Prefer composition over inheritance (組合超越繼承)
這句話也讓我想了很久
物件的好處不就是要繼承嗎?
怎麼又要我們不要用繼承,那過去在學的是什麼

原因1:父類別的改變就會直接影響所有的子類別
原因2:因為程式只會對父類別操作,所以子類別需熟悉父類的實作(例如父類別的function實作二件事,而子類別只實無一件事)

因此用composition不會影響原結構而且易於抽換不同的物件
所以"Prefer composition over inheritance"
而這句就代表了「程式應易抽換,而非再利用」

真是太深奧了...

星期四, 5月 08, 2014

DB 記憶體緩慢上升

最近DBA提到DB的記憶體有緩慢上升的問題

後來知道這是DB的機制,本來就會把記憶體吃滿
但DBA還是提出這樣他無法告之記憶體是否需擴充

針對這問題得看塞的內容是什麼
經過分析,我們的sql plan重複使用太低
也就是sql statement不重複,造成每次得重新compile新的sql

  • 減少Compile次數
    • 使用Stored Procedure
      微軟建議SQL compile 不要超過 Batch Request的10%, 但我們的系統大約在40%
      因此建議我們用Stored Procedure,當然我們沒用這方面
    • 使用prepare(bind)
      我本以為prepare只是用來過濾sql injection
      原來db在執行時,也得把sql statement先compile過
      因此where的條件不同,就會被當成新的statement

      這時便可透過prepare,把參數給參數化 (我想不到更好的詞了 Orz)
      如此一來該句只會被compile一次~

      p.s. sql也是需被compile的,嗯... 我從沒想過這問題...

    • PHP的PDO未實際改寫
      我們早就用bind的方式寫sql,但不曉得為何仍沒有轉換
      後來才發現原來PDO沒有實際轉換,而只是replace而已
      p.s. 不確定是PDO or 其他地方,先拿PDO當替死鬼


星期一, 3月 03, 2014

tmux亂碼

把vi設定好後,本以為完成了
set encoding=utf-8
set fileencodings=utf-8,cp950,latin1

但有時正常,有時又亂碼,一直搞不懂
cli下的中文是「?????」
而vi下的會是「______________」

後來發現在進tmux後,才會發生這問題
查了一下,加上以下這段再重開tmux就可以了
vi ~/.bash_profile
export LANG="zh_TW.utf8"
export LC_ALL="zh_TW.utf8"

Reference
tmux,亂碼已成往事

星期四, 2月 20, 2014

MS SQL資料庫定序(Collation)的議題

問題
當兩個column join時,而兩個定序不同,這時這個sql session就直接死給你看

解決方法
  1. 從db設定(但資料要重建)
    db, column都可以指定
  2. sql query直接指定
    SELECT str FROM test ORDER BY str COLLATE CHINESE_TAIWAN_STROKE_CI_AS
CS_AI vs CI_AS 傻傻搞不清楚
  • CaseSensitive_AccentInsensitive
  • CaseInsensitive_AccentSensitive
其他還有WS (Width sensitivity),即全型、半型字是否相同

Reference

星期日, 2月 09, 2014

[書]even faster web sites performance-best practices for web developers

針對js, css, image, browser等深入探討,以求最佳的效能


Ch1. Understanding Ajax Performance

Trade-offs - Fast. Good. Cheap. Pick Two.
  • 低於Inefficiency line就會流失user
  • 先利用YSlow改善
  • 利用ajax可大副降n,當然前提要考量ajax本體application要小
  • 事後再抓資料呈現
  • DOM及CSS的處理比JS的速度慢的多,針對JS加速不如小心處理DOM及CSS

Ch.2 Createing Responsive Web Applications

What is fast enough
  • ajax實現快速反應系統
  • 只針對不夠快的程式調整,重點是如何定義「不夠快」
    • 0.1 second : Limit for users feeling that they are directly manipulating objects in the UI. 例如hover
    • 1 second: Limit for users feeling that they are freely navigating the command space without having to unduly wait for the computer. 0.2秒~1秒會感覺在運作
    • 10 seconds : Limit for users keeping their attention on the task.
  • 也就是說application要在0.1s內啟動, 在1s內有所回應
  • 超過1s會讓user感覺到慢, 超過10s.... 該調程式了...

Meausuring Latency
  • 可利用firebug的profiler找出js的執行時間
  • Threading - js沒有mutilthread,不要想有的沒的 這只會把程式搞複雜
  • HTML5有Web Workers可達到threads效果,拿來當背景程式跑長時間的script
  • 如果browser不支援,google有Gears plugin-in

Effects of Memory Use on Response Time

  • memory也會造成效能issue
  • 在run GC時,會run整個heap,回收不再使用的物件,因此大量使用下,會讓系統發生短暫凍結
  • OS會提供virtual memory這比實體memory慢的多
  • Troubleshooting Memory Issues
    • 針js的memory沒有神器,只能追問題所在,參考 http://blog.pavlov.net/2008/03/11/firefox-3-memory-usage/
    • Use the delete keyword to remove JavaScript objects that are no longer needed
      from memory.

ch.3 Splitting the Initial Payload

  • 必要的application script先讀,不重要的後讀
  • 不相關的script模組就不要讀
  • 後讀的ui相關script要能先呈現loading圖示,避免user使用(lazy-loaded code)
  • stub function
    • 先回應空的,等載完後再覆寫
  • splitting script & CSS都能達到效果

Ch4. Loading Scripts without Blocking

  • 下載external script 會造成blocking(下載中的資源不會被擋)



ie8, Safari 4, Chrome 2可同時下載,但得等js載完且跑完,才會再下載其他資源
有方法可避開blocking的問題,但同時也有race conditions問題
即script如有順序問題,後者先執行會發生錯誤
解決方法
  • XHR Eval
    • 當資源載後,用eval
    • 缺點:需在同一domain
  • XHR Injection
    • 把js當dom方式插入
    • 缺點:比eval慢
  • Script in Iframe
    • 開iframe把script當html下載
    • 缺點:需在同一domain, iframe耗資源
  • Script DOM Element
    • 方法:create個dom,改src,簡單易懂
    • var scriptElem = document.createElement('script');
      scriptElem.src = 'http://anydomain.com/A.js';
      document.getElementsByTagName('head')[0].appendChild(scriptElem);
  • Script Defer
    • 增加defer屬性,可平行下載
    • 缺點:只有ie支援
  • document.write Script Tag
    • 類似defer,可平行下載
    • 缺點:只有ie會平行下載
Ensuring (or Avoiding) Ordered Execution
利用script src寫法可確認依序下載


Ch.5 Coupling Asynchronous Scripts

Ch.6 Positioning Inline Scripts

Ch.7 Writing Efficient JavaScript
Managing Scope

Ch.8 Scaling with Comet

Ch.9 Going Beyond Gzipping

  • Besides proper configuration of HTTP caching headers, enabling gzip compression is typically the most important technique for speeding up your web page
  • 目前的browser都支援gzip,但會因firewall或防毒軟體限制而禁作gzip
  • 針對這些可以有以下做法
    • Design to Minimize Uncompressed Size
      • Use Event Delegation (選完才載入)
    • Use relative URLs
      • 同網站內的uri可以用相對路徑,這樣文字相對少
    • Strip whitespace
    • Strip attirbute quotes
      • html裡的attribute內容如為純文字(含括號,底線,分號等)可省略雙引號
    • Avoid inline styling
      • style多為重覆使用,寫在css共用
    • Alias JavaScript
      • Wasteful
        • var foo = $("foo);
        • foo.style.left = "0";
        • foo.style.right = "0";
      • Better
        • var foo = $("foo).style;
        • foo.left = "0";
        • foo.right = "0";
  • 以上約可節省11.7的傳輸量
Educate Users
  • 發生user不支援Accept-Encoding,應給個訊息提供,教育user
    • ex. Your Internet connection is slowed because it does not allow compression.
    • 不過經過proxy來的是無法解決的
Fix this Hide

Ch.10 Optimizing Images

  • GIF - 適用小動畫
  • PNG - 適用圖表(graphics - icons, logos, diagrams) 
  • JPG - 適用照片(photos)
Truecolor versus palette image formats
Interlacing

Stripping JPEG Metadata

  • Comments
  •  Application-specific (e.g., Photoshop) internal information
  •  EXIF information such as camera make and model, the date the photo was taken, the geolocation of the photo, thumbnails, or even audio

Ch.11 Sharding Dominant Domains

Ch.12 Flushing the Document Early

Ch.13 Using Iframes Sparingly

Ch.14 Simplifying CSS Selectors

  • 將css置於head中,以提高progressive rendering. (See High Performance Web Sites, Chapter 5.)
  • ie可能發生css expression被執行上千次
  • 避免inline styling,以減少download size
CSS Selectors有以下幾種方式
  • ID SelectorsExample: #toc { margin-left: 20px; }Simple and efficient
  • Class SelectorsExample: .chapter { font-weight: bold; }
  • Type SelectorsExample: A { text-decoration: none; }a lightweight way to add styling to all elements of a specified type, without having to add any extra characters
  • Adjacent Sibling SelectorsExample: H1 + #toc { margin-top: 40px; }
  • Child SelectorsExample: #toc > LI { font-weight: bold; }找出#toc下所有的LI(1層)
  • Descendant SelectorsExample: #toc A { color: #444; }找出#toc下所有的A(n層)
  • Universal SelectorsExample: * { font-family: Arial; }
  • Attribute SelectorsExample: [href="#index"] { font-style: italic; }
  • Pseudo-Classes and Pseudo-ElementsExample: A:hover { text-decoration: underline

以下討論performace

Rightmost First

Consider the following rule:
#toc > LI { font-weight: bold; }
由於id最有效,因此大家會認為先找#toc,再找底下的LI是較好的方法(左到右)
但其實browser是從右到左,因此這段selector反而相當沒效率,但先找出所有的LI,再看他的parent是不是#toc
可以想見Descendant Selectors就更差了,所有的node除非找到#toc,否則都要走完

Writing Efficient CSS Selectors

  • Avoid universal rules
    In addition to the traditional definition of universal selectors, Hyatt lumps adjacent
    sibling selectors, child selectors, descendant selectors, and attribute selectors into
    this category of “universal rules.” He recommends using ID, class, and tag selectors
    exclusively.
  • Don’t qualify ID selectors
    Because there is only one element in the page with a given ID, there’s no need to
    add additional qualifiers. For example, DIV #toc is unnecessary and should be

    simplified to #toc.
  • Don’t qualify class selectorsInstead of qualifying class selectors for specific tags, extend the class name to be specific to the use case. For example, change LI .chapter to .li-chapter , or better yet, .list-chapter.
  • Make rules as specific as possibleDon’t be tempted to build long selectors, such as OL LI A. It’s better to create a class, such as .list-anchor, and add it to the appropriate elements.
  • Avoid descendant selectorsDescendant selectors are typically the most expensive to process. Child selectors are often what’s intended and can be more efficient. It’s even better to follow the next guideline to avoid child selectors as well.
  • Avoid tag-child selectorsIf you have a child selector that is based on a tag, such as #toc > LI > A, use a class associated with each of those tag elements, such as .toc-anchor
  • Question all usages of the child selectorThis is another reminder to review all places where child selectors are used, and replace them with specific classes when possible.
  • Rely on inheritanceLearn which properties are inherited, and avoid rules that specify these inherited styles. For example, specify list-style-image on the list element instead of on eachlist item element. Consult the list

星期六, 1月 18, 2014

利用git管理production及development程式

個人開發可利用branch避免開發中的code影響緊急bug修正的問題
不過在團隊開發下,不曉得怎麼區分管理

看了網路上的建議,自己簡化為
建立production branch
1.開發用master
2.緊急上版用production修bug

另外...
由於公司內規定得透過包版上patch
而公司用CCCQ管理包版,因此每次都得再重上程式
這辦法也解決每次上patch都不確認是否有包到這次異動的檔案
看production merge後異動的檔案,即為patch內容
真是太棒了

不過
其實作者是建議切成staging, development, production三個
前者可拿來驗證後才准入後者
但是上測試機一樣得進CCCQ,才能包版更新... 所以就沒考慮了
反正開發機試完,只能進CCCQ上測試機...

Reference
Developing and Deploying with Branches