星期四, 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當替死鬼