星期四, 6月 02, 2016

[Coding Style] Train Wrecks

啥系Train Wrecks
字面上來看就是”火車事故” 或 “火車殘骸”
Train Wrecks

這裡是用來比喻以下的程式碥
滿常看到程式寫成這樣
這樣的程式很難理解,因為有4個objects需理解(ctxt+3個getXxx)
而這裡有三層,短短一行就得讀很久

那該怎麼寫呢

1.Split
閱讀者可以直接看到Class Type會比較容易閱讀些
不過也不是很好

2.寫成屬性呢
比function好一些,畢竟function還有logic,而property就單純些
不過會expose internal structure
所以也不是很建議

3.Hybrids
省略…看標題應該就懂了…

4.Hiding Structure
最好的方式,就是不要讓人想,所以細節直接包起來最快
直接在ctxt寫個function,不用看細節(這招真好,不虧是Uncle Bob)
p.s. 這裡小小的跳過一段,程式最終的用意是要取file path,再寫file,所以直接回給OutputStream


總結
過去就一直覺得Train Wrecks的寫法很難閱讀
幸好被大師指正,有理由可以不這樣寫了

Reference
唔... 我忘了...

星期四, 4月 14, 2016

第一次 的引導經驗

預先準備


  • 題目:開發流程自省會議
  • 目標:讓不同開發Team瞭解彼此的開發流程
  • 設定:每個人都有發言,對話有堆壘
  • ORID的問題內容
    • O
      • 開發過程有有什麼會議
      • 參與的角色
      • 會議時間
      • 有什麼產出
      • 會議用途、目標
    • R
      • 對於各種會議的感受
    • I
      • 為何感到XX,能具體說明嗎
      • 遭遇到什麼問題
      • 有什麼方法可以克服
    • D
      • 下次發生,會有什麼做法

成果


  • 大家有聽到不同的聲音
  • 對話也有堆疊,感覺不錯

好的地方


  • 連貫性的題目
  • 原本以為容易回答,反造成大家會等待說出該項目的成員持續回答後續問題
  • O的題目是要讓大家開口,當下有發現,趕緊換問法"有誰能說出更多xxx"
  • 讓每個人發言
  • 有1,2位也許因主管在而沒開口,除了直接指定外,最後請每個人分享心得,算有讓對方願意開口說
  • 改掉主持人式風格
    • 儘量以"大家覺得","誰能夠說明"或"還有人要補充",取代指名

改善


  • 聚焦與發散
  • 原寫下幾個提出的會議想聚焦,卻反而讓大家圍繞到白板上的題目
  • 也許是題目本身就太大

星期六, 3月 26, 2016

JavaScript Convention

JavaScript不應該四散在html裡
至少應寫成獨立的js

  1. html較小,能較快的呈現
  2. 雖然需另一個request取js,不過該js可被cache


三種類型的js檔
1. 3rd-party js
a. jQuery
2. Component.js
a. Untity.js
b. 自行開發
3. Local.js

原則上禁止寫js在html裡,不過某些例外還是方便簡單
1.寫在html tag裡比較方便

1. Close Window


2. Back to Previous Page


2.local.js 只有一小段
如果只有幾行… 就算了啦… ( 20行內)

Reference
Top 10 JavaScript Snippets for Common Tasks

不要挑最便宜的產品,要挑品質好一點的產品


購買東西時,通常會拿最便宜的就好,例如:捲筒廁紙
原本想說這東西不就拿來擦屁屁的,哪會有什麼差
本來沒注意,但有次去高檔餐廳上廁所
隨意撕就延著切線完美的撕下
但家裡的,每次撕都會殘留下一小段沒撕完整
這才發現怎麼差這麼多

「最低價」導向會造成惡性循環

挑最便宜的產品等於鼓勵廠商追求低成本
當然成本能低是好事,好一點廠商自我改善,降低營運成本,讓售價可以比市面更便宜
但就會有廠商會偷工減料,或是用差的原物料
更沒良心的就是用傷身的手法使成本更低(用化學藥劑等)

有良心的廠商成本比別人高,沒有獲利而倒閉
最後留下一群黑心廠商,繼續拚低價,更嘗試更可怕的手法

你們亞洲人命不值錢

上次聽在汽車製造業的朋友提到汽車安全係數問題
板金要厚,安全係數才會高,但相對會耗油
他們實在做不出安全係數高,又不耗油的汽車

因此找來日本某汽車 大廠的顧問,詢問究竟如何打造安全係數高又省油的車
顧問回答:「板金薄一點,就省油啦,安全係數低沒關係,反正你們亞洲人命不值錢」
朋友當下聽到有點生氣,怎麼這麼說話,但顧問繼續說:
「這是你們自己選擇的,你們只在意耗油,不在乎安全」

我是不知道朋友的反應,但自己是滿汗顏
因為我也會挑省油的,而這正是我們逼廠商要走的方向
是我們自己選擇的...

這東西太便宜了,是不是有問題呀...

公司附近有A, B兩間小吃店,兩間都有相同的一道湯-「蕃茄蔬菜湯」
A的價格較貴,料較少,湯頭也淡,且沒冷氣
而B的價格較便宜,料也多,且湯頭也好喝,還有冷氣!
請問你會挑哪一間的湯?

當然是B呀,CP較對高,而且有冷氣
但... 反過來想想... B的材料是不是有問題呀
那有每樣好的呀...

後來A沒營業了,雖然不知道跟生意有沒有關係
但總覺得怪怪的,我也不太敢跟B買湯喝

「品質」導向才能形成正向循環

最近有體會到,挑商品應注意「品質」
用品質好一點,是為了讓好的廠商留在市面上
這裡是說挑品質好一點,不是挑貴的
也許品質好一點會貴一些,但重點是讓好的廠商可以存活下來
而且這會是一個好的正向循環




星期日, 3月 20, 2016

JavaScript Convention - 全域變數篇

為Application建立一個全域物件
所有變數、函數都放置於底下
/* 最上層進入點 */
//全域物件
var APP = {};
 
 
//模組物件容器
APP.modules = {};
 
/* 各模組進入點 */
//ex. 商品詳細頁
APP.modules.productDetail = {};


加上防禦性
/* 最上層進入點 */
//全域物件
var APP = {};
 
//模組物件容器
APP.modules = {};
 
/* 各模組進入點 */
//ex. 商品詳細頁
var APP = APP || {};
APP.modules.productDetail = {};

證人初體驗

最近因朋友遇到些問題,被傳去當證人
雖然覺得照實回答即可,不過過程中對方律師會挖洞給你
造成自己前後回答的矛盾,我方的律師就說那故意設定的
事後想想真有感覺是中對方的圈套

寫一篇當心得,也好提醒自己要改進的地方

心得一:別緊張,放輕鬆
一緊張腦子一片空白,自己都不知道自己在說什麼

心得二:事前準備
事情經過如何,先想過,回答就很順口

心得三:不用加油添醋
有時為了強調會加點東西,但反而越講越不清楚,更造成自己前後矛盾
這次就是中這個計,對我方有利的點,就說了幾個,對方律師就刻意說"只"有這樣而已
很自然地多說了幾點,說出了對方期望我跳進去的洞,就提出證據說並沒有這一點

事實是什麼就是什麼,不用加油添醋

最後還是要再強調一次 --- 別緊張,放輕鬆!!!
事後再看對方提的證據,根本就跟我說的沒關係
是自己緊張到壓力大,就自亂陣腳了

在很多有衝突會議上也是,有時被嗆了幾句
壓力大到眼前一片黑,什麼東西也想不到
但事後回想到好方法回擊,但已經晚了幾個小時

技巧
最近看一本書「邏輯贏話術」學了幾個不錯的技巧
辯論前,有以下正面的想法(依情境不同),就能有效積極面對

  • 辯論
    • 我是來練習改進我的辯論技巧
    • 我會達成這一切
    • 不入虎穴、焉得虎子
    • 放棄奮鬥就等於失敗
  • 演溝(面對大眾)
    • 我要表現出自己最好的實力
    • 我很棒
    • 我很懷疑,這些聽眾是否真能聽得我的報告




星期一, 12月 21, 2015

Java Web Services and Security 課堂筆記



  • 過去有PRC, RMI, COMBO,不過都過時了
  • Base64會做Binary大1/3倍,300KB=>400KB
  • XML定義
    • Well-Formed XML
      • 有PI
      • 唯一root
      • 對應的tag
      • 大小寫有分
    • Validated XML(Valid XML)
      • DTD
      • XML Schema
  • 歷史
    • XML已式微,但有其功能
      • 交換資料可驗證
        • ex, 潤年 2015-02-29(不需AP判斷)
    • SOAP也式微,但
      • 電子簽章等
      • 自己寫也可以... 所以有點雞肋
  • 名詞
    • AP Server
      • Web Container
      • EJB Container
      • 實做Jave EE製定的規格
    • Tomcat只有web container及實做一點點Java EE的規格
  • 名詞
    • REpresentational Service
      • 可output各式的format, json, xml, csv, ...
  • Convention
    • db命名單數 tb_member
    • RESTFul複數 members
  • JSON定義
    • [ { a: 1 } ] , 不合法(但可用),最上層要加{ }
    • [ ]的Security Issue
    • javascript會呼叫array construction,而js允許亡寫array的constructor,駭客可透過此攻擊系統
    • 修改方法:利用{ }包起來





星期一, 12月 14, 2015

加強json_encode的xss 防禦

由於常把資料從db拉出來,再整個json_encode丟給前端
因此要一個個filter還挺累的
如果可以直接對encode過的string filter最好了~

幸好json_encode有好用的參數
完整參數如下
json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS);
PHP官網有完整範例,以下截錄
$a = array('',"'bar'",'"baz"','&blong&', "\xc3\xa9");

echo "Normal: ",  json_encode($a), "\n";
echo "Tags: ",    json_encode($a, JSON_HEX_TAG), "\n";
echo "Apos: ",    json_encode($a, JSON_HEX_APOS), "\n";
echo "Quot: ",    json_encode($a, JSON_HEX_QUOT), "\n";
echo "Amp: ",     json_encode($a, JSON_HEX_AMP), "\n";
echo "Unicode: ", json_encode($a, JSON_UNESCAPED_UNICODE), "\n";
echo "All: ",     json_encode($a, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE), "\n\n";

Normal: ["","'bar'","\"baz\"","&blong&","\u00e9"]
Tags: ["\u003Cfoo\u003E","'bar'","\"baz\"","&blong&","\u00e9"]
Apos: ["","\u0027bar\u0027","\"baz\"","&blong&","\u00e9"]
Quot: ["","'bar'","\u0022baz\u0022","&blong&","\u00e9"]
Amp: ["","'bar'","\"baz\"","\u0026blong\u0026","\u00e9"]
Unicode: ["","'bar'","\"baz\"","&blong&","e"]
All: ["\u003Cfoo\u003E","\u0027bar\u0027","\u0022baz\u0022","\u0026blong\u0026","e"]
Reference
Example #2 A json_encode() example showing some options in use

星期五, 10月 23, 2015

擴充Phalcon的filter過濾 xss 攻擊


其實直接用htmlentities or htmlspecialchars就可以了
不過因為一些問題,所以得加上一些參數
見這篇 到底要用htmlenties 還是htmlspecialchars

如果各自使用htmlentities 又容易漏參數
於是想寫個helper類的來幫助

後來想想,幹脆直接擴充phalcon的filter,再透過di統一取得
如此一來就能規範大家用相同的設定也挺不錯的

service.php的設定
$di->setShared("filter", function(
    $filter = new \Phalcon\Filter();
    // Using an anonymous function
    $filter->add('xss', function ($value) {
        $flags = ENT_QUOTES;
        $encoding = "UTF-8";
        $doubleEncode = false;
        return htmlspecialchars($value, $flags, $encoding, $doubleEncode);
    });
    return $filter
));

使用方法
$filter = $di->get("filter");          //取得filter
 
//統一透過filter,寫法能夠一致
$filter->sanitize($value, "xss");      //自寫的,用specialchars
$filter->sanitize($value, "string");   //用htmlentities,不建議用
$filter->sanitize($value, "int");
$filter->sanitize($value, "email");

星期三, 10月 21, 2015

到底要用htmlenties 還是htmlspecialchars

基本上... 要看情況,但先寫通用的結論,就是用htmlspecialchars()
但是!!!! 要加幾個參數,完整如下
htmlspecialchars("i'm 魚乾'", ENT_QUOTES, "UTF-8", false)

先說明後面三個parameters,再說明為何不用htmlentities

  • param 2: $flags = ENT_QUOTES
    避免SQL Injection,所以一律對單引號做轉換
  • param 3: $encoding = "UTF-8",
    encoding一定要加,免得被不同版本的PHP影響
    5.4 預設"UTF-8"
    5.6 是吃default_charset設定
  • param 4: $double_encode = false
    避免重覆encode, ex: &的&會重覆encode


為何不用htmlentities

因為特殊字元會有亂碼問題
htmlentities遇到認不出文字,會轉成亂碼or特殊字
echo htmlentities('魚乾') . PHP_EOL;                 //é­▒ä¹¾ ö
echo htmlspecialchars('魚乾 ö'). PHP_EOL;            //魚乾 ö

//雖然可以decode還原,但如果直接看DB資料時總怪怪的

中文字加上固定的encoding就ok了,但有些字還是會被encode
echo htmlentities('魚乾 ö') . PHP_EOL;                    //é­▒ä¹¾ ö
echo htmlentities('魚乾 ö',ENT_QUOTES,"UTF-8") . PHP_EOL; //魚乾 ö 為會轉為  ö
echo htmlspecialchars('魚乾 ö'). PHP_EOL;                 //魚乾 ö

結論:
內容並不是我們想轉換的特殊字,所以遇到特殊字就不要理,這是htmlspecialchars的理念
那何時適用htmlentities?
就... 你要encode特殊字的時候....
何時會需要... 存的media不支援特殊字時...吧...




星期二, 9月 01, 2015

DevOps conf 2015 (9/1)

*因為沒有提供投影片,所以抄的零零落落

開場
  • 搶先一步的IT競爭力
    • 南非Standard Bank加快發佈軟體2000倍
    • 反之,若是競爭對手的速度快2000倍
  • 實例Standard Bank
    • 除了Dev與Ops Team外,更應用在流程面
      • 新服務申請新的Server,層層的人工簽核
    • 由於改變流程,因此花時間讓高層瞭解
      • 熟悉用詞
      • 導入衝擊
    • 建立文化
      • 將Dev, Ops於同一辦公室工作
      • 宣言服裝(ChopChop)
Conquer CI Server - 樂天 直井和久
  • 因無人專職維運CI Server,同仁也不太會用,所以效能低落
    • 專職維運CI Server
  • Project Metrics
    • 指標太多,訂出要衡量什麼,才能取捨
    • Show progress easily
    • observer the transition
  • Reduce exchange between Dev & Ops team
    • 許多環境設定waste time on communication
    • 透過CHEF, Docker
      • Developer可自行測試
      • Operation直接放設定檔
    • 調整CI Alert mail
      • 寫看的懂,留useful的資訊
      • you don't need to measure everything. only useful information
      • 逐步設定其他的metric
  • how we nurture member
    • share knowledge face-to-face weekly.
  • Conclusion
    • Find/measure/review Project Metrics to consolidate ... 忘了
    • Use useful information for communication
  • 相關軟體
    • Cobertura
    • Jacoco

Enterprise DevOps - Michael Ducy

  • Cultural and Professional movement
    • Book: The Phoenix Project
  • Increasing the flow of work through the IT system
  • DevOps are CALMS
    • Culture (learning, improvement, failure and betterment)
    • Automation (work flow)
    • Lean 
    • Measurement (看的到,才知道要改善什麼)
    • Sharing 
  • "... software is eating the world" Marc Anderson
  • Lean
    • 每次上版要花多少時間在process
      • it's a waste
  • 30 Day Challenges (DevOps Dojo)
    • Time boxed Project
    • Give origination a chance to experiment
    • Eliminate old process to prove new 
    • Eliminate waste
  • Culture 無法被管理
    • 是有最底層的membr形成
    • Managers are no longer a manager
      • "the team i support"
    • The Coaching kata

Yahoo 持續交付 - 應百怡
  • CD如何保持Speed & Quality
    • Speed
      • Eliminate human involvement
      • Small batch
        • Easy to identity issue
          • Check & revise
    • Quality
      • Build the  right thing
        • Small batch
        • Build the thing right
          • Lots test
  • No human allowed
  • Yahoo CEO
    • NO CD, NO LAUNCH, NO FOOLING
  • 5 Stage
雲端OS Team落實CI - 雙子星執行長 符儒嘉
  • Biz -> Dev -> Test -> Ops -> Market
    • Dev過程有Agile
    • Test有CD
    • Ops有 infrastructure as code
  • Branching Methodology
    • feature 
    • release integration
    • release candidate
Whoscall - 葉秉哲
  • get a little better every single day
  • 要monitoring什麼
    • 從Risk management出發(risk有機會的意思)
      • CPU Usage, 不busy的可調整
    • Application 
      • Metric
        • availible
        • response time
        • error
      • Service
        • pingdom => slack
        • Crashlytics => slack
          • 分析crash report
    • DB
      • Metric
        • R/W lock
        • Size
        • Load
        • Speed
      • Service
        • MongoDB Cloud Manager
    • Poor Performance
      • Metric
        • instance metrics
        • application metrics
        • resource
    • Malfunction
      • log分析
        • fluentd->elesticsearch
        • 較複雜的用BigQuery
      • New Realic
        • 看stack trace
        • 各段執行時間
      • Java Metrics
        • 程式自己定metric,不用再刻前後執行執行時間
      • sentry
        • slack
        • hook在app裡

      • Service
        • 統一的fluentD 格式 
          • fluentD
            • ruby實作,部份用c,效能較好
          • logstash
            • java實作,需jvm,效能較差 (講師:java魔人不要罵我)
        • 普羅米修期
          • 多維度,時間序列



星期四, 8月 13, 2015

Linux排程重覆執行問題

有時排程未跑完,下一個週期的排程又被啟動
雖然自己有想法解這問題,不過這應該一堆神人遇過,一定有厲害的解法
請教了google大神,果然出現超強解法
只要改crontab的指令就好,連程式都不用改

* * * * *  sh '/home/fish/test.sh'  #原寫法
* * * * *  flock -xn /tmp/test.lock -c '/home/fish/test.sh' #flock寫法

注意事項
  1. test.lock 會自動產生,不用理,放在/tmp可避免權限問題
  2. 利用flock,得確定執行角色有test.sh的執行權限

超簡單又不用改程式,爽~~~~~~~~~~~

more~

以上的寫法是當重覆執行時,新的排程就直接放棄不執行
但如果是要執行,但可等個幾分鐘怎麼做哩
只要改參數即可
#等60秒後,再執行(要拿掉n,加上w)
* * * * *  flock -x /tmp/test.lock -w 60 -c '/home/fish/test.sh' 


星期三, 8月 05, 2015

Jira, Confluence Chart Plugin中文亂碼

JVM 內建字型不足所導致

1.install missing Chinese fonts

  • cjkuni-ukai-fonts (楷體)
  • cjkuni-uming-fonts (明體)
  • cjkuni-fonts-common
  • cjkuni-fonts-ghostscript
  • wqy-zenhei-fonts (文泉驛,黑體)
  • wqy-zenhei-fonts-common


2.copy to jvm
mkdir /opt/atlassian/confluence/jre/lib/fonts/fallback
cp /usr/share/fonts/cjkuni-ukai/ukai.ttc /opt/atlassian/confluence/jre/lib/fonts/fallback
cp /usr/share/fonts/cjkuni-uming/uming.ttc /opt/atlassian/confluence/jre/lib/fonts/fallback
cp /usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc /opt/atlassian/confluence/jre/lib/fonts/fallback

p.s. 不知道cjkuni-fonts-common, cjkuni-fonts-ghostscript, wqy-zenhei-fonts-common在哪... 等待有緣人指點一下

3. restart Jira, Confluence

Reference



星期一, 7月 20, 2015

列出排序後的圖檔

說明:
每個分類會有對應的圖檔,原本利用id當檔名存
但因介接系統只認檔名,所在在相同檔名下,更換圖檔內容不會觸發介接系統更新圖
因此利用filename加timestamp來觸發(跟css, js加上?v=xxx同義)

做法:
資料夾下會有多個圖檔,而圖檔的filename會夾timestamp,
在不靠其他persistent data的做法下(記在db or file),就直接sort timestamp當最新的圖檔


  1. 取得所有jpg圖
  2. $files = glob("/path/to/directory/*.jpg");
    --
    Array
    (
        [0] => /path/to/directory/1.jpg
        [1] => /path/to/directory/2.jpg
        [2] => /path/to/directory/3.jpg
    )
    
  3. 加上其他圖檔格式(靠GLOB_BRACE)
    $images = glob("files/*.{jpg,gif,png}", GLOB_BRACE);
    
  4. 還有大小寫問題 >_<
    $images = glob("files/*.{[jJ][pP][gG],[gG][iI][fF],[pP][nN][gG]}", GLOB_BRACE);
    


  5. 排序部份靠php,完整的寫法如下(如果還要其他圖檔格式,就自己加囉)
    $images = glob("files/*.{[jJ][pP][gG],[gG][iI][fF],[pP][nN][gG]}", GLOB_BRACE);
    $sorted = rsort($images); //由大到小
    


Reference
Using PHP's glob() function to find files in a directory

星期四, 6月 18, 2015

Scrum是提早給feedback,但講好的需求,就是要上線啊

看到好多單位都能研究新的技術,並提出相關的應用
心裡在想為何別人能持續在技術有進步

公司最近有個顧問要離開
提到「這幾個月他工作滿開心的,因為沒有人assign工作給他,所以有時間鑽研他有興趣的議題」

也讓我回想到去年底時,因健況出了問題,在家專心養病
沒有時程壓力,便有時間大量閱讀某技術的相關資料
今年回來時,也帶顉同事使用該技術

後來在David Ko的Blog看到這張圖
要 Output 還是要 Outcome

讓我回想,回到工作崗位後,疲於趕user的feature,一直在拚output
如果省下時間只做有價值的產品
我想整個team都會有更多時間在打混開發更有價值的東西,以及技術研究上 XD

local server拿ISO當yum repo server

Linux Server在內網,被限禁無法對外連
因此要yum install時,都得自己找rpm
而公司又會鎖ftp,因此找rpm都很難找

最近要裝新東西,實在被搞煩了
看一下有好東西,可以直接拿ISO檔當yum repository
Step1. mount iso
Creating a Local Yum Repository Using an ISO Image
Step2. setup yum server
Setting up a Local Yum Server Using an ISO Image

還滿容易的~
現在下yum install就自己裝好了
好感動,差點哭出來...


p.s. yum install可能還會出現以下錯誤
GPG key retrieval failed: [Errno 14] Could not open/read file:///etc/pki/rpm-gpg/RPM-GPG-KEY
只要加上--nogpgcheck即可
[root]#yum install --nogpgcheck {packagename}

星期六, 6月 06, 2015

Kanban Board應放哪裡

因團隊是在會議室內,理所當然放會議室裡
daily meeting,討論issue等,也都在會議室內

由於自主管理,主管也不太曉得我們在做什麼
反正沒出什麼包,就放給我們自己玩
只不過都關在房間裡,有天反問我,不曉得team在做什麼
這實在很難解釋...

後來有個團隊沒有會議室,只好將看板貼在放走廊上
嘿~ 這還不錯,因旁人都看的到,感覺有在做事
所以也把看板搬出來了

幾天後主管就說感覺工作氣氛不一樣
每個team比較活絡有互動~

有時還是得表現給別人看(誤)

提早得到feedback,但調整也得花時間呀~ user老大

最近開始run scrum
每回合產出的項目,也讓user實際操作體驗
在正式上線前得到不少feedback及調整需求
感覺挺不錯的~

西嘎西!!! (日語:但是)
「需求要調整,原定的功能也得在原定時程完成,也就是上線的時程不變」
我咧...
開發單位:不是有說好需求要排優先,那優先權較低的可以拿掉呀
需求單位:所有的需求都已經砍過了,沒有辦法法再砍了,一定要全上...

怪不得的有團隊明明開發差不多了
卻說上線前幾天才能給user測試
私底下問,才得知user就不會有時間改需求
把球丟回給user...

這叫「上有需求變更,下有裝死對策」

星期二, 3月 24, 2015

排程與apache建立共用folder


由於透過排程建立image資料夾丟圖片
而後台(人工)作業也會透過apache建立資料夾丟圖片
但權限不同(owner不同),造成無法丟入圖檔
最麻煩的是Server被禁止無法在php裡執行chmod

想了幾個做法
  1. 透過localhost/shell啟動apache/[cron-user]建立folder  (failed)
    原本想用排程透過curl呼叫"建立folder"的PHP (owner 為apache)
    但因為一樣是建立自己的帳號,反而是自己無權限丟檔  o_Q
  2. 排程執行固定執行Shell (work around)
    可以,但因為要改對方建立的folder,所以得要有root權限,不太好的解法 
  3. 透過apache執行排程 (solution)
    原本想建立apache user來寫排程,但Admin不同意
    後來看到可以sudo為apache來寫排程,這樣一來都是owner都是apache~ YA~
    sudo -u apache crontab -e

星期日, 3月 08, 2015

PHP到底有沒有DB Connection Pooling

一直沒搞懂到底PHP有沒有Connection Pooling...
看了Persistent connections,又有人說不要用
沒事就被打個槍,還是好好研究一下

先簡單的來說有什麼做法(linux下)
  1. PHP的MSSQL extension
    1. 就是常見的pconnect,不建議
  2. PHP的PDO extension
    • 做法
      • 將connection cache下來,當其他的php script request,再重覆使用
        寫法如下
        <?php
        $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
            PDO::ATTR_PERSISTENT => true
        ));
        實驗結果PDO可以的ATTR_PERSISTENT ,還可關掉ODBC的pooling
    • 討論
      • PHP官網指出,如果有ODBC做pooling的話,就用ODBC做,因為可讓同process其他的模組使用
  3. ODBC Connection Pooling(unixODBC)
    • 做法
      • 存在Web Server裡,供給Web Server Process使用
      • 前提是使用的ODBC driver及library要有支援
      • PDO_ODBC及unixODBC v2.0後都有支援Connection Pool
    • 另外利用ODBC的還有以下,但各自有沒有再實作pooling沒研究
      • Microsoft ODBC
      • Easysoft ODBC
  4. freeTDS
    • 做法:利用linux process管理connection
    • 怪可怕的,如果process掛了,那connection就GG了
    • 而且只接受TDS 4.2, 也不接受ntext

Summary

看起來利用ODBC比較做是比較建議的做法
另外就不用再用PDO做persistent,因為會被cache住,不會還給ODBC.

  • 使用Pooling注意事項
    勿改變connection 狀態,例如改default db,造成使用同組db帳密的request會讀取錯誤


Reference
Connections and Connection management
ODBC Connection pooling

星期一, 3月 02, 2015

Code Review項目

一直覺得Code Review滿重要的
高效代碼審查:來自前質疑者的9個建議有提到Code Review有助於以下

  • 抓bug
  • 保證代碼的可讀性,可維護性
  • 在團隊中散播代碼的知識
  • 讓新人適應團隊的工作方式
  • 讓大家接觸不同的思路

文章還有提到些具體的做法
我也要加入Working Agreement

  • 每次的pull request都要求所有team member做code review
  • 條列check item
    • 這項還滿不錯的,至少每個人會習慣必要的項目
      自己寫code時也會注意


Reference: 高效代碼審查:來自前質疑者的9個建議

禁止root遠端ssh登入 linux


新架了Linux Server,沒想到才幾天而已
就發現root在2小時內,就有7000多次的登入失敗記錄

太可怕了... 趕快加個限制
禁止root遠端ssh登入 linux

vi /etc/ssh/sshd_config
--
PermitRootLogin no
--
/etc/init.d/sshd restart

Reference:
Security Tip: Disable Root SSH Login on Linux

星期二, 2月 17, 2015

API Response Format

對API的response沒有設定標準格式
每次寫API就在想,網路上看到這版本還不錯
再小調整一下,符合自己需要的
統一這個版本了
{
    success: <boolean>,
    error : { /* Only included if success is false. */
        code: (customize error code)
        msg: (for message)
    },        
    response: {} /* Only included if success is true */
}


Reference
Sentiment Analysis Endpoint

星期四, 1月 08, 2015

導Agile可以,但品質要顧好

前陣子學Agile,懂了點皮毛,正在公司導Agile
最近主管回覆:「導Agile可以,但品質要顧好」
聽起來很不合agile的邏輯,想了好久

Agile是Rough, adaptive plan,不是No plan...

我在想主管應該是以為Agile是No Design, No Plan在開發
因此對Agile會有些品質的誤解
在 Henrik Kniberg 的 文章 What is Scrum? 裡有張圖還不錯


應該就能知道Agile是Rough, adaptive plan
而不是No plan的開發









品質應該更好... 顧吧

對主管的話特別有反應是因為....
Agile把feature size切小,不敢說小就簡單
但至少開發, Tester對該週期開發的feature掌握度高
即使出搥了,也能快速的找出問題修正

公司有個team
每個月上20多個features,要上線時都要搞半夜上線
一有問題,就得從這堆features找bug
我實在很佩服,問他們不會壓力很大嗎
還說不會哩... 真是神人....

每個release短一點,features少一點

如果改成每週上5個features,我想相對大家會容易應付些
雖然每週上線壓力有點大,不過總比一個月上20多個feature好一些
而且如同agile說的,也許剩餘的feature會因些feedback有所調整或消失...

星期四, 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

星期六, 12月 21, 2013

Loading Scripts Without Blocking

最近同事發現有隻script會block其他request
查了一下原來script還真有這問題
在「Even Fast Web Sites」有提到
SCRIPT tags have a negative impact on page performance because of their blocking
behavior. While scripts are being downloaded and executed, most browsers won’t
download anything else. There are times when it’s necessary to have this blocking, but
it’s important to identify situations when JavaScript can be loaded independent of the
rest of the page.

可以實際試一下
http://stevesouders.com/cuzillion/?ex=10008&title=Scripts+Block+Downloads









作者的說明是...
This page has two scripts at the top, A.js and B.js, followed by an image, a stylesheet, and an iframe. The scripts are each programmed to take one second to download and one second to execute. The white gaps in the HTTP profile indicate where the scripts are executed. This shows that while scripts are being downloaded and executed, all other downloads are blocked. Only after the scripts have finished are the image, stylesheet, and iframe merrily downloaded in parallel.

中文就是指...
可以看出兩個script會等待,且會block其他requests下載
兩段的空白是script執行時間,完成後才會進行下一步
二個scripts都好了,才會再同時download其他resources

解決方法
作者有提出幾種方法,不過似乎都不能一次解決
書是2009年出的,想說有沒有新的解決方法,google看到了這段

reference: What is a non-blocking script?
  1. create a script node dynamically and
    var scriptElem = document.createElement('script');|
    scriptElem.src = 'http://anydomain.com/A.js';
    document.getElementsByTagName('head')[0].appendChild(scriptElem);
  2. use the HTML5 async attribute of a <script> tag.
    # 我是註解
    <script type="text/javascript" async src="foo.js"> </script>
    
作者有提到要注意script是否有前後執行的順序
特別是處理UI的javascript(UI沒反應or掛了)
因為以上的方法只要下載完就會執行,不管在html裡的順序
ie可設定defer屬性使script同時下載,並依序執行

「Even Fast Web Sites」的作者有建議
後讀的ui相關script要能先呈現loading圖示,避免user使用(lazy-loaded code)
或者可做stub function,先回應空的,等載完後再覆寫

星期四, 11月 28, 2013

db 的index有這麼多搞頭

最近系統流量大,在db遇到些瓶頸
經過dba分析,對index也有比較深入的瞭解


  • index不只index
    以前說設index,就只知道較常查詢的欄位拿來設為index就好了
    經dba細心分析,才知道除了設定外,連多個欄位組合的index前後的順序也有差
    較常查詢的欄位要放前面
  • select除了設index外,還可以...
    可以針對sql語句,帶出指定的select column,也可以指定where的column
  • insert, update也可以設定index
  • cluster index & noncluster index
    看不懂這東西,經dba解釋
    cluster index會將同table的其他欄位一起帶出
    所以cluster index只會有一個
  • 反之nocluster不會,不過就可以彈性的指定必要的欄位 東西帶的少了,搜尋效率自然提升
  • no lock
    可以dirty read的select就加no lock(mssql)吧
    避免waiting
  • db的原生函式會造成full table scan
    本想說先在sql的where句做了一些轉型,這樣比較好過濾
    但dba提出這造成full table scan,效能很差
    改完後,這top sql(slow log)就不見了
  • 用變數存GETDATE
    條件式或異動欄位常用到GETDATE(),有隻SQL用到5次
    DBA建議先存變數裡,這樣compile 1次,也只跑1次

還挺了滿多觀念的,一時還無法全吸收
再慢慢整理了

linux複製資料,並排除指定資料夾

要複製資料夾很容易,不過要排除某個資料夾就不知怎麼做了
最近需手動複製git資料夾,複製.git太多太久,所以想拿掉
查了一下只要這麼下就可以了

rsync -av --progress sourcDir tmp --exclude srouceDir/.git
說明:複製sourceDir 到tmp底下,要排除sourceDir/.git這資料夾